]> git.saurik.com Git - apple/network_cmds.git/blob - netstat.tproj/if.c
network_cmds-433.tar.gz
[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 #ifndef lint
62 /*
63 static char sccsid[] = "@(#)if.c 8.3 (Berkeley) 4/28/95";
64 */
65 static const char rcsid[] =
66 "$Id: if.c,v 1.7 2006/01/16 04:53:59 lindak Exp $";
67 #endif /* not lint */
68
69 #include <sys/types.h>
70 #include <sys/socket.h>
71 #include <sys/sysctl.h>
72 #include <sys/ioctl.h>
73 #include <sys/time.h>
74
75 #include <net/if.h>
76 #include <net/if_var.h>
77 #include <net/if_dl.h>
78 #include <net/if_types.h>
79 #include <net/if_mib.h>
80 #include <net/if_llreach.h>
81 #include <net/ethernet.h>
82 #include <net/route.h>
83
84 #include <net/pktsched/pktsched.h>
85 #include <net/classq/if_classq.h>
86
87 #include <netinet/in.h>
88 #include <netinet/in_var.h>
89
90 #include <arpa/inet.h>
91
92 #include <signal.h>
93 #include <stdio.h>
94 #include <string.h>
95 #include <unistd.h>
96 #include <stdlib.h>
97 #include <err.h>
98 #include <errno.h>
99
100 #include "netstat.h"
101
102 #define YES 1
103 #define NO 0
104
105 #define ROUNDUP(a, size) (((a) & ((size) - 1)) ? (1 + ((a)|(size - 1))) : (a))
106
107 #define NEXT_SA(p) (struct sockaddr *) \
108 ((caddr_t)p + (p->sa_len ? ROUNDUP(p->sa_len, sizeof(uint32_t)) : \
109 sizeof(uint32_t)))
110
111 static void sidewaysintpr ();
112 static void catchalarm (int);
113 static char *sec2str(time_t);
114 static void llreach_sysctl(uint32_t);
115 static char *nsec_to_str(unsigned long long);
116 static char *qtype2str(classq_type_t);
117 static char *sched2str(unsigned int);
118 static char *qid2str(unsigned int);
119 static char *qstate2str(unsigned int);
120 static char *tcqslot2str(unsigned int);
121 static char *rate2str(long double);
122
123 #define AVGN_MAX 8
124
125 struct queue_stats {
126 int avgn;
127 double avg_bytes;
128 double avg_packets;
129 u_int64_t prev_bytes;
130 u_int64_t prev_packets;
131 unsigned int printed;
132 unsigned int handle;
133 };
134
135 static void print_cbqstats(int slot, struct cbq_classstats *,
136 struct queue_stats *);
137 static void print_priqstats(int slot, struct priq_classstats *,
138 struct queue_stats *);
139 static void print_hfscstats(int slot, struct hfsc_classstats *,
140 struct queue_stats *);
141 static void print_fairqstats(int slot, struct fairq_classstats *,
142 struct queue_stats *);
143 static void print_tcqstats(int slot, struct tcq_classstats *,
144 struct queue_stats *);
145 static void print_qfqstats(int slot, struct qfq_classstats *,
146 struct queue_stats *);
147 static void print_sfbstats(struct sfb_stats *);
148 static void update_avg(struct if_ifclassq_stats *, struct queue_stats *);
149
150 struct queue_stats qstats[IFCQ_SC_MAX];
151
152 #ifdef INET6
153 char *netname6 (struct sockaddr_in6 *, struct sockaddr *);
154 static char ntop_buf[INET6_ADDRSTRLEN]; /* for inet_ntop() */
155 #endif
156
157 /*
158 * Display a formatted value, or a '-' in the same space.
159 */
160 static void
161 show_stat(const char *fmt, int width, u_int64_t value, short showvalue)
162 {
163 char newfmt[32];
164
165 /* Construct the format string */
166 if (showvalue) {
167 snprintf(newfmt, sizeof(newfmt), "%%%d%s", width, fmt);
168 printf(newfmt, value);
169 } else {
170 snprintf(newfmt, sizeof(newfmt), "%%%ds", width);
171 printf(newfmt, "-");
172 }
173 }
174
175 size_t
176 get_rti_info(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
177 {
178 int i;
179 size_t len = 0;
180
181 for (i = 0; i < RTAX_MAX; i++) {
182 if (addrs & (1 << i)) {
183 rti_info[i] = sa;
184 if (sa->sa_len < sizeof(struct sockaddr))
185 len += sizeof(struct sockaddr);
186 else
187 len += sa->sa_len;
188 sa = NEXT_SA(sa);
189 } else {
190 rti_info[i] = NULL;
191 }
192 }
193 return len;
194 }
195
196 static void
197 multipr(int family, char *buf, char *lim)
198 {
199 char *next;
200
201 for (next = buf; next < lim; ) {
202 struct ifma_msghdr2 *ifmam = (struct ifma_msghdr2 *)next;
203 struct sockaddr *rti_info[RTAX_MAX];
204 struct sockaddr *sa;
205 const char *fmt = 0;
206
207 next += ifmam->ifmam_msglen;
208 if (ifmam->ifmam_type == RTM_IFINFO2)
209 break;
210 else if (ifmam->ifmam_type != RTM_NEWMADDR2)
211 continue;
212 get_rti_info(ifmam->ifmam_addrs, (struct sockaddr*)(ifmam + 1), rti_info);
213 sa = rti_info[RTAX_IFA];
214
215 if (sa->sa_family != family)
216 continue;
217 switch (sa->sa_family) {
218 case AF_INET: {
219 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
220
221 fmt = routename(sin->sin_addr.s_addr);
222 break;
223 }
224 #ifdef INET6
225 case AF_INET6: {
226 struct sockaddr_in6 sin6;
227
228 memcpy(&sin6, sa, sizeof(struct sockaddr_in6));
229
230 if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
231 IN6_IS_ADDR_MC_NODELOCAL(&sin6.sin6_addr) ||
232 IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) {
233 sin6.sin6_scope_id = ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
234 sin6.sin6_addr.s6_addr[2] = 0;
235 sin6.sin6_addr.s6_addr[3] = 0;
236 }
237
238 printf("%23s %-19.19s(refs: %d)\n", "",
239 inet_ntop(AF_INET6, &sin6.sin6_addr,
240 ntop_buf, sizeof(ntop_buf)),
241 ifmam->ifmam_refcount);
242 break;
243 }
244 #endif /* INET6 */
245 case AF_LINK: {
246 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
247
248 switch (sdl->sdl_type) {
249 case IFT_ETHER:
250 case IFT_FDDI:
251 fmt = ether_ntoa((struct ether_addr *)
252 LLADDR(sdl));
253 break;
254 }
255 break;
256 }
257 }
258 if (fmt)
259 printf("%23s %s\n", "", fmt);
260 }
261 }
262
263 /*
264 * Print a description of the network interfaces.
265 */
266 void
267 intpr(void (*pfunc)(char *))
268 {
269 u_int64_t opackets = 0;
270 u_int64_t ipackets = 0;
271 u_int64_t obytes = 0;
272 u_int64_t ibytes = 0;
273 u_int64_t oerrors = 0;
274 u_int64_t ierrors = 0;
275 u_int64_t collisions = 0;
276 u_int64_t fpackets = 0;
277 u_int64_t fbytes = 0;
278 uint32_t mtu = 0;
279 int timer = 0;
280 int drops = 0;
281 struct sockaddr *sa = NULL;
282 char name[32];
283 short network_layer;
284 short link_layer;
285 int mib[6];
286 char *buf = NULL, *lim, *next;
287 size_t len;
288 struct if_msghdr *ifm;
289 struct sockaddr *rti_info[RTAX_MAX];
290 unsigned int ifindex = 0;
291
292 if (interval) {
293 sidewaysintpr();
294 return;
295 }
296
297 if (interface != 0)
298 ifindex = if_nametoindex(interface);
299
300 mib[0] = CTL_NET; // networking subsystem
301 mib[1] = PF_ROUTE; // type of information
302 mib[2] = 0; // protocol (IPPROTO_xxx)
303 mib[3] = 0; // address family
304 mib[4] = NET_RT_IFLIST2; // operation
305 mib[5] = 0;
306 if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
307 return;
308 if ((buf = malloc(len)) == NULL) {
309 printf("malloc failed\n");
310 exit(1);
311 }
312 if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
313 if (buf)
314 free(buf);
315 return;
316 }
317
318 if (!pfunc) {
319 printf("%-5.5s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
320 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
321 if (prioflag >= 0)
322 printf(" %8.8s %8.8s", "Itcpkts", "Ipvpkts");
323 if (bflag) {
324 printf(" %10.10s","Ibytes");
325 if (prioflag >= 0)
326 printf(" %8.8s %8.8s", "Itcbytes", "Ipvbytes");
327 }
328 printf(" %8.8s %5.5s", "Opkts", "Oerrs");
329 if (prioflag >= 0)
330 printf(" %8.8s %8.8s", "Otcpkts", "Opvpkts");
331 if (bflag) {
332 printf(" %10.10s","Obytes");
333 if (prioflag >= 0)
334 printf(" %8.8s %8.8s", "Otcbytes", "Opvbytes");
335 }
336 printf(" %5s", "Coll");
337 if (tflag)
338 printf(" %s", "Time");
339 if (dflag)
340 printf(" %s", "Drop");
341 if (Fflag) {
342 printf(" %8.8s", "Fpkts");
343 if (bflag)
344 printf(" %10.10s", "Fbytes");
345 }
346 putchar('\n');
347 }
348 lim = buf + len;
349 for (next = buf; next < lim; ) {
350 char *cp;
351 int n, m;
352 struct ifmibdata_supplemental ifmsupp;
353 u_int64_t ift_itcp = 0; /* input tc packets */
354 u_int64_t ift_itcb = 0; /* input tc bytes */
355 u_int64_t ift_otcp = 0; /* output tc packets */
356 u_int64_t ift_otcb = 0; /* output tc bytes */
357 u_int64_t ift_ipvp = 0; /* input priv tc packets */
358 u_int64_t ift_ipvb = 0; /* input priv tc bytes */
359 u_int64_t ift_opvp = 0; /* output priv tc packets */
360 u_int64_t ift_opvb = 0; /* output priv tc bytes */
361
362 bzero(&ifmsupp, sizeof(struct ifmibdata_supplemental));
363
364 network_layer = 0;
365 link_layer = 0;
366 ifm = (struct if_msghdr *)next;
367 next += ifm->ifm_msglen;
368
369 if (ifm->ifm_type == RTM_IFINFO2) {
370 struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm;
371 struct sockaddr_dl *sdl =
372 (struct sockaddr_dl *)(if2m + 1);
373 int mibname[6];
374 size_t miblen = sizeof(struct ifmibdata_supplemental);
375
376 strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
377 name[sdl->sdl_nlen] = 0;
378 if (interface != 0 && if2m->ifm_index != ifindex)
379 continue;
380 cp = index(name, '\0');
381
382 if (pfunc) {
383 (*pfunc)(name);
384 continue;
385 }
386
387 if ((if2m->ifm_flags & IFF_UP) == 0)
388 *cp++ = '*';
389 *cp = '\0';
390
391 /*
392 * Get the interface stats. These may get
393 * overriden below on a per-interface basis.
394 */
395 opackets = if2m->ifm_data.ifi_opackets;
396 ipackets = if2m->ifm_data.ifi_ipackets;
397 obytes = if2m->ifm_data.ifi_obytes;
398 ibytes = if2m->ifm_data.ifi_ibytes;
399 oerrors =if2m->ifm_data.ifi_oerrors;
400 ierrors = if2m->ifm_data.ifi_ierrors;
401 collisions = if2m->ifm_data.ifi_collisions;
402 timer = if2m->ifm_timer;
403 drops = if2m->ifm_snd_drops;
404 mtu = if2m->ifm_data.ifi_mtu;
405
406 /* Common OID prefix */
407 mibname[0] = CTL_NET;
408 mibname[1] = PF_LINK;
409 mibname[2] = NETLINK_GENERIC;
410 mibname[3] = IFMIB_IFDATA;
411 mibname[4] = if2m->ifm_index;
412 mibname[5] = IFDATA_SUPPLEMENTAL;
413 if (sysctl(mibname, 6, &ifmsupp, &miblen, NULL, 0) == -1)
414 err(1, "sysctl IFDATA_SUPPLEMENTAL");
415
416 fpackets = ifmsupp.ifmd_data_extended.ifi_fpackets;
417 fbytes = ifmsupp.ifmd_data_extended.ifi_fbytes;
418
419 if (prioflag >= 0) {
420 switch (prioflag) {
421 case SO_TC_BE:
422 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ibepackets;
423 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ibebytes;
424 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_obepackets;
425 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_obebytes;
426 break;
427 case SO_TC_BK:
428 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ibkpackets;
429 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ibkbytes;
430 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_obkpackets;
431 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_obkbytes;
432 break;
433 case SO_TC_VI:
434 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ivipackets;
435 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ivibytes;
436 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_ovipackets;
437 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_ovibytes;
438 break;
439 case SO_TC_VO:
440 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ivopackets;
441 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ivobytes;
442 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_ovopackets;
443 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_ovobytes;
444 break;
445 default:
446 ift_itcp = 0;
447 ift_itcb = 0;
448 ift_otcp = 0;
449 ift_otcb = 0;
450 ift_ipvp = 0;
451 ift_ipvb = 0;
452 ift_opvp = 0;
453 ift_opvb = 0;
454 break;
455 }
456 ift_ipvp = ifmsupp.ifmd_traffic_class.ifi_ipvpackets;
457 ift_ipvb = ifmsupp.ifmd_traffic_class.ifi_ipvbytes;
458 ift_opvp = ifmsupp.ifmd_traffic_class.ifi_opvpackets;
459 ift_opvb = ifmsupp.ifmd_traffic_class.ifi_opvbytes;
460 }
461
462 get_rti_info(if2m->ifm_addrs,
463 (struct sockaddr*)(if2m + 1), rti_info);
464 sa = rti_info[RTAX_IFP];
465 } else if (ifm->ifm_type == RTM_NEWADDR) {
466 struct ifa_msghdr *ifam = (struct ifa_msghdr *)ifm;
467
468 if (interface != 0 && ifam->ifam_index != ifindex)
469 continue;
470 get_rti_info(ifam->ifam_addrs,
471 (struct sockaddr*)(ifam + 1), rti_info);
472 sa = rti_info[RTAX_IFA];
473 } else {
474 continue;
475 }
476 printf("%-5.5s %-5u ", name, mtu);
477
478 if (sa == 0) {
479 printf("%-13.13s ", "none");
480 printf("%-15.15s ", "none");
481 } else {
482 switch (sa->sa_family) {
483 case AF_UNSPEC:
484 printf("%-13.13s ", "none");
485 printf("%-15.15s ", "none");
486 break;
487
488 case AF_INET: {
489 struct sockaddr_in *sin =
490 (struct sockaddr_in *)sa;
491 struct sockaddr_in mask;
492
493 mask.sin_addr.s_addr = 0;
494 memcpy(&mask, rti_info[RTAX_NETMASK],
495 ((struct sockaddr_in *)
496 rti_info[RTAX_NETMASK])->sin_len);
497
498 printf("%-13.13s ",
499 netname(sin->sin_addr.s_addr &
500 mask.sin_addr.s_addr,
501 ntohl(mask.sin_addr.s_addr)));
502
503 printf("%-15.15s ",
504 routename(sin->sin_addr.s_addr));
505
506 network_layer = 1;
507 break;
508 }
509 #ifdef INET6
510 case AF_INET6: {
511 struct sockaddr_in6 *sin6 =
512 (struct sockaddr_in6 *)sa;
513 struct sockaddr *mask =
514 (struct sockaddr *)rti_info[RTAX_NETMASK];
515
516 printf("%-11.11s ", netname6(sin6, mask));
517 printf("%-17.17s ", (char *)inet_ntop(AF_INET6,
518 &sin6->sin6_addr, ntop_buf,
519 sizeof(ntop_buf)));
520
521 network_layer = 1;
522 break;
523 }
524 #endif /*INET6*/
525 case AF_LINK: {
526 struct sockaddr_dl *sdl =
527 (struct sockaddr_dl *)sa;
528 char linknum[10];
529 cp = (char *)LLADDR(sdl);
530 n = sdl->sdl_alen;
531 snprintf(linknum, sizeof(linknum),
532 "<Link#%d>", sdl->sdl_index);
533 m = printf("%-11.11s ", linknum);
534 goto hexprint;
535 }
536
537 default:
538 m = printf("(%d)", sa->sa_family);
539 for (cp = sa->sa_len + (char *)sa;
540 --cp > sa->sa_data && (*cp == 0);) {}
541 n = cp - sa->sa_data + 1;
542 cp = sa->sa_data;
543 hexprint:
544 while (--n >= 0)
545 m += printf("%02x%c", *cp++ & 0xff,
546 n > 0 ? ':' : ' ');
547 m = 30 - m;
548 while (m-- > 0)
549 putchar(' ');
550
551 link_layer = 1;
552 break;
553 }
554 }
555
556 show_stat("llu", 8, ipackets, link_layer|network_layer);
557 printf(" ");
558 show_stat("llu", 5, ierrors, link_layer);
559 printf(" ");
560 if (prioflag >= 0) {
561 show_stat("llu", 8, ift_itcp, link_layer|network_layer);
562 printf(" ");
563 show_stat("llu", 8, ift_ipvp, link_layer|network_layer);
564 printf(" ");
565 }
566 if (bflag) {
567 show_stat("llu", 10, ibytes, link_layer|network_layer);
568 printf(" ");
569 if (prioflag >= 0) {
570 show_stat("llu", 8, ift_itcb, link_layer|network_layer);
571 printf(" ");
572 show_stat("llu", 8, ift_ipvb, link_layer|network_layer);
573 printf(" ");
574 }
575 }
576 show_stat("llu", 8, opackets, link_layer|network_layer);
577 printf(" ");
578 show_stat("llu", 5, oerrors, link_layer);
579 printf(" ");
580 if (prioflag >= 0) {
581 show_stat("llu", 8, ift_otcp, link_layer|network_layer);
582 printf(" ");
583 show_stat("llu", 8, ift_opvp, link_layer|network_layer);
584 printf(" ");
585 }
586 if (bflag) {
587 show_stat("llu", 10, obytes, link_layer|network_layer);
588 printf(" ");
589 if (prioflag >= 0) {
590 show_stat("llu", 8, ift_otcb, link_layer|network_layer);
591 printf(" ");
592 show_stat("llu", 8, ift_opvb, link_layer|network_layer);
593 printf(" ");
594 }
595 }
596 show_stat("llu", 5, collisions, link_layer);
597 if (tflag) {
598 printf(" ");
599 show_stat("d", 3, timer, link_layer);
600 }
601 if (dflag) {
602 printf(" ");
603 show_stat("d", 3, drops, link_layer);
604 }
605 if (Fflag) {
606 printf(" ");
607 show_stat("llu", 8, fpackets, link_layer|network_layer);
608 if (bflag) {
609 printf(" ");
610 show_stat("llu", 10, fbytes,
611 link_layer|network_layer);
612 }
613 }
614 putchar('\n');
615
616 if (aflag)
617 multipr(sa->sa_family, next, lim);
618 }
619 free(buf);
620 }
621
622 struct iftot {
623 SLIST_ENTRY(iftot) chain;
624 char ift_name[16]; /* interface name */
625 u_int64_t ift_ip; /* input packets */
626 u_int64_t ift_ie; /* input errors */
627 u_int64_t ift_op; /* output packets */
628 u_int64_t ift_oe; /* output errors */
629 u_int64_t ift_co; /* collisions */
630 u_int64_t ift_dr; /* drops */
631 u_int64_t ift_ib; /* input bytes */
632 u_int64_t ift_ob; /* output bytes */
633 u_int64_t ift_itcp; /* input tc packets */
634 u_int64_t ift_itcb; /* input tc bytes */
635 u_int64_t ift_otcp; /* output tc packets */
636 u_int64_t ift_otcb; /* output tc bytes */
637 u_int64_t ift_ipvp; /* input priv tc packets */
638 u_int64_t ift_ipvb; /* input priv tc bytes */
639 u_int64_t ift_opvp; /* output priv tc packets */
640 u_int64_t ift_opvb; /* output priv tc bytes */
641 u_int64_t ift_fp; /* forwarded packets */
642 u_int64_t ift_fb; /* forwarded bytes */
643 };
644
645 u_char signalled; /* set if alarm goes off "early" */
646
647 /*
648 * Print a running summary of interface statistics.
649 * Repeat display every interval seconds, showing statistics
650 * collected over that interval. Assumes that interval is non-zero.
651 * First line printed at top of screen is always cumulative.
652 * XXX - should be rewritten to use ifmib(4).
653 */
654 static void
655 sidewaysintpr()
656 {
657 struct iftot *total, *sum, *interesting;
658 register int line;
659 int first;
660 int name[6];
661 size_t len;
662 unsigned int ifcount, i;
663 struct ifmibdata *ifmdall = 0;
664 int interesting_row;
665 sigset_t sigset, oldsigset;
666 struct itimerval timer_interval;
667
668 /* Common OID prefix */
669 name[0] = CTL_NET;
670 name[1] = PF_LINK;
671 name[2] = NETLINK_GENERIC;
672
673 len = sizeof(int);
674 name[3] = IFMIB_SYSTEM;
675 name[4] = IFMIB_IFCOUNT;
676 if (sysctl(name, 5, &ifcount, &len, 0, 0) == 1)
677 err(1, "sysctl IFMIB_IFCOUNT");
678
679 len = ifcount * sizeof(struct ifmibdata);
680 ifmdall = malloc(len);
681 if (ifmdall == 0)
682 err(1, "malloc failed");
683 name[3] = IFMIB_IFALLDATA;
684 name[4] = 0;
685 name[5] = IFDATA_GENERAL;
686 if (sysctl(name, 6, ifmdall, &len, (void *)0, 0) == -1)
687 err(1, "sysctl IFMIB_IFALLDATA");
688
689 interesting = NULL;
690 interesting_row = 0;
691 for (i = 0; i < ifcount; i++) {
692 struct ifmibdata *ifmd = ifmdall + i;
693
694 if (interface && strcmp(ifmd->ifmd_name, interface) == 0) {
695 if ((interesting = calloc(ifcount,
696 sizeof(struct iftot))) == NULL)
697 err(1, "malloc failed");
698 interesting_row = if_nametoindex(interface);
699 snprintf(interesting->ift_name, 16, "(%s)",
700 ifmd->ifmd_name);;
701 }
702 }
703 if ((total = calloc(1, sizeof(struct iftot))) == NULL)
704 err(1, "malloc failed");
705
706 if ((sum = calloc(1, sizeof(struct iftot))) == NULL)
707 err(1, "malloc failed");
708
709 /* create a timer that fires repeatedly every interval seconds */
710 timer_interval.it_value.tv_sec = interval;
711 timer_interval.it_value.tv_usec = 0;
712 timer_interval.it_interval.tv_sec = interval;
713 timer_interval.it_interval.tv_usec = 0;
714 (void)signal(SIGALRM, catchalarm);
715 signalled = NO;
716 (void)setitimer(ITIMER_REAL, &timer_interval, NULL);
717 first = 1;
718 banner:
719 if (vflag > 0)
720 printf("%9s", " ");
721
722 if (prioflag >= 0)
723 printf("%39s %39s %36s", "input",
724 interesting ? interesting->ift_name : "(Total)", "output");
725 else
726 printf("%17s %14s %16s", "input",
727 interesting ? interesting->ift_name : "(Total)", "output");
728 putchar('\n');
729
730 if (vflag > 0)
731 printf("%9s", " ");
732
733 printf("%10s %5s %10s ", "packets", "errs", "bytes");
734 if (prioflag >= 0)
735 printf(" %10s %10s %10s %10s",
736 "tcpkts", "tcbytes", "pvpkts", "pvbytes");
737 printf("%10s %5s %10s %5s", "packets", "errs", "bytes", "colls");
738 if (dflag)
739 printf(" %5.5s", "drops");
740 if (prioflag >= 0)
741 printf(" %10s %10s %10s %10s",
742 "tcpkts", "tcbytes", "pvpkts", "pvbytes");
743 if (Fflag)
744 printf(" %10s %10s", "fpackets", "fbytes");
745 putchar('\n');
746 fflush(stdout);
747 line = 0;
748 loop:
749 if (vflag && !first)
750 print_time();
751
752 if (interesting != NULL) {
753 struct ifmibdata ifmd;
754 struct ifmibdata_supplemental ifmsupp;
755
756 len = sizeof(struct ifmibdata);
757 name[3] = IFMIB_IFDATA;
758 name[4] = interesting_row;
759 name[5] = IFDATA_GENERAL;
760 if (sysctl(name, 6, &ifmd, &len, (void *)0, 0) == -1)
761 err(1, "sysctl IFDATA_GENERAL %d", interesting_row);
762
763 len = sizeof(struct ifmibdata_supplemental);
764 name[3] = IFMIB_IFDATA;
765 name[4] = interesting_row;
766 name[5] = IFDATA_SUPPLEMENTAL;
767 if (sysctl(name, 6, &ifmsupp, &len, (void *)0, 0) == -1)
768 err(1, "sysctl IFDATA_SUPPLEMENTAL %d",
769 interesting_row);
770
771 if (!first) {
772 printf("%10llu %5llu %10llu ",
773 ifmd.ifmd_data.ifi_ipackets - interesting->ift_ip,
774 ifmd.ifmd_data.ifi_ierrors - interesting->ift_ie,
775 ifmd.ifmd_data.ifi_ibytes - interesting->ift_ib);
776 switch (prioflag) {
777 case SO_TC_BE:
778 printf("%10llu %10llu ",
779 ifmsupp.ifmd_traffic_class.ifi_ibepackets -
780 interesting->ift_itcp,
781 ifmsupp.ifmd_traffic_class.ifi_ibebytes -
782 interesting->ift_itcb);
783 break;
784 case SO_TC_BK:
785 printf("%10llu %10llu ",
786 ifmsupp.ifmd_traffic_class.ifi_ibkpackets -
787 interesting->ift_itcp,
788 ifmsupp.ifmd_traffic_class.ifi_ibkbytes -
789 interesting->ift_itcb);
790 break;
791 case SO_TC_VI:
792 printf("%10llu %10llu ",
793 ifmsupp.ifmd_traffic_class.ifi_ivipackets -
794 interesting->ift_itcp,
795 ifmsupp.ifmd_traffic_class.ifi_ivibytes -
796 interesting->ift_itcb);
797 break;
798 case SO_TC_VO:
799 printf("%10llu %10llu ",
800 ifmsupp.ifmd_traffic_class.ifi_ivopackets -
801 interesting->ift_itcp,
802 ifmsupp.ifmd_traffic_class.ifi_ivobytes -
803 interesting->ift_itcb);
804 break;
805 default:
806 break;
807 }
808 if (prioflag >= 0) {
809 printf("%10llu %10llu ",
810 ifmsupp.ifmd_traffic_class.ifi_ipvpackets -
811 interesting->ift_ipvp,
812 ifmsupp.ifmd_traffic_class.ifi_ipvbytes -
813 interesting->ift_ipvb);
814 }
815 printf("%10llu %5llu %10llu %5llu",
816 ifmd.ifmd_data.ifi_opackets - interesting->ift_op,
817 ifmd.ifmd_data.ifi_oerrors - interesting->ift_oe,
818 ifmd.ifmd_data.ifi_obytes - interesting->ift_ob,
819 ifmd.ifmd_data.ifi_collisions - interesting->ift_co);
820 if (dflag)
821 printf(" %5llu",
822 ifmd.ifmd_snd_drops - interesting->ift_dr);
823 switch (prioflag) {
824 case SO_TC_BE:
825 printf(" %10llu %10llu",
826 ifmsupp.ifmd_traffic_class.ifi_obepackets -
827 interesting->ift_otcp,
828 ifmsupp.ifmd_traffic_class.ifi_obebytes -
829 interesting->ift_otcb);
830 break;
831 case SO_TC_BK:
832 printf(" %10llu %10llu",
833 ifmsupp.ifmd_traffic_class.ifi_obkpackets -
834 interesting->ift_otcp,
835 ifmsupp.ifmd_traffic_class.ifi_obkbytes -
836 interesting->ift_otcb);
837 break;
838 case SO_TC_VI:
839 printf(" %10llu %10llu",
840 ifmsupp.ifmd_traffic_class.ifi_ovipackets -
841 interesting->ift_otcp,
842 ifmsupp.ifmd_traffic_class.ifi_ovibytes -
843 interesting->ift_otcb);
844 break;
845 case SO_TC_VO:
846 printf(" %10llu %10llu",
847 ifmsupp.ifmd_traffic_class.ifi_ovopackets -
848 interesting->ift_otcp,
849 ifmsupp.ifmd_traffic_class.ifi_ovobytes -
850 interesting->ift_otcb);
851 break;
852 default:
853 break;
854 }
855 if (prioflag >= 0) {
856 printf("%10llu %10llu ",
857 ifmsupp.ifmd_traffic_class.ifi_opvpackets -
858 interesting->ift_opvp,
859 ifmsupp.ifmd_traffic_class.ifi_opvbytes -
860 interesting->ift_opvb);
861 }
862 if (Fflag) {
863 printf("%10llu %10llu",
864 ifmsupp.ifmd_data_extended.ifi_fpackets -
865 interesting->ift_fp,
866 ifmsupp.ifmd_data_extended.ifi_fbytes -
867 interesting->ift_fb);
868 }
869 }
870 interesting->ift_ip = ifmd.ifmd_data.ifi_ipackets;
871 interesting->ift_ie = ifmd.ifmd_data.ifi_ierrors;
872 interesting->ift_ib = ifmd.ifmd_data.ifi_ibytes;
873 interesting->ift_op = ifmd.ifmd_data.ifi_opackets;
874 interesting->ift_oe = ifmd.ifmd_data.ifi_oerrors;
875 interesting->ift_ob = ifmd.ifmd_data.ifi_obytes;
876 interesting->ift_co = ifmd.ifmd_data.ifi_collisions;
877 interesting->ift_dr = ifmd.ifmd_snd_drops;
878
879 /* private counters */
880 switch (prioflag) {
881 case SO_TC_BE:
882 interesting->ift_itcp =
883 ifmsupp.ifmd_traffic_class.ifi_ibepackets;
884 interesting->ift_itcb =
885 ifmsupp.ifmd_traffic_class.ifi_ibebytes;
886 interesting->ift_otcp =
887 ifmsupp.ifmd_traffic_class.ifi_obepackets;
888 interesting->ift_otcb =
889 ifmsupp.ifmd_traffic_class.ifi_obebytes;
890 break;
891 case SO_TC_BK:
892 interesting->ift_itcp =
893 ifmsupp.ifmd_traffic_class.ifi_ibkpackets;
894 interesting->ift_itcb =
895 ifmsupp.ifmd_traffic_class.ifi_ibkbytes;
896 interesting->ift_otcp =
897 ifmsupp.ifmd_traffic_class.ifi_obkpackets;
898 interesting->ift_otcb =
899 ifmsupp.ifmd_traffic_class.ifi_obkbytes;
900 break;
901 case SO_TC_VI:
902 interesting->ift_itcp =
903 ifmsupp.ifmd_traffic_class.ifi_ivipackets;
904 interesting->ift_itcb =
905 ifmsupp.ifmd_traffic_class.ifi_ivibytes;
906 interesting->ift_otcp =
907 ifmsupp.ifmd_traffic_class.ifi_ovipackets;
908 interesting->ift_otcb =
909 ifmsupp.ifmd_traffic_class.ifi_ovibytes;
910 break;
911 case SO_TC_VO:
912 interesting->ift_itcp =
913 ifmsupp.ifmd_traffic_class.ifi_ivopackets;
914 interesting->ift_itcb =
915 ifmsupp.ifmd_traffic_class.ifi_ivobytes;
916 interesting->ift_otcp =
917 ifmsupp.ifmd_traffic_class.ifi_ovopackets;
918 interesting->ift_otcb =
919 ifmsupp.ifmd_traffic_class.ifi_ovobytes;
920 break;
921 default:
922 break;
923 }
924 if (prioflag >= 0) {
925 interesting->ift_ipvp =
926 ifmsupp.ifmd_traffic_class.ifi_ipvpackets;
927 interesting->ift_ipvb =
928 ifmsupp.ifmd_traffic_class.ifi_ipvbytes;
929 interesting->ift_opvp =
930 ifmsupp.ifmd_traffic_class.ifi_opvpackets;
931 interesting->ift_opvb =
932 ifmsupp.ifmd_traffic_class.ifi_opvbytes;
933 }
934 interesting->ift_fp = ifmsupp.ifmd_data_extended.ifi_fpackets;
935 interesting->ift_fb = ifmsupp.ifmd_data_extended.ifi_fbytes;
936 } else {
937 unsigned int latest_ifcount;
938 struct ifmibdata_supplemental *ifmsuppall = NULL;
939
940 len = sizeof(int);
941 name[3] = IFMIB_SYSTEM;
942 name[4] = IFMIB_IFCOUNT;
943 if (sysctl(name, 5, &latest_ifcount, &len, 0, 0) == 1)
944 err(1, "sysctl IFMIB_IFCOUNT");
945 if (latest_ifcount > ifcount) {
946 ifcount = latest_ifcount;
947 len = ifcount * sizeof(struct ifmibdata);
948 free(ifmdall);
949 ifmdall = malloc(len);
950 if (ifmdall == 0)
951 err(1, "malloc ifmdall failed");
952 } else if (latest_ifcount > ifcount) {
953 ifcount = latest_ifcount;
954 len = ifcount * sizeof(struct ifmibdata);
955 }
956 len = ifcount * sizeof(struct ifmibdata);
957 name[3] = IFMIB_IFALLDATA;
958 name[4] = 0;
959 name[5] = IFDATA_GENERAL;
960 if (sysctl(name, 6, ifmdall, &len, (void *)0, 0) == -1)
961 err(1, "sysctl IFMIB_IFALLDATA");
962
963 len = ifcount * sizeof(struct ifmibdata_supplemental);
964 ifmsuppall = malloc(len);
965 if (ifmsuppall == NULL)
966 err(1, "malloc ifmsuppall failed");
967 name[3] = IFMIB_IFALLDATA;
968 name[4] = 0;
969 name[5] = IFDATA_SUPPLEMENTAL;
970 if (sysctl(name, 6, ifmsuppall, &len, (void *)0, 0) == -1)
971 err(1, "sysctl IFMIB_IFALLDATA SUPPLEMENTAL");
972
973 sum->ift_ip = 0;
974 sum->ift_ie = 0;
975 sum->ift_ib = 0;
976 sum->ift_op = 0;
977 sum->ift_oe = 0;
978 sum->ift_ob = 0;
979 sum->ift_co = 0;
980 sum->ift_dr = 0;
981 sum->ift_itcp = 0;
982 sum->ift_itcb = 0;
983 sum->ift_otcp = 0;
984 sum->ift_otcb = 0;
985 sum->ift_ipvp = 0;
986 sum->ift_ipvb = 0;
987 sum->ift_opvp = 0;
988 sum->ift_opvb = 0;
989 sum->ift_fp = 0;
990 sum->ift_fb = 0;
991 for (i = 0; i < ifcount; i++) {
992 struct ifmibdata *ifmd = ifmdall + i;
993 struct ifmibdata_supplemental *ifmsupp = ifmsuppall + i;
994
995 sum->ift_ip += ifmd->ifmd_data.ifi_ipackets;
996 sum->ift_ie += ifmd->ifmd_data.ifi_ierrors;
997 sum->ift_ib += ifmd->ifmd_data.ifi_ibytes;
998 sum->ift_op += ifmd->ifmd_data.ifi_opackets;
999 sum->ift_oe += ifmd->ifmd_data.ifi_oerrors;
1000 sum->ift_ob += ifmd->ifmd_data.ifi_obytes;
1001 sum->ift_co += ifmd->ifmd_data.ifi_collisions;
1002 sum->ift_dr += ifmd->ifmd_snd_drops;
1003 /* private counters */
1004 if (prioflag >= 0) {
1005 switch (prioflag) {
1006 case SO_TC_BE:
1007 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ibepackets;
1008 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ibebytes;
1009 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_obepackets;
1010 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_obebytes;
1011 break;
1012 case SO_TC_BK:
1013 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ibkpackets;
1014 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ibkbytes;
1015 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_obkpackets;
1016 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_obkbytes;
1017 break;
1018 case SO_TC_VI:
1019 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ivipackets;
1020 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ivibytes;
1021 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_ovipackets;
1022 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_ovibytes;
1023 break;
1024 case SO_TC_VO:
1025 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ivopackets;
1026 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ivobytes;
1027 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_ovopackets;
1028 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_ovobytes;
1029 break;
1030 default:
1031 break;
1032 }
1033 sum->ift_ipvp += ifmsupp->ifmd_traffic_class.ifi_ipvpackets;
1034 sum->ift_ipvb += ifmsupp->ifmd_traffic_class.ifi_ipvbytes;
1035 sum->ift_opvp += ifmsupp->ifmd_traffic_class.ifi_opvpackets;
1036 sum->ift_opvb += ifmsupp->ifmd_traffic_class.ifi_opvbytes;
1037 }
1038 sum->ift_fp += ifmsupp->ifmd_data_extended.ifi_fpackets;
1039 sum->ift_fb += ifmsupp->ifmd_data_extended.ifi_fbytes;
1040 }
1041 if (!first) {
1042 printf("%10llu %5llu %10llu ",
1043 sum->ift_ip - total->ift_ip,
1044 sum->ift_ie - total->ift_ie,
1045 sum->ift_ib - total->ift_ib);
1046 if (prioflag >= 0)
1047 printf(" %10llu %10llu %10llu %10llu",
1048 sum->ift_itcp - total->ift_itcp,
1049 sum->ift_itcb - total->ift_itcb,
1050 sum->ift_ipvp - total->ift_ipvp,
1051 sum->ift_ipvb - total->ift_ipvb);
1052 printf("%10llu %5llu %10llu %5llu",
1053 sum->ift_op - total->ift_op,
1054 sum->ift_oe - total->ift_oe,
1055 sum->ift_ob - total->ift_ob,
1056 sum->ift_co - total->ift_co);
1057 if (dflag)
1058 printf(" %5llu", sum->ift_dr - total->ift_dr);
1059 if (prioflag >= 0)
1060 printf(" %10llu %10llu %10llu %10llu",
1061 sum->ift_otcp - total->ift_otcp,
1062 sum->ift_otcb - total->ift_otcb,
1063 sum->ift_opvp - total->ift_opvp,
1064 sum->ift_opvb - total->ift_opvb);
1065 if (Fflag)
1066 printf(" %10llu %10llu",
1067 sum->ift_fp - total->ift_fp,
1068 sum->ift_fb - total->ift_fb);
1069 }
1070 *total = *sum;
1071 }
1072 if (!first)
1073 putchar('\n');
1074 fflush(stdout);
1075 sigemptyset(&sigset);
1076 sigaddset(&sigset, SIGALRM);
1077 (void)sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
1078 if (!signalled) {
1079 sigemptyset(&sigset);
1080 sigsuspend(&sigset);
1081 }
1082 (void)sigprocmask(SIG_SETMASK, &oldsigset, NULL);
1083
1084 signalled = NO;
1085 line++;
1086 first = 0;
1087 if (line == 21)
1088 goto banner;
1089 else
1090 goto loop;
1091 /*NOTREACHED*/
1092 }
1093
1094 void
1095 intervalpr(void (*pr)(uint32_t, char *, int), uint32_t off, char *name , int af)
1096 {
1097 struct itimerval timer_interval;
1098 sigset_t sigset, oldsigset;
1099
1100 /* create a timer that fires repeatedly every interval seconds */
1101 timer_interval.it_value.tv_sec = interval;
1102 timer_interval.it_value.tv_usec = 0;
1103 timer_interval.it_interval.tv_sec = interval;
1104 timer_interval.it_interval.tv_usec = 0;
1105 (void) signal(SIGALRM, catchalarm);
1106 signalled = NO;
1107 (void) setitimer(ITIMER_REAL, &timer_interval, NULL);
1108
1109 for (;;) {
1110 pr(off, name, af);
1111
1112 fflush(stdout);
1113 sigemptyset(&sigset);
1114 sigaddset(&sigset, SIGALRM);
1115 (void) sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
1116 if (!signalled) {
1117 sigemptyset(&sigset);
1118 sigsuspend(&sigset);
1119 }
1120 (void) sigprocmask(SIG_SETMASK, &oldsigset, NULL);
1121 signalled = NO;
1122 }
1123 }
1124
1125 /*
1126 * Called if an interval expires before sidewaysintpr has completed a loop.
1127 * Sets a flag to not wait for the alarm.
1128 */
1129 static void
1130 catchalarm(int signo )
1131 {
1132 signalled = YES;
1133 }
1134
1135 static char *
1136 sec2str(total)
1137 time_t total;
1138 {
1139 static char result[256];
1140 int days, hours, mins, secs;
1141 int first = 1;
1142 char *p = result;
1143
1144 days = total / 3600 / 24;
1145 hours = (total / 3600) % 24;
1146 mins = (total / 60) % 60;
1147 secs = total % 60;
1148
1149 if (days) {
1150 first = 0;
1151 p += snprintf(p, sizeof(result) - (p - result), "%dd", days);
1152 }
1153 if (!first || hours) {
1154 first = 0;
1155 p += snprintf(p, sizeof(result) - (p - result), "%dh", hours);
1156 }
1157 if (!first || mins) {
1158 first = 0;
1159 p += snprintf(p, sizeof(result) - (p - result), "%dm", mins);
1160 }
1161 snprintf(p, sizeof(result) - (p - result), "%ds", secs);
1162
1163 return(result);
1164 }
1165
1166 void
1167 intpr_ri(void (*pfunc)(char *))
1168 {
1169 int mib[6];
1170 char *buf = NULL, *lim, *next;
1171 size_t len;
1172 unsigned int ifindex = 0;
1173 struct if_msghdr2 *if2m;
1174
1175 if (interface != 0) {
1176 ifindex = if_nametoindex(interface);
1177 if (ifindex == 0) {
1178 printf("interface name is not valid: %s\n", interface);
1179 exit(1);
1180 }
1181 }
1182
1183 mib[0] = CTL_NET; /* networking subsystem */
1184 mib[1] = PF_ROUTE; /* type of information */
1185 mib[2] = 0; /* protocol (IPPROTO_xxx) */
1186 mib[3] = 0; /* address family */
1187 mib[4] = NET_RT_IFLIST2; /* operation */
1188 mib[5] = 0;
1189 if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
1190 return;
1191 if ((buf = malloc(len)) == NULL) {
1192 printf("malloc failed\n");
1193 exit(1);
1194 }
1195 if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
1196 free(buf);
1197 return;
1198 }
1199
1200 printf("%-6s %-17s %8.8s %-9.9s %4s %4s",
1201 "Proto", "Linklayer Address", "Netif", "Expire", "Refs",
1202 "Prbs");
1203 if (xflag)
1204 printf(" %7s %7s %7s", "RSSI", "LQM", "NPM");
1205 printf("\n");
1206
1207 lim = buf + len;
1208 if2m = (struct if_msghdr2 *)buf;
1209
1210 for (next = buf; next < lim; ) {
1211 if2m = (struct if_msghdr2 *)next;
1212 next += if2m->ifm_msglen;
1213
1214 if (if2m->ifm_type != RTM_IFINFO2)
1215 continue;
1216 else if (interface != 0 && if2m->ifm_index != ifindex)
1217 continue;
1218
1219 llreach_sysctl(if2m->ifm_index);
1220 }
1221 free(buf);
1222 }
1223
1224 static void
1225 llreach_sysctl(uint32_t ifindex)
1226 {
1227 #define MAX_SYSCTL_TRY 5
1228 int mib[6], i, ntry = 0;
1229 size_t mibsize, len, needed, cnt;
1230 struct if_llreach_info *lri;
1231 struct timeval time;
1232 char *buf;
1233 char ifname[IF_NAMESIZE];
1234
1235 bzero(&mib, sizeof (mib));
1236 mibsize = sizeof (mib) / sizeof (mib[0]);
1237 if (sysctlnametomib("net.link.generic.system.llreach_info", mib,
1238 &mibsize) == -1) {
1239 perror("sysctlnametomib");
1240 return;
1241 }
1242
1243 needed = 0;
1244 mib[5] = ifindex;
1245
1246 mibsize = sizeof (mib) / sizeof (mib[0]);
1247 do {
1248 if (sysctl(mib, mibsize, NULL, &needed, NULL, 0) == -1) {
1249 perror("sysctl net.link.generic.system.llreach_info");
1250 return;
1251 }
1252 if ((buf = malloc(needed)) == NULL) {
1253 perror("malloc");
1254 return;
1255 }
1256 if (sysctl(mib, mibsize, buf, &needed, NULL, 0) == -1) {
1257 if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
1258 perror("sysctl");
1259 goto out_free;
1260 }
1261 free(buf);
1262 buf = NULL;
1263 }
1264 } while (buf == NULL);
1265
1266 len = needed;
1267 cnt = len / sizeof (*lri);
1268 lri = (struct if_llreach_info *)buf;
1269
1270 gettimeofday(&time, 0);
1271 if (if_indextoname(ifindex, ifname) == NULL)
1272 snprintf(ifname, sizeof (ifname), "%s", "?");
1273
1274 for (i = 0; i < cnt; i++, lri++) {
1275 printf("0x%-4x %-17s %8.8s ", lri->lri_proto,
1276 ether_ntoa((struct ether_addr *)lri->lri_addr), ifname);
1277
1278 if (lri->lri_expire > time.tv_sec)
1279 printf("%-9.9s", sec2str(lri->lri_expire - time.tv_sec));
1280 else if (lri->lri_expire == 0)
1281 printf("%-9.9s", "permanent");
1282 else
1283 printf("%-9.9s", "expired");
1284
1285 printf(" %4d", lri->lri_refcnt);
1286 if (lri->lri_probes)
1287 printf(" %4d", lri->lri_probes);
1288
1289 if (xflag) {
1290 if (!lri->lri_probes)
1291 printf(" %-4.4s", "none");
1292
1293 if (lri->lri_rssi != IFNET_RSSI_UNKNOWN)
1294 printf(" %7d", lri->lri_rssi);
1295 else
1296 printf(" %-7.7s", "unknown");
1297
1298 switch (lri->lri_lqm)
1299 {
1300 case IFNET_LQM_THRESH_OFF:
1301 printf(" %-7.7s", "off");
1302 break;
1303 case IFNET_LQM_THRESH_UNKNOWN:
1304 printf(" %-7.7s", "unknown");
1305 break;
1306 case IFNET_LQM_THRESH_POOR:
1307 printf(" %-7.7s", "poor");
1308 break;
1309 case IFNET_LQM_THRESH_GOOD:
1310 printf(" %-7.7s", "good");
1311 break;
1312 default:
1313 printf(" %7d", lri->lri_lqm);
1314 break;
1315 }
1316
1317 switch (lri->lri_npm)
1318 {
1319 case IFNET_NPM_THRESH_UNKNOWN:
1320 printf(" %-7.7s", "unknown");
1321 break;
1322 case IFNET_NPM_THRESH_NEAR:
1323 printf(" %-7.7s", "near");
1324 break;
1325 case IFNET_NPM_THRESH_GENERAL:
1326 printf(" %-7.7s", "general");
1327 break;
1328 case IFNET_NPM_THRESH_FAR:
1329 printf(" %-7.7s", "far");
1330 break;
1331 default:
1332 printf(" %7d", lri->lri_npm);
1333 break;
1334 }
1335 }
1336
1337 printf("\n");
1338 len -= sizeof (*lri);
1339 }
1340
1341 if (len > 0) {
1342 fprintf(stderr, "warning: %u trailing bytes from %s\n",
1343 (unsigned int)len, "net.link.generic.system.llreach_info");
1344 }
1345
1346 out_free:
1347 free(buf);
1348 #undef MAX_SYSCTL_TRY
1349 }
1350
1351 void
1352 aqstatpr(void)
1353 {
1354 unsigned int ifindex;
1355 struct itimerval timer_interval;
1356 struct if_qstatsreq ifqr;
1357 struct if_ifclassq_stats *ifcqs;
1358 sigset_t sigset, oldsigset;
1359 u_int32_t scheduler;
1360 int s, n, tcq = 0;
1361
1362 if (cq < -1 || cq >= IFCQ_SC_MAX) {
1363 fprintf(stderr, "Invalid classq index (range is 0-%d)\n",
1364 IFCQ_SC_MAX-1);
1365 return;
1366 }
1367 ifindex = if_nametoindex(interface);
1368 if (ifindex == 0) {
1369 fprintf(stderr, "Invalid interface name\n");
1370 return;
1371 }
1372
1373 ifcqs = malloc(sizeof (*ifcqs));
1374 if (ifcqs == NULL) {
1375 fprintf(stderr, "Unable to allocate memory\n");
1376 return;
1377 }
1378
1379 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1380 perror("Warning: socket(AF_INET)");
1381 free(ifcqs);
1382 return;
1383 }
1384
1385 bzero(&ifqr, sizeof (ifqr));
1386 strlcpy(ifqr.ifqr_name, interface, sizeof (ifqr.ifqr_name));
1387 ifqr.ifqr_buf = ifcqs;
1388 ifqr.ifqr_len = sizeof (*ifcqs);
1389
1390 loop:
1391 if (interval > 0) {
1392 /* create a timer that fires repeatedly every interval seconds */
1393 timer_interval.it_value.tv_sec = interval;
1394 timer_interval.it_value.tv_usec = 0;
1395 timer_interval.it_interval.tv_sec = interval;
1396 timer_interval.it_interval.tv_usec = 0;
1397 (void) signal(SIGALRM, catchalarm);
1398 signalled = NO;
1399 (void) setitimer(ITIMER_REAL, &timer_interval, NULL);
1400 }
1401
1402 ifqr.ifqr_slot = 0;
1403 if (ioctl(s, SIOCGIFQUEUESTATS, (char *)&ifqr) < 0) {
1404 if (errno == ENXIO) {
1405 printf("Queue statistics are not available on %s\n",
1406 interface);
1407 } else {
1408 perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
1409 }
1410 goto done;
1411 }
1412 scheduler = ifcqs->ifqs_scheduler;
1413 tcq = (scheduler == PKTSCHEDT_TCQ);
1414
1415 printf("%s:\n"
1416 "%s [ sched: %9s %sqlength: %3d/%3d ]\n",
1417 interface, tcq ? " " : "", sched2str(ifcqs->ifqs_scheduler),
1418 tcq ? "" : " ", ifcqs->ifqs_len, ifcqs->ifqs_maxlen);
1419 printf("%s [ pkts: %10llu %sbytes: %10llu "
1420 "%sdropped pkts: %6llu bytes: %6llu ]\n",
1421 (scheduler != PKTSCHEDT_TCQ) ? "" : " ",
1422 ifcqs->ifqs_xmitcnt.packets, tcq ? "" : " ",
1423 ifcqs->ifqs_xmitcnt.bytes, tcq ? "" : " ",
1424 ifcqs->ifqs_dropcnt.packets, ifcqs->ifqs_dropcnt.bytes);
1425
1426 for (n = 0; n < IFCQ_SC_MAX; n++) {
1427 qstats[n].printed = 0;
1428 if (!tcq)
1429 continue;
1430 ifqr.ifqr_slot = n;
1431 if (ioctl(s, SIOCGIFQUEUESTATS, (char *)&ifqr) < 0) {
1432 perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
1433 goto done;
1434 }
1435 qstats[n].handle = ifcqs->ifqs_tcq_stats.class_handle;
1436 }
1437
1438 for (n = 0; n < IFCQ_SC_MAX && scheduler != PKTSCHEDT_NONE; n++) {
1439 if (cq >= 0 && cq != n)
1440 continue;
1441
1442 ifqr.ifqr_slot = n;
1443 if (ioctl(s, SIOCGIFQUEUESTATS, (char *)&ifqr) < 0) {
1444 perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
1445 goto done;
1446 }
1447
1448 update_avg(ifcqs, &qstats[n]);
1449
1450 switch (scheduler) {
1451 case PKTSCHEDT_CBQ:
1452 print_cbqstats(n, &ifcqs->ifqs_cbq_stats,
1453 &qstats[n]);
1454 break;
1455 case PKTSCHEDT_HFSC:
1456 print_hfscstats(n, &ifcqs->ifqs_hfsc_stats,
1457 &qstats[n]);
1458 break;
1459 case PKTSCHEDT_PRIQ:
1460 print_priqstats(n, &ifcqs->ifqs_priq_stats,
1461 &qstats[n]);
1462 break;
1463 case PKTSCHEDT_FAIRQ:
1464 print_fairqstats(n, &ifcqs->ifqs_fairq_stats,
1465 &qstats[n]);
1466 break;
1467 case PKTSCHEDT_TCQ:
1468 print_tcqstats(n, &ifcqs->ifqs_tcq_stats,
1469 &qstats[n]);
1470 break;
1471 case PKTSCHEDT_QFQ:
1472 print_qfqstats(n, &ifcqs->ifqs_qfq_stats,
1473 &qstats[n]);
1474 break;
1475 case PKTSCHEDT_NONE:
1476 default:
1477 break;
1478 }
1479 }
1480
1481 fflush(stdout);
1482
1483 if (interval > 0) {
1484 sigemptyset(&sigset);
1485 sigaddset(&sigset, SIGALRM);
1486 (void) sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
1487 if (!signalled) {
1488 sigemptyset(&sigset);
1489 sigsuspend(&sigset);
1490 }
1491 (void) sigprocmask(SIG_SETMASK, &oldsigset, NULL);
1492
1493 signalled = NO;
1494 goto loop;
1495 }
1496
1497 done:
1498 free(ifcqs);
1499 close(s);
1500 }
1501
1502 static void
1503 print_cbqstats(int slot, struct cbq_classstats *cs, struct queue_stats *qs)
1504 {
1505 printf(" %2d: [ pkts: %10llu bytes: %10llu "
1506 "dropped pkts: %6llu bytes: %6llu ]\n", slot,
1507 (unsigned long long)cs->xmit_cnt.packets,
1508 (unsigned long long)cs->xmit_cnt.bytes,
1509 (unsigned long long)cs->drop_cnt.packets,
1510 (unsigned long long)cs->drop_cnt.bytes);
1511 printf(" [ qlength: %3d/%3d borrows: %6u "
1512 "suspends: %6u qalg: %s ]\n", cs->qcnt, cs->qmax,
1513 cs->borrows, cs->delays, qtype2str(cs->qtype));
1514 printf(" [ service class: %5s ]\n", qid2str(cs->handle));
1515
1516 if (qs->avgn >= 2) {
1517 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1518 qs->avg_packets / interval,
1519 rate2str((8 * qs->avg_bytes) / interval));
1520 }
1521
1522 if (qflag < 2)
1523 return;
1524
1525 switch (cs->qtype) {
1526 case Q_SFB:
1527 print_sfbstats(&cs->sfb);
1528 break;
1529 default:
1530 break;
1531 }
1532 }
1533
1534 static void
1535 print_priqstats(int slot, struct priq_classstats *cs, struct queue_stats *qs)
1536 {
1537 printf(" %2d: [ pkts: %10llu bytes: %10llu "
1538 "dropped pkts: %6llu bytes: %6llu ]\n", slot,
1539 (unsigned long long)cs->xmitcnt.packets,
1540 (unsigned long long)cs->xmitcnt.bytes,
1541 (unsigned long long)cs->dropcnt.packets,
1542 (unsigned long long)cs->dropcnt.bytes);
1543 printf(" [ qlength: %3d/%3d qalg: %11s service class: %5s ]\n",
1544 cs->qlength, cs->qlimit, qtype2str(cs->qtype),
1545 qid2str(cs->class_handle));
1546
1547 if (qs->avgn >= 2) {
1548 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1549 qs->avg_packets / interval,
1550 rate2str((8 * qs->avg_bytes) / interval));
1551 }
1552
1553 if (qflag < 2)
1554 return;
1555
1556 switch (cs->qtype) {
1557 case Q_SFB:
1558 print_sfbstats(&cs->sfb);
1559 break;
1560 default:
1561 break;
1562 }
1563 }
1564
1565 static void
1566 print_hfscstats(int slot, struct hfsc_classstats *cs, struct queue_stats *qs)
1567 {
1568 printf(" %2d: [ pkts: %10llu bytes: %10llu "
1569 "dropped pkts: %6llu bytes: %6llu ]\n", slot,
1570 (unsigned long long)cs->xmit_cnt.packets,
1571 (unsigned long long)cs->xmit_cnt.bytes,
1572 (unsigned long long)cs->drop_cnt.packets,
1573 (unsigned long long)cs->drop_cnt.bytes);
1574 printf(" [ qlength: %3d/%3d qalg: %11s service class: %5s ]\n",
1575 cs->qlength, cs->qlimit, qtype2str(cs->qtype),
1576 qid2str(cs->class_handle));
1577
1578 if (qs->avgn >= 2) {
1579 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1580 qs->avg_packets / interval,
1581 rate2str((8 * qs->avg_bytes) / interval));
1582 }
1583
1584 if (qflag < 2)
1585 return;
1586
1587 switch (cs->qtype) {
1588 case Q_SFB:
1589 print_sfbstats(&cs->sfb);
1590 break;
1591 default:
1592 break;
1593 }
1594 }
1595
1596 static void
1597 print_fairqstats(int slot, struct fairq_classstats *cs, struct queue_stats *qs)
1598 {
1599 printf(" %2d: [ pkts: %10llu bytes: %10llu "
1600 "dropped pkts: %6llu bytes: %6llu ]\n", slot,
1601 (unsigned long long)cs->xmit_cnt.packets,
1602 (unsigned long long)cs->xmit_cnt.bytes,
1603 (unsigned long long)cs->drop_cnt.packets,
1604 (unsigned long long)cs->drop_cnt.bytes);
1605 printf(" [ qlength: %3d/%3d qalg: %11s service class: %5s ]]\n",
1606 cs->qlength, cs->qlimit, qtype2str(cs->qtype),
1607 qid2str(cs->class_handle));
1608
1609 if (qs->avgn >= 2) {
1610 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1611 qs->avg_packets / interval,
1612 rate2str((8 * qs->avg_bytes) / interval));
1613 }
1614
1615 if (qflag < 2)
1616 return;
1617
1618 switch (cs->qtype) {
1619 case Q_SFB:
1620 print_sfbstats(&cs->sfb);
1621 break;
1622 default:
1623 break;
1624 }
1625 }
1626
1627 static void
1628 print_tcqstats(int slot, struct tcq_classstats *cs, struct queue_stats *qs)
1629 {
1630 int n;
1631
1632 if (qs->printed)
1633 return;
1634
1635 qs->handle = cs->class_handle;
1636 qs->printed++;
1637
1638 for (n = 0; n < IFCQ_SC_MAX; n++) {
1639 if (&qstats[n] != qs && qstats[n].handle == qs->handle)
1640 qstats[n].printed++;
1641 }
1642
1643 printf("%5s: [ pkts: %10llu bytes: %10llu "
1644 "dropped pkts: %6llu bytes: %6llu ]\n", tcqslot2str(slot),
1645 (unsigned long long)cs->xmitcnt.packets,
1646 (unsigned long long)cs->xmitcnt.bytes,
1647 (unsigned long long)cs->dropcnt.packets,
1648 (unsigned long long)cs->dropcnt.bytes);
1649 printf(" [ qlength: %3d/%3d qalg: %11s "
1650 "svc class: %9s %-13s ]\n", cs->qlength, cs->qlimit,
1651 qtype2str(cs->qtype), qid2str(cs->class_handle),
1652 qstate2str(cs->qstate));
1653
1654 if (qs->avgn >= 2) {
1655 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1656 qs->avg_packets / interval,
1657 rate2str((8 * qs->avg_bytes) / interval));
1658 }
1659
1660 if (qflag < 2)
1661 return;
1662
1663 switch (cs->qtype) {
1664 case Q_SFB:
1665 print_sfbstats(&cs->sfb);
1666 break;
1667 default:
1668 break;
1669 }
1670 }
1671
1672 static void
1673 print_qfqstats(int slot, struct qfq_classstats *cs, struct queue_stats *qs)
1674 {
1675 printf(" %2d: [ pkts: %10llu bytes: %10llu "
1676 "dropped pkts: %6llu bytes: %6llu ]\n", slot,
1677 (unsigned long long)cs->xmitcnt.packets,
1678 (unsigned long long)cs->xmitcnt.bytes,
1679 (unsigned long long)cs->dropcnt.packets,
1680 (unsigned long long)cs->dropcnt.bytes);
1681 printf(" [ qlength: %3d/%3d index: %10u weight: %12u "
1682 "lmax: %7u ]\n", cs->qlength, cs->qlimit, cs->index,
1683 cs->weight, cs->lmax);
1684 printf(" [ qalg: %10s svc class: %6s %-35s ]\n",
1685 qtype2str(cs->qtype), qid2str(cs->class_handle),
1686 qstate2str(cs->qstate));
1687
1688 if (qs->avgn >= 2) {
1689 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1690 qs->avg_packets / interval,
1691 rate2str((8 * qs->avg_bytes) / interval));
1692 }
1693
1694 if (qflag < 2)
1695 return;
1696
1697 switch (cs->qtype) {
1698 case Q_SFB:
1699 print_sfbstats(&cs->sfb);
1700 break;
1701 default:
1702 break;
1703 }
1704 }
1705
1706 static void
1707 print_sfbstats(struct sfb_stats *sfb)
1708 {
1709 struct sfbstats *sp = &sfb->sfbstats;
1710 int i, j, cur = sfb->current;
1711
1712 printf("\n");
1713 printf(" [ early drop: %12llu rlimit drop: %11llu "
1714 "marked: %11llu ]\n",
1715 sp->drop_early, sp->drop_pbox, sp->marked_packets);
1716 printf(" [ penalized: %13llu rehash cnt: %12llu "
1717 "current: %10u ]\n", sp->pbox_packets, sp->num_rehash, cur);
1718 printf(" [ deque avg: %13s ", nsec_to_str(sp->dequeue_avg));
1719 printf("rehash intvl: %11s]\n", nsec_to_str(sp->rehash_intval));
1720 printf(" [ holdtime: %14s ", nsec_to_str(sp->hold_time));
1721 printf("pboxtime: %14s ]\n", nsec_to_str(sp->pbox_time));
1722 printf(" [ allocation: %12u drop thresh: %11u ]\n",
1723 sfb->allocation, sfb->dropthresh);
1724 printf(" [ flow controlled: %7llu adv feedback: %10llu ]\n",
1725 sp->flow_controlled, sp->flow_feedback);
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 }