]> git.saurik.com Git - apple/network_cmds.git/blob - netstat.tproj/if.c
network_cmds-396.6.tar.gz
[apple/network_cmds.git] / netstat.tproj / if.c
1 /*
2 * Copyright (c) 2008-2012 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 uint32_t mtu = 0;
277 short timer = 0;
278 int drops = 0;
279 struct sockaddr *sa = NULL;
280 char name[32];
281 short network_layer;
282 short link_layer;
283 int mib[6];
284 char *buf = NULL, *lim, *next;
285 size_t len;
286 struct if_msghdr *ifm;
287 struct sockaddr *rti_info[RTAX_MAX];
288 unsigned int ifindex = 0;
289
290 if (interval) {
291 sidewaysintpr();
292 return;
293 }
294
295 if (interface != 0)
296 ifindex = if_nametoindex(interface);
297
298 mib[0] = CTL_NET; // networking subsystem
299 mib[1] = PF_ROUTE; // type of information
300 mib[2] = 0; // protocol (IPPROTO_xxx)
301 mib[3] = 0; // address family
302 mib[4] = NET_RT_IFLIST2; // operation
303 mib[5] = 0;
304 if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
305 return;
306 if ((buf = malloc(len)) == NULL) {
307 printf("malloc failed\n");
308 exit(1);
309 }
310 if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
311 if (buf)
312 free(buf);
313 return;
314 }
315
316 if (!pfunc) {
317 printf("%-5.5s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
318 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
319 if (prioflag >= 0)
320 printf(" %8.8s %8.8s", "Itcpkts", "Ipvpkts");
321 if (bflag) {
322 printf(" %10.10s","Ibytes");
323 if (prioflag >= 0)
324 printf(" %8.8s %8.8s", "Itcbytes", "Ipvbytes");
325 }
326 printf(" %8.8s %5.5s", "Opkts", "Oerrs");
327 if (prioflag >= 0)
328 printf(" %8.8s %8.8s", "Otcpkts", "Opvpkts");
329 if (bflag) {
330 printf(" %10.10s","Obytes");
331 if (prioflag >= 0)
332 printf(" %8.8s %8.8s", "Otcbytes", "Opvbytes");
333 }
334 printf(" %5s", "Coll");
335 if (tflag)
336 printf(" %s", "Time");
337 if (dflag)
338 printf(" %s", "Drop");
339 putchar('\n');
340 }
341 lim = buf + len;
342 for (next = buf; next < lim; ) {
343 char *cp;
344 int n, m;
345 struct ifmibdata_supplemental ifmsupp;
346 u_int64_t ift_itcp = 0; /* input tc packets */
347 u_int64_t ift_itcb = 0; /* input tc bytes */
348 u_int64_t ift_otcp = 0; /* output tc packets */
349 u_int64_t ift_otcb = 0; /* output tc bytes */
350 u_int64_t ift_ipvp = 0; /* input priv tc packets */
351 u_int64_t ift_ipvb = 0; /* input priv tc bytes */
352 u_int64_t ift_opvp = 0; /* output priv tc packets */
353 u_int64_t ift_opvb = 0; /* output priv tc bytes */
354
355 bzero(&ifmsupp, sizeof(struct ifmibdata_supplemental));
356
357 network_layer = 0;
358 link_layer = 0;
359 ifm = (struct if_msghdr *)next;
360 next += ifm->ifm_msglen;
361
362 if (ifm->ifm_type == RTM_IFINFO2) {
363 struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm;
364 struct sockaddr_dl *sdl = (struct sockaddr_dl *)(if2m + 1);
365
366 strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
367 name[sdl->sdl_nlen] = 0;
368 if (interface != 0 && if2m->ifm_index != ifindex)
369 continue;
370 cp = index(name, '\0');
371
372 if (pfunc) {
373 (*pfunc)(name);
374 continue;
375 }
376
377 if ((if2m->ifm_flags & IFF_UP) == 0)
378 *cp++ = '*';
379 *cp = '\0';
380
381 /*
382 * Get the interface stats. These may get
383 * overriden below on a per-interface basis.
384 */
385 opackets = if2m->ifm_data.ifi_opackets;
386 ipackets = if2m->ifm_data.ifi_ipackets;
387 obytes = if2m->ifm_data.ifi_obytes;
388 ibytes = if2m->ifm_data.ifi_ibytes;
389 oerrors =if2m->ifm_data.ifi_oerrors;
390 ierrors = if2m->ifm_data.ifi_ierrors;
391 collisions = if2m->ifm_data.ifi_collisions;
392 timer = if2m->ifm_timer;
393 drops = if2m->ifm_snd_drops;
394 mtu = if2m->ifm_data.ifi_mtu;
395
396 if (prioflag >= 0) {
397 int name[6];
398 size_t miblen = sizeof(struct ifmibdata_supplemental);
399
400 /* Common OID prefix */
401 name[0] = CTL_NET;
402 name[1] = PF_LINK;
403 name[2] = NETLINK_GENERIC;
404 name[3] = IFMIB_IFDATA;
405 name[4] = if2m->ifm_index;
406 name[5] = IFDATA_SUPPLEMENTAL;
407 if (sysctl(name, 6, &ifmsupp, &miblen, (void *)0, 0) == -1)
408 err(1, "sysctl IFDATA_SUPPLEMENTAL");
409
410 switch (prioflag) {
411 case SO_TC_BE:
412 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ibepackets;
413 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ibebytes;
414 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_obepackets;
415 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_obebytes;
416 break;
417 case SO_TC_BK:
418 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ibkpackets;
419 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ibkbytes;
420 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_obkpackets;
421 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_obkbytes;
422 break;
423 case SO_TC_VI:
424 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ivipackets;
425 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ivibytes;
426 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_ovipackets;
427 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_ovibytes;
428 break;
429 case SO_TC_VO:
430 ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ivopackets;
431 ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ivobytes;
432 ift_otcp = ifmsupp.ifmd_traffic_class.ifi_ovopackets;
433 ift_otcb = ifmsupp.ifmd_traffic_class.ifi_ovobytes;
434 break;
435 default:
436 ift_itcp = 0;
437 ift_itcb = 0;
438 ift_otcp = 0;
439 ift_otcb = 0;
440 ift_ipvp = 0;
441 ift_ipvb = 0;
442 ift_opvp = 0;
443 ift_opvb = 0;
444 break;
445 }
446 ift_ipvp = ifmsupp.ifmd_traffic_class.ifi_ipvpackets;
447 ift_ipvb = ifmsupp.ifmd_traffic_class.ifi_ipvbytes;
448 ift_opvp = ifmsupp.ifmd_traffic_class.ifi_opvpackets;
449 ift_opvb = ifmsupp.ifmd_traffic_class.ifi_opvbytes;
450 }
451
452 get_rti_info(if2m->ifm_addrs, (struct sockaddr*)(if2m + 1), rti_info);
453 sa = rti_info[RTAX_IFP];
454 } else if (ifm->ifm_type == RTM_NEWADDR) {
455 struct ifa_msghdr *ifam = (struct ifa_msghdr *)ifm;
456
457 if (interface != 0 && ifam->ifam_index != ifindex)
458 continue;
459 get_rti_info(ifam->ifam_addrs, (struct sockaddr*)(ifam + 1), rti_info);
460 sa = rti_info[RTAX_IFA];
461 } else {
462 continue;
463 }
464 printf("%-5.5s %-5u ", name, mtu);
465
466 if (sa == 0) {
467 printf("%-13.13s ", "none");
468 printf("%-15.15s ", "none");
469 } else {
470 switch (sa->sa_family) {
471 case AF_UNSPEC:
472 printf("%-13.13s ", "none");
473 printf("%-15.15s ", "none");
474 break;
475
476 case AF_INET: {
477 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
478 struct sockaddr_in mask;
479
480 mask.sin_addr.s_addr = 0;
481 memcpy(&mask,
482 rti_info[RTAX_NETMASK],
483 ((struct sockaddr_in *)rti_info[RTAX_NETMASK])->sin_len);
484
485 printf("%-13.13s ",
486 netname(sin->sin_addr.s_addr & mask.sin_addr.s_addr,
487 ntohl(mask.sin_addr.s_addr)));
488
489 printf("%-15.15s ",
490 routename(sin->sin_addr.s_addr));
491
492 network_layer = 1;
493 break;
494 }
495 #ifdef INET6
496 case AF_INET6: {
497 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
498 struct sockaddr *mask = (struct sockaddr *)rti_info[RTAX_NETMASK];
499
500 printf("%-11.11s ",
501 netname6(sin6,
502 mask));
503 printf("%-17.17s ",
504 (char *)inet_ntop(AF_INET6,
505 &sin6->sin6_addr,
506 ntop_buf, sizeof(ntop_buf)));
507
508 network_layer = 1;
509 break;
510 }
511 #endif /*INET6*/
512 case AF_LINK: {
513 struct sockaddr_dl *sdl =
514 (struct sockaddr_dl *)sa;
515 char linknum[10];
516 cp = (char *)LLADDR(sdl);
517 n = sdl->sdl_alen;
518 snprintf(linknum, sizeof(linknum), "<Link#%d>", sdl->sdl_index);
519 m = printf("%-11.11s ", linknum);
520 goto hexprint;
521 }
522
523 default:
524 m = printf("(%d)", sa->sa_family);
525 for (cp = sa->sa_len + (char *)sa;
526 --cp > sa->sa_data && (*cp == 0);) {}
527 n = cp - sa->sa_data + 1;
528 cp = sa->sa_data;
529 hexprint:
530 while (--n >= 0)
531 m += printf("%02x%c", *cp++ & 0xff,
532 n > 0 ? ':' : ' ');
533 m = 30 - m;
534 while (m-- > 0)
535 putchar(' ');
536
537 link_layer = 1;
538 break;
539 }
540 }
541
542 show_stat("llu", 8, ipackets, link_layer|network_layer);
543 printf(" ");
544 show_stat("llu", 5, ierrors, link_layer);
545 printf(" ");
546 if (prioflag >= 0) {
547 show_stat("llu", 8, ift_itcp, link_layer|network_layer);
548 printf(" ");
549 show_stat("llu", 8, ift_ipvp, link_layer|network_layer);
550 printf(" ");
551 }
552 if (bflag) {
553 show_stat("llu", 10, ibytes, link_layer|network_layer);
554 printf(" ");
555 if (prioflag >= 0) {
556 show_stat("llu", 8, ift_itcb, link_layer|network_layer);
557 printf(" ");
558 show_stat("llu", 8, ift_ipvb, link_layer|network_layer);
559 printf(" ");
560 }
561 }
562 show_stat("llu", 8, opackets, link_layer|network_layer);
563 printf(" ");
564 show_stat("llu", 5, oerrors, link_layer);
565 printf(" ");
566 if (prioflag >= 0) {
567 show_stat("llu", 8, ift_otcp, link_layer|network_layer);
568 printf(" ");
569 show_stat("llu", 8, ift_opvp, link_layer|network_layer);
570 printf(" ");
571 }
572 if (bflag) {
573 show_stat("llu", 10, obytes, link_layer|network_layer);
574 printf(" ");
575 if (prioflag >= 0) {
576 show_stat("llu", 8, ift_otcb, link_layer|network_layer);
577 printf(" ");
578 show_stat("llu", 8, ift_opvb, link_layer|network_layer);
579 printf(" ");
580 }
581 }
582 show_stat("llu", 5, collisions, link_layer);
583 if (tflag) {
584 printf(" ");
585 show_stat("ll", 3, timer, link_layer);
586 }
587 if (dflag) {
588 printf(" ");
589 show_stat("ll", 3, drops, link_layer);
590 }
591 putchar('\n');
592
593 if (aflag)
594 multipr(sa->sa_family, next, lim);
595 }
596 free(buf);
597 }
598
599 struct iftot {
600 SLIST_ENTRY(iftot) chain;
601 char ift_name[16]; /* interface name */
602 u_int64_t ift_ip; /* input packets */
603 u_int64_t ift_ie; /* input errors */
604 u_int64_t ift_op; /* output packets */
605 u_int64_t ift_oe; /* output errors */
606 u_int64_t ift_co; /* collisions */
607 u_int64_t ift_dr; /* drops */
608 u_int64_t ift_ib; /* input bytes */
609 u_int64_t ift_ob; /* output bytes */
610 u_int64_t ift_itcp; /* input tc packets */
611 u_int64_t ift_itcb; /* input tc bytes */
612 u_int64_t ift_otcp; /* output tc packets */
613 u_int64_t ift_otcb; /* output tc bytes */
614 u_int64_t ift_ipvp; /* input priv tc packets */
615 u_int64_t ift_ipvb; /* input priv tc bytes */
616 u_int64_t ift_opvp; /* output priv tc packets */
617 u_int64_t ift_opvb; /* output priv tc bytes */
618 };
619
620 u_char signalled; /* set if alarm goes off "early" */
621
622 /*
623 * Print a running summary of interface statistics.
624 * Repeat display every interval seconds, showing statistics
625 * collected over that interval. Assumes that interval is non-zero.
626 * First line printed at top of screen is always cumulative.
627 * XXX - should be rewritten to use ifmib(4).
628 */
629 static void
630 sidewaysintpr()
631 {
632 struct iftot *total, *sum, *interesting;
633 register int line;
634 int first;
635 int name[6];
636 size_t len;
637 unsigned int ifcount, i;
638 struct ifmibdata *ifmdall = 0;
639 int interesting_row;
640 sigset_t sigset, oldsigset;
641 struct itimerval timer_interval;
642
643 /* Common OID prefix */
644 name[0] = CTL_NET;
645 name[1] = PF_LINK;
646 name[2] = NETLINK_GENERIC;
647
648 len = sizeof(int);
649 name[3] = IFMIB_SYSTEM;
650 name[4] = IFMIB_IFCOUNT;
651 if (sysctl(name, 5, &ifcount, &len, 0, 0) == 1)
652 err(1, "sysctl IFMIB_IFCOUNT");
653
654 len = ifcount * sizeof(struct ifmibdata);
655 ifmdall = malloc(len);
656 if (ifmdall == 0)
657 err(1, "malloc failed");
658 name[3] = IFMIB_IFALLDATA;
659 name[4] = 0;
660 name[5] = IFDATA_GENERAL;
661 if (sysctl(name, 6, ifmdall, &len, (void *)0, 0) == -1)
662 err(1, "sysctl IFMIB_IFALLDATA");
663
664 interesting = NULL;
665 interesting_row = 0;
666 for (i = 0; i < ifcount; i++) {
667 struct ifmibdata *ifmd = ifmdall + i;
668
669 if (interface && strcmp(ifmd->ifmd_name, interface) == 0) {
670 if ((interesting = calloc(ifcount, sizeof(struct iftot))) == NULL)
671 err(1, "malloc failed");
672 interesting_row = if_nametoindex(interface);
673 snprintf(interesting->ift_name, 16, "(%s)", ifmd->ifmd_name);;
674 }
675 }
676 if ((total = calloc(1, sizeof(struct iftot))) == NULL)
677 err(1, "malloc failed");
678
679 if ((sum = calloc(1, sizeof(struct iftot))) == NULL)
680 err(1, "malloc failed");
681
682 /* create a timer that fires repeatedly every interval seconds */
683 timer_interval.it_value.tv_sec = interval;
684 timer_interval.it_value.tv_usec = 0;
685 timer_interval.it_interval.tv_sec = interval;
686 timer_interval.it_interval.tv_usec = 0;
687 (void)signal(SIGALRM, catchalarm);
688 signalled = NO;
689 (void)setitimer(ITIMER_REAL, &timer_interval, NULL);
690 first = 1;
691 banner:
692 if (prioflag >= 0)
693 printf("%39s %39s %36s", "input",
694 interesting ? interesting->ift_name : "(Total)", "output");
695 else
696 printf("%17s %14s %16s", "input",
697 interesting ? interesting->ift_name : "(Total)", "output");
698 putchar('\n');
699 printf("%10s %5s %10s ",
700 "packets", "errs", "bytes");
701 if (prioflag >= 0)
702 printf(" %10s %10s %10s %10s", "tcpkts", "tcbytes", "pvpkts", "pvbytes");
703 printf("%10s %5s %10s %5s",
704 "packets", "errs", "bytes", "colls");
705 if (dflag)
706 printf(" %5.5s", "drops");
707 if (prioflag >= 0)
708 printf(" %10s %10s %10s %10s", "tcpkts", "tcbytes", "pvpkts", "pvbytes");
709 putchar('\n');
710 fflush(stdout);
711 line = 0;
712 loop:
713 if (interesting != NULL) {
714 struct ifmibdata ifmd;
715 struct ifmibdata_supplemental ifmsupp;
716
717 len = sizeof(struct ifmibdata);
718 name[3] = IFMIB_IFDATA;
719 name[4] = interesting_row;
720 name[5] = IFDATA_GENERAL;
721 if (sysctl(name, 6, &ifmd, &len, (void *)0, 0) == -1)
722 err(1, "sysctl IFDATA_GENERAL %d", interesting_row);
723
724 if (prioflag >= 0) {
725 len = sizeof(struct ifmibdata_supplemental);
726 name[3] = IFMIB_IFDATA;
727 name[4] = interesting_row;
728 name[5] = IFDATA_SUPPLEMENTAL;
729 if (sysctl(name, 6, &ifmsupp, &len, (void *)0, 0) == -1)
730 err(1, "sysctl IFDATA_SUPPLEMENTAL %d", interesting_row);
731 }
732
733 if (!first) {
734 printf("%10llu %5llu %10llu ",
735 ifmd.ifmd_data.ifi_ipackets - interesting->ift_ip,
736 ifmd.ifmd_data.ifi_ierrors - interesting->ift_ie,
737 ifmd.ifmd_data.ifi_ibytes - interesting->ift_ib);
738 switch (prioflag) {
739 case SO_TC_BE:
740 printf("%10llu %10llu ",
741 ifmsupp.ifmd_traffic_class.ifi_ibepackets - interesting->ift_itcp,
742 ifmsupp.ifmd_traffic_class.ifi_ibebytes - interesting->ift_itcb);
743 break;
744 case SO_TC_BK:
745 printf("%10llu %10llu ",
746 ifmsupp.ifmd_traffic_class.ifi_ibkpackets - interesting->ift_itcp,
747 ifmsupp.ifmd_traffic_class.ifi_ibkbytes - interesting->ift_itcb);
748 break;
749 case SO_TC_VI:
750 printf("%10llu %10llu ",
751 ifmsupp.ifmd_traffic_class.ifi_ivipackets - interesting->ift_itcp,
752 ifmsupp.ifmd_traffic_class.ifi_ivibytes - interesting->ift_itcb);
753 break;
754 case SO_TC_VO:
755 printf("%10llu %10llu ",
756 ifmsupp.ifmd_traffic_class.ifi_ivopackets - interesting->ift_itcp,
757 ifmsupp.ifmd_traffic_class.ifi_ivobytes - interesting->ift_itcb);
758 break;
759 default:
760 break;
761 }
762 if (prioflag >= 0) {
763 printf("%10llu %10llu ",
764 ifmsupp.ifmd_traffic_class.ifi_ipvpackets - interesting->ift_ipvp,
765 ifmsupp.ifmd_traffic_class.ifi_ipvbytes - interesting->ift_ipvb);
766 }
767 printf("%10llu %5llu %10llu %5llu",
768 ifmd.ifmd_data.ifi_opackets - interesting->ift_op,
769 ifmd.ifmd_data.ifi_oerrors - interesting->ift_oe,
770 ifmd.ifmd_data.ifi_obytes - interesting->ift_ob,
771 ifmd.ifmd_data.ifi_collisions - interesting->ift_co);
772 if (dflag)
773 printf(" %5llu", ifmd.ifmd_snd_drops - interesting->ift_dr);
774 switch (prioflag) {
775 case SO_TC_BE:
776 printf(" %10llu %10llu",
777 ifmsupp.ifmd_traffic_class.ifi_obepackets - interesting->ift_otcp,
778 ifmsupp.ifmd_traffic_class.ifi_obebytes - interesting->ift_otcb);
779 break;
780 case SO_TC_BK:
781 printf(" %10llu %10llu",
782 ifmsupp.ifmd_traffic_class.ifi_obkpackets - interesting->ift_otcp,
783 ifmsupp.ifmd_traffic_class.ifi_obkbytes - interesting->ift_otcb);
784 break;
785 case SO_TC_VI:
786 printf(" %10llu %10llu",
787 ifmsupp.ifmd_traffic_class.ifi_ovipackets - interesting->ift_otcp,
788 ifmsupp.ifmd_traffic_class.ifi_ovibytes - interesting->ift_otcb);
789 break;
790 case SO_TC_VO:
791 printf(" %10llu %10llu",
792 ifmsupp.ifmd_traffic_class.ifi_ovopackets - interesting->ift_otcp,
793 ifmsupp.ifmd_traffic_class.ifi_ovobytes - interesting->ift_otcb);
794 break;
795 default:
796 break;
797 }
798 if (prioflag >= 0) {
799 printf("%10llu %10llu ",
800 ifmsupp.ifmd_traffic_class.ifi_opvpackets - interesting->ift_opvp,
801 ifmsupp.ifmd_traffic_class.ifi_opvbytes - interesting->ift_opvb);
802 }
803 }
804 interesting->ift_ip = ifmd.ifmd_data.ifi_ipackets;
805 interesting->ift_ie = ifmd.ifmd_data.ifi_ierrors;
806 interesting->ift_ib = ifmd.ifmd_data.ifi_ibytes;
807 interesting->ift_op = ifmd.ifmd_data.ifi_opackets;
808 interesting->ift_oe = ifmd.ifmd_data.ifi_oerrors;
809 interesting->ift_ob = ifmd.ifmd_data.ifi_obytes;
810 interesting->ift_co = ifmd.ifmd_data.ifi_collisions;
811 interesting->ift_dr = ifmd.ifmd_snd_drops;
812 /* private counters */
813 switch (prioflag) {
814 case SO_TC_BE:
815 interesting->ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ibepackets;
816 interesting->ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ibebytes;
817 interesting->ift_otcp = ifmsupp.ifmd_traffic_class.ifi_obepackets;
818 interesting->ift_otcb = ifmsupp.ifmd_traffic_class.ifi_obebytes;
819 break;
820 case SO_TC_BK:
821 interesting->ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ibkpackets;
822 interesting->ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ibkbytes;
823 interesting->ift_otcp = ifmsupp.ifmd_traffic_class.ifi_obkpackets;
824 interesting->ift_otcb = ifmsupp.ifmd_traffic_class.ifi_obkbytes;
825 break;
826 case SO_TC_VI:
827 interesting->ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ivipackets;
828 interesting->ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ivibytes;
829 interesting->ift_otcp = ifmsupp.ifmd_traffic_class.ifi_ovipackets;
830 interesting->ift_otcb = ifmsupp.ifmd_traffic_class.ifi_ovibytes;
831 break;
832 case SO_TC_VO:
833 interesting->ift_itcp = ifmsupp.ifmd_traffic_class.ifi_ivopackets;
834 interesting->ift_itcb = ifmsupp.ifmd_traffic_class.ifi_ivobytes;
835 interesting->ift_otcp = ifmsupp.ifmd_traffic_class.ifi_ovopackets;
836 interesting->ift_otcb = ifmsupp.ifmd_traffic_class.ifi_ovobytes;
837 break;
838 default:
839 break;
840 }
841 if (prioflag >= 0) {
842 interesting->ift_ipvp = ifmsupp.ifmd_traffic_class.ifi_ipvpackets;
843 interesting->ift_ipvb = ifmsupp.ifmd_traffic_class.ifi_ipvbytes;
844 interesting->ift_opvp = ifmsupp.ifmd_traffic_class.ifi_opvpackets;
845 interesting->ift_opvb = ifmsupp.ifmd_traffic_class.ifi_opvbytes;
846 }
847 } else {
848 unsigned int latest_ifcount;
849 struct ifmibdata_supplemental *ifmsuppall = NULL;
850
851 len = sizeof(int);
852 name[3] = IFMIB_SYSTEM;
853 name[4] = IFMIB_IFCOUNT;
854 if (sysctl(name, 5, &latest_ifcount, &len, 0, 0) == 1)
855 err(1, "sysctl IFMIB_IFCOUNT");
856 if (latest_ifcount > ifcount) {
857 ifcount = latest_ifcount;
858 len = ifcount * sizeof(struct ifmibdata);
859 free(ifmdall);
860 ifmdall = malloc(len);
861 if (ifmdall == 0)
862 err(1, "malloc ifmdall failed");
863 } else if (latest_ifcount > ifcount) {
864 ifcount = latest_ifcount;
865 len = ifcount * sizeof(struct ifmibdata);
866 }
867 len = ifcount * sizeof(struct ifmibdata);
868 name[3] = IFMIB_IFALLDATA;
869 name[4] = 0;
870 name[5] = IFDATA_GENERAL;
871 if (sysctl(name, 6, ifmdall, &len, (void *)0, 0) == -1)
872 err(1, "sysctl IFMIB_IFALLDATA");
873 if (prioflag >= 0) {
874 len = ifcount * sizeof(struct ifmibdata_supplemental);
875 ifmsuppall = malloc(len);
876 if (ifmsuppall == NULL)
877 err(1, "malloc ifmsuppall failed");
878 name[3] = IFMIB_IFALLDATA;
879 name[4] = 0;
880 name[5] = IFDATA_SUPPLEMENTAL;
881 if (sysctl(name, 6, ifmsuppall, &len, (void *)0, 0) == -1)
882 err(1, "sysctl IFMIB_IFALLDATA SUPPLEMENTAL");
883 }
884 sum->ift_ip = 0;
885 sum->ift_ie = 0;
886 sum->ift_ib = 0;
887 sum->ift_op = 0;
888 sum->ift_oe = 0;
889 sum->ift_ob = 0;
890 sum->ift_co = 0;
891 sum->ift_dr = 0;
892 sum->ift_itcp = 0;
893 sum->ift_itcb = 0;
894 sum->ift_otcp = 0;
895 sum->ift_otcb = 0;
896 sum->ift_ipvp = 0;
897 sum->ift_ipvb = 0;
898 sum->ift_opvp = 0;
899 sum->ift_opvb = 0;
900 for (i = 0; i < ifcount; i++) {
901 struct ifmibdata *ifmd = ifmdall + i;
902
903 sum->ift_ip += ifmd->ifmd_data.ifi_ipackets;
904 sum->ift_ie += ifmd->ifmd_data.ifi_ierrors;
905 sum->ift_ib += ifmd->ifmd_data.ifi_ibytes;
906 sum->ift_op += ifmd->ifmd_data.ifi_opackets;
907 sum->ift_oe += ifmd->ifmd_data.ifi_oerrors;
908 sum->ift_ob += ifmd->ifmd_data.ifi_obytes;
909 sum->ift_co += ifmd->ifmd_data.ifi_collisions;
910 sum->ift_dr += ifmd->ifmd_snd_drops;
911 /* private counters */
912 if (prioflag >= 0) {
913 struct ifmibdata_supplemental *ifmsupp = ifmsuppall + i;
914 switch (prioflag) {
915 case SO_TC_BE:
916 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ibepackets;
917 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ibebytes;
918 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_obepackets;
919 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_obebytes;
920 break;
921 case SO_TC_BK:
922 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ibkpackets;
923 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ibkbytes;
924 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_obkpackets;
925 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_obkbytes;
926 break;
927 case SO_TC_VI:
928 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ivipackets;
929 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ivibytes;
930 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_ovipackets;
931 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_ovibytes;
932 break;
933 case SO_TC_VO:
934 sum->ift_itcp += ifmsupp->ifmd_traffic_class.ifi_ivopackets;
935 sum->ift_itcb += ifmsupp->ifmd_traffic_class.ifi_ivobytes;
936 sum->ift_otcp += ifmsupp->ifmd_traffic_class.ifi_ovopackets;
937 sum->ift_otcb += ifmsupp->ifmd_traffic_class.ifi_ovobytes;
938 break;
939 default:
940 break;
941 }
942 sum->ift_ipvp += ifmsupp->ifmd_traffic_class.ifi_ipvpackets;
943 sum->ift_ipvb += ifmsupp->ifmd_traffic_class.ifi_ipvbytes;
944 sum->ift_opvp += ifmsupp->ifmd_traffic_class.ifi_opvpackets;
945 sum->ift_opvb += ifmsupp->ifmd_traffic_class.ifi_opvbytes;
946 }
947 }
948 if (!first) {
949 printf("%10llu %5llu %10llu ",
950 sum->ift_ip - total->ift_ip,
951 sum->ift_ie - total->ift_ie,
952 sum->ift_ib - total->ift_ib);
953 if (prioflag >= 0)
954 printf(" %10llu %10llu %10llu %10llu",
955 sum->ift_itcp - total->ift_itcp,
956 sum->ift_itcb - total->ift_itcb,
957 sum->ift_ipvp - total->ift_ipvp,
958 sum->ift_ipvb - total->ift_ipvb);
959 printf("%10llu %5llu %10llu %5llu",
960 sum->ift_op - total->ift_op,
961 sum->ift_oe - total->ift_oe,
962 sum->ift_ob - total->ift_ob,
963 sum->ift_co - total->ift_co);
964 if (dflag)
965 printf(" %5llu", sum->ift_dr - total->ift_dr);
966 if (prioflag >= 0)
967 printf(" %10llu %10llu %10llu %10llu",
968 sum->ift_otcp - total->ift_otcp,
969 sum->ift_otcb - total->ift_otcb,
970 sum->ift_opvp - total->ift_opvp,
971 sum->ift_opvb - total->ift_opvb);
972 }
973 *total = *sum;
974 }
975 if (!first)
976 putchar('\n');
977 fflush(stdout);
978 sigemptyset(&sigset);
979 sigaddset(&sigset, SIGALRM);
980 (void)sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
981 if (!signalled) {
982 sigemptyset(&sigset);
983 sigsuspend(&sigset);
984 }
985 (void)sigprocmask(SIG_SETMASK, &oldsigset, NULL);
986
987 signalled = NO;
988 line++;
989 first = 0;
990 if (line == 21)
991 goto banner;
992 else
993 goto loop;
994 /*NOTREACHED*/
995 }
996
997 void
998 intervalpr(void (*pr)(uint32_t, char *, int), uint32_t off, char *name , int af)
999 {
1000 struct itimerval timer_interval;
1001 sigset_t sigset, oldsigset;
1002
1003 /* create a timer that fires repeatedly every interval seconds */
1004 timer_interval.it_value.tv_sec = interval;
1005 timer_interval.it_value.tv_usec = 0;
1006 timer_interval.it_interval.tv_sec = interval;
1007 timer_interval.it_interval.tv_usec = 0;
1008 (void) signal(SIGALRM, catchalarm);
1009 signalled = NO;
1010 (void) setitimer(ITIMER_REAL, &timer_interval, NULL);
1011
1012 for (;;) {
1013 pr(off, name, af);
1014
1015 fflush(stdout);
1016 sigemptyset(&sigset);
1017 sigaddset(&sigset, SIGALRM);
1018 (void) sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
1019 if (!signalled) {
1020 sigemptyset(&sigset);
1021 sigsuspend(&sigset);
1022 }
1023 (void) sigprocmask(SIG_SETMASK, &oldsigset, NULL);
1024 signalled = NO;
1025 }
1026 }
1027
1028 /*
1029 * Called if an interval expires before sidewaysintpr has completed a loop.
1030 * Sets a flag to not wait for the alarm.
1031 */
1032 static void
1033 catchalarm(int signo )
1034 {
1035 signalled = YES;
1036 }
1037
1038 static char *
1039 sec2str(total)
1040 time_t total;
1041 {
1042 static char result[256];
1043 int days, hours, mins, secs;
1044 int first = 1;
1045 char *p = result;
1046
1047 days = total / 3600 / 24;
1048 hours = (total / 3600) % 24;
1049 mins = (total / 60) % 60;
1050 secs = total % 60;
1051
1052 if (days) {
1053 first = 0;
1054 p += snprintf(p, sizeof(result) - (p - result), "%dd", days);
1055 }
1056 if (!first || hours) {
1057 first = 0;
1058 p += snprintf(p, sizeof(result) - (p - result), "%dh", hours);
1059 }
1060 if (!first || mins) {
1061 first = 0;
1062 p += snprintf(p, sizeof(result) - (p - result), "%dm", mins);
1063 }
1064 snprintf(p, sizeof(result) - (p - result), "%ds", secs);
1065
1066 return(result);
1067 }
1068
1069 void
1070 intpr_ri(void (*pfunc)(char *))
1071 {
1072 int mib[6];
1073 char *buf = NULL, *lim, *next;
1074 size_t len;
1075 unsigned int ifindex = 0;
1076 struct if_msghdr2 *if2m;
1077
1078 if (interface != 0) {
1079 ifindex = if_nametoindex(interface);
1080 if (ifindex == 0) {
1081 printf("interface name is not valid: %s\n", interface);
1082 exit(1);
1083 }
1084 }
1085
1086 mib[0] = CTL_NET; /* networking subsystem */
1087 mib[1] = PF_ROUTE; /* type of information */
1088 mib[2] = 0; /* protocol (IPPROTO_xxx) */
1089 mib[3] = 0; /* address family */
1090 mib[4] = NET_RT_IFLIST2; /* operation */
1091 mib[5] = 0;
1092 if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
1093 return;
1094 if ((buf = malloc(len)) == NULL) {
1095 printf("malloc failed\n");
1096 exit(1);
1097 }
1098 if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
1099 free(buf);
1100 return;
1101 }
1102
1103 printf("%-6s %-17s %8.8s %-9.9s %4s %4s",
1104 "Proto", "Linklayer Address", "Netif", "Expire", "Refs",
1105 "Prbs");
1106 if (xflag)
1107 printf(" %7s %7s %7s", "RSSI", "LQM", "NPM");
1108 printf("\n");
1109
1110 lim = buf + len;
1111 if2m = (struct if_msghdr2 *)buf;
1112
1113 for (next = buf; next < lim; ) {
1114 if2m = (struct if_msghdr2 *)next;
1115 next += if2m->ifm_msglen;
1116
1117 if (if2m->ifm_type != RTM_IFINFO2)
1118 continue;
1119 else if (interface != 0 && if2m->ifm_index != ifindex)
1120 continue;
1121
1122 llreach_sysctl(if2m->ifm_index);
1123 }
1124 free(buf);
1125 }
1126
1127 static void
1128 llreach_sysctl(uint32_t ifindex)
1129 {
1130 #define MAX_SYSCTL_TRY 5
1131 int mib[6], i, ntry = 0;
1132 size_t mibsize, len, needed, cnt;
1133 struct if_llreach_info *lri;
1134 struct timeval time;
1135 char *buf;
1136 char ifname[IF_NAMESIZE];
1137
1138 bzero(&mib, sizeof (mib));
1139 mibsize = sizeof (mib) / sizeof (mib[0]);
1140 if (sysctlnametomib("net.link.generic.system.llreach_info", mib,
1141 &mibsize) == -1) {
1142 perror("sysctlnametomib");
1143 return;
1144 }
1145
1146 needed = 0;
1147 mib[5] = ifindex;
1148
1149 mibsize = sizeof (mib) / sizeof (mib[0]);
1150 do {
1151 if (sysctl(mib, mibsize, NULL, &needed, NULL, 0) == -1) {
1152 perror("sysctl net.link.generic.system.llreach_info");
1153 return;
1154 }
1155 if ((buf = malloc(needed)) == NULL) {
1156 perror("malloc");
1157 return;
1158 }
1159 if (sysctl(mib, mibsize, buf, &needed, NULL, 0) == -1) {
1160 if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
1161 perror("sysctl");
1162 goto out_free;
1163 }
1164 free(buf);
1165 buf = NULL;
1166 }
1167 } while (buf == NULL);
1168
1169 len = needed;
1170 cnt = len / sizeof (*lri);
1171 lri = (struct if_llreach_info *)buf;
1172
1173 gettimeofday(&time, 0);
1174 if (if_indextoname(ifindex, ifname) == NULL)
1175 snprintf(ifname, sizeof (ifname), "%s", "?");
1176
1177 for (i = 0; i < cnt; i++, lri++) {
1178 printf("0x%-4x %-17s %8.8s ", lri->lri_proto,
1179 ether_ntoa((struct ether_addr *)lri->lri_addr), ifname);
1180
1181 if (lri->lri_expire > time.tv_sec)
1182 printf("%-9.9s", sec2str(lri->lri_expire - time.tv_sec));
1183 else if (lri->lri_expire == 0)
1184 printf("%-9.9s", "permanent");
1185 else
1186 printf("%-9.9s", "expired");
1187
1188 printf(" %4d", lri->lri_refcnt);
1189 if (lri->lri_probes)
1190 printf(" %4d", lri->lri_probes);
1191
1192 if (xflag) {
1193 if (!lri->lri_probes)
1194 printf(" %-4.4s", "none");
1195
1196 if (lri->lri_rssi != IFNET_RSSI_UNKNOWN)
1197 printf(" %7d", lri->lri_rssi);
1198 else
1199 printf(" %-7.7s", "unknown");
1200
1201 switch (lri->lri_lqm)
1202 {
1203 case IFNET_LQM_THRESH_OFF:
1204 printf(" %-7.7s", "off");
1205 break;
1206 case IFNET_LQM_THRESH_UNKNOWN:
1207 printf(" %-7.7s", "unknown");
1208 break;
1209 case IFNET_LQM_THRESH_POOR:
1210 printf(" %-7.7s", "poor");
1211 break;
1212 case IFNET_LQM_THRESH_GOOD:
1213 printf(" %-7.7s", "good");
1214 break;
1215 default:
1216 printf(" %7d", lri->lri_lqm);
1217 break;
1218 }
1219
1220 switch (lri->lri_npm)
1221 {
1222 case IFNET_NPM_THRESH_UNKNOWN:
1223 printf(" %-7.7s", "unknown");
1224 break;
1225 case IFNET_NPM_THRESH_NEAR:
1226 printf(" %-7.7s", "near");
1227 break;
1228 case IFNET_NPM_THRESH_GENERAL:
1229 printf(" %-7.7s", "general");
1230 break;
1231 case IFNET_NPM_THRESH_FAR:
1232 printf(" %-7.7s", "far");
1233 break;
1234 default:
1235 printf(" %7d", lri->lri_npm);
1236 break;
1237 }
1238 }
1239
1240 printf("\n");
1241 len -= sizeof (*lri);
1242 }
1243
1244 if (len > 0) {
1245 fprintf(stderr, "warning: %u trailing bytes from %s\n",
1246 (unsigned int)len, "net.link.generic.system.llreach_info");
1247 }
1248
1249 out_free:
1250 free(buf);
1251 #undef MAX_SYSCTL_TRY
1252 }
1253
1254 void
1255 aqstatpr(void)
1256 {
1257 unsigned int ifindex;
1258 struct itimerval timer_interval;
1259 struct if_qstatsreq ifqr;
1260 struct if_ifclassq_stats *ifcqs;
1261 sigset_t sigset, oldsigset;
1262 u_int32_t scheduler;
1263 int s, n, tcq = 0;
1264
1265 if (cq < -1 || cq >= IFCQ_SC_MAX) {
1266 fprintf(stderr, "Invalid classq index (range is 0-%d)\n",
1267 IFCQ_SC_MAX-1);
1268 return;
1269 }
1270 ifindex = if_nametoindex(interface);
1271 if (ifindex == 0) {
1272 fprintf(stderr, "Invalid interface name\n");
1273 return;
1274 }
1275
1276 ifcqs = malloc(sizeof (*ifcqs));
1277 if (ifcqs == NULL) {
1278 fprintf(stderr, "Unable to allocate memory\n");
1279 return;
1280 }
1281
1282 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1283 perror("Warning: socket(AF_INET)");
1284 free(ifcqs);
1285 return;
1286 }
1287
1288 bzero(&ifqr, sizeof (ifqr));
1289 strlcpy(ifqr.ifqr_name, interface, sizeof (ifqr.ifqr_name));
1290 ifqr.ifqr_buf = ifcqs;
1291 ifqr.ifqr_len = sizeof (*ifcqs);
1292
1293 loop:
1294 if (interval > 0) {
1295 /* create a timer that fires repeatedly every interval seconds */
1296 timer_interval.it_value.tv_sec = interval;
1297 timer_interval.it_value.tv_usec = 0;
1298 timer_interval.it_interval.tv_sec = interval;
1299 timer_interval.it_interval.tv_usec = 0;
1300 (void) signal(SIGALRM, catchalarm);
1301 signalled = NO;
1302 (void) setitimer(ITIMER_REAL, &timer_interval, NULL);
1303 }
1304
1305 ifqr.ifqr_slot = 0;
1306 if (ioctl(s, SIOCGIFQUEUESTATS, (char *)&ifqr) < 0) {
1307 if (errno == ENXIO) {
1308 printf("Queue statistics are not available on %s\n",
1309 interface);
1310 } else {
1311 perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
1312 }
1313 goto done;
1314 }
1315 scheduler = ifcqs->ifqs_scheduler;
1316 tcq = (scheduler == PKTSCHEDT_TCQ);
1317
1318 printf("%s:\n"
1319 "%s [ sched: %9s %sqlength: %3d/%3d ]\n",
1320 interface, tcq ? " " : "", sched2str(ifcqs->ifqs_scheduler),
1321 tcq ? "" : " ", ifcqs->ifqs_len, ifcqs->ifqs_maxlen);
1322 printf("%s [ pkts: %10llu %sbytes: %10llu "
1323 "%sdropped pkts: %6llu bytes: %6llu ]\n",
1324 (scheduler != PKTSCHEDT_TCQ) ? "" : " ",
1325 ifcqs->ifqs_xmitcnt.packets, tcq ? "" : " ",
1326 ifcqs->ifqs_xmitcnt.bytes, tcq ? "" : " ",
1327 ifcqs->ifqs_dropcnt.packets, ifcqs->ifqs_dropcnt.bytes);
1328
1329 for (n = 0; n < IFCQ_SC_MAX; n++) {
1330 qstats[n].printed = 0;
1331 if (!tcq)
1332 continue;
1333 ifqr.ifqr_slot = n;
1334 if (ioctl(s, SIOCGIFQUEUESTATS, (char *)&ifqr) < 0) {
1335 perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
1336 goto done;
1337 }
1338 qstats[n].handle = ifcqs->ifqs_tcq_stats.class_handle;
1339 }
1340
1341 for (n = 0; n < IFCQ_SC_MAX && scheduler != PKTSCHEDT_NONE; n++) {
1342 if (cq >= 0 && cq != n)
1343 continue;
1344
1345 ifqr.ifqr_slot = n;
1346 if (ioctl(s, SIOCGIFQUEUESTATS, (char *)&ifqr) < 0) {
1347 perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
1348 goto done;
1349 }
1350
1351 update_avg(ifcqs, &qstats[n]);
1352
1353 switch (scheduler) {
1354 case PKTSCHEDT_CBQ:
1355 print_cbqstats(n, &ifcqs->ifqs_cbq_stats,
1356 &qstats[n]);
1357 break;
1358 case PKTSCHEDT_HFSC:
1359 print_hfscstats(n, &ifcqs->ifqs_hfsc_stats,
1360 &qstats[n]);
1361 break;
1362 case PKTSCHEDT_PRIQ:
1363 print_priqstats(n, &ifcqs->ifqs_priq_stats,
1364 &qstats[n]);
1365 break;
1366 case PKTSCHEDT_FAIRQ:
1367 print_fairqstats(n, &ifcqs->ifqs_fairq_stats,
1368 &qstats[n]);
1369 break;
1370 case PKTSCHEDT_TCQ:
1371 print_tcqstats(n, &ifcqs->ifqs_tcq_stats,
1372 &qstats[n]);
1373 break;
1374 case PKTSCHEDT_QFQ:
1375 print_qfqstats(n, &ifcqs->ifqs_qfq_stats,
1376 &qstats[n]);
1377 break;
1378 case PKTSCHEDT_NONE:
1379 default:
1380 break;
1381 }
1382 }
1383
1384 fflush(stdout);
1385
1386 if (interval > 0) {
1387 sigemptyset(&sigset);
1388 sigaddset(&sigset, SIGALRM);
1389 (void) sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
1390 if (!signalled) {
1391 sigemptyset(&sigset);
1392 sigsuspend(&sigset);
1393 }
1394 (void) sigprocmask(SIG_SETMASK, &oldsigset, NULL);
1395
1396 signalled = NO;
1397 goto loop;
1398 }
1399
1400 done:
1401 free(ifcqs);
1402 close(s);
1403 }
1404
1405 static void
1406 print_cbqstats(int slot, struct cbq_classstats *cs, struct queue_stats *qs)
1407 {
1408 printf(" %2d: [ pkts: %10llu bytes: %10llu "
1409 "dropped pkts: %6llu bytes: %6llu ]\n", slot,
1410 (unsigned long long)cs->xmit_cnt.packets,
1411 (unsigned long long)cs->xmit_cnt.bytes,
1412 (unsigned long long)cs->drop_cnt.packets,
1413 (unsigned long long)cs->drop_cnt.bytes);
1414 printf(" [ qlength: %3d/%3d borrows: %6u "
1415 "suspends: %6u qalg: %s ]\n", cs->qcnt, cs->qmax,
1416 cs->borrows, cs->delays, qtype2str(cs->qtype));
1417 printf(" [ service class: %5s ]\n", qid2str(cs->handle));
1418
1419 if (qs->avgn >= 2) {
1420 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1421 qs->avg_packets / interval,
1422 rate2str((8 * qs->avg_bytes) / interval));
1423 }
1424
1425 if (qflag < 2)
1426 return;
1427
1428 switch (cs->qtype) {
1429 case Q_SFB:
1430 print_sfbstats(&cs->sfb);
1431 break;
1432 default:
1433 break;
1434 }
1435 }
1436
1437 static void
1438 print_priqstats(int slot, struct priq_classstats *cs, struct queue_stats *qs)
1439 {
1440 printf(" %2d: [ pkts: %10llu bytes: %10llu "
1441 "dropped pkts: %6llu bytes: %6llu ]\n", slot,
1442 (unsigned long long)cs->xmitcnt.packets,
1443 (unsigned long long)cs->xmitcnt.bytes,
1444 (unsigned long long)cs->dropcnt.packets,
1445 (unsigned long long)cs->dropcnt.bytes);
1446 printf(" [ qlength: %3d/%3d qalg: %11s service class: %5s ]\n",
1447 cs->qlength, cs->qlimit, qtype2str(cs->qtype),
1448 qid2str(cs->class_handle));
1449
1450 if (qs->avgn >= 2) {
1451 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1452 qs->avg_packets / interval,
1453 rate2str((8 * qs->avg_bytes) / interval));
1454 }
1455
1456 if (qflag < 2)
1457 return;
1458
1459 switch (cs->qtype) {
1460 case Q_SFB:
1461 print_sfbstats(&cs->sfb);
1462 break;
1463 default:
1464 break;
1465 }
1466 }
1467
1468 static void
1469 print_hfscstats(int slot, struct hfsc_classstats *cs, struct queue_stats *qs)
1470 {
1471 printf(" %2d: [ pkts: %10llu bytes: %10llu "
1472 "dropped pkts: %6llu bytes: %6llu ]\n", slot,
1473 (unsigned long long)cs->xmit_cnt.packets,
1474 (unsigned long long)cs->xmit_cnt.bytes,
1475 (unsigned long long)cs->drop_cnt.packets,
1476 (unsigned long long)cs->drop_cnt.bytes);
1477 printf(" [ qlength: %3d/%3d qalg: %11s service class: %5s ]\n",
1478 cs->qlength, cs->qlimit, qtype2str(cs->qtype),
1479 qid2str(cs->class_handle));
1480
1481 if (qs->avgn >= 2) {
1482 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1483 qs->avg_packets / interval,
1484 rate2str((8 * qs->avg_bytes) / interval));
1485 }
1486
1487 if (qflag < 2)
1488 return;
1489
1490 switch (cs->qtype) {
1491 case Q_SFB:
1492 print_sfbstats(&cs->sfb);
1493 break;
1494 default:
1495 break;
1496 }
1497 }
1498
1499 static void
1500 print_fairqstats(int slot, struct fairq_classstats *cs, struct queue_stats *qs)
1501 {
1502 printf(" %2d: [ pkts: %10llu bytes: %10llu "
1503 "dropped pkts: %6llu bytes: %6llu ]\n", slot,
1504 (unsigned long long)cs->xmit_cnt.packets,
1505 (unsigned long long)cs->xmit_cnt.bytes,
1506 (unsigned long long)cs->drop_cnt.packets,
1507 (unsigned long long)cs->drop_cnt.bytes);
1508 printf(" [ qlength: %3d/%3d qalg: %11s service class: %5s ]]\n",
1509 cs->qlength, cs->qlimit, qtype2str(cs->qtype),
1510 qid2str(cs->class_handle));
1511
1512 if (qs->avgn >= 2) {
1513 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1514 qs->avg_packets / interval,
1515 rate2str((8 * qs->avg_bytes) / interval));
1516 }
1517
1518 if (qflag < 2)
1519 return;
1520
1521 switch (cs->qtype) {
1522 case Q_SFB:
1523 print_sfbstats(&cs->sfb);
1524 break;
1525 default:
1526 break;
1527 }
1528 }
1529
1530 static void
1531 print_tcqstats(int slot, struct tcq_classstats *cs, struct queue_stats *qs)
1532 {
1533 int n;
1534
1535 if (qs->printed)
1536 return;
1537
1538 qs->handle = cs->class_handle;
1539 qs->printed++;
1540
1541 for (n = 0; n < IFCQ_SC_MAX; n++) {
1542 if (&qstats[n] != qs && qstats[n].handle == qs->handle)
1543 qstats[n].printed++;
1544 }
1545
1546 printf("%5s: [ pkts: %10llu bytes: %10llu "
1547 "dropped pkts: %6llu bytes: %6llu ]\n", tcqslot2str(slot),
1548 (unsigned long long)cs->xmitcnt.packets,
1549 (unsigned long long)cs->xmitcnt.bytes,
1550 (unsigned long long)cs->dropcnt.packets,
1551 (unsigned long long)cs->dropcnt.bytes);
1552 printf(" [ qlength: %3d/%3d qalg: %11s "
1553 "svc class: %9s %-13s ]\n", cs->qlength, cs->qlimit,
1554 qtype2str(cs->qtype), qid2str(cs->class_handle),
1555 qstate2str(cs->qstate));
1556
1557 if (qs->avgn >= 2) {
1558 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1559 qs->avg_packets / interval,
1560 rate2str((8 * qs->avg_bytes) / interval));
1561 }
1562
1563 if (qflag < 2)
1564 return;
1565
1566 switch (cs->qtype) {
1567 case Q_SFB:
1568 print_sfbstats(&cs->sfb);
1569 break;
1570 default:
1571 break;
1572 }
1573 }
1574
1575 static void
1576 print_qfqstats(int slot, struct qfq_classstats *cs, struct queue_stats *qs)
1577 {
1578 printf(" %2d: [ pkts: %10llu bytes: %10llu "
1579 "dropped pkts: %6llu bytes: %6llu ]\n", slot,
1580 (unsigned long long)cs->xmitcnt.packets,
1581 (unsigned long long)cs->xmitcnt.bytes,
1582 (unsigned long long)cs->dropcnt.packets,
1583 (unsigned long long)cs->dropcnt.bytes);
1584 printf(" [ qlength: %3d/%3d index: %10u weight: %12u "
1585 "lmax: %7u ]\n", cs->qlength, cs->qlimit, cs->index,
1586 cs->weight, cs->lmax);
1587 printf(" [ qalg: %10s svc class: %6s %-35s ]\n",
1588 qtype2str(cs->qtype), qid2str(cs->class_handle),
1589 qstate2str(cs->qstate));
1590
1591 if (qs->avgn >= 2) {
1592 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1593 qs->avg_packets / interval,
1594 rate2str((8 * qs->avg_bytes) / interval));
1595 }
1596
1597 if (qflag < 2)
1598 return;
1599
1600 switch (cs->qtype) {
1601 case Q_SFB:
1602 print_sfbstats(&cs->sfb);
1603 break;
1604 default:
1605 break;
1606 }
1607 }
1608
1609 static void
1610 print_sfbstats(struct sfb_stats *sfb)
1611 {
1612 struct sfbstats *sp = &sfb->sfbstats;
1613 int i, j, cur = sfb->current;
1614
1615 printf("\n");
1616 printf(" [ early drop: %12llu rlimit drop: %11llu "
1617 "marked: %11llu ]\n",
1618 sp->drop_early, sp->drop_pbox, sp->marked_packets);
1619 printf(" [ penalized: %13llu rehash cnt: %12llu "
1620 "current: %10u ]\n", sp->pbox_packets, sp->num_rehash, cur);
1621 printf(" [ deque avg: %13s ", nsec_to_str(sp->dequeue_avg));
1622 printf("rehash intvl: %11s]\n", nsec_to_str(sp->rehash_intval));
1623 printf(" [ holdtime: %14s ", nsec_to_str(sp->hold_time));
1624 printf("pboxtime: %14s ]\n", nsec_to_str(sp->pbox_time));
1625 printf(" [ allocation: %12u drop thresh: %11u ]\n",
1626 sfb->allocation, sfb->dropthresh);
1627 printf(" [ flow controlled: %7llu adv feedback: %10llu ]\n",
1628 sp->flow_controlled, sp->flow_feedback);
1629
1630 printf("\n\t\t\t\tCurrent bins (set %d)", cur);
1631 for (i = 0; i < SFB_LEVELS; ++i) {
1632 unsigned int q;
1633 double p;
1634
1635 printf("\n\tLevel: %d\n", i);
1636 for (j = 0; j < SFB_BINS; ++j) {
1637 if ((j % 4) == 0)
1638 printf("\t%6d:\t", j + 1);
1639 p = sfb->binstats[cur].stats[i][j].pmark;
1640 q = sfb->binstats[cur].stats[i][j].pkts;
1641 if (p > 0) {
1642 p /= (1 << SFB_FP_SHIFT);
1643 printf("[%1.4f %4u]", p, q);
1644 } else {
1645 printf("[ ]");
1646 }
1647 if (j > 0 && ((j + 1) % 4) == 0)
1648 printf("\n");
1649 }
1650 }
1651
1652 cur ^= 1;
1653 printf("\n\t\t\t\tWarm up bins (set %d)", cur);
1654 for (i = 0; i < SFB_LEVELS; ++i) {
1655 unsigned int q;
1656 double p;
1657
1658 printf("\n\tLevel: %d\n", i);
1659 for (j = 0; j < SFB_BINS; ++j) {
1660 if ((j % 4) == 0)
1661 printf("\t%6d:\t", j + 1);
1662 p = sfb->binstats[cur].stats[i][j].pmark;
1663 q = sfb->binstats[cur].stats[i][j].pkts;
1664 if (p > 0) {
1665 p /= (1 << SFB_FP_SHIFT);
1666 printf("[%1.4f %4u]", p, q);
1667 } else {
1668 printf("[ ]");
1669 }
1670 if (j > 0 && ((j + 1) % 4) == 0)
1671 printf("\n");
1672 }
1673 }
1674 printf("\n");
1675 }
1676
1677 static void
1678 update_avg(struct if_ifclassq_stats *ifcqs, struct queue_stats *qs)
1679 {
1680 u_int64_t b, p;
1681 int n;
1682
1683 n = qs->avgn;
1684
1685 switch (ifcqs->ifqs_scheduler) {
1686 case PKTSCHEDT_CBQ:
1687 b = ifcqs->ifqs_cbq_stats.xmit_cnt.bytes;
1688 p = ifcqs->ifqs_cbq_stats.xmit_cnt.packets;
1689 break;
1690 case PKTSCHEDT_PRIQ:
1691 b = ifcqs->ifqs_priq_stats.xmitcnt.bytes;
1692 p = ifcqs->ifqs_priq_stats.xmitcnt.packets;
1693 break;
1694 case PKTSCHEDT_HFSC:
1695 b = ifcqs->ifqs_hfsc_stats.xmit_cnt.bytes;
1696 p = ifcqs->ifqs_hfsc_stats.xmit_cnt.packets;
1697 break;
1698 case PKTSCHEDT_FAIRQ:
1699 b = ifcqs->ifqs_fairq_stats.xmit_cnt.bytes;
1700 p = ifcqs->ifqs_fairq_stats.xmit_cnt.packets;
1701 break;
1702 case PKTSCHEDT_TCQ:
1703 b = ifcqs->ifqs_tcq_stats.xmitcnt.bytes;
1704 p = ifcqs->ifqs_tcq_stats.xmitcnt.packets;
1705 break;
1706 case PKTSCHEDT_QFQ:
1707 b = ifcqs->ifqs_qfq_stats.xmitcnt.bytes;
1708 p = ifcqs->ifqs_qfq_stats.xmitcnt.packets;
1709 break;
1710 default:
1711 b = 0;
1712 p = 0;
1713 break;
1714 }
1715
1716 if (n == 0) {
1717 qs->prev_bytes = b;
1718 qs->prev_packets = p;
1719 qs->avgn++;
1720 return;
1721 }
1722
1723 if (b >= qs->prev_bytes)
1724 qs->avg_bytes = ((qs->avg_bytes * (n - 1)) +
1725 (b - qs->prev_bytes)) / n;
1726
1727 if (p >= qs->prev_packets)
1728 qs->avg_packets = ((qs->avg_packets * (n - 1)) +
1729 (p - qs->prev_packets)) / n;
1730
1731 qs->prev_bytes = b;
1732 qs->prev_packets = p;
1733 if (n < AVGN_MAX)
1734 qs->avgn++;
1735 }
1736
1737 static char *
1738 qtype2str(classq_type_t t)
1739 {
1740 char *c;
1741
1742 switch (t) {
1743 case Q_DROPHEAD:
1744 c = "DROPHEAD";
1745 break;
1746 case Q_DROPTAIL:
1747 c = "DROPTAIL";
1748 break;
1749 case Q_RED:
1750 c = "RED";
1751 break;
1752 case Q_RIO:
1753 c = "RIO";
1754 break;
1755 case Q_BLUE:
1756 c = "BLUE";
1757 break;
1758 case Q_SFB:
1759 c = "SFB";
1760 break;
1761 default:
1762 c = "UNKNOWN";
1763 break;
1764 }
1765
1766 return (c);
1767 }
1768
1769 #define NSEC_PER_SEC 1000000000 /* nanoseconds per second */
1770 #define USEC_PER_SEC 1000000 /* nanoseconds per second */
1771 #define MSEC_PER_SEC 1000 /* nanoseconds per second */
1772
1773 static char *
1774 nsec_to_str(unsigned long long nsec)
1775 {
1776 static char buf[32];
1777 const char *u;
1778 long double n = nsec, t;
1779
1780 if (nsec >= NSEC_PER_SEC) {
1781 t = n / NSEC_PER_SEC;
1782 u = "sec ";
1783 } else if (n >= USEC_PER_SEC) {
1784 t = n / USEC_PER_SEC;
1785 u = "msec";
1786 } else if (n >= MSEC_PER_SEC) {
1787 t = n / MSEC_PER_SEC;
1788 u = "usec";
1789 } else {
1790 t = n;
1791 u = "nsec";
1792 }
1793
1794 snprintf(buf, sizeof (buf), "%-4.2Lf %4s", t, u);
1795 return (buf);
1796 }
1797
1798 static char *
1799 sched2str(unsigned int s)
1800 {
1801 char *c;
1802
1803 switch (s) {
1804 case PKTSCHEDT_NONE:
1805 c = "NONE";
1806 break;
1807 case PKTSCHEDT_CBQ:
1808 c = "CBQ";
1809 break;
1810 case PKTSCHEDT_HFSC:
1811 c = "HFSC";
1812 break;
1813 case PKTSCHEDT_PRIQ:
1814 c = "PRIQ";
1815 break;
1816 case PKTSCHEDT_FAIRQ:
1817 c = "FAIRQ";
1818 break;
1819 case PKTSCHEDT_TCQ:
1820 c = "TCQ";
1821 break;
1822 case PKTSCHEDT_QFQ:
1823 c = "QFQ";
1824 break;
1825 default:
1826 c = "UNKNOWN";
1827 break;
1828 }
1829
1830 return (c);
1831 }
1832
1833 static char *
1834 qid2str(unsigned int s)
1835 {
1836 char *c;
1837
1838 switch (s) {
1839 case 0:
1840 c = "BE";
1841 break;
1842 case 1:
1843 c = "BK_SYS";
1844 break;
1845 case 2:
1846 c = "BK";
1847 break;
1848 case 3:
1849 c = "RD";
1850 break;
1851 case 4:
1852 c = "OAM";
1853 break;
1854 case 5:
1855 c = "AV";
1856 break;
1857 case 6:
1858 c = "RV";
1859 break;
1860 case 7:
1861 c = "VI";
1862 break;
1863 case 8:
1864 c = "VO";
1865 break;
1866 case 9:
1867 c = "CTL";
1868 break;
1869 default:
1870 c = "UNKNOWN";
1871 break;
1872 }
1873
1874 return (c);
1875 }
1876
1877 static char *
1878 tcqslot2str(unsigned int s)
1879 {
1880 char *c;
1881
1882 switch (s) {
1883 case 0:
1884 case 3:
1885 case 4:
1886 c = "0,3,4";
1887 break;
1888 case 1:
1889 case 2:
1890 c = "1,2";
1891 break;
1892 case 5:
1893 case 6:
1894 case 7:
1895 c = "5-7";
1896 break;
1897 case 8:
1898 case 9:
1899 c = "8,9";
1900 break;
1901 default:
1902 c = "?";
1903 break;
1904 }
1905
1906 return (c);
1907 }
1908
1909 static char *
1910 qstate2str(unsigned int s)
1911 {
1912 char *c;
1913
1914 switch (s) {
1915 case QS_RUNNING:
1916 c = "(RUNNING)";
1917 break;
1918 case QS_SUSPENDED:
1919 c = "(SUSPENDED)";
1920 break;
1921 default:
1922 c = "(UNKNOWN)";
1923 break;
1924 }
1925
1926 return (c);
1927 }
1928
1929 #define R2S_BUFS 8
1930 #define RATESTR_MAX 16
1931
1932 static char *
1933 rate2str(long double rate)
1934 {
1935 char *buf;
1936 static char r2sbuf[R2S_BUFS][RATESTR_MAX]; /* ring bufer */
1937 static int idx = 0;
1938 int i;
1939 static const char unit[] = " KMG";
1940
1941 buf = r2sbuf[idx++];
1942 if (idx == R2S_BUFS)
1943 idx = 0;
1944
1945 for (i = 0; rate >= 1000 && i <= 3; i++)
1946 rate /= 1000;
1947
1948 if ((int)(rate * 100) % 100)
1949 snprintf(buf, RATESTR_MAX, "%.2Lf%cb", rate, unit[i]);
1950 else
1951 snprintf(buf, RATESTR_MAX, "%lld%cb", (int64_t)rate, unit[i]);
1952
1953 return (buf);
1954 }
1955
1956 void
1957 rxpollstatpr(void)
1958 {
1959 struct ifmibdata_supplemental ifmsupp;
1960 size_t miblen = sizeof (ifmsupp);
1961 struct itimerval timer_interval;
1962 struct if_rxpoll_stats *sp;
1963 sigset_t sigset, oldsigset;
1964 unsigned int ifindex;
1965 int name[6];
1966
1967 ifindex = if_nametoindex(interface);
1968 if (ifindex == 0) {
1969 fprintf(stderr, "Invalid interface name\n");
1970 return;
1971 }
1972
1973 bzero(&ifmsupp, sizeof (struct ifmibdata_supplemental));
1974
1975 loop:
1976 if (interval > 0) {
1977 /* create a timer that fires repeatedly every interval seconds */
1978 timer_interval.it_value.tv_sec = interval;
1979 timer_interval.it_value.tv_usec = 0;
1980 timer_interval.it_interval.tv_sec = interval;
1981 timer_interval.it_interval.tv_usec = 0;
1982 (void) signal(SIGALRM, catchalarm);
1983 signalled = NO;
1984 (void) setitimer(ITIMER_REAL, &timer_interval, NULL);
1985 }
1986
1987 /* Common OID prefix */
1988 name[0] = CTL_NET;
1989 name[1] = PF_LINK;
1990 name[2] = NETLINK_GENERIC;
1991 name[3] = IFMIB_IFDATA;
1992 name[4] = ifindex;
1993 name[5] = IFDATA_SUPPLEMENTAL;
1994 if (sysctl(name, 6, &ifmsupp, &miblen, NULL, 0) == -1)
1995 err(1, "sysctl IFDATA_SUPPLEMENTAL");
1996
1997 sp = &ifmsupp.ifmd_rxpoll_stats;
1998
1999 printf("%-4s [ poll on requests: %15u errors: %27u ]\n",
2000 interface, sp->ifi_poll_on_req, sp->ifi_poll_on_err);
2001 printf(" [ poll off requests: %15u errors: %27u ]\n",
2002 sp->ifi_poll_off_req, sp->ifi_poll_off_err);
2003 printf(" [ polled packets: %18llu polled bytes: %21llu ]\n",
2004 sp->ifi_poll_packets, sp->ifi_poll_bytes);
2005 printf(" [ sampled packets avg/min/max: %12u / %12u / %12u ]\n",
2006 sp->ifi_poll_packets_avg, sp->ifi_poll_packets_min,
2007 sp->ifi_poll_packets_max);
2008 printf(" [ sampled bytes avg/min/max: %12u / %12u / %12u ]\n",
2009 sp->ifi_poll_bytes_avg, sp->ifi_poll_bytes_min,
2010 sp->ifi_poll_bytes_max);
2011 printf(" [ sampled wakeups avg: %12u ]\n",
2012 sp->ifi_poll_wakeups_avg);
2013 printf(" [ packets lowat/hiwat threshold: %10u / %10u ]\n",
2014 sp->ifi_poll_packets_lowat, sp->ifi_poll_packets_hiwat);
2015 printf(" [ bytes lowat/hiwat threshold: %10u / %10u ]\n",
2016 sp->ifi_poll_bytes_lowat, sp->ifi_poll_bytes_hiwat);
2017 printf(" [ wakeups lowat/hiwat threshold: %10u / %10u ]\n",
2018 sp->ifi_poll_wakeups_lowat, sp->ifi_poll_wakeups_hiwat);
2019
2020 fflush(stdout);
2021
2022 if (interval > 0) {
2023 sigemptyset(&sigset);
2024 sigaddset(&sigset, SIGALRM);
2025 (void) sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
2026 if (!signalled) {
2027 sigemptyset(&sigset);
2028 sigsuspend(&sigset);
2029 }
2030 (void) sigprocmask(SIG_SETMASK, &oldsigset, NULL);
2031
2032 signalled = NO;
2033 goto loop;
2034 }
2035 }