+ /* The rest is for when verbose is set; if not set, we're done */
+ if (!verbose)
+ goto done;
+
+ if (ioctl(s, SIOCGIFTYPE, &ifr) != -1) {
+ char *c = ift2str(ifr.ifr_type.ift_type,
+ ifr.ifr_type.ift_family, ifr.ifr_type.ift_subfamily);
+ if (c != NULL)
+ printf("\ttype: %s\n", c);
+ }
+
+ if (verbose > 0) {
+ struct if_agentidsreq ifar;
+ memset(&ifar, 0, sizeof(ifar));
+
+ strlcpy(ifar.ifar_name, name, sizeof(ifar.ifar_name));
+
+ if (ioctl(s, SIOCGIFAGENTIDS, &ifar) != -1) {
+ if (ifar.ifar_count != 0) {
+ ifar.ifar_uuids = calloc(ifar.ifar_count, sizeof(uuid_t));
+ if (ifar.ifar_uuids != NULL) {
+ if (ioctl(s, SIOCGIFAGENTIDS, &ifar) != 1) {
+ for (int agent_i = 0; agent_i < ifar.ifar_count; agent_i++) {
+ struct netagent_req nar;
+ memset(&nar, 0, sizeof(nar));
+
+ uuid_copy(nar.netagent_uuid, ifar.ifar_uuids[agent_i]);
+
+ if (ioctl(s, SIOCGIFAGENTDATA, &nar) != 1) {
+ printf("\tagent domain:%s type:%s flags:0x%x desc:\"%s\"\n",
+ nar.netagent_domain, nar.netagent_type,
+ nar.netagent_flags, nar.netagent_desc);
+ }
+ }
+ }
+ free(ifar.ifar_uuids);
+ }
+ }
+ }
+ }
+
+ if (ioctl(s, SIOCGIFLINKQUALITYMETRIC, &ifr) != -1) {
+ int lqm = ifr.ifr_link_quality_metric;
+ if (verbose > 1) {
+ printf("\tlink quality: %d ", lqm);
+ if (lqm == IFNET_LQM_THRESH_OFF)
+ printf("(off)");
+ else if (lqm == IFNET_LQM_THRESH_UNKNOWN)
+ printf("(unknown)");
+ else if (lqm > IFNET_LQM_THRESH_UNKNOWN &&
+ lqm <= IFNET_LQM_THRESH_BAD)
+ printf("(bad)");
+ else if (lqm > IFNET_LQM_THRESH_UNKNOWN &&
+ lqm <= IFNET_LQM_THRESH_POOR)
+ printf("(poor)");
+ else if (lqm > IFNET_LQM_THRESH_POOR &&
+ lqm <= IFNET_LQM_THRESH_GOOD)
+ printf("(good)");
+ else
+ printf("(?)");
+ printf("\n");
+ } else if (lqm > IFNET_LQM_THRESH_UNKNOWN) {
+ printf("\tlink quality: %d ", lqm);
+ if (lqm <= IFNET_LQM_THRESH_BAD)
+ printf("(bad)");
+ else if (lqm <= IFNET_LQM_THRESH_POOR)
+ printf("(poor)");
+ else if (lqm <= IFNET_LQM_THRESH_GOOD)
+ printf("(good)");
+ else
+ printf("(?)");
+ printf("\n");
+ }
+ }
+
+ if (verbose > 0) {
+ if (ioctl(s, SIOCGIFINTERFACESTATE, &ifr) != -1) {
+ printf("\tstate");
+ if (ifr.ifr_interface_state.valid_bitmask &
+ IF_INTERFACE_STATE_RRC_STATE_VALID) {
+ uint8_t rrc_state = ifr.ifr_interface_state.rrc_state;
+
+ printf(" rrc: %u ", rrc_state);
+ if (rrc_state == IF_INTERFACE_STATE_RRC_STATE_CONNECTED)
+ printf("(connected)");
+ else if (rrc_state == IF_INTERFACE_STATE_RRC_STATE_IDLE)
+ printf("(idle)");
+ else
+ printf("(?)");
+ }
+ if (ifr.ifr_interface_state.valid_bitmask &
+ IF_INTERFACE_STATE_INTERFACE_AVAILABILITY_VALID) {
+ uint8_t ifavail = ifr.ifr_interface_state.interface_availability;
+
+ printf(" availability: %u ", ifavail);
+ if (ifavail == IF_INTERFACE_STATE_INTERFACE_AVAILABLE)
+ printf("(true)");
+ else if (ifavail == IF_INTERFACE_STATE_INTERFACE_UNAVAILABLE)
+ printf("(false)");
+ else
+ printf("(?)");
+ } else {
+ printf(" availability: (not valid)");
+ }
+ if (verbose > 1 &&
+ ifr.ifr_interface_state.valid_bitmask &
+ IF_INTERFACE_STATE_LQM_STATE_VALID) {
+ int8_t lqm = ifr.ifr_interface_state.lqm_state;
+
+ printf(" lqm: %d", lqm);
+
+ if (lqm == IFNET_LQM_THRESH_OFF)
+ printf("(off)");
+ else if (lqm == IFNET_LQM_THRESH_UNKNOWN)
+ printf("(unknown)");
+ else if (lqm == IFNET_LQM_THRESH_BAD)
+ printf("(bad)");
+ else if (lqm == IFNET_LQM_THRESH_POOR)
+ printf("(poor)");
+ else if (lqm == IFNET_LQM_THRESH_GOOD)
+ printf("(good)");
+ else
+ printf("(?)");
+ }
+ }
+ printf("\n");
+ }
+
+ bzero(&iflpr, sizeof (iflpr));
+ strncpy(iflpr.iflpr_name, name, sizeof (iflpr.iflpr_name));
+ if (ioctl(s, SIOCGIFLINKPARAMS, &iflpr) != -1) {
+ u_int64_t ibw_max = iflpr.iflpr_input_bw.max_bw;
+ u_int64_t ibw_eff = iflpr.iflpr_input_bw.eff_bw;
+ u_int64_t obw_max = iflpr.iflpr_output_bw.max_bw;
+ u_int64_t obw_eff = iflpr.iflpr_output_bw.eff_bw;
+ u_int64_t obw_tbr = iflpr.iflpr_output_tbr_rate;
+ u_int32_t obw_pct = iflpr.iflpr_output_tbr_percent;
+ u_int64_t ilt_max = iflpr.iflpr_input_lt.max_lt;
+ u_int64_t ilt_eff = iflpr.iflpr_input_lt.eff_lt;
+ u_int64_t olt_max = iflpr.iflpr_output_lt.max_lt;
+ u_int64_t olt_eff = iflpr.iflpr_output_lt.eff_lt;
+
+
+ if (eflags & IFEF_TXSTART) {
+ u_int32_t flags = iflpr.iflpr_flags;
+ u_int32_t sched = iflpr.iflpr_output_sched;
+ struct if_throttlereq iftr;
+
+ printf("\tscheduler: %s%s ",
+ (flags & IFLPRF_ALTQ) ? "ALTQ_" : "",
+ sched2str(sched));
+ if (flags & IFLPRF_DRVMANAGED)
+ printf("(driver managed)");
+ printf("\n");
+
+ bzero(&iftr, sizeof (iftr));
+ strncpy(iftr.ifthr_name, name,
+ sizeof (iftr.ifthr_name));
+ if (ioctl(s, SIOCGIFTHROTTLE, &iftr) != -1 &&
+ iftr.ifthr_level != IFNET_THROTTLE_OFF)
+ printf("\tthrottling: level %d (%s)\n",
+ iftr.ifthr_level, tl2str(iftr.ifthr_level));
+ }
+
+ if (obw_tbr != 0 && obw_eff > obw_tbr)
+ obw_eff = obw_tbr;
+
+ if (ibw_max != 0 || obw_max != 0) {
+ if (ibw_max == obw_max && ibw_eff == obw_eff &&
+ ibw_max == ibw_eff && obw_tbr == 0) {
+ printf("\tlink rate: %s\n",
+ bps_to_str(ibw_max));
+ } else {
+ printf("\tuplink rate: %s [eff] / ",
+ bps_to_str(obw_eff));
+ if (obw_tbr != 0) {
+ if (obw_pct == 0)
+ printf("%s [tbr] / ",
+ bps_to_str(obw_tbr));
+ else
+ printf("%s [tbr %u%%] / ",
+ bps_to_str(obw_tbr),
+ obw_pct);
+ }
+ printf("%s", bps_to_str(obw_max));
+ if (obw_tbr != 0)
+ printf(" [max]");
+ printf("\n");
+ if (ibw_eff == ibw_max) {
+ printf("\tdownlink rate: %s\n",
+ bps_to_str(ibw_max));
+ } else {
+ printf("\tdownlink rate: "
+ "%s [eff] / ", bps_to_str(ibw_eff));
+ printf("%s [max]\n",
+ bps_to_str(ibw_max));
+ }
+ }
+ } else if (obw_tbr != 0) {
+ printf("\tuplink rate: %s [tbr]\n",
+ bps_to_str(obw_tbr));
+ }
+
+ if (ilt_max != 0 || olt_max != 0) {
+ if (ilt_max == olt_max && ilt_eff == olt_eff &&
+ ilt_max == ilt_eff) {
+ printf("\tlink latency: %s\n",
+ ns_to_str(ilt_max));
+ } else {
+ if (olt_max != 0 && olt_eff == olt_max) {
+ printf("\tuplink latency: %s\n",
+ ns_to_str(olt_max));
+ } else if (olt_max != 0) {
+ printf("\tuplink latency: "
+ "%s [eff] / ", ns_to_str(olt_eff));
+ printf("%s [max]\n",
+ ns_to_str(olt_max));
+ }
+ if (ilt_max != 0 && ilt_eff == ilt_max) {
+ printf("\tdownlink latency: %s\n",
+ ns_to_str(ilt_max));
+ } else if (ilt_max != 0) {
+ printf("\tdownlink latency: "
+ "%s [eff] / ", ns_to_str(ilt_eff));
+ printf("%s [max]\n",
+ ns_to_str(ilt_max));
+ }
+ }
+ }
+ }
+
+ /* Common OID prefix */
+ mib[0] = CTL_NET;
+ mib[1] = PF_LINK;
+ mib[2] = NETLINK_GENERIC;
+ mib[3] = IFMIB_IFDATA;
+ mib[4] = if_nametoindex(name);
+ mib[5] = IFDATA_SUPPLEMENTAL;
+ if (sysctl(mib, 6, &ifmsupp, &miblen, (void *)0, 0) == -1)
+ err(1, "sysctl IFDATA_SUPPLEMENTAL");
+
+ if (ifmsupp.ifmd_data_extended.ifi_alignerrs != 0) {
+ printf("\tunaligned pkts: %llu\n",
+ ifmsupp.ifmd_data_extended.ifi_alignerrs);
+ }
+ if (ifmsupp.ifmd_data_extended.ifi_dt_bytes != 0) {
+ printf("\tdata milestone interval: %s\n",
+ bytes_to_str(ifmsupp.ifmd_data_extended.ifi_dt_bytes));
+ }
+
+ bzero(&ifdr, sizeof (ifdr));
+ strncpy(ifdr.ifdr_name, name, sizeof (ifdr.ifdr_name));
+ if (ioctl(s, SIOCGIFDESC, &ifdr) != -1 && ifdr.ifdr_len) {
+ printf("\tdesc: %s\n", ifdr.ifdr_desc);
+ }
+
+ if (ioctl(s, SIOCGIFLOG, &ifr) != -1 && ifr.ifr_log.ifl_level) {
+ printf("\tlogging: level %d ", ifr.ifr_log.ifl_level);
+ printb("facilities", ifr.ifr_log.ifl_flags, IFRLOGF_BITS);
+ putchar('\n');
+ }
+
+ if (ioctl(s, SIOCGIFDELEGATE, &ifr) != -1 && ifr.ifr_delegated) {
+ char delegatedif[IFNAMSIZ+1];
+ if (if_indextoname(ifr.ifr_delegated, delegatedif) != NULL)
+ printf("\teffective interface: %s\n", delegatedif);
+ }
+
+ if(ioctl(s, SIOCGSTARTDELAY, &ifr) != -1) {
+ if (ifr.ifr_start_delay_qlen > 0 &&
+ ifr.ifr_start_delay_timeout > 0) {
+ printf("\ttxstart qlen: %u packets "
+ "timeout: %u microseconds\n",
+ ifr.ifr_start_delay_qlen,
+ ifr.ifr_start_delay_timeout/1000);
+ }
+ }
+
+done: