1/* 2 * Copyright (c) 2008-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright (c) 1983, 1988, 1993 30 * The Regents of the University of California. All rights reserved. 31 * 32 * Redistribution and use in source and binary forms, with or without 33 * modification, are permitted provided that the following conditions 34 * are met: 35 * 1. Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * 2. Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in the 39 * documentation and/or other materials provided with the distribution. 40 * 3. All advertising materials mentioning features or use of this software 41 * must display the following acknowledgement: 42 * This product includes software developed by the University of 43 * California, Berkeley and its contributors. 44 * 4. Neither the name of the University nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 */ 60 61#include <sys/types.h> 62#include <sys/socket.h> 63#include <sys/sysctl.h> 64#include <sys/ioctl.h> 65#include <sys/time.h> 66 67#include <net/if.h> 68#include <net/if_var.h> 69#include <net/if_dl.h> 70#include <net/if_types.h> 71#include <net/if_mib.h> 72#include <net/if_llreach.h> 73#include <net/ethernet.h> 74#include <net/route.h> 75 76#include <net/pktsched/pktsched.h> 77#include <net/classq/if_classq.h> 78 79#include <netinet/in.h> 80#include <netinet/in_var.h> 81 82#include <arpa/inet.h> 83 84#include <signal.h> 85#include <stdio.h> 86#include <string.h> 87#include <unistd.h> 88#include <stdlib.h> 89#include <err.h> 90#include <errno.h> 91 92#include "netstat.h" 93 94#define YES 1 95#define NO 0 96 97#define ROUNDUP(a, size) (((a) & ((size) - 1)) ? (1 + ((a)|(size - 1))) : (a)) 98 99#define NEXT_SA(p) (struct sockaddr *) \ 100 ((caddr_t)p + (p->sa_len ? ROUNDUP(p->sa_len, sizeof(uint32_t)) : \ 101 sizeof(uint32_t))) 102 103static void sidewaysintpr (); 104static void catchalarm (int); 105static char *sec2str(time_t); 106static void llreach_sysctl(uint32_t); 107static char *nsec_to_str(unsigned long long); 108static char *qtype2str(classq_type_t); 109static char *sched2str(unsigned int); 110static char *qid2str(unsigned int); 111static char *qstate2str(unsigned int); 112static char *tcqslot2str(unsigned int); 113static char *rate2str(long double); 114 115#define AVGN_MAX 8 116 117struct queue_stats { 118 int avgn; 119 double avg_bytes; 120 double avg_packets; 121 u_int64_t prev_bytes; 122 u_int64_t prev_packets; 123 unsigned int printed; 124 unsigned int handle; 125}; 126 127static void print_cbqstats(int slot, struct cbq_classstats *, 128 struct queue_stats *); 129static void print_priqstats(int slot, struct priq_classstats *, 130 struct queue_stats *); 131static void print_hfscstats(int slot, struct hfsc_classstats *, 132 struct queue_stats *); 133static void print_fairqstats(int slot, struct fairq_classstats *, 134 struct queue_stats *); 135static void print_tcqstats(int slot, struct tcq_classstats *, 136 struct queue_stats *); 137static void print_qfqstats(int slot, struct qfq_classstats *, 138 struct queue_stats *); 139static void print_sfbstats(struct sfb_stats *); 140static void update_avg(struct if_ifclassq_stats *, struct queue_stats *); 141 142struct queue_stats qstats[IFCQ_SC_MAX]; 143 144#ifdef INET6 145char *netname6 (struct sockaddr_in6 *, struct sockaddr *); 146static char ntop_buf[INET6_ADDRSTRLEN]; /* for inet_ntop() */ 147#endif 148 149/* 150 * Display a formatted value, or a '-' in the same space. 151 */ 152static void 153show_stat(const char *fmt, int width, u_int64_t value, short showvalue) 154{ 155 char newfmt[32]; 156 157 /* Construct the format string */ 158 if (showvalue) { 159 snprintf(newfmt, sizeof(newfmt), "%%%d%s", width, fmt); 160 printf(newfmt, value); 161 } else { 162 snprintf(newfmt, sizeof(newfmt), "%%%ds", width); 163 printf(newfmt, "-"); 164 } 165} 166 167size_t 168get_rti_info(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 169{ 170 int i; 171 size_t len = 0; 172 173 for (i = 0; i < RTAX_MAX; i++) { 174 if (addrs & (1 << i)) { 175 rti_info[i] = sa; 176 if (sa->sa_len < sizeof(struct sockaddr)) 177 len += sizeof(struct sockaddr); 178 else 179 len += sa->sa_len; 180 sa = NEXT_SA(sa); 181 } else { 182 rti_info[i] = NULL; 183 } 184 } 185 return len; 186} 187 188static void 189multipr(int family, char *buf, char *lim) 190{ 191 char *next; 192 193 for (next = buf; next < lim; ) { 194 struct ifma_msghdr2 *ifmam = (struct ifma_msghdr2 *)next; 195 struct sockaddr *rti_info[RTAX_MAX]; 196 struct sockaddr *sa; 197 const char *fmt = 0; 198 199 next += ifmam->ifmam_msglen; 200 if (ifmam->ifmam_type == RTM_IFINFO2) 201 break; 202 else if (ifmam->ifmam_type != RTM_NEWMADDR2) 203 continue; 204 get_rti_info(ifmam->ifmam_addrs, (struct sockaddr*)(ifmam + 1), rti_info); 205 sa = rti_info[RTAX_IFA]; 206 207 if (sa->sa_family != family) 208 continue; 209 switch (sa->sa_family) { 210 case AF_INET: { 211 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 212 213 fmt = routename(sin->sin_addr.s_addr); 214 break; 215 } 216 #ifdef INET6 217 case AF_INET6: { 218 struct sockaddr_in6 sin6; 219 220 memcpy(&sin6, sa, sizeof(struct sockaddr_in6)); 221 222 if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) || 223 IN6_IS_ADDR_MC_NODELOCAL(&sin6.sin6_addr) || 224 IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) { 225 sin6.sin6_scope_id = ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]); 226 sin6.sin6_addr.s6_addr[2] = 0; 227 sin6.sin6_addr.s6_addr[3] = 0; 228 } 229 230 printf("%23s %-19.19s(refs: %d)\n", "", 231 inet_ntop(AF_INET6, &sin6.sin6_addr, 232 ntop_buf, sizeof(ntop_buf)), 233 ifmam->ifmam_refcount); 234 break; 235 } 236 #endif /* INET6 */ 237 case AF_LINK: { 238 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; 239 240 switch (sdl->sdl_type) { 241 case IFT_ETHER: 242 case IFT_FDDI: 243 fmt = ether_ntoa((struct ether_addr *) 244 LLADDR(sdl)); 245 break; 246 } 247 break; 248 } 249 } 250 if (fmt) 251 printf("%23s %s\n", "", fmt); 252 } 253} 254 255/* 256 * Print a description of the network interfaces. 257 */ 258void 259intpr(void (*pfunc)(char *)) 260{ 261 u_int64_t opackets = 0; 262 u_int64_t ipackets = 0; 263 u_int64_t obytes = 0; 264 u_int64_t ibytes = 0; 265 u_int64_t oerrors = 0; 266 u_int64_t ierrors = 0; 267 u_int64_t collisions = 0; 268 u_int64_t fpackets = 0; 269 u_int64_t fbytes = 0; 270 uint32_t mtu = 0; 271 int timer = 0; 272 int drops = 0; 273 struct sockaddr *sa = NULL; 274 char name[32]; 275 short network_layer; 276 short link_layer; 277 int mib[6]; 278 char *buf = NULL, *lim, *next; 279 size_t len; 280 struct if_msghdr *ifm; 281 struct sockaddr *rti_info[RTAX_MAX]; 282 unsigned int ifindex = 0; 283 284 if (interval) { 285 sidewaysintpr(); 286 return; 287 } 288 289 if (interface != 0) 290 ifindex = if_nametoindex(interface); 291 292 mib[0] = CTL_NET; // networking subsystem 293 mib[1] = PF_ROUTE; // type of information 294 mib[2] = 0; // protocol (IPPROTO_xxx) 295 mib[3] = 0; // address family 296 mib[4] = NET_RT_IFLIST2; // operation 297 mib[5] = 0; 298 if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) 299 return; 300 if ((buf = malloc(len)) == NULL) { 301 printf("malloc failed\n"); 302 exit(1); 303 } 304 if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { 305 if (buf) 306 free(buf); 307 return; 308 } 309 310 if (!pfunc) { 311 printf("%-5.5s %-5.5s %-13.13s %-15.15s %8.8s %5.5s", 312 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs"); 313 if (prioflag >= 0) 314 printf(" %8.8s %8.8s", "Itcpkts", "Ipvpkts"); 315 if (bflag) { 316 printf(" %10.10s","Ibytes"); 317 if (prioflag >= 0) 318 printf(" %8.8s %8.8s", "Itcbytes", "Ipvbytes"); 319 } 320 printf(" %8.8s %5.5s", "Opkts", "Oerrs"); 321 if (prioflag >= 0) 322 printf(" %8.8s %8.8s", "Otcpkts", "Opvpkts"); 323 if (bflag) { 324 printf(" %10.10s","Obytes"); 325 if (prioflag >= 0) 326 printf(" %8.8s %8.8s", "Otcbytes", "Opvbytes"); 327 } 328 printf(" %5s", "Coll"); 329 if (tflag) 330 printf(" %s", "Time"); 331 if (dflag) 332 printf(" %s", "Drop"); 333 if (Fflag) { 334 printf(" %8.8s", "Fpkts"); 335 if (bflag) 336 printf(" %10.10s", "Fbytes"); 337 } 338 putchar('\n'); 339 } 340 lim = buf + len; 341 for (next = buf; next < lim; ) { 342 char *cp; 343 int n, m; 344 struct ifmibdata_supplemental ifmsupp; 345 u_int64_t ift_itcp = 0; /* input tc packets */ 346 u_int64_t ift_itcb = 0; /* input tc bytes */ 347 u_int64_t ift_otcp = 0; /* output tc packets */ 348 u_int64_t ift_otcb = 0; /* output tc bytes */ 349 u_int64_t ift_ipvp = 0; /* input priv tc packets */ 350 u_int64_t ift_ipvb = 0; /* input priv tc bytes */ 351 u_int64_t ift_opvp = 0; /* output priv tc packets */ 352 u_int64_t ift_opvb = 0; /* output priv tc bytes */ 353 354 bzero(&ifmsupp, sizeof(struct ifmibdata_supplemental)); 355 356 network_layer = 0; 357 link_layer = 0; 358 ifm = (struct if_msghdr *)next; 359 next += ifm->ifm_msglen; 360 361 if (ifm->ifm_type == RTM_IFINFO2) { 362 struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm; 363 struct sockaddr_dl *sdl = 364 (struct sockaddr_dl *)(if2m + 1); 365 int mibname[6]; 366 size_t miblen = sizeof(struct ifmibdata_supplemental); 367 368 strncpy(name, sdl->sdl_data, sdl->sdl_nlen); 369 name[sdl->sdl_nlen] = 0; 370 if (interface != 0 && if2m->ifm_index != ifindex) 371 continue; 372 cp = index(name, '\0'); 373 374 if (pfunc) { 375 (*pfunc)(name); 376 continue; 377 } 378 379 if ((if2m->ifm_flags & IFF_UP) == 0) 380 *cp++ = '*'; 381 *cp = '\0'; 382 383 /* 384 * Get the interface stats. These may get 385 * overriden below on a per-interface basis. 386 */ 387 opackets = if2m->ifm_data.ifi_opackets; 388 ipackets = if2m->ifm_data.ifi_ipackets; 389 obytes = if2m->ifm_data.ifi_obytes; 390 ibytes = if2m->ifm_data.ifi_ibytes; 391 oerrors =if2m->ifm_data.ifi_oerrors; 392 ierrors = if2m->ifm_data.ifi_ierrors; 393 collisions = if2m->ifm_data.ifi_collisions; 394 timer = if2m->ifm_timer; 395 drops = if2m->ifm_snd_drops; 396 mtu = if2m->ifm_data.ifi_mtu; 397 398 /* Common OID prefix */ 399 mibname[0] = CTL_NET; 400 mibname[1] = PF_LINK; 401 mibname[2] = NETLINK_GENERIC; 402 mibname[3] = IFMIB_IFDATA; 403 mibname[4] = if2m->ifm_index; 404 mibname[5] = IFDATA_SUPPLEMENTAL; 405 if (sysctl(mibname, 6, &ifmsupp, &miblen, NULL, 0) == -1) 406 err(1, "sysctl IFDATA_SUPPLEMENTAL"); 407 408 fpackets = ifmsupp.ifmd_data_extended.ifi_fpackets; 409 fbytes = ifmsupp.ifmd_data_extended.ifi_fbytes; 410 411 if (prioflag >= 0) { 412 switch (prioflag) { 413 case SO_TC_BE: 414 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ibepackets; 415 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ibebytes; 416 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_obepackets; 417 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_obebytes; 418 break; 419 case SO_TC_BK: 420 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ibkpackets; 421 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ibkbytes; 422 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_obkpackets; 423 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_obkbytes; 424 break; 425 case SO_TC_VI: 426 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ivipackets; 427 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ivibytes; 428 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_ovipackets; 429 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_ovibytes; 430 break; 431 case SO_TC_VO: 432 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ivopackets; 433 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ivobytes; 434 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_ovopackets; 435 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_ovobytes; 436 break; 437 default: 438 ift_itcp = 0; 439 ift_itcb = 0; 440 ift_otcp = 0; 441 ift_otcb = 0; 442 ift_ipvp = 0; 443 ift_ipvb = 0; 444 ift_opvp = 0; 445 ift_opvb = 0; 446 break; 447 } 448 ift_ipvp = ifmsupp.ifmd_traffic_class.ifi_ipvpackets; 449 ift_ipvb = ifmsupp.ifmd_traffic_class.ifi_ipvbytes; 450 ift_opvp = ifmsupp.ifmd_traffic_class.ifi_opvpackets; 451 ift_opvb = ifmsupp.ifmd_traffic_class.ifi_opvbytes; 452 } 453 454 get_rti_info(if2m->ifm_addrs, 455 (struct sockaddr*)(if2m + 1), rti_info); 456 sa = rti_info[RTAX_IFP]; 457 } else if (ifm->ifm_type == RTM_NEWADDR) { 458 struct ifa_msghdr *ifam = (struct ifa_msghdr *)ifm; 459 460 if (interface != 0 && ifam->ifam_index != ifindex) 461 continue; 462 get_rti_info(ifam->ifam_addrs, 463 (struct sockaddr*)(ifam + 1), rti_info); 464 sa = rti_info[RTAX_IFA]; 465 } else { 466 continue; 467 } 468 printf("%-5.5s %-5u ", name, mtu); 469 470 if (sa == 0) { 471 printf("%-13.13s ", "none"); 472 printf("%-15.15s ", "none"); 473 } else { 474 switch (sa->sa_family) { 475 case AF_UNSPEC: 476 printf("%-13.13s ", "none"); 477 printf("%-15.15s ", "none"); 478 break; 479 480 case AF_INET: { 481 struct sockaddr_in *sin = 482 (struct sockaddr_in *)sa; 483 struct sockaddr_in mask; 484 485 mask.sin_addr.s_addr = 0; 486 memcpy(&mask, rti_info[RTAX_NETMASK], 487 ((struct sockaddr_in *) 488 rti_info[RTAX_NETMASK])->sin_len); 489 490 printf("%-13.13s ", 491 netname(sin->sin_addr.s_addr & 492 mask.sin_addr.s_addr, 493 ntohl(mask.sin_addr.s_addr))); 494 495 printf("%-15.15s ", 496 routename(sin->sin_addr.s_addr)); 497 498 network_layer = 1; 499 break; 500 } 501#ifdef INET6 502 case AF_INET6: { 503 struct sockaddr_in6 *sin6 = 504 (struct sockaddr_in6 *)sa; 505 struct sockaddr *mask = 506 (struct sockaddr *)rti_info[RTAX_NETMASK]; 507 508 printf("%-11.11s ", netname6(sin6, mask)); 509 printf("%-17.17s ", (char *)inet_ntop(AF_INET6, 510 &sin6->sin6_addr, ntop_buf, 511 sizeof(ntop_buf))); 512 513 network_layer = 1; 514 break; 515 } 516#endif /*INET6*/ 517 case AF_LINK: { 518 struct sockaddr_dl *sdl = 519 (struct sockaddr_dl *)sa; 520 char linknum[10]; 521 cp = (char *)LLADDR(sdl); 522 n = sdl->sdl_alen; 523 snprintf(linknum, sizeof(linknum), 524 "<Link#%d>", sdl->sdl_index); 525 m = printf("%-11.11s ", linknum); 526 goto hexprint; 527 } 528 529 default: 530 m = printf("(%d)", sa->sa_family); 531 for (cp = sa->sa_len + (char *)sa; 532 --cp > sa->sa_data && (*cp == 0);) {} 533 n = cp - sa->sa_data + 1; 534 cp = sa->sa_data; 535 hexprint: 536 while (--n >= 0) 537 m += printf("%02x%c", *cp++ & 0xff, 538 n > 0 ? ':' : ' '); 539 m = 30 - m; 540 while (m-- > 0) 541 putchar(' '); 542 543 link_layer = 1; 544 break; 545 } 546 } 547 548 show_stat("llu", 8, ipackets, link_layer|network_layer); 549 printf(" "); 550 show_stat("llu", 5, ierrors, link_layer); 551 printf(" "); 552 if (prioflag >= 0) { 553 show_stat("llu", 8, ift_itcp, link_layer|network_layer); 554 printf(" "); 555 show_stat("llu", 8, ift_ipvp, link_layer|network_layer); 556 printf(" "); 557 } 558 if (bflag) { 559 show_stat("llu", 10, ibytes, link_layer|network_layer); 560 printf(" "); 561 if (prioflag >= 0) { 562 show_stat("llu", 8, ift_itcb, link_layer|network_layer); 563 printf(" "); 564 show_stat("llu", 8, ift_ipvb, link_layer|network_layer); 565 printf(" "); 566 } 567 } 568 show_stat("llu", 8, opackets, link_layer|network_layer); 569 printf(" "); 570 show_stat("llu", 5, oerrors, link_layer); 571 printf(" "); 572 if (prioflag >= 0) { 573 show_stat("llu", 8, ift_otcp, link_layer|network_layer); 574 printf(" "); 575 show_stat("llu", 8, ift_opvp, link_layer|network_layer); 576 printf(" "); 577 } 578 if (bflag) { 579 show_stat("llu", 10, obytes, link_layer|network_layer); 580 printf(" "); 581 if (prioflag >= 0) { 582 show_stat("llu", 8, ift_otcb, link_layer|network_layer); 583 printf(" "); 584 show_stat("llu", 8, ift_opvb, link_layer|network_layer); 585 printf(" "); 586 } 587 } 588 show_stat("llu", 5, collisions, link_layer); 589 if (tflag) { 590 printf(" "); 591 show_stat("d", 3, timer, link_layer); 592 } 593 if (dflag) { 594 printf(" "); 595 show_stat("d", 3, drops, link_layer); 596 } 597 if (Fflag) { 598 printf(" "); 599 show_stat("llu", 8, fpackets, link_layer|network_layer); 600 if (bflag) { 601 printf(" "); 602 show_stat("llu", 10, fbytes, 603 link_layer|network_layer); 604 } 605 } 606 putchar('\n'); 607 608 if (aflag) 609 multipr(sa->sa_family, next, lim); 610 } 611 free(buf); 612} 613 614struct iftot { 615 SLIST_ENTRY(iftot) chain; 616 char ift_name[16]; /* interface name */ 617 u_int64_t ift_ip; /* input packets */ 618 u_int64_t ift_ie; /* input errors */ 619 u_int64_t ift_op; /* output packets */ 620 u_int64_t ift_oe; /* output errors */ 621 u_int64_t ift_co; /* collisions */ 622 u_int64_t ift_dr; /* drops */ 623 u_int64_t ift_ib; /* input bytes */ 624 u_int64_t ift_ob; /* output bytes */ 625 u_int64_t ift_itcp; /* input tc packets */ 626 u_int64_t ift_itcb; /* input tc bytes */ 627 u_int64_t ift_otcp; /* output tc packets */ 628 u_int64_t ift_otcb; /* output tc bytes */ 629 u_int64_t ift_ipvp; /* input priv tc packets */ 630 u_int64_t ift_ipvb; /* input priv tc bytes */ 631 u_int64_t ift_opvp; /* output priv tc packets */ 632 u_int64_t ift_opvb; /* output priv tc bytes */ 633 u_int64_t ift_fp; /* forwarded packets */ 634 u_int64_t ift_fb; /* forwarded bytes */ 635}; 636 637u_char signalled; /* set if alarm goes off "early" */ 638 639/* 640 * Print a running summary of interface statistics. 641 * Repeat display every interval seconds, showing statistics 642 * collected over that interval. Assumes that interval is non-zero. 643 * First line printed at top of screen is always cumulative. 644 * XXX - should be rewritten to use ifmib(4). 645 */ 646static void 647sidewaysintpr() 648{ 649 struct iftot *total, *sum, *interesting; 650 register int line; 651 int first; 652 int name[6]; 653 size_t len; 654 unsigned int ifcount, i; 655 struct ifmibdata *ifmdall = 0; 656 int interesting_row; 657 sigset_t sigset, oldsigset; 658 struct itimerval timer_interval; 659 660 /* Common OID prefix */ 661 name[0] = CTL_NET; 662 name[1] = PF_LINK; 663 name[2] = NETLINK_GENERIC; 664 665 len = sizeof(int); 666 name[3] = IFMIB_SYSTEM; 667 name[4] = IFMIB_IFCOUNT; 668 if (sysctl(name, 5, &ifcount, &len, 0, 0) == 1) 669 err(1, "sysctl IFMIB_IFCOUNT"); 670 671 len = ifcount * sizeof(struct ifmibdata); 672 ifmdall = malloc(len); 673 if (ifmdall == 0) 674 err(1, "malloc failed"); 675 name[3] = IFMIB_IFALLDATA; 676 name[4] = 0; 677 name[5] = IFDATA_GENERAL; 678 if (sysctl(name, 6, ifmdall, &len, (void *)0, 0) == -1) 679 err(1, "sysctl IFMIB_IFALLDATA"); 680 681 interesting = NULL; 682 interesting_row = 0; 683 for (i = 0; i < ifcount; i++) { 684 struct ifmibdata *ifmd = ifmdall + i; 685 686 if (interface && strcmp(ifmd->ifmd_name, interface) == 0) { 687 if ((interesting = calloc(ifcount, 688 sizeof(struct iftot))) == NULL) 689 err(1, "malloc failed"); 690 interesting_row = if_nametoindex(interface); 691 snprintf(interesting->ift_name, 16, "(%s)", 692 ifmd->ifmd_name);; 693 } 694 } 695 if ((total = calloc(1, sizeof(struct iftot))) == NULL) 696 err(1, "malloc failed"); 697 698 if ((sum = calloc(1, sizeof(struct iftot))) == NULL) 699 err(1, "malloc failed"); 700 701 /* create a timer that fires repeatedly every interval seconds */ 702 timer_interval.it_value.tv_sec = interval; 703 timer_interval.it_value.tv_usec = 0; 704 timer_interval.it_interval.tv_sec = interval; 705 timer_interval.it_interval.tv_usec = 0; 706 (void)signal(SIGALRM, catchalarm); 707 signalled = NO; 708 (void)setitimer(ITIMER_REAL, &timer_interval, NULL); 709 first = 1; 710banner: 711 if (vflag > 0) 712 printf("%9s", " "); 713 714 if (prioflag >= 0) 715 printf("%39s %39s %36s", "input", 716 interesting ? interesting->ift_name : "(Total)", "output"); 717 else 718 printf("%17s %14s %16s", "input", 719 interesting ? interesting->ift_name : "(Total)", "output"); 720 putchar('\n'); 721 722 if (vflag > 0) 723 printf("%9s", " "); 724 725 printf("%10s %5s %10s ", "packets", "errs", "bytes"); 726 if (prioflag >= 0) 727 printf(" %10s %10s %10s %10s", 728 "tcpkts", "tcbytes", "pvpkts", "pvbytes"); 729 printf("%10s %5s %10s %5s", "packets", "errs", "bytes", "colls"); 730 if (dflag) 731 printf(" %5.5s", "drops"); 732 if (prioflag >= 0) 733 printf(" %10s %10s %10s %10s", 734 "tcpkts", "tcbytes", "pvpkts", "pvbytes"); 735 if (Fflag) 736 printf(" %10s %10s", "fpackets", "fbytes"); 737 putchar('\n'); 738 fflush(stdout); 739 line = 0; 740loop: 741 if (vflag && !first) 742 print_time(); 743 744 if (interesting != NULL) { 745 struct ifmibdata ifmd; 746 struct ifmibdata_supplemental ifmsupp; 747 748 len = sizeof(struct ifmibdata); 749 name[3] = IFMIB_IFDATA; 750 name[4] = interesting_row; 751 name[5] = IFDATA_GENERAL; 752 if (sysctl(name, 6, &ifmd, &len, (void *)0, 0) == -1) 753 err(1, "sysctl IFDATA_GENERAL %d", interesting_row); 754 755 len = sizeof(struct ifmibdata_supplemental); 756 name[3] = IFMIB_IFDATA; 757 name[4] = interesting_row; 758 name[5] = IFDATA_SUPPLEMENTAL; 759 if (sysctl(name, 6, &ifmsupp, &len, (void *)0, 0) == -1) 760 err(1, "sysctl IFDATA_SUPPLEMENTAL %d", 761 interesting_row); 762 763 if (!first) { 764 printf("%10llu %5llu %10llu ", 765 ifmd.ifmd_data.ifi_ipackets - interesting->ift_ip, 766 ifmd.ifmd_data.ifi_ierrors - interesting->ift_ie, 767 ifmd.ifmd_data.ifi_ibytes - interesting->ift_ib); 768 switch (prioflag) { 769 case SO_TC_BE: 770 printf("%10llu %10llu ", 771 ifmsupp.ifmd_traffic_class.ifi_ibepackets - 772 interesting->ift_itcp, 773 ifmsupp.ifmd_traffic_class.ifi_ibebytes - 774 interesting->ift_itcb); 775 break; 776 case SO_TC_BK: 777 printf("%10llu %10llu ", 778 ifmsupp.ifmd_traffic_class.ifi_ibkpackets - 779 interesting->ift_itcp, 780 ifmsupp.ifmd_traffic_class.ifi_ibkbytes - 781 interesting->ift_itcb); 782 break; 783 case SO_TC_VI: 784 printf("%10llu %10llu ", 785 ifmsupp.ifmd_traffic_class.ifi_ivipackets - 786 interesting->ift_itcp, 787 ifmsupp.ifmd_traffic_class.ifi_ivibytes - 788 interesting->ift_itcb); 789 break; 790 case SO_TC_VO: 791 printf("%10llu %10llu ", 792 ifmsupp.ifmd_traffic_class.ifi_ivopackets - 793 interesting->ift_itcp, 794 ifmsupp.ifmd_traffic_class.ifi_ivobytes - 795 interesting->ift_itcb); 796 break; 797 default: 798 break; 799 } 800 if (prioflag >= 0) { 801 printf("%10llu %10llu ", 802 ifmsupp.ifmd_traffic_class.ifi_ipvpackets - 803 interesting->ift_ipvp, 804 ifmsupp.ifmd_traffic_class.ifi_ipvbytes - 805 interesting->ift_ipvb); 806 } 807 printf("%10llu %5llu %10llu %5llu", 808 ifmd.ifmd_data.ifi_opackets - interesting->ift_op, 809 ifmd.ifmd_data.ifi_oerrors - interesting->ift_oe, 810 ifmd.ifmd_data.ifi_obytes - interesting->ift_ob, 811 ifmd.ifmd_data.ifi_collisions - interesting->ift_co); 812 if (dflag) 813 printf(" %5llu", 814 ifmd.ifmd_snd_drops - interesting->ift_dr); 815 switch (prioflag) { 816 case SO_TC_BE: 817 printf(" %10llu %10llu", 818 ifmsupp.ifmd_traffic_class.ifi_obepackets - 819 interesting->ift_otcp, 820 ifmsupp.ifmd_traffic_class.ifi_obebytes - 821 interesting->ift_otcb); 822 break; 823 case SO_TC_BK: 824 printf(" %10llu %10llu", 825 ifmsupp.ifmd_traffic_class.ifi_obkpackets - 826 interesting->ift_otcp, 827 ifmsupp.ifmd_traffic_class.ifi_obkbytes - 828 interesting->ift_otcb); 829 break; 830 case SO_TC_VI: 831 printf(" %10llu %10llu", 832 ifmsupp.ifmd_traffic_class.ifi_ovipackets - 833 interesting->ift_otcp, 834 ifmsupp.ifmd_traffic_class.ifi_ovibytes - 835 interesting->ift_otcb); 836 break; 837 case SO_TC_VO: 838 printf(" %10llu %10llu", 839 ifmsupp.ifmd_traffic_class.ifi_ovopackets - 840 interesting->ift_otcp, 841 ifmsupp.ifmd_traffic_class.ifi_ovobytes - 842 interesting->ift_otcb); 843 break; 844 default: 845 break; 846 } 847 if (prioflag >= 0) { 848 printf("%10llu %10llu ", 849 ifmsupp.ifmd_traffic_class.ifi_opvpackets - 850 interesting->ift_opvp, 851 ifmsupp.ifmd_traffic_class.ifi_opvbytes - 852 interesting->ift_opvb); 853 } 854 if (Fflag) { 855 printf("%10llu %10llu", 856 ifmsupp.ifmd_data_extended.ifi_fpackets - 857 interesting->ift_fp, 858 ifmsupp.ifmd_data_extended.ifi_fbytes - 859 interesting->ift_fb); 860 } 861 } 862 interesting->ift_ip = ifmd.ifmd_data.ifi_ipackets; 863 interesting->ift_ie = ifmd.ifmd_data.ifi_ierrors; 864 interesting->ift_ib = ifmd.ifmd_data.ifi_ibytes; 865 interesting->ift_op = ifmd.ifmd_data.ifi_opackets; 866 interesting->ift_oe = ifmd.ifmd_data.ifi_oerrors; 867 interesting->ift_ob = ifmd.ifmd_data.ifi_obytes; 868 interesting->ift_co = ifmd.ifmd_data.ifi_collisions; 869 interesting->ift_dr = ifmd.ifmd_snd_drops; 870 871 /* private counters */ 872 switch (prioflag) { 873 case SO_TC_BE: 874 interesting->ift_itcp = 875 ifmsupp.ifmd_traffic_class.ifi_ibepackets; 876 interesting->ift_itcb = 877 ifmsupp.ifmd_traffic_class.ifi_ibebytes; 878 interesting->ift_otcp = 879 ifmsupp.ifmd_traffic_class.ifi_obepackets; 880 interesting->ift_otcb = 881 ifmsupp.ifmd_traffic_class.ifi_obebytes; 882 break; 883 case SO_TC_BK: 884 interesting->ift_itcp = 885 ifmsupp.ifmd_traffic_class.ifi_ibkpackets; 886 interesting->ift_itcb = 887 ifmsupp.ifmd_traffic_class.ifi_ibkbytes; 888 interesting->ift_otcp = 889 ifmsupp.ifmd_traffic_class.ifi_obkpackets; 890 interesting->ift_otcb = 891 ifmsupp.ifmd_traffic_class.ifi_obkbytes; 892 break; 893 case SO_TC_VI: 894 interesting->ift_itcp = 895 ifmsupp.ifmd_traffic_class.ifi_ivipackets; 896 interesting->ift_itcb = 897 ifmsupp.ifmd_traffic_class.ifi_ivibytes; 898 interesting->ift_otcp = 899 ifmsupp.ifmd_traffic_class.ifi_ovipackets; 900 interesting->ift_otcb = 901 ifmsupp.ifmd_traffic_class.ifi_ovibytes; 902 break; 903 case SO_TC_VO: 904 interesting->ift_itcp = 905 ifmsupp.ifmd_traffic_class.ifi_ivopackets; 906 interesting->ift_itcb = 907 ifmsupp.ifmd_traffic_class.ifi_ivobytes; 908 interesting->ift_otcp = 909 ifmsupp.ifmd_traffic_class.ifi_ovopackets; 910 interesting->ift_otcb = 911 ifmsupp.ifmd_traffic_class.ifi_ovobytes; 912 break; 913 default: 914 break; 915 } 916 if (prioflag >= 0) { 917 interesting->ift_ipvp = 918 ifmsupp.ifmd_traffic_class.ifi_ipvpackets; 919 interesting->ift_ipvb = 920 ifmsupp.ifmd_traffic_class.ifi_ipvbytes; 921 interesting->ift_opvp = 922 ifmsupp.ifmd_traffic_class.ifi_opvpackets; 923 interesting->ift_opvb = 924 ifmsupp.ifmd_traffic_class.ifi_opvbytes; 925 } 926 interesting->ift_fp = ifmsupp.ifmd_data_extended.ifi_fpackets; 927 interesting->ift_fb = ifmsupp.ifmd_data_extended.ifi_fbytes; 928 } else { 929 unsigned int latest_ifcount; 930 struct ifmibdata_supplemental *ifmsuppall = NULL; 931 932 len = sizeof(int); 933 name[3] = IFMIB_SYSTEM; 934 name[4] = IFMIB_IFCOUNT; 935 if (sysctl(name, 5, &latest_ifcount, &len, 0, 0) == 1) 936 err(1, "sysctl IFMIB_IFCOUNT"); 937 if (latest_ifcount > ifcount) { 938 ifcount = latest_ifcount; 939 len = ifcount * sizeof(struct ifmibdata); 940 free(ifmdall); 941 ifmdall = malloc(len); 942 if (ifmdall == 0) 943 err(1, "malloc ifmdall failed"); 944 } else if (latest_ifcount > ifcount) { 945 ifcount = latest_ifcount; 946 len = ifcount * sizeof(struct ifmibdata); 947 } 948 len = ifcount * sizeof(struct ifmibdata); 949 name[3] = IFMIB_IFALLDATA; 950 name[4] = 0; 951 name[5] = IFDATA_GENERAL; 952 if (sysctl(name, 6, ifmdall, &len, (void *)0, 0) == -1) 953 err(1, "sysctl IFMIB_IFALLDATA"); 954 955 len = ifcount * sizeof(struct ifmibdata_supplemental); 956 ifmsuppall = malloc(len); 957 if (ifmsuppall == NULL) 958 err(1, "malloc ifmsuppall failed"); 959 name[3] = IFMIB_IFALLDATA; 960 name[4] = 0; 961 name[5] = IFDATA_SUPPLEMENTAL; 962 if (sysctl(name, 6, ifmsuppall, &len, (void *)0, 0) == -1) 963 err(1, "sysctl IFMIB_IFALLDATA SUPPLEMENTAL"); 964 965 sum->ift_ip = 0; 966 sum->ift_ie = 0; 967 sum->ift_ib = 0; 968 sum->ift_op = 0; 969 sum->ift_oe = 0; 970 sum->ift_ob = 0; 971 sum->ift_co = 0; 972 sum->ift_dr = 0; 973 sum->ift_itcp = 0; 974 sum->ift_itcb = 0; 975 sum->ift_otcp = 0; 976 sum->ift_otcb = 0; 977 sum->ift_ipvp = 0; 978 sum->ift_ipvb = 0; 979 sum->ift_opvp = 0; 980 sum->ift_opvb = 0; 981 sum->ift_fp = 0; 982 sum->ift_fb = 0; 983 for (i = 0; i < ifcount; i++) { 984 struct ifmibdata *ifmd = ifmdall + i; 985 struct ifmibdata_supplemental *ifmsupp = ifmsuppall + i; 986 987 sum->ift_ip += ifmd->ifmd_data.ifi_ipackets; 988 sum->ift_ie += ifmd->ifmd_data.ifi_ierrors; 989 sum->ift_ib += ifmd->ifmd_data.ifi_ibytes; 990 sum->ift_op += ifmd->ifmd_data.ifi_opackets; 991 sum->ift_oe += ifmd->ifmd_data.ifi_oerrors; 992 sum->ift_ob += ifmd->ifmd_data.ifi_obytes; 993 sum->ift_co += ifmd->ifmd_data.ifi_collisions; 994 sum->ift_dr += ifmd->ifmd_snd_drops; 995 /* private counters */ 996 if (prioflag >= 0) { 997 switch (prioflag) { 998 case SO_TC_BE: 999 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ibepackets; 1000 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ibebytes; 1001 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_obepackets; 1002 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_obebytes; 1003 break; 1004 case SO_TC_BK: 1005 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ibkpackets; 1006 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ibkbytes; 1007 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_obkpackets; 1008 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_obkbytes; 1009 break; 1010 case SO_TC_VI: 1011 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ivipackets; 1012 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ivibytes; 1013 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_ovipackets; 1014 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_ovibytes; 1015 break; 1016 case SO_TC_VO: 1017 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ivopackets; 1018 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ivobytes; 1019 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_ovopackets; 1020 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_ovobytes; 1021 break; 1022 default: 1023 break; 1024 } 1025 sum->ift_ipvp += ifmsupp->ifmd_traffic_class.ifi_ipvpackets; 1026 sum->ift_ipvb += ifmsupp->ifmd_traffic_class.ifi_ipvbytes; 1027 sum->ift_opvp += ifmsupp->ifmd_traffic_class.ifi_opvpackets; 1028 sum->ift_opvb += ifmsupp->ifmd_traffic_class.ifi_opvbytes; 1029 } 1030 sum->ift_fp += ifmsupp->ifmd_data_extended.ifi_fpackets; 1031 sum->ift_fb += ifmsupp->ifmd_data_extended.ifi_fbytes; 1032 } 1033 if (!first) { 1034 printf("%10llu %5llu %10llu ", 1035 sum->ift_ip - total->ift_ip, 1036 sum->ift_ie - total->ift_ie, 1037 sum->ift_ib - total->ift_ib); 1038 if (prioflag >= 0) 1039 printf(" %10llu %10llu %10llu %10llu", 1040 sum->ift_itcp - total->ift_itcp, 1041 sum->ift_itcb - total->ift_itcb, 1042 sum->ift_ipvp - total->ift_ipvp, 1043 sum->ift_ipvb - total->ift_ipvb); 1044 printf("%10llu %5llu %10llu %5llu", 1045 sum->ift_op - total->ift_op, 1046 sum->ift_oe - total->ift_oe, 1047 sum->ift_ob - total->ift_ob, 1048 sum->ift_co - total->ift_co); 1049 if (dflag) 1050 printf(" %5llu", sum->ift_dr - total->ift_dr); 1051 if (prioflag >= 0) 1052 printf(" %10llu %10llu %10llu %10llu", 1053 sum->ift_otcp - total->ift_otcp, 1054 sum->ift_otcb - total->ift_otcb, 1055 sum->ift_opvp - total->ift_opvp, 1056 sum->ift_opvb - total->ift_opvb); 1057 if (Fflag) 1058 printf(" %10llu %10llu", 1059 sum->ift_fp - total->ift_fp, 1060 sum->ift_fb - total->ift_fb); 1061 } 1062 *total = *sum; 1063 } 1064 if (!first) 1065 putchar('\n'); 1066 fflush(stdout); 1067 sigemptyset(&sigset); 1068 sigaddset(&sigset, SIGALRM); 1069 (void)sigprocmask(SIG_BLOCK, &sigset, &oldsigset); 1070 if (!signalled) { 1071 sigemptyset(&sigset); 1072 sigsuspend(&sigset); 1073 } 1074 (void)sigprocmask(SIG_SETMASK, &oldsigset, NULL); 1075 1076 signalled = NO; 1077 line++; 1078 first = 0; 1079 if (line == 21) 1080 goto banner; 1081 else 1082 goto loop; 1083 /*NOTREACHED*/ 1084} 1085 1086void 1087intervalpr(void (*pr)(uint32_t, char *, int), uint32_t off, char *name , int af) 1088{ 1089 struct itimerval timer_interval; 1090 sigset_t sigset, oldsigset; 1091 1092 /* create a timer that fires repeatedly every interval seconds */ 1093 timer_interval.it_value.tv_sec = interval; 1094 timer_interval.it_value.tv_usec = 0; 1095 timer_interval.it_interval.tv_sec = interval; 1096 timer_interval.it_interval.tv_usec = 0; 1097 (void) signal(SIGALRM, catchalarm); 1098 signalled = NO; 1099 (void) setitimer(ITIMER_REAL, &timer_interval, NULL); 1100 1101 for (;;) { 1102 pr(off, name, af); 1103 1104 fflush(stdout); 1105 sigemptyset(&sigset); 1106 sigaddset(&sigset, SIGALRM); 1107 (void) sigprocmask(SIG_BLOCK, &sigset, &oldsigset); 1108 if (!signalled) { 1109 sigemptyset(&sigset); 1110 sigsuspend(&sigset); 1111 } 1112 (void) sigprocmask(SIG_SETMASK, &oldsigset, NULL); 1113 signalled = NO; 1114 } 1115} 1116 1117/* 1118 * Called if an interval expires before sidewaysintpr has completed a loop. 1119 * Sets a flag to not wait for the alarm. 1120 */ 1121static void 1122catchalarm(int signo ) 1123{ 1124 signalled = YES; 1125} 1126 1127static char * 1128sec2str(total) 1129 time_t total; 1130{ 1131 static char result[256]; 1132 int days, hours, mins, secs; 1133 int first = 1; 1134 char *p = result; 1135 1136 days = total / 3600 / 24; 1137 hours = (total / 3600) % 24; 1138 mins = (total / 60) % 60; 1139 secs = total % 60; 1140 1141 if (days) { 1142 first = 0; 1143 p += snprintf(p, sizeof(result) - (p - result), "%dd", days); 1144 } 1145 if (!first || hours) { 1146 first = 0; 1147 p += snprintf(p, sizeof(result) - (p - result), "%dh", hours); 1148 } 1149 if (!first || mins) { 1150 first = 0; 1151 p += snprintf(p, sizeof(result) - (p - result), "%dm", mins); 1152 } 1153 snprintf(p, sizeof(result) - (p - result), "%ds", secs); 1154 1155 return(result); 1156} 1157 1158void 1159intpr_ri(void (*pfunc)(char *)) 1160{ 1161 int mib[6]; 1162 char *buf = NULL, *lim, *next; 1163 size_t len; 1164 unsigned int ifindex = 0; 1165 struct if_msghdr2 *if2m; 1166 1167 if (interface != 0) { 1168 ifindex = if_nametoindex(interface); 1169 if (ifindex == 0) { 1170 printf("interface name is not valid: %s\n", interface); 1171 exit(1); 1172 } 1173 } 1174 1175 mib[0] = CTL_NET; /* networking subsystem */ 1176 mib[1] = PF_ROUTE; /* type of information */ 1177 mib[2] = 0; /* protocol (IPPROTO_xxx) */ 1178 mib[3] = 0; /* address family */ 1179 mib[4] = NET_RT_IFLIST2; /* operation */ 1180 mib[5] = 0; 1181 if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) 1182 return; 1183 if ((buf = malloc(len)) == NULL) { 1184 printf("malloc failed\n"); 1185 exit(1); 1186 } 1187 if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { 1188 free(buf); 1189 return; 1190 } 1191 1192 printf("%-6s %-17s %8.8s %-9.9s %4s %4s", 1193 "Proto", "Linklayer Address", "Netif", "Expire", "Refs", 1194 "Prbs"); 1195 if (xflag) 1196 printf(" %7s %7s %7s", "RSSI", "LQM", "NPM"); 1197 printf("\n"); 1198 1199 lim = buf + len; 1200 if2m = (struct if_msghdr2 *)buf; 1201 1202 for (next = buf; next < lim; ) { 1203 if2m = (struct if_msghdr2 *)next; 1204 next += if2m->ifm_msglen; 1205 1206 if (if2m->ifm_type != RTM_IFINFO2) 1207 continue; 1208 else if (interface != 0 && if2m->ifm_index != ifindex) 1209 continue; 1210 1211 llreach_sysctl(if2m->ifm_index); 1212 } 1213 free(buf); 1214} 1215 1216static void 1217llreach_sysctl(uint32_t ifindex) 1218{ 1219#define MAX_SYSCTL_TRY 5 1220 int mib[6], i, ntry = 0; 1221 size_t mibsize, len, needed, cnt; 1222 struct if_llreach_info *lri; 1223 struct timeval time; 1224 char *buf; 1225 char ifname[IF_NAMESIZE]; 1226 1227 bzero(&mib, sizeof (mib)); 1228 mibsize = sizeof (mib) / sizeof (mib[0]); 1229 if (sysctlnametomib("net.link.generic.system.llreach_info", mib, 1230 &mibsize) == -1) { 1231 perror("sysctlnametomib"); 1232 return; 1233 } 1234 1235 needed = 0; 1236 mib[5] = ifindex; 1237 1238 mibsize = sizeof (mib) / sizeof (mib[0]); 1239 do { 1240 if (sysctl(mib, mibsize, NULL, &needed, NULL, 0) == -1) { 1241 perror("sysctl net.link.generic.system.llreach_info"); 1242 return; 1243 } 1244 if ((buf = malloc(needed)) == NULL) { 1245 perror("malloc"); 1246 return; 1247 } 1248 if (sysctl(mib, mibsize, buf, &needed, NULL, 0) == -1) { 1249 if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) { 1250 perror("sysctl"); 1251 goto out_free; 1252 } 1253 free(buf); 1254 buf = NULL; 1255 } 1256 } while (buf == NULL); 1257 1258 len = needed; 1259 cnt = len / sizeof (*lri); 1260 lri = (struct if_llreach_info *)buf; 1261 1262 gettimeofday(&time, 0); 1263 if (if_indextoname(ifindex, ifname) == NULL) 1264 snprintf(ifname, sizeof (ifname), "%s", "?"); 1265 1266 for (i = 0; i < cnt; i++, lri++) { 1267 printf("0x%-4x %-17s %8.8s ", lri->lri_proto, 1268 ether_ntoa((struct ether_addr *)lri->lri_addr), ifname); 1269 1270 if (lri->lri_expire > time.tv_sec) 1271 printf("%-9.9s", sec2str(lri->lri_expire - time.tv_sec)); 1272 else if (lri->lri_expire == 0) 1273 printf("%-9.9s", "permanent"); 1274 else 1275 printf("%-9.9s", "expired"); 1276 1277 printf(" %4d", lri->lri_refcnt); 1278 if (lri->lri_probes) 1279 printf(" %4d", lri->lri_probes); 1280 1281 if (xflag) { 1282 if (!lri->lri_probes) 1283 printf(" %-4.4s", "none"); 1284 1285 if (lri->lri_rssi != IFNET_RSSI_UNKNOWN) 1286 printf(" %7d", lri->lri_rssi); 1287 else 1288 printf(" %-7.7s", "unknown"); 1289 1290 switch (lri->lri_lqm) 1291 { 1292 case IFNET_LQM_THRESH_OFF: 1293 printf(" %-7.7s", "off"); 1294 break; 1295 case IFNET_LQM_THRESH_UNKNOWN: 1296 printf(" %-7.7s", "unknown"); 1297 break; 1298 case IFNET_LQM_THRESH_POOR: 1299 printf(" %-7.7s", "poor"); 1300 break; 1301 case IFNET_LQM_THRESH_GOOD: 1302 printf(" %-7.7s", "good"); 1303 break; 1304 default: 1305 printf(" %7d", lri->lri_lqm); 1306 break; 1307 } 1308 1309 switch (lri->lri_npm) 1310 { 1311 case IFNET_NPM_THRESH_UNKNOWN: 1312 printf(" %-7.7s", "unknown"); 1313 break; 1314 case IFNET_NPM_THRESH_NEAR: 1315 printf(" %-7.7s", "near"); 1316 break; 1317 case IFNET_NPM_THRESH_GENERAL: 1318 printf(" %-7.7s", "general"); 1319 break; 1320 case IFNET_NPM_THRESH_FAR: 1321 printf(" %-7.7s", "far"); 1322 break; 1323 default: 1324 printf(" %7d", lri->lri_npm); 1325 break; 1326 } 1327 } 1328 1329 printf("\n"); 1330 len -= sizeof (*lri); 1331 } 1332 1333 if (len > 0) { 1334 fprintf(stderr, "warning: %u trailing bytes from %s\n", 1335 (unsigned int)len, "net.link.generic.system.llreach_info"); 1336 } 1337 1338out_free: 1339 free(buf); 1340#undef MAX_SYSCTL_TRY 1341} 1342 1343void 1344aqstatpr(void) 1345{ 1346 unsigned int ifindex; 1347 struct itimerval timer_interval; 1348 struct if_qstatsreq ifqr; 1349 struct if_ifclassq_stats *ifcqs; 1350 sigset_t sigset, oldsigset; 1351 u_int32_t scheduler; 1352 int s, n, tcq = 0; 1353 1354 if (cq < -1 || cq >= IFCQ_SC_MAX) { 1355 fprintf(stderr, "Invalid classq index (range is 0-%d)\n", 1356 IFCQ_SC_MAX-1); 1357 return; 1358 } 1359 ifindex = if_nametoindex(interface); 1360 if (ifindex == 0) { 1361 fprintf(stderr, "Invalid interface name\n"); 1362 return; 1363 } 1364 1365 ifcqs = malloc(sizeof (*ifcqs)); 1366 if (ifcqs == NULL) { 1367 fprintf(stderr, "Unable to allocate memory\n"); 1368 return; 1369 } 1370 1371 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 1372 perror("Warning: socket(AF_INET)"); 1373 free(ifcqs); 1374 return; 1375 } 1376 1377 bzero(&ifqr, sizeof (ifqr)); 1378 strlcpy(ifqr.ifqr_name, interface, sizeof (ifqr.ifqr_name)); 1379 ifqr.ifqr_buf = ifcqs; 1380 ifqr.ifqr_len = sizeof (*ifcqs); 1381 1382loop: 1383 if (interval > 0) { 1384 /* create a timer that fires repeatedly every interval seconds */ 1385 timer_interval.it_value.tv_sec = interval; 1386 timer_interval.it_value.tv_usec = 0; 1387 timer_interval.it_interval.tv_sec = interval; 1388 timer_interval.it_interval.tv_usec = 0; 1389 (void) signal(SIGALRM, catchalarm); 1390 signalled = NO; 1391 (void) setitimer(ITIMER_REAL, &timer_interval, NULL); 1392 } 1393 1394 ifqr.ifqr_slot = 0; 1395 if (ioctl(s, SIOCGIFQUEUESTATS, (char *)&ifqr) < 0) { 1396 if (errno == ENXIO) { 1397 printf("Queue statistics are not available on %s\n", 1398 interface); 1399 } else { 1400 perror("Warning: ioctl(SIOCGIFQUEUESTATS)"); 1401 } 1402 goto done; 1403 } 1404 scheduler = ifcqs->ifqs_scheduler; 1405 tcq = (scheduler == PKTSCHEDT_TCQ); 1406 1407 printf("%s:\n" 1408 "%s [ sched: %9s %sqlength: %3d/%3d ]\n", 1409 interface, tcq ? " " : "", sched2str(ifcqs->ifqs_scheduler), 1410 tcq ? "" : " ", ifcqs->ifqs_len, ifcqs->ifqs_maxlen); 1411 printf("%s [ pkts: %10llu %sbytes: %10llu " 1412 "%sdropped pkts: %6llu bytes: %6llu ]\n", 1413 (scheduler != PKTSCHEDT_TCQ) ? "" : " ", 1414 ifcqs->ifqs_xmitcnt.packets, tcq ? "" : " ", 1415 ifcqs->ifqs_xmitcnt.bytes, tcq ? "" : " ", 1416 ifcqs->ifqs_dropcnt.packets, ifcqs->ifqs_dropcnt.bytes); 1417 1418 for (n = 0; n < IFCQ_SC_MAX; n++) { 1419 qstats[n].printed = 0; 1420 if (!tcq) 1421 continue; 1422 ifqr.ifqr_slot = n; 1423 if (ioctl(s, SIOCGIFQUEUESTATS, (char *)&ifqr) < 0) { 1424 perror("Warning: ioctl(SIOCGIFQUEUESTATS)"); 1425 goto done; 1426 } 1427 qstats[n].handle = ifcqs->ifqs_tcq_stats.class_handle; 1428 } 1429 1430 for (n = 0; n < IFCQ_SC_MAX && scheduler != PKTSCHEDT_NONE; n++) { 1431 if (cq >= 0 && cq != n) 1432 continue; 1433 1434 ifqr.ifqr_slot = n; 1435 if (ioctl(s, SIOCGIFQUEUESTATS, (char *)&ifqr) < 0) { 1436 perror("Warning: ioctl(SIOCGIFQUEUESTATS)"); 1437 goto done; 1438 } 1439 1440 update_avg(ifcqs, &qstats[n]); 1441 1442 switch (scheduler) { 1443 case PKTSCHEDT_CBQ: 1444 print_cbqstats(n, &ifcqs->ifqs_cbq_stats, 1445 &qstats[n]); 1446 break; 1447 case PKTSCHEDT_HFSC: 1448 print_hfscstats(n, &ifcqs->ifqs_hfsc_stats, 1449 &qstats[n]); 1450 break; 1451 case PKTSCHEDT_PRIQ: 1452 print_priqstats(n, &ifcqs->ifqs_priq_stats, 1453 &qstats[n]); 1454 break; 1455 case PKTSCHEDT_FAIRQ: 1456 print_fairqstats(n, &ifcqs->ifqs_fairq_stats, 1457 &qstats[n]); 1458 break; 1459 case PKTSCHEDT_TCQ: 1460 print_tcqstats(n, &ifcqs->ifqs_tcq_stats, 1461 &qstats[n]); 1462 break; 1463 case PKTSCHEDT_QFQ: 1464 print_qfqstats(n, &ifcqs->ifqs_qfq_stats, 1465 &qstats[n]); 1466 break; 1467 case PKTSCHEDT_NONE: 1468 default: 1469 break; 1470 } 1471 } 1472 1473 fflush(stdout); 1474 1475 if (interval > 0) { 1476 sigemptyset(&sigset); 1477 sigaddset(&sigset, SIGALRM); 1478 (void) sigprocmask(SIG_BLOCK, &sigset, &oldsigset); 1479 if (!signalled) { 1480 sigemptyset(&sigset); 1481 sigsuspend(&sigset); 1482 } 1483 (void) sigprocmask(SIG_SETMASK, &oldsigset, NULL); 1484 1485 signalled = NO; 1486 goto loop; 1487 } 1488 1489done: 1490 free(ifcqs); 1491 close(s); 1492} 1493 1494static void 1495print_cbqstats(int slot, struct cbq_classstats *cs, struct queue_stats *qs) 1496{ 1497 printf(" %2d: [ pkts: %10llu bytes: %10llu " 1498 "dropped pkts: %6llu bytes: %6llu ]\n", slot, 1499 (unsigned long long)cs->xmit_cnt.packets, 1500 (unsigned long long)cs->xmit_cnt.bytes, 1501 (unsigned long long)cs->drop_cnt.packets, 1502 (unsigned long long)cs->drop_cnt.bytes); 1503 printf(" [ qlength: %3d/%3d borrows: %6u " 1504 "suspends: %6u qalg: %s ]\n", cs->qcnt, cs->qmax, 1505 cs->borrows, cs->delays, qtype2str(cs->qtype)); 1506 printf(" [ service class: %5s ]\n", qid2str(cs->handle)); 1507 1508 if (qs->avgn >= 2) { 1509 printf(" [ measured: %7.1f packets/s, %s/s ]\n", 1510 qs->avg_packets / interval, 1511 rate2str((8 * qs->avg_bytes) / interval)); 1512 } 1513 1514 if (qflag < 2) 1515 return; 1516 1517 switch (cs->qtype) { 1518 case Q_SFB: 1519 print_sfbstats(&cs->sfb); 1520 break; 1521 default: 1522 break; 1523 } 1524} 1525 1526static void 1527print_priqstats(int slot, struct priq_classstats *cs, struct queue_stats *qs) 1528{ 1529 printf(" %2d: [ pkts: %10llu bytes: %10llu " 1530 "dropped pkts: %6llu bytes: %6llu ]\n", slot, 1531 (unsigned long long)cs->xmitcnt.packets, 1532 (unsigned long long)cs->xmitcnt.bytes, 1533 (unsigned long long)cs->dropcnt.packets, 1534 (unsigned long long)cs->dropcnt.bytes); 1535 printf(" [ qlength: %3d/%3d qalg: %11s service class: %5s ]\n", 1536 cs->qlength, cs->qlimit, qtype2str(cs->qtype), 1537 qid2str(cs->class_handle)); 1538 1539 if (qs->avgn >= 2) { 1540 printf(" [ measured: %7.1f packets/s, %s/s ]\n", 1541 qs->avg_packets / interval, 1542 rate2str((8 * qs->avg_bytes) / interval)); 1543 } 1544 1545 if (qflag < 2) 1546 return; 1547 1548 switch (cs->qtype) { 1549 case Q_SFB: 1550 print_sfbstats(&cs->sfb); 1551 break; 1552 default: 1553 break; 1554 } 1555} 1556 1557static void 1558print_hfscstats(int slot, struct hfsc_classstats *cs, struct queue_stats *qs) 1559{ 1560 printf(" %2d: [ pkts: %10llu bytes: %10llu " 1561 "dropped pkts: %6llu bytes: %6llu ]\n", slot, 1562 (unsigned long long)cs->xmit_cnt.packets, 1563 (unsigned long long)cs->xmit_cnt.bytes, 1564 (unsigned long long)cs->drop_cnt.packets, 1565 (unsigned long long)cs->drop_cnt.bytes); 1566 printf(" [ qlength: %3d/%3d qalg: %11s service class: %5s ]\n", 1567 cs->qlength, cs->qlimit, qtype2str(cs->qtype), 1568 qid2str(cs->class_handle)); 1569 1570 if (qs->avgn >= 2) { 1571 printf(" [ measured: %7.1f packets/s, %s/s ]\n", 1572 qs->avg_packets / interval, 1573 rate2str((8 * qs->avg_bytes) / interval)); 1574 } 1575 1576 if (qflag < 2) 1577 return; 1578 1579 switch (cs->qtype) { 1580 case Q_SFB: 1581 print_sfbstats(&cs->sfb); 1582 break; 1583 default: 1584 break; 1585 } 1586} 1587 1588static void 1589print_fairqstats(int slot, struct fairq_classstats *cs, struct queue_stats *qs) 1590{ 1591 printf(" %2d: [ pkts: %10llu bytes: %10llu " 1592 "dropped pkts: %6llu bytes: %6llu ]\n", slot, 1593 (unsigned long long)cs->xmit_cnt.packets, 1594 (unsigned long long)cs->xmit_cnt.bytes, 1595 (unsigned long long)cs->drop_cnt.packets, 1596 (unsigned long long)cs->drop_cnt.bytes); 1597 printf(" [ qlength: %3d/%3d qalg: %11s service class: %5s ]]\n", 1598 cs->qlength, cs->qlimit, qtype2str(cs->qtype), 1599 qid2str(cs->class_handle)); 1600 1601 if (qs->avgn >= 2) { 1602 printf(" [ measured: %7.1f packets/s, %s/s ]\n", 1603 qs->avg_packets / interval, 1604 rate2str((8 * qs->avg_bytes) / interval)); 1605 } 1606 1607 if (qflag < 2) 1608 return; 1609 1610 switch (cs->qtype) { 1611 case Q_SFB: 1612 print_sfbstats(&cs->sfb); 1613 break; 1614 default: 1615 break; 1616 } 1617} 1618 1619static void 1620print_tcqstats(int slot, struct tcq_classstats *cs, struct queue_stats *qs) 1621{ 1622 int n; 1623 1624 if (qs->printed) 1625 return; 1626 1627 qs->handle = cs->class_handle; 1628 qs->printed++; 1629 1630 for (n = 0; n < IFCQ_SC_MAX; n++) { 1631 if (&qstats[n] != qs && qstats[n].handle == qs->handle) 1632 qstats[n].printed++; 1633 } 1634 1635 printf("%5s: [ pkts: %10llu bytes: %10llu " 1636 "dropped pkts: %6llu bytes: %6llu ]\n", tcqslot2str(slot), 1637 (unsigned long long)cs->xmitcnt.packets, 1638 (unsigned long long)cs->xmitcnt.bytes, 1639 (unsigned long long)cs->dropcnt.packets, 1640 (unsigned long long)cs->dropcnt.bytes); 1641 printf(" [ qlength: %3d/%3d qalg: %11s " 1642 "svc class: %9s %-13s ]\n", cs->qlength, cs->qlimit, 1643 qtype2str(cs->qtype), qid2str(cs->class_handle), 1644 qstate2str(cs->qstate)); 1645 1646 if (qs->avgn >= 2) { 1647 printf(" [ measured: %7.1f packets/s, %s/s ]\n", 1648 qs->avg_packets / interval, 1649 rate2str((8 * qs->avg_bytes) / interval)); 1650 } 1651 1652 if (qflag < 2) 1653 return; 1654 1655 switch (cs->qtype) { 1656 case Q_SFB: 1657 print_sfbstats(&cs->sfb); 1658 break; 1659 default: 1660 break; 1661 } 1662} 1663 1664static void 1665print_qfqstats(int slot, struct qfq_classstats *cs, struct queue_stats *qs) 1666{ 1667 printf(" %2d: [ pkts: %10llu bytes: %10llu " 1668 "dropped pkts: %6llu bytes: %6llu ]\n", slot, 1669 (unsigned long long)cs->xmitcnt.packets, 1670 (unsigned long long)cs->xmitcnt.bytes, 1671 (unsigned long long)cs->dropcnt.packets, 1672 (unsigned long long)cs->dropcnt.bytes); 1673 printf(" [ qlength: %3d/%3d index: %10u weight: %12u " 1674 "lmax: %7u ]\n", cs->qlength, cs->qlimit, cs->index, 1675 cs->weight, cs->lmax); 1676 printf(" [ qalg: %10s svc class: %6s %-35s ]\n", 1677 qtype2str(cs->qtype), qid2str(cs->class_handle), 1678 qstate2str(cs->qstate)); 1679 1680 if (qs->avgn >= 2) { 1681 printf(" [ measured: %7.1f packets/s, %s/s ]\n", 1682 qs->avg_packets / interval, 1683 rate2str((8 * qs->avg_bytes) / interval)); 1684 } 1685 1686 if (qflag < 2) 1687 return; 1688 1689 switch (cs->qtype) { 1690 case Q_SFB: 1691 print_sfbstats(&cs->sfb); 1692 break; 1693 default: 1694 break; 1695 } 1696} 1697 1698static void 1699print_sfbstats(struct sfb_stats *sfb) 1700{ 1701 struct sfbstats *sp = &sfb->sfbstats; 1702 int i, j, cur = sfb->current; 1703 1704 printf("\n"); 1705 printf(" [target delay: %14s ", 1706 nsec_to_str(sfb->target_qdelay)); 1707 printf("update interval: %14s]\n", 1708 nsec_to_str(sfb->update_interval)); 1709 printf(" [ early drop: %12llu rlimit drop: %11llu " 1710 "marked: %11llu ]\n", 1711 sp->drop_early, sp->drop_pbox, sp->marked_packets); 1712 printf(" [ penalized: %13llu rehash cnt: %12llu " 1713 "current: %10u ]\n", sp->pbox_packets, sp->num_rehash, cur); 1714 printf(" [ deque avg: %13s ", nsec_to_str(sp->dequeue_avg)); 1715 printf("rehash intvl: %11s]\n", nsec_to_str(sp->rehash_intval)); 1716 printf(" [ holdtime: %14s ", nsec_to_str(sp->hold_time)); 1717 printf("pboxtime: %14s ]\n", nsec_to_str(sp->pbox_time)); 1718 printf(" [ allocation: %12u drop thresh: %11u ]\n", 1719 sfb->allocation, sfb->dropthresh); 1720 printf(" [ flow controlled: %7llu adv feedback: %10llu ]\n", 1721 sp->flow_controlled, sp->flow_feedback); 1722 printf(" [ min queue delay: %10s delay_fcthreshold: %12llu]\n " 1723 " [stalls: %12lu]\n", 1724 nsec_to_str(sfb->min_estdelay), sfb->delay_fcthreshold, 1725 sp->dequeue_stall); 1726 1727 printf("\n\t\t\t\tCurrent bins (set %d)", cur); 1728 for (i = 0; i < SFB_LEVELS; ++i) { 1729 unsigned int q; 1730 double p; 1731 1732 printf("\n\tLevel: %d\n", i); 1733 for (j = 0; j < SFB_BINS; ++j) { 1734 if ((j % 4) == 0) 1735 printf("\t%6d:\t", j + 1); 1736 p = sfb->binstats[cur].stats[i][j].pmark; 1737 q = sfb->binstats[cur].stats[i][j].pkts; 1738 if (p > 0) { 1739 p /= (1 << SFB_FP_SHIFT); 1740 printf("[%1.4f %4u]", p, q); 1741 } else { 1742 printf("[ ]"); 1743 } 1744 if (j > 0 && ((j + 1) % 4) == 0) 1745 printf("\n"); 1746 } 1747 } 1748 1749 cur ^= 1; 1750 printf("\n\t\t\t\tWarm up bins (set %d)", cur); 1751 for (i = 0; i < SFB_LEVELS; ++i) { 1752 unsigned int q; 1753 double p; 1754 1755 printf("\n\tLevel: %d\n", i); 1756 for (j = 0; j < SFB_BINS; ++j) { 1757 if ((j % 4) == 0) 1758 printf("\t%6d:\t", j + 1); 1759 p = sfb->binstats[cur].stats[i][j].pmark; 1760 q = sfb->binstats[cur].stats[i][j].pkts; 1761 if (p > 0) { 1762 p /= (1 << SFB_FP_SHIFT); 1763 printf("[%1.4f %4u]", p, q); 1764 } else { 1765 printf("[ ]"); 1766 } 1767 if (j > 0 && ((j + 1) % 4) == 0) 1768 printf("\n"); 1769 } 1770 } 1771 printf("\n"); 1772} 1773 1774static void 1775update_avg(struct if_ifclassq_stats *ifcqs, struct queue_stats *qs) 1776{ 1777 u_int64_t b, p; 1778 int n; 1779 1780 n = qs->avgn; 1781 1782 switch (ifcqs->ifqs_scheduler) { 1783 case PKTSCHEDT_CBQ: 1784 b = ifcqs->ifqs_cbq_stats.xmit_cnt.bytes; 1785 p = ifcqs->ifqs_cbq_stats.xmit_cnt.packets; 1786 break; 1787 case PKTSCHEDT_PRIQ: 1788 b = ifcqs->ifqs_priq_stats.xmitcnt.bytes; 1789 p = ifcqs->ifqs_priq_stats.xmitcnt.packets; 1790 break; 1791 case PKTSCHEDT_HFSC: 1792 b = ifcqs->ifqs_hfsc_stats.xmit_cnt.bytes; 1793 p = ifcqs->ifqs_hfsc_stats.xmit_cnt.packets; 1794 break; 1795 case PKTSCHEDT_FAIRQ: 1796 b = ifcqs->ifqs_fairq_stats.xmit_cnt.bytes; 1797 p = ifcqs->ifqs_fairq_stats.xmit_cnt.packets; 1798 break; 1799 case PKTSCHEDT_TCQ: 1800 b = ifcqs->ifqs_tcq_stats.xmitcnt.bytes; 1801 p = ifcqs->ifqs_tcq_stats.xmitcnt.packets; 1802 break; 1803 case PKTSCHEDT_QFQ: 1804 b = ifcqs->ifqs_qfq_stats.xmitcnt.bytes; 1805 p = ifcqs->ifqs_qfq_stats.xmitcnt.packets; 1806 break; 1807 default: 1808 b = 0; 1809 p = 0; 1810 break; 1811 } 1812 1813 if (n == 0) { 1814 qs->prev_bytes = b; 1815 qs->prev_packets = p; 1816 qs->avgn++; 1817 return; 1818 } 1819 1820 if (b >= qs->prev_bytes) 1821 qs->avg_bytes = ((qs->avg_bytes * (n - 1)) + 1822 (b - qs->prev_bytes)) / n; 1823 1824 if (p >= qs->prev_packets) 1825 qs->avg_packets = ((qs->avg_packets * (n - 1)) + 1826 (p - qs->prev_packets)) / n; 1827 1828 qs->prev_bytes = b; 1829 qs->prev_packets = p; 1830 if (n < AVGN_MAX) 1831 qs->avgn++; 1832} 1833 1834static char * 1835qtype2str(classq_type_t t) 1836{ 1837 char *c; 1838 1839 switch (t) { 1840 case Q_DROPHEAD: 1841 c = "DROPHEAD"; 1842 break; 1843 case Q_DROPTAIL: 1844 c = "DROPTAIL"; 1845 break; 1846 case Q_RED: 1847 c = "RED"; 1848 break; 1849 case Q_RIO: 1850 c = "RIO"; 1851 break; 1852 case Q_BLUE: 1853 c = "BLUE"; 1854 break; 1855 case Q_SFB: 1856 c = "SFB"; 1857 break; 1858 default: 1859 c = "UNKNOWN"; 1860 break; 1861 } 1862 1863 return (c); 1864} 1865 1866#define NSEC_PER_SEC 1000000000 /* nanoseconds per second */ 1867#define USEC_PER_SEC 1000000 /* nanoseconds per second */ 1868#define MSEC_PER_SEC 1000 /* nanoseconds per second */ 1869 1870static char * 1871nsec_to_str(unsigned long long nsec) 1872{ 1873 static char buf[32]; 1874 const char *u; 1875 long double n = nsec, t; 1876 1877 if (nsec >= NSEC_PER_SEC) { 1878 t = n / NSEC_PER_SEC; 1879 u = "sec "; 1880 } else if (n >= USEC_PER_SEC) { 1881 t = n / USEC_PER_SEC; 1882 u = "msec"; 1883 } else if (n >= MSEC_PER_SEC) { 1884 t = n / MSEC_PER_SEC; 1885 u = "usec"; 1886 } else { 1887 t = n; 1888 u = "nsec"; 1889 } 1890 1891 snprintf(buf, sizeof (buf), "%-4.2Lf %4s", t, u); 1892 return (buf); 1893} 1894 1895static char * 1896sched2str(unsigned int s) 1897{ 1898 char *c; 1899 1900 switch (s) { 1901 case PKTSCHEDT_NONE: 1902 c = "NONE"; 1903 break; 1904 case PKTSCHEDT_CBQ: 1905 c = "CBQ"; 1906 break; 1907 case PKTSCHEDT_HFSC: 1908 c = "HFSC"; 1909 break; 1910 case PKTSCHEDT_PRIQ: 1911 c = "PRIQ"; 1912 break; 1913 case PKTSCHEDT_FAIRQ: 1914 c = "FAIRQ"; 1915 break; 1916 case PKTSCHEDT_TCQ: 1917 c = "TCQ"; 1918 break; 1919 case PKTSCHEDT_QFQ: 1920 c = "QFQ"; 1921 break; 1922 default: 1923 c = "UNKNOWN"; 1924 break; 1925 } 1926 1927 return (c); 1928} 1929 1930static char * 1931qid2str(unsigned int s) 1932{ 1933 char *c; 1934 1935 switch (s) { 1936 case 0: 1937 c = "BE"; 1938 break; 1939 case 1: 1940 c = "BK_SYS"; 1941 break; 1942 case 2: 1943 c = "BK"; 1944 break; 1945 case 3: 1946 c = "RD"; 1947 break; 1948 case 4: 1949 c = "OAM"; 1950 break; 1951 case 5: 1952 c = "AV"; 1953 break; 1954 case 6: 1955 c = "RV"; 1956 break; 1957 case 7: 1958 c = "VI"; 1959 break; 1960 case 8: 1961 c = "VO"; 1962 break; 1963 case 9: 1964 c = "CTL"; 1965 break; 1966 default: 1967 c = "UNKNOWN"; 1968 break; 1969 } 1970 1971 return (c); 1972} 1973 1974static char * 1975tcqslot2str(unsigned int s) 1976{ 1977 char *c; 1978 1979 switch (s) { 1980 case 0: 1981 case 3: 1982 case 4: 1983 c = "0,3,4"; 1984 break; 1985 case 1: 1986 case 2: 1987 c = "1,2"; 1988 break; 1989 case 5: 1990 case 6: 1991 case 7: 1992 c = "5-7"; 1993 break; 1994 case 8: 1995 case 9: 1996 c = "8,9"; 1997 break; 1998 default: 1999 c = "?"; 2000 break; 2001 } 2002 2003 return (c); 2004} 2005 2006static char * 2007qstate2str(unsigned int s) 2008{ 2009 char *c; 2010 2011 switch (s) { 2012 case QS_RUNNING: 2013 c = "(RUNNING)"; 2014 break; 2015 case QS_SUSPENDED: 2016 c = "(SUSPENDED)"; 2017 break; 2018 default: 2019 c = "(UNKNOWN)"; 2020 break; 2021 } 2022 2023 return (c); 2024} 2025 2026#define R2S_BUFS 8 2027#define RATESTR_MAX 16 2028 2029static char * 2030rate2str(long double rate) 2031{ 2032 char *buf; 2033 static char r2sbuf[R2S_BUFS][RATESTR_MAX]; /* ring bufer */ 2034 static int idx = 0; 2035 int i; 2036 static const char unit[] = " KMG"; 2037 2038 buf = r2sbuf[idx++]; 2039 if (idx == R2S_BUFS) 2040 idx = 0; 2041 2042 for (i = 0; rate >= 1000 && i <= 3; i++) 2043 rate /= 1000; 2044 2045 if ((int)(rate * 100) % 100) 2046 snprintf(buf, RATESTR_MAX, "%.2Lf%cb", rate, unit[i]); 2047 else 2048 snprintf(buf, RATESTR_MAX, "%lld%cb", (int64_t)rate, unit[i]); 2049 2050 return (buf); 2051} 2052 2053void 2054rxpollstatpr(void) 2055{ 2056 struct ifmibdata_supplemental ifmsupp; 2057 size_t miblen = sizeof (ifmsupp); 2058 struct itimerval timer_interval; 2059 struct if_rxpoll_stats *sp; 2060 sigset_t sigset, oldsigset; 2061 unsigned int ifindex; 2062 int name[6]; 2063 2064 ifindex = if_nametoindex(interface); 2065 if (ifindex == 0) { 2066 fprintf(stderr, "Invalid interface name\n"); 2067 return; 2068 } 2069 2070 bzero(&ifmsupp, sizeof (struct ifmibdata_supplemental)); 2071 2072loop: 2073 if (interval > 0) { 2074 /* create a timer that fires repeatedly every interval seconds */ 2075 timer_interval.it_value.tv_sec = interval; 2076 timer_interval.it_value.tv_usec = 0; 2077 timer_interval.it_interval.tv_sec = interval; 2078 timer_interval.it_interval.tv_usec = 0; 2079 (void) signal(SIGALRM, catchalarm); 2080 signalled = NO; 2081 (void) setitimer(ITIMER_REAL, &timer_interval, NULL); 2082 } 2083 2084 /* Common OID prefix */ 2085 name[0] = CTL_NET; 2086 name[1] = PF_LINK; 2087 name[2] = NETLINK_GENERIC; 2088 name[3] = IFMIB_IFDATA; 2089 name[4] = ifindex; 2090 name[5] = IFDATA_SUPPLEMENTAL; 2091 if (sysctl(name, 6, &ifmsupp, &miblen, NULL, 0) == -1) 2092 err(1, "sysctl IFDATA_SUPPLEMENTAL"); 2093 2094 sp = &ifmsupp.ifmd_rxpoll_stats; 2095 2096 printf("%-4s [ poll on requests: %15u errors: %27u ]\n", 2097 interface, sp->ifi_poll_on_req, sp->ifi_poll_on_err); 2098 printf(" [ poll off requests: %15u errors: %27u ]\n", 2099 sp->ifi_poll_off_req, sp->ifi_poll_off_err); 2100 printf(" [ polled packets: %18llu polled bytes: %21llu ]\n", 2101 sp->ifi_poll_packets, sp->ifi_poll_bytes); 2102 printf(" [ sampled packets avg/min/max: %12u / %12u / %12u ]\n", 2103 sp->ifi_poll_packets_avg, sp->ifi_poll_packets_min, 2104 sp->ifi_poll_packets_max); 2105 printf(" [ sampled bytes avg/min/max: %12u / %12u / %12u ]\n", 2106 sp->ifi_poll_bytes_avg, sp->ifi_poll_bytes_min, 2107 sp->ifi_poll_bytes_max); 2108 printf(" [ sampled wakeups avg: %12u ]\n", 2109 sp->ifi_poll_wakeups_avg); 2110 printf(" [ packets lowat/hiwat threshold: %10u / %10u ]\n", 2111 sp->ifi_poll_packets_lowat, sp->ifi_poll_packets_hiwat); 2112 printf(" [ bytes lowat/hiwat threshold: %10u / %10u ]\n", 2113 sp->ifi_poll_bytes_lowat, sp->ifi_poll_bytes_hiwat); 2114 printf(" [ wakeups lowat/hiwat threshold: %10u / %10u ]\n", 2115 sp->ifi_poll_wakeups_lowat, sp->ifi_poll_wakeups_hiwat); 2116 2117 fflush(stdout); 2118 2119 if (interval > 0) { 2120 sigemptyset(&sigset); 2121 sigaddset(&sigset, SIGALRM); 2122 (void) sigprocmask(SIG_BLOCK, &sigset, &oldsigset); 2123 if (!signalled) { 2124 sigemptyset(&sigset); 2125 sigsuspend(&sigset); 2126 } 2127 (void) sigprocmask(SIG_SETMASK, &oldsigset, NULL); 2128 2129 signalled = NO; 2130 goto loop; 2131 } 2132} 2133