]> git.saurik.com Git - apple/network_cmds.git/blob - netstat.tproj/if.c
1fc4c3afcae80b988e328db7fd005d4aa337226c
[apple/network_cmds.git] / netstat.tproj / if.c
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
103 static void sidewaysintpr ();
104 static void catchalarm (int);
105 static char *sec2str(time_t);
106 static void llreach_sysctl(uint32_t);
107 static char *nsec_to_str(unsigned long long);
108 static char *qtype2str(classq_type_t);
109 static char *sched2str(unsigned int);
110 static char *qid2str(unsigned int);
111 static char *qstate2str(unsigned int);
112 static char *tcqslot2str(unsigned int);
113 static char *rate2str(long double);
114
115 #define AVGN_MAX 8
116
117 struct 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
127 static void print_cbqstats(int slot, struct cbq_classstats *,
128 struct queue_stats *);
129 static void print_priqstats(int slot, struct priq_classstats *,
130 struct queue_stats *);
131 static void print_hfscstats(int slot, struct hfsc_classstats *,
132 struct queue_stats *);
133 static void print_fairqstats(int slot, struct fairq_classstats *,
134 struct queue_stats *);
135 static void print_tcqstats(int slot, struct tcq_classstats *,
136 struct queue_stats *);
137 static void print_qfqstats(int slot, struct qfq_classstats *,
138 struct queue_stats *);
139 static void print_sfbstats(struct sfb_stats *);
140 static void update_avg(struct if_ifclassq_stats *, struct queue_stats *);
141
142 struct queue_stats qstats[IFCQ_SC_MAX];
143
144 #ifdef INET6
145 char *netname6 (struct sockaddr_in6 *, struct sockaddr *);
146 static char ntop_buf[INET6_ADDRSTRLEN]; /* for inet_ntop() */
147 #endif
148
149 /*
150 * Display a formatted value, or a '-' in the same space.
151 */
152 static void
153 show_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
167 size_t
168 get_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
188 static void
189 multipr(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 */
258 void
259 intpr(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
614 struct 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
637 u_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 */
646 static void
647 sidewaysintpr()
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;
710 banner:
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;
740 loop:
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
1086 void
1087 intervalpr(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 */
1121 static void
1122 catchalarm(int signo )
1123 {
1124 signalled = YES;
1125 }
1126
1127 static char *
1128 sec2str(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
1158 void
1159 intpr_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
1216 static void
1217 llreach_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
1338 out_free:
1339 free(buf);
1340 #undef MAX_SYSCTL_TRY
1341 }
1342
1343 void
1344 aqstatpr(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
1382 loop:
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
1489 done:
1490 free(ifcqs);
1491 close(s);
1492 }
1493
1494 static void
1495 print_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
1526 static void
1527 print_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
1557 static void
1558 print_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
1588 static void
1589 print_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
1619 static void
1620 print_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
1664 static void
1665 print_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
1698 static void
1699 print_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
1774 static void
1775 update_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
1834 static char *
1835 qtype2str(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
1870 static char *
1871 nsec_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
1895 static char *
1896 sched2str(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
1930 static char *
1931 qid2str(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
1974 static char *
1975 tcqslot2str(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
2006 static char *
2007 qstate2str(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
2029 static char *
2030 rate2str(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
2053 void
2054 rxpollstatpr(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
2072 loop:
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 }