2 * Copyright (c) 2008-2019 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1983, 1988, 1993
30 * The Regents of the University of California. All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
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.
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
61 #include <sys/types.h>
62 #include <sys/socket.h>
63 #include <sys/sysctl.h>
64 #include <sys/ioctl.h>
66 #include <sys/kern_control.h>
69 #include <net/if_var.h>
70 #include <net/if_dl.h>
71 #include <net/if_types.h>
72 #include <net/if_mib.h>
73 #include <net/if_llreach.h>
74 #include <net/ethernet.h>
75 #include <net/route.h>
76 #include <net/ntstat.h>
78 #include <net/pktsched/pktsched.h>
79 #include <net/classq/if_classq.h>
81 #include <netinet/in.h>
82 #include <netinet/in_var.h>
84 #include <arpa/inet.h>
103 #define ROUNDUP(a, size) (((a) & ((size) - 1)) ? (1 + ((a)|(size - 1))) : (a))
105 #define NEXT_SA(p) (struct sockaddr *) \
106 ((caddr_t)p + (p->sa_len ? ROUNDUP(p->sa_len, sizeof(uint32_t)) : \
109 static void sidewaysintpr ();
110 static void catchalarm (int);
111 static char *sec2str(time_t);
112 static void llreach_sysctl(uint32_t);
113 static char *nsec_to_str(unsigned long long);
114 static char *qtype2str(classq_type_t
);
115 static char *sched2str(unsigned int);
116 static char *qid2str(unsigned int);
117 static char *qstate2str(unsigned int);
118 static char *tcqslot2str(unsigned int);
119 static char *rate2str(long double);
120 static char *pri2str(unsigned int i
);
128 u_int64_t prev_bytes
;
129 u_int64_t prev_packets
;
130 unsigned int printed
;
134 static void print_tcqstats(int slot
, struct tcq_classstats
*,
135 struct queue_stats
*);
136 static void print_qfqstats(int slot
, struct qfq_classstats
*,
137 struct queue_stats
*);
138 static void print_sfbstats(struct sfb_stats
*);
139 static void update_avg(struct if_ifclassq_stats
*, struct queue_stats
*);
140 static void print_fq_codel_stats(int slot
, struct fq_codel_classstats
*,
141 struct queue_stats
*);
143 struct queue_stats qstats
[IFCQ_SC_MAX
];
146 char *netname6 (struct sockaddr_in6
*, struct sockaddr
*);
147 static char ntop_buf
[INET6_ADDRSTRLEN
]; /* for inet_ntop() */
151 * Display a formatted value, or a '-' in the same space.
154 show_stat(const char *fmt
, int width
, u_int64_t value
, short showvalue
)
158 /* Construct the format string */
160 snprintf(newfmt
, sizeof(newfmt
), "%%%d%s", width
, fmt
);
161 printf(newfmt
, value
);
163 snprintf(newfmt
, sizeof(newfmt
), "%%%ds", width
);
169 get_rti_info(int addrs
, struct sockaddr
*sa
, struct sockaddr
**rti_info
)
174 for (i
= 0; i
< RTAX_MAX
; i
++) {
175 if (addrs
& (1 << i
)) {
177 if (sa
->sa_len
< sizeof(struct sockaddr
))
178 len
+= sizeof(struct sockaddr
);
190 multipr(int family
, char *buf
, char *lim
)
194 for (next
= buf
; next
< lim
; ) {
195 struct ifma_msghdr2
*ifmam
= (struct ifma_msghdr2
*)next
;
196 struct sockaddr
*rti_info
[RTAX_MAX
];
200 next
+= ifmam
->ifmam_msglen
;
201 if (ifmam
->ifmam_type
== RTM_IFINFO2
)
203 else if (ifmam
->ifmam_type
!= RTM_NEWMADDR2
)
205 get_rti_info(ifmam
->ifmam_addrs
, (struct sockaddr
*)(ifmam
+ 1), rti_info
);
206 sa
= rti_info
[RTAX_IFA
];
208 if (sa
->sa_family
!= family
)
210 switch (sa
->sa_family
) {
212 struct sockaddr_in
*sin
= (struct sockaddr_in
*)sa
;
214 fmt
= routename(sin
->sin_addr
.s_addr
);
219 struct sockaddr_in6 sin6
;
221 memcpy(&sin6
, sa
, sizeof(struct sockaddr_in6
));
223 if (IN6_IS_ADDR_LINKLOCAL(&sin6
.sin6_addr
) ||
224 IN6_IS_ADDR_MC_NODELOCAL(&sin6
.sin6_addr
) ||
225 IN6_IS_ADDR_MC_LINKLOCAL(&sin6
.sin6_addr
)) {
226 sin6
.sin6_scope_id
= ntohs(*(u_int16_t
*)&sin6
.sin6_addr
.s6_addr
[2]);
227 sin6
.sin6_addr
.s6_addr
[2] = 0;
228 sin6
.sin6_addr
.s6_addr
[3] = 0;
231 printf("%23s %-19.19s(refs: %d)\n", "",
232 inet_ntop(AF_INET6
, &sin6
.sin6_addr
,
233 ntop_buf
, sizeof(ntop_buf
)),
234 ifmam
->ifmam_refcount
);
239 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)sa
;
241 switch (sdl
->sdl_type
) {
244 fmt
= ether_ntoa((struct ether_addr
*)
252 printf("%23s %s\n", "", fmt
);
257 * Print a description of the network interfaces.
260 intpr(void (*pfunc
)(char *))
262 u_int64_t opackets
= 0;
263 u_int64_t ipackets
= 0;
264 u_int64_t obytes
= 0;
265 u_int64_t ibytes
= 0;
266 u_int64_t oerrors
= 0;
267 u_int64_t ierrors
= 0;
268 u_int64_t collisions
= 0;
269 u_int64_t fpackets
= 0;
270 u_int64_t fbytes
= 0;
274 struct sockaddr
*sa
= NULL
;
279 char *buf
= NULL
, *lim
, *next
;
281 struct if_msghdr
*ifm
;
282 struct sockaddr
*rti_info
[RTAX_MAX
];
283 unsigned int ifindex
= 0;
291 ifindex
= if_nametoindex(interface
);
293 mib
[0] = CTL_NET
; // networking subsystem
294 mib
[1] = PF_ROUTE
; // type of information
295 mib
[2] = 0; // protocol (IPPROTO_xxx)
296 mib
[3] = 0; // address family
297 mib
[4] = NET_RT_IFLIST2
; // operation
299 if (sysctl(mib
, 6, NULL
, &len
, NULL
, 0) < 0)
301 if ((buf
= malloc(len
)) == NULL
) {
302 printf("malloc failed\n");
305 if (sysctl(mib
, 6, buf
, &len
, NULL
, 0) < 0) {
313 printf("%-10.10s %-5.5s %-39.39s %-39.39s %8.8s %5.5s",
314 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
316 printf("%-10.10s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
317 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
320 printf(" %8.8s %8.8s", "Itcpkts", "Ipvpkts");
322 printf(" %10.10s","Ibytes");
324 printf(" %8.8s %8.8s", "Itcbytes", "Ipvbytes");
326 printf(" %8.8s %5.5s", "Opkts", "Oerrs");
328 printf(" %8.8s %8.8s", "Otcpkts", "Opvpkts");
330 printf(" %10.10s","Obytes");
332 printf(" %8.8s %8.8s", "Otcbytes", "Opvbytes");
334 printf(" %5s", "Coll");
336 printf(" %s", "Time");
338 printf(" %s", "Drop");
340 printf(" %8.8s", "Fpkts");
342 printf(" %10.10s", "Fbytes");
347 for (next
= buf
; next
< lim
; ) {
350 struct ifmibdata_supplemental ifmsupp
;
351 u_int64_t ift_itcp
= 0; /* input tc packets */
352 u_int64_t ift_itcb
= 0; /* input tc bytes */
353 u_int64_t ift_otcp
= 0; /* output tc packets */
354 u_int64_t ift_otcb
= 0; /* output tc bytes */
355 u_int64_t ift_ipvp
= 0; /* input priv tc packets */
356 u_int64_t ift_ipvb
= 0; /* input priv tc bytes */
357 u_int64_t ift_opvp
= 0; /* output priv tc packets */
358 u_int64_t ift_opvb
= 0; /* output priv tc bytes */
360 bzero(&ifmsupp
, sizeof(struct ifmibdata_supplemental
));
364 ifm
= (struct if_msghdr
*)next
;
365 next
+= ifm
->ifm_msglen
;
367 if (ifm
->ifm_type
== RTM_IFINFO2
) {
368 struct if_msghdr2
*if2m
= (struct if_msghdr2
*)ifm
;
369 struct sockaddr_dl
*sdl
=
370 (struct sockaddr_dl
*)(if2m
+ 1);
372 size_t miblen
= sizeof(struct ifmibdata_supplemental
);
374 if (interface
!= 0 && if2m
->ifm_index
!= ifindex
)
377 /* The interface name is not a zero-ended string */
378 memcpy(name
, sdl
->sdl_data
, MIN(sizeof(name
) - 1, sdl
->sdl_nlen
));
379 name
[MIN(sizeof(name
) - 1, sdl
->sdl_nlen
)] = 0;
386 cp
= index(name
, '\0');
387 if ((if2m
->ifm_flags
& IFF_UP
) == 0)
392 * Get the interface stats. These may get
393 * overriden below on a per-interface basis.
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
;
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");
416 fpackets
= ifmsupp
.ifmd_data_extended
.ifi_fpackets
;
417 fbytes
= ifmsupp
.ifmd_data_extended
.ifi_fbytes
;
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
;
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
;
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
;
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
;
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
;
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
;
468 if (interface
!= 0 && ifam
->ifam_index
!= ifindex
)
470 get_rti_info(ifam
->ifam_addrs
,
471 (struct sockaddr
*)(ifam
+ 1), rti_info
);
472 sa
= rti_info
[RTAX_IFA
];
477 printf("%-10.10s %-5u ", name
, mtu
);
479 printf("%-5.5s %-5u ", name
, mtu
);
483 printf(lflag
? "%-39.39s " : "%-13.13s ", "none");
484 printf(lflag
? "%-39.39s " : "%-15.15s ", "none");
486 switch (sa
->sa_family
) {
488 printf(lflag
? "%-39.39s " : "%-13.13s ", "none");
489 printf(lflag
? "%-39.39s " : "%-15.15s ", "none");
493 struct sockaddr_in
*sin
=
494 (struct sockaddr_in
*)sa
;
495 struct sockaddr_in mask
;
497 mask
.sin_addr
.s_addr
= 0;
498 memcpy(&mask
, rti_info
[RTAX_NETMASK
],
499 ((struct sockaddr_in
*)
500 rti_info
[RTAX_NETMASK
])->sin_len
);
502 printf(lflag
? "%-39.39s " : "%-13.13s ",
503 netname(sin
->sin_addr
.s_addr
&
504 mask
.sin_addr
.s_addr
,
505 ntohl(mask
.sin_addr
.s_addr
)));
507 printf(lflag
? "%-39.39s " : "%-15.15s ",
508 routename(sin
->sin_addr
.s_addr
));
515 struct sockaddr_in6
*sin6
=
516 (struct sockaddr_in6
*)sa
;
517 struct sockaddr
*mask
=
518 (struct sockaddr
*)rti_info
[RTAX_NETMASK
];
520 printf(lflag
? "%-39.39s " : "%-11.11s ", netname6(sin6
, mask
));
521 printf(lflag
? "%-39.39s " : "%-17.17s ", (char *)inet_ntop(AF_INET6
,
522 &sin6
->sin6_addr
, ntop_buf
,
530 struct sockaddr_dl
*sdl
=
531 (struct sockaddr_dl
*)sa
;
533 cp
= (char *)LLADDR(sdl
);
535 snprintf(linknum
, sizeof(linknum
),
536 "<Link#%d>", sdl
->sdl_index
);
537 m
= printf(lflag
? "%-39.39s " : "%-11.11s ", linknum
);
542 m
= printf("(%d)", sa
->sa_family
);
543 for (cp
= sa
->sa_len
+ (char *)sa
;
544 --cp
> sa
->sa_data
&& (*cp
== 0);) {}
545 n
= cp
- sa
->sa_data
+ 1;
549 m
+= printf("%02x%c", *cp
++ & 0xff,
551 m
= (lflag
? 80 : 30) - m
;
560 show_stat("llu", 8, ipackets
, link_layer
|network_layer
);
562 show_stat("llu", 5, ierrors
, link_layer
);
565 show_stat("llu", 8, ift_itcp
, link_layer
|network_layer
);
567 show_stat("llu", 8, ift_ipvp
, link_layer
|network_layer
);
571 show_stat("llu", 10, ibytes
, link_layer
|network_layer
);
574 show_stat("llu", 8, ift_itcb
, link_layer
|network_layer
);
576 show_stat("llu", 8, ift_ipvb
, link_layer
|network_layer
);
580 show_stat("llu", 8, opackets
, link_layer
|network_layer
);
582 show_stat("llu", 5, oerrors
, link_layer
);
585 show_stat("llu", 8, ift_otcp
, link_layer
|network_layer
);
587 show_stat("llu", 8, ift_opvp
, link_layer
|network_layer
);
591 show_stat("llu", 10, obytes
, link_layer
|network_layer
);
594 show_stat("llu", 8, ift_otcb
, link_layer
|network_layer
);
596 show_stat("llu", 8, ift_opvb
, link_layer
|network_layer
);
600 show_stat("llu", 5, collisions
, link_layer
);
603 show_stat("d", 3, timer
, link_layer
);
607 show_stat("d", 3, drops
, link_layer
);
611 show_stat("llu", 8, fpackets
, link_layer
|network_layer
);
614 show_stat("llu", 10, fbytes
,
615 link_layer
|network_layer
);
621 multipr(sa
->sa_family
, next
, lim
);
627 SLIST_ENTRY(iftot
) chain
;
628 char ift_name
[16]; /* interface name */
629 u_int64_t ift_ip
; /* input packets */
630 u_int64_t ift_ie
; /* input errors */
631 u_int64_t ift_op
; /* output packets */
632 u_int64_t ift_oe
; /* output errors */
633 u_int64_t ift_co
; /* collisions */
634 u_int64_t ift_dr
; /* drops */
635 u_int64_t ift_ib
; /* input bytes */
636 u_int64_t ift_ob
; /* output bytes */
637 u_int64_t ift_itcp
; /* input tc packets */
638 u_int64_t ift_itcb
; /* input tc bytes */
639 u_int64_t ift_otcp
; /* output tc packets */
640 u_int64_t ift_otcb
; /* output tc bytes */
641 u_int64_t ift_ipvp
; /* input priv tc packets */
642 u_int64_t ift_ipvb
; /* input priv tc bytes */
643 u_int64_t ift_opvp
; /* output priv tc packets */
644 u_int64_t ift_opvb
; /* output priv tc bytes */
645 u_int64_t ift_fp
; /* forwarded packets */
646 u_int64_t ift_fb
; /* forwarded bytes */
649 u_char signalled
; /* set if alarm goes off "early" */
652 * Print a running summary of interface statistics.
653 * Repeat display every interval seconds, showing statistics
654 * collected over that interval. Assumes that interval is non-zero.
655 * First line printed at top of screen is always cumulative.
656 * XXX - should be rewritten to use ifmib(4).
661 struct iftot
*total
, *sum
, *interesting
;
666 unsigned int ifcount
, i
;
667 struct ifmibdata
*ifmdall
= 0;
669 sigset_t sigset
, oldsigset
;
670 struct itimerval timer_interval
;
672 /* Common OID prefix */
675 name
[2] = NETLINK_GENERIC
;
678 name
[3] = IFMIB_SYSTEM
;
679 name
[4] = IFMIB_IFCOUNT
;
680 if (sysctl(name
, 5, &ifcount
, &len
, 0, 0) == 1)
681 err(1, "sysctl IFMIB_IFCOUNT");
683 len
= ifcount
* sizeof(struct ifmibdata
);
684 ifmdall
= malloc(len
);
686 err(1, "malloc failed");
687 name
[3] = IFMIB_IFALLDATA
;
689 name
[5] = IFDATA_GENERAL
;
690 if (sysctl(name
, 6, ifmdall
, &len
, (void *)0, 0) == -1)
691 err(1, "sysctl IFMIB_IFALLDATA");
695 for (i
= 0; i
< ifcount
; i
++) {
696 struct ifmibdata
*ifmd
= ifmdall
+ i
;
698 if (interface
&& strcmp(ifmd
->ifmd_name
, interface
) == 0) {
699 if ((interesting
= calloc(ifcount
,
700 sizeof(struct iftot
))) == NULL
)
701 err(1, "malloc failed");
702 interesting_row
= if_nametoindex(interface
);
703 snprintf(interesting
->ift_name
, 16, "(%s)",
707 if ((total
= calloc(1, sizeof(struct iftot
))) == NULL
)
708 err(1, "malloc failed");
710 if ((sum
= calloc(1, sizeof(struct iftot
))) == NULL
)
711 err(1, "malloc failed");
713 /* create a timer that fires repeatedly every interval seconds */
714 timer_interval
.it_value
.tv_sec
= interval
;
715 timer_interval
.it_value
.tv_usec
= 0;
716 timer_interval
.it_interval
.tv_sec
= interval
;
717 timer_interval
.it_interval
.tv_usec
= 0;
718 (void)signal(SIGALRM
, catchalarm
);
720 (void)setitimer(ITIMER_REAL
, &timer_interval
, NULL
);
727 printf("%39s %39s %36s", "input",
728 interesting
? interesting
->ift_name
: "(Total)", "output");
730 printf("%17s %14s %16s", "input",
731 interesting
? interesting
->ift_name
: "(Total)", "output");
737 printf("%10s %5s %10s ", "packets", "errs", "bytes");
739 printf(" %10s %10s %10s %10s",
740 "tcpkts", "tcbytes", "pvpkts", "pvbytes");
741 printf("%10s %5s %10s %5s", "packets", "errs", "bytes", "colls");
743 printf(" %5.5s", "drops");
745 printf(" %10s %10s %10s %10s",
746 "tcpkts", "tcbytes", "pvpkts", "pvbytes");
748 printf(" %10s %10s", "fpackets", "fbytes");
756 if (interesting
!= NULL
) {
757 struct ifmibdata ifmd
;
758 struct ifmibdata_supplemental ifmsupp
;
760 len
= sizeof(struct ifmibdata
);
761 name
[3] = IFMIB_IFDATA
;
762 name
[4] = interesting_row
;
763 name
[5] = IFDATA_GENERAL
;
764 if (sysctl(name
, 6, &ifmd
, &len
, (void *)0, 0) == -1)
765 err(1, "sysctl IFDATA_GENERAL %d", interesting_row
);
767 len
= sizeof(struct ifmibdata_supplemental
);
768 name
[3] = IFMIB_IFDATA
;
769 name
[4] = interesting_row
;
770 name
[5] = IFDATA_SUPPLEMENTAL
;
771 if (sysctl(name
, 6, &ifmsupp
, &len
, (void *)0, 0) == -1)
772 err(1, "sysctl IFDATA_SUPPLEMENTAL %d",
776 printf("%10llu %5llu %10llu ",
777 ifmd
.ifmd_data
.ifi_ipackets
- interesting
->ift_ip
,
778 ifmd
.ifmd_data
.ifi_ierrors
- interesting
->ift_ie
,
779 ifmd
.ifmd_data
.ifi_ibytes
- interesting
->ift_ib
);
782 printf("%10llu %10llu ",
783 ifmsupp
.ifmd_traffic_class
.ifi_ibepackets
-
784 interesting
->ift_itcp
,
785 ifmsupp
.ifmd_traffic_class
.ifi_ibebytes
-
786 interesting
->ift_itcb
);
789 printf("%10llu %10llu ",
790 ifmsupp
.ifmd_traffic_class
.ifi_ibkpackets
-
791 interesting
->ift_itcp
,
792 ifmsupp
.ifmd_traffic_class
.ifi_ibkbytes
-
793 interesting
->ift_itcb
);
796 printf("%10llu %10llu ",
797 ifmsupp
.ifmd_traffic_class
.ifi_ivipackets
-
798 interesting
->ift_itcp
,
799 ifmsupp
.ifmd_traffic_class
.ifi_ivibytes
-
800 interesting
->ift_itcb
);
803 printf("%10llu %10llu ",
804 ifmsupp
.ifmd_traffic_class
.ifi_ivopackets
-
805 interesting
->ift_itcp
,
806 ifmsupp
.ifmd_traffic_class
.ifi_ivobytes
-
807 interesting
->ift_itcb
);
813 printf("%10llu %10llu ",
814 ifmsupp
.ifmd_traffic_class
.ifi_ipvpackets
-
815 interesting
->ift_ipvp
,
816 ifmsupp
.ifmd_traffic_class
.ifi_ipvbytes
-
817 interesting
->ift_ipvb
);
819 printf("%10llu %5llu %10llu %5llu",
820 ifmd
.ifmd_data
.ifi_opackets
- interesting
->ift_op
,
821 ifmd
.ifmd_data
.ifi_oerrors
- interesting
->ift_oe
,
822 ifmd
.ifmd_data
.ifi_obytes
- interesting
->ift_ob
,
823 ifmd
.ifmd_data
.ifi_collisions
- interesting
->ift_co
);
826 ifmd
.ifmd_snd_drops
- interesting
->ift_dr
);
829 printf(" %10llu %10llu",
830 ifmsupp
.ifmd_traffic_class
.ifi_obepackets
-
831 interesting
->ift_otcp
,
832 ifmsupp
.ifmd_traffic_class
.ifi_obebytes
-
833 interesting
->ift_otcb
);
836 printf(" %10llu %10llu",
837 ifmsupp
.ifmd_traffic_class
.ifi_obkpackets
-
838 interesting
->ift_otcp
,
839 ifmsupp
.ifmd_traffic_class
.ifi_obkbytes
-
840 interesting
->ift_otcb
);
843 printf(" %10llu %10llu",
844 ifmsupp
.ifmd_traffic_class
.ifi_ovipackets
-
845 interesting
->ift_otcp
,
846 ifmsupp
.ifmd_traffic_class
.ifi_ovibytes
-
847 interesting
->ift_otcb
);
850 printf(" %10llu %10llu",
851 ifmsupp
.ifmd_traffic_class
.ifi_ovopackets
-
852 interesting
->ift_otcp
,
853 ifmsupp
.ifmd_traffic_class
.ifi_ovobytes
-
854 interesting
->ift_otcb
);
860 printf("%10llu %10llu ",
861 ifmsupp
.ifmd_traffic_class
.ifi_opvpackets
-
862 interesting
->ift_opvp
,
863 ifmsupp
.ifmd_traffic_class
.ifi_opvbytes
-
864 interesting
->ift_opvb
);
867 printf("%10llu %10llu",
868 ifmsupp
.ifmd_data_extended
.ifi_fpackets
-
870 ifmsupp
.ifmd_data_extended
.ifi_fbytes
-
871 interesting
->ift_fb
);
874 interesting
->ift_ip
= ifmd
.ifmd_data
.ifi_ipackets
;
875 interesting
->ift_ie
= ifmd
.ifmd_data
.ifi_ierrors
;
876 interesting
->ift_ib
= ifmd
.ifmd_data
.ifi_ibytes
;
877 interesting
->ift_op
= ifmd
.ifmd_data
.ifi_opackets
;
878 interesting
->ift_oe
= ifmd
.ifmd_data
.ifi_oerrors
;
879 interesting
->ift_ob
= ifmd
.ifmd_data
.ifi_obytes
;
880 interesting
->ift_co
= ifmd
.ifmd_data
.ifi_collisions
;
881 interesting
->ift_dr
= ifmd
.ifmd_snd_drops
;
883 /* private counters */
886 interesting
->ift_itcp
=
887 ifmsupp
.ifmd_traffic_class
.ifi_ibepackets
;
888 interesting
->ift_itcb
=
889 ifmsupp
.ifmd_traffic_class
.ifi_ibebytes
;
890 interesting
->ift_otcp
=
891 ifmsupp
.ifmd_traffic_class
.ifi_obepackets
;
892 interesting
->ift_otcb
=
893 ifmsupp
.ifmd_traffic_class
.ifi_obebytes
;
896 interesting
->ift_itcp
=
897 ifmsupp
.ifmd_traffic_class
.ifi_ibkpackets
;
898 interesting
->ift_itcb
=
899 ifmsupp
.ifmd_traffic_class
.ifi_ibkbytes
;
900 interesting
->ift_otcp
=
901 ifmsupp
.ifmd_traffic_class
.ifi_obkpackets
;
902 interesting
->ift_otcb
=
903 ifmsupp
.ifmd_traffic_class
.ifi_obkbytes
;
906 interesting
->ift_itcp
=
907 ifmsupp
.ifmd_traffic_class
.ifi_ivipackets
;
908 interesting
->ift_itcb
=
909 ifmsupp
.ifmd_traffic_class
.ifi_ivibytes
;
910 interesting
->ift_otcp
=
911 ifmsupp
.ifmd_traffic_class
.ifi_ovipackets
;
912 interesting
->ift_otcb
=
913 ifmsupp
.ifmd_traffic_class
.ifi_ovibytes
;
916 interesting
->ift_itcp
=
917 ifmsupp
.ifmd_traffic_class
.ifi_ivopackets
;
918 interesting
->ift_itcb
=
919 ifmsupp
.ifmd_traffic_class
.ifi_ivobytes
;
920 interesting
->ift_otcp
=
921 ifmsupp
.ifmd_traffic_class
.ifi_ovopackets
;
922 interesting
->ift_otcb
=
923 ifmsupp
.ifmd_traffic_class
.ifi_ovobytes
;
929 interesting
->ift_ipvp
=
930 ifmsupp
.ifmd_traffic_class
.ifi_ipvpackets
;
931 interesting
->ift_ipvb
=
932 ifmsupp
.ifmd_traffic_class
.ifi_ipvbytes
;
933 interesting
->ift_opvp
=
934 ifmsupp
.ifmd_traffic_class
.ifi_opvpackets
;
935 interesting
->ift_opvb
=
936 ifmsupp
.ifmd_traffic_class
.ifi_opvbytes
;
938 interesting
->ift_fp
= ifmsupp
.ifmd_data_extended
.ifi_fpackets
;
939 interesting
->ift_fb
= ifmsupp
.ifmd_data_extended
.ifi_fbytes
;
941 unsigned int latest_ifcount
;
942 struct ifmibdata_supplemental
*ifmsuppall
= NULL
;
945 name
[3] = IFMIB_SYSTEM
;
946 name
[4] = IFMIB_IFCOUNT
;
947 if (sysctl(name
, 5, &latest_ifcount
, &len
, 0, 0) == 1)
948 err(1, "sysctl IFMIB_IFCOUNT");
949 if (latest_ifcount
> ifcount
) {
950 ifcount
= latest_ifcount
;
951 len
= ifcount
* sizeof(struct ifmibdata
);
953 ifmdall
= malloc(len
);
955 err(1, "malloc ifmdall failed");
956 } else if (latest_ifcount
> ifcount
) {
957 ifcount
= latest_ifcount
;
958 len
= ifcount
* sizeof(struct ifmibdata
);
960 len
= ifcount
* sizeof(struct ifmibdata
);
961 name
[3] = IFMIB_IFALLDATA
;
963 name
[5] = IFDATA_GENERAL
;
964 if (sysctl(name
, 6, ifmdall
, &len
, (void *)0, 0) == -1)
965 err(1, "sysctl IFMIB_IFALLDATA");
967 len
= ifcount
* sizeof(struct ifmibdata_supplemental
);
968 ifmsuppall
= malloc(len
);
969 if (ifmsuppall
== NULL
)
970 err(1, "malloc ifmsuppall failed");
971 name
[3] = IFMIB_IFALLDATA
;
973 name
[5] = IFDATA_SUPPLEMENTAL
;
974 if (sysctl(name
, 6, ifmsuppall
, &len
, (void *)0, 0) == -1)
975 err(1, "sysctl IFMIB_IFALLDATA SUPPLEMENTAL");
995 for (i
= 0; i
< ifcount
; i
++) {
996 struct ifmibdata
*ifmd
= ifmdall
+ i
;
997 struct ifmibdata_supplemental
*ifmsupp
= ifmsuppall
+ i
;
999 sum
->ift_ip
+= ifmd
->ifmd_data
.ifi_ipackets
;
1000 sum
->ift_ie
+= ifmd
->ifmd_data
.ifi_ierrors
;
1001 sum
->ift_ib
+= ifmd
->ifmd_data
.ifi_ibytes
;
1002 sum
->ift_op
+= ifmd
->ifmd_data
.ifi_opackets
;
1003 sum
->ift_oe
+= ifmd
->ifmd_data
.ifi_oerrors
;
1004 sum
->ift_ob
+= ifmd
->ifmd_data
.ifi_obytes
;
1005 sum
->ift_co
+= ifmd
->ifmd_data
.ifi_collisions
;
1006 sum
->ift_dr
+= ifmd
->ifmd_snd_drops
;
1007 /* private counters */
1008 if (prioflag
>= 0) {
1011 sum
->ift_itcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ibepackets
;
1012 sum
->ift_itcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ibebytes
;
1013 sum
->ift_otcp
+= ifmsupp
->ifmd_traffic_class
.ifi_obepackets
;
1014 sum
->ift_otcb
+= ifmsupp
->ifmd_traffic_class
.ifi_obebytes
;
1017 sum
->ift_itcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ibkpackets
;
1018 sum
->ift_itcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ibkbytes
;
1019 sum
->ift_otcp
+= ifmsupp
->ifmd_traffic_class
.ifi_obkpackets
;
1020 sum
->ift_otcb
+= ifmsupp
->ifmd_traffic_class
.ifi_obkbytes
;
1023 sum
->ift_itcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ivipackets
;
1024 sum
->ift_itcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ivibytes
;
1025 sum
->ift_otcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ovipackets
;
1026 sum
->ift_otcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ovibytes
;
1029 sum
->ift_itcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ivopackets
;
1030 sum
->ift_itcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ivobytes
;
1031 sum
->ift_otcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ovopackets
;
1032 sum
->ift_otcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ovobytes
;
1037 sum
->ift_ipvp
+= ifmsupp
->ifmd_traffic_class
.ifi_ipvpackets
;
1038 sum
->ift_ipvb
+= ifmsupp
->ifmd_traffic_class
.ifi_ipvbytes
;
1039 sum
->ift_opvp
+= ifmsupp
->ifmd_traffic_class
.ifi_opvpackets
;
1040 sum
->ift_opvb
+= ifmsupp
->ifmd_traffic_class
.ifi_opvbytes
;
1042 sum
->ift_fp
+= ifmsupp
->ifmd_data_extended
.ifi_fpackets
;
1043 sum
->ift_fb
+= ifmsupp
->ifmd_data_extended
.ifi_fbytes
;
1046 printf("%10llu %5llu %10llu ",
1047 sum
->ift_ip
- total
->ift_ip
,
1048 sum
->ift_ie
- total
->ift_ie
,
1049 sum
->ift_ib
- total
->ift_ib
);
1051 printf(" %10llu %10llu %10llu %10llu",
1052 sum
->ift_itcp
- total
->ift_itcp
,
1053 sum
->ift_itcb
- total
->ift_itcb
,
1054 sum
->ift_ipvp
- total
->ift_ipvp
,
1055 sum
->ift_ipvb
- total
->ift_ipvb
);
1056 printf("%10llu %5llu %10llu %5llu",
1057 sum
->ift_op
- total
->ift_op
,
1058 sum
->ift_oe
- total
->ift_oe
,
1059 sum
->ift_ob
- total
->ift_ob
,
1060 sum
->ift_co
- total
->ift_co
);
1062 printf(" %5llu", sum
->ift_dr
- total
->ift_dr
);
1064 printf(" %10llu %10llu %10llu %10llu",
1065 sum
->ift_otcp
- total
->ift_otcp
,
1066 sum
->ift_otcb
- total
->ift_otcb
,
1067 sum
->ift_opvp
- total
->ift_opvp
,
1068 sum
->ift_opvb
- total
->ift_opvb
);
1070 printf(" %10llu %10llu",
1071 sum
->ift_fp
- total
->ift_fp
,
1072 sum
->ift_fb
- total
->ift_fb
);
1081 sigemptyset(&sigset
);
1082 sigaddset(&sigset
, SIGALRM
);
1083 (void)sigprocmask(SIG_BLOCK
, &sigset
, &oldsigset
);
1085 sigemptyset(&sigset
);
1086 sigsuspend(&sigset
);
1088 (void)sigprocmask(SIG_SETMASK
, &oldsigset
, NULL
);
1101 intervalpr(void (*pr
)(uint32_t, char *, int), uint32_t off
, char *name
, int af
)
1103 struct itimerval timer_interval
;
1104 sigset_t sigset
, oldsigset
;
1106 /* create a timer that fires repeatedly every interval seconds */
1107 timer_interval
.it_value
.tv_sec
= interval
;
1108 timer_interval
.it_value
.tv_usec
= 0;
1109 timer_interval
.it_interval
.tv_sec
= interval
;
1110 timer_interval
.it_interval
.tv_usec
= 0;
1111 (void) signal(SIGALRM
, catchalarm
);
1113 (void) setitimer(ITIMER_REAL
, &timer_interval
, NULL
);
1119 sigemptyset(&sigset
);
1120 sigaddset(&sigset
, SIGALRM
);
1121 (void) sigprocmask(SIG_BLOCK
, &sigset
, &oldsigset
);
1123 sigemptyset(&sigset
);
1124 sigsuspend(&sigset
);
1126 (void) sigprocmask(SIG_SETMASK
, &oldsigset
, NULL
);
1132 * Called if an interval expires before sidewaysintpr has completed a loop.
1133 * Sets a flag to not wait for the alarm.
1136 catchalarm(int signo
)
1145 static char result
[256];
1146 int days
, hours
, mins
, secs
;
1150 days
= total
/ 3600 / 24;
1151 hours
= (total
/ 3600) % 24;
1152 mins
= (total
/ 60) % 60;
1157 p
+= snprintf(p
, sizeof(result
) - (p
- result
), "%dd", days
);
1159 if (!first
|| hours
) {
1161 p
+= snprintf(p
, sizeof(result
) - (p
- result
), "%dh", hours
);
1163 if (!first
|| mins
) {
1165 p
+= snprintf(p
, sizeof(result
) - (p
- result
), "%dm", mins
);
1167 snprintf(p
, sizeof(result
) - (p
- result
), "%ds", secs
);
1173 intpr_ri(void (*pfunc
)(char *))
1176 char *buf
= NULL
, *lim
, *next
;
1178 unsigned int ifindex
= 0;
1179 struct if_msghdr2
*if2m
;
1181 if (interface
!= 0) {
1182 ifindex
= if_nametoindex(interface
);
1184 printf("interface name is not valid: %s\n", interface
);
1189 mib
[0] = CTL_NET
; /* networking subsystem */
1190 mib
[1] = PF_ROUTE
; /* type of information */
1191 mib
[2] = 0; /* protocol (IPPROTO_xxx) */
1192 mib
[3] = 0; /* address family */
1193 mib
[4] = NET_RT_IFLIST2
; /* operation */
1195 if (sysctl(mib
, 6, NULL
, &len
, NULL
, 0) < 0)
1197 if ((buf
= malloc(len
)) == NULL
) {
1198 printf("malloc failed\n");
1201 if (sysctl(mib
, 6, buf
, &len
, NULL
, 0) < 0) {
1206 printf("%-6s %-17s %8.8s %-9.9s %4s %4s",
1207 "Proto", "Linklayer Address", "Netif", "Expire", "Refs",
1210 printf(" %7s %7s %7s", "RSSI", "LQM", "NPM");
1214 if2m
= (struct if_msghdr2
*)buf
;
1216 for (next
= buf
; next
< lim
; ) {
1217 if2m
= (struct if_msghdr2
*)next
;
1218 next
+= if2m
->ifm_msglen
;
1220 if (if2m
->ifm_type
!= RTM_IFINFO2
)
1222 else if (interface
!= 0 && if2m
->ifm_index
!= ifindex
)
1225 llreach_sysctl(if2m
->ifm_index
);
1231 llreach_sysctl(uint32_t ifindex
)
1233 #define MAX_SYSCTL_TRY 5
1234 int mib
[6], i
, ntry
= 0;
1235 size_t mibsize
, len
, needed
, cnt
;
1236 struct if_llreach_info
*lri
;
1237 struct timeval time
;
1239 char ifname
[IF_NAMESIZE
];
1241 bzero(&mib
, sizeof (mib
));
1242 mibsize
= sizeof (mib
) / sizeof (mib
[0]);
1243 if (sysctlnametomib("net.link.generic.system.llreach_info", mib
,
1245 perror("sysctlnametomib");
1252 mibsize
= sizeof (mib
) / sizeof (mib
[0]);
1254 if (sysctl(mib
, mibsize
, NULL
, &needed
, NULL
, 0) == -1) {
1255 perror("sysctl net.link.generic.system.llreach_info");
1258 if ((buf
= malloc(needed
)) == NULL
) {
1262 if (sysctl(mib
, mibsize
, buf
, &needed
, NULL
, 0) == -1) {
1263 if (errno
!= ENOMEM
|| ++ntry
>= MAX_SYSCTL_TRY
) {
1270 } while (buf
== NULL
);
1273 cnt
= len
/ sizeof (*lri
);
1274 lri
= (struct if_llreach_info
*)buf
;
1276 gettimeofday(&time
, 0);
1277 if (if_indextoname(ifindex
, ifname
) == NULL
)
1278 snprintf(ifname
, sizeof (ifname
), "%s", "?");
1280 for (i
= 0; i
< cnt
; i
++, lri
++) {
1281 printf("0x%-4x %-17s %8.8s ", lri
->lri_proto
,
1282 ether_ntoa((struct ether_addr
*)lri
->lri_addr
), ifname
);
1284 if (lri
->lri_expire
> time
.tv_sec
)
1285 printf("%-9.9s", sec2str(lri
->lri_expire
- time
.tv_sec
));
1286 else if (lri
->lri_expire
== 0)
1287 printf("%-9.9s", "permanent");
1289 printf("%-9.9s", "expired");
1291 printf(" %4d", lri
->lri_refcnt
);
1292 if (lri
->lri_probes
)
1293 printf(" %4d", lri
->lri_probes
);
1296 if (!lri
->lri_probes
)
1297 printf(" %-4.4s", "none");
1299 if (lri
->lri_rssi
!= IFNET_RSSI_UNKNOWN
)
1300 printf(" %7d", lri
->lri_rssi
);
1302 printf(" %-7.7s", "unknown");
1304 switch (lri
->lri_lqm
)
1306 case IFNET_LQM_THRESH_OFF
:
1307 printf(" %-7.7s", "off");
1309 case IFNET_LQM_THRESH_UNKNOWN
:
1310 printf(" %-7.7s", "unknown");
1312 case IFNET_LQM_THRESH_POOR
:
1313 printf(" %-7.7s", "poor");
1315 case IFNET_LQM_THRESH_GOOD
:
1316 printf(" %-7.7s", "good");
1319 printf(" %7d", lri
->lri_lqm
);
1323 switch (lri
->lri_npm
)
1325 case IFNET_NPM_THRESH_UNKNOWN
:
1326 printf(" %-7.7s", "unknown");
1328 case IFNET_NPM_THRESH_NEAR
:
1329 printf(" %-7.7s", "near");
1331 case IFNET_NPM_THRESH_GENERAL
:
1332 printf(" %-7.7s", "general");
1334 case IFNET_NPM_THRESH_FAR
:
1335 printf(" %-7.7s", "far");
1338 printf(" %7d", lri
->lri_npm
);
1344 len
-= sizeof (*lri
);
1348 fprintf(stderr
, "warning: %u trailing bytes from %s\n",
1349 (unsigned int)len
, "net.link.generic.system.llreach_info");
1354 #undef MAX_SYSCTL_TRY
1360 unsigned int ifindex
;
1361 struct itimerval timer_interval
;
1362 struct if_qstatsreq ifqr
;
1363 struct if_ifclassq_stats
*ifcqs
;
1364 sigset_t sigset
, oldsigset
;
1365 u_int32_t scheduler
;
1368 if (cq
< -1 || cq
>= IFCQ_SC_MAX
) {
1369 fprintf(stderr
, "Invalid classq index (range is 0-%d)\n",
1373 ifindex
= if_nametoindex(interface
);
1375 fprintf(stderr
, "Invalid interface name\n");
1379 ifcqs
= malloc(sizeof (*ifcqs
));
1380 if (ifcqs
== NULL
) {
1381 fprintf(stderr
, "Unable to allocate memory\n");
1385 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
1386 perror("Warning: socket(AF_INET)");
1391 bzero(&ifqr
, sizeof (ifqr
));
1392 strlcpy(ifqr
.ifqr_name
, interface
, sizeof (ifqr
.ifqr_name
));
1393 ifqr
.ifqr_buf
= ifcqs
;
1394 ifqr
.ifqr_len
= sizeof (*ifcqs
);
1398 /* create a timer that fires repeatedly every interval seconds */
1399 timer_interval
.it_value
.tv_sec
= interval
;
1400 timer_interval
.it_value
.tv_usec
= 0;
1401 timer_interval
.it_interval
.tv_sec
= interval
;
1402 timer_interval
.it_interval
.tv_usec
= 0;
1403 (void) signal(SIGALRM
, catchalarm
);
1405 (void) setitimer(ITIMER_REAL
, &timer_interval
, NULL
);
1409 if (ioctl(s
, SIOCGIFQUEUESTATS
, (char *)&ifqr
) < 0) {
1410 if (errno
== ENXIO
) {
1411 printf("Queue statistics are not available on %s\n",
1414 perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
1418 scheduler
= ifcqs
->ifqs_scheduler
;
1419 tcq
= (scheduler
== PKTSCHEDT_TCQ
);
1422 "%s [ sched: %9s %sqlength: %3d/%3d ]\n",
1423 interface
, tcq
? " " : "", sched2str(ifcqs
->ifqs_scheduler
),
1424 tcq
? "" : " ", ifcqs
->ifqs_len
, ifcqs
->ifqs_maxlen
);
1425 printf("%s [ pkts: %10llu %sbytes: %10llu "
1426 "%sdropped pkts: %6llu bytes: %6llu ]\n",
1427 (scheduler
!= PKTSCHEDT_TCQ
) ? "" : " ",
1428 ifcqs
->ifqs_xmitcnt
.packets
, tcq
? "" : " ",
1429 ifcqs
->ifqs_xmitcnt
.bytes
, tcq
? "" : " ",
1430 ifcqs
->ifqs_dropcnt
.packets
, ifcqs
->ifqs_dropcnt
.bytes
);
1432 for (n
= 0; n
< IFCQ_SC_MAX
; n
++) {
1433 qstats
[n
].printed
= 0;
1437 if (ioctl(s
, SIOCGIFQUEUESTATS
, (char *)&ifqr
) < 0) {
1438 perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
1441 qstats
[n
].handle
= ifcqs
->ifqs_tcq_stats
.class_handle
;
1444 for (n
= 0; n
< IFCQ_SC_MAX
&& scheduler
!= PKTSCHEDT_NONE
; n
++) {
1445 if (cq
>= 0 && cq
!= n
)
1449 if (ioctl(s
, SIOCGIFQUEUESTATS
, (char *)&ifqr
) < 0) {
1450 perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
1454 update_avg(ifcqs
, &qstats
[n
]);
1456 switch (scheduler
) {
1458 print_tcqstats(n
, &ifcqs
->ifqs_tcq_stats
,
1462 print_qfqstats(n
, &ifcqs
->ifqs_qfq_stats
,
1465 case PKTSCHEDT_FQ_CODEL
:
1466 print_fq_codel_stats(n
,
1467 &ifcqs
->ifqs_fq_codel_stats
,
1470 case PKTSCHEDT_NONE
:
1479 sigemptyset(&sigset
);
1480 sigaddset(&sigset
, SIGALRM
);
1481 (void) sigprocmask(SIG_BLOCK
, &sigset
, &oldsigset
);
1483 sigemptyset(&sigset
);
1484 sigsuspend(&sigset
);
1486 (void) sigprocmask(SIG_SETMASK
, &oldsigset
, NULL
);
1498 print_tcqstats(int slot
, struct tcq_classstats
*cs
, struct queue_stats
*qs
)
1505 qs
->handle
= cs
->class_handle
;
1508 for (n
= 0; n
< IFCQ_SC_MAX
; n
++) {
1509 if (&qstats
[n
] != qs
&& qstats
[n
].handle
== qs
->handle
)
1510 qstats
[n
].printed
++;
1513 printf("%5s: [ pkts: %10llu bytes: %10llu "
1514 "dropped pkts: %6llu bytes: %6llu ]\n", tcqslot2str(slot
),
1515 (unsigned long long)cs
->xmitcnt
.packets
,
1516 (unsigned long long)cs
->xmitcnt
.bytes
,
1517 (unsigned long long)cs
->dropcnt
.packets
,
1518 (unsigned long long)cs
->dropcnt
.bytes
);
1519 printf(" [ qlength: %3d/%3d qalg: %11s "
1520 "svc class: %9s %-13s ]\n", cs
->qlength
, cs
->qlimit
,
1521 qtype2str(cs
->qtype
), qid2str(cs
->class_handle
),
1522 qstate2str(cs
->qstate
));
1524 if (qs
->avgn
>= 2) {
1525 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1526 qs
->avg_packets
/ interval
,
1527 rate2str((8 * qs
->avg_bytes
) / interval
));
1533 switch (cs
->qtype
) {
1535 print_sfbstats(&cs
->sfb
);
1543 print_qfqstats(int slot
, struct qfq_classstats
*cs
, struct queue_stats
*qs
)
1545 printf(" %2d: [ pkts: %10llu bytes: %10llu "
1546 "dropped pkts: %6llu bytes: %6llu ]\n", slot
,
1547 (unsigned long long)cs
->xmitcnt
.packets
,
1548 (unsigned long long)cs
->xmitcnt
.bytes
,
1549 (unsigned long long)cs
->dropcnt
.packets
,
1550 (unsigned long long)cs
->dropcnt
.bytes
);
1551 printf(" [ qlength: %3d/%3d index: %10u weight: %12u "
1552 "lmax: %7u ]\n", cs
->qlength
, cs
->qlimit
, cs
->index
,
1553 cs
->weight
, cs
->lmax
);
1554 printf(" [ qalg: %10s svc class: %6s %-35s ]\n",
1555 qtype2str(cs
->qtype
), qid2str(cs
->class_handle
),
1556 qstate2str(cs
->qstate
));
1558 if (qs
->avgn
>= 2) {
1559 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1560 qs
->avg_packets
/ interval
,
1561 rate2str((8 * qs
->avg_bytes
) / interval
));
1567 switch (cs
->qtype
) {
1569 print_sfbstats(&cs
->sfb
);
1577 print_fq_codel_stats(int pri
, struct fq_codel_classstats
*fqst
,
1578 struct queue_stats
*qs
)
1582 if (fqst
->fcls_service_class
== 0 && fqst
->fcls_pri
== 0)
1584 printf("=====================================================\n");
1585 printf(" [ pri: %s (%d)\tsrv_cl: 0x%x\tquantum: %d\tdrr_max: %d ]\n",
1586 pri2str(fqst
->fcls_pri
), fqst
->fcls_pri
,
1587 fqst
->fcls_service_class
, fqst
->fcls_quantum
,
1588 fqst
->fcls_drr_max
);
1589 printf(" [ queued pkts: %llu\tbytes: %llu ]\n",
1590 fqst
->fcls_pkt_cnt
, fqst
->fcls_byte_cnt
);
1591 printf(" [ dequeued pkts: %llu\tbytes: %llu ]\n",
1592 fqst
->fcls_dequeue
, fqst
->fcls_dequeue_bytes
);
1593 printf(" [ budget: %lld\ttarget qdelay: %10s\t",
1594 fqst
->fcls_budget
, nsec_to_str(fqst
->fcls_target_qdelay
));
1595 printf("update interval:%10s ]\n",
1596 nsec_to_str(fqst
->fcls_update_interval
));
1597 printf(" [ flow control: %u\tfeedback: %u\tstalls: %u\tfailed: %u ]\n",
1598 fqst
->fcls_flow_control
, fqst
->fcls_flow_feedback
,
1599 fqst
->fcls_dequeue_stall
, fqst
->fcls_flow_control_fail
);
1600 printf(" [ drop overflow: %llu\tearly: %llu\tmemfail: %u\tduprexmt:%u ]\n",
1601 fqst
->fcls_drop_overflow
, fqst
->fcls_drop_early
,
1602 fqst
->fcls_drop_memfailure
, fqst
->fcls_dup_rexmts
);
1603 printf(" [ flows total: %u\tnew: %u\told: %u ]\n",
1604 fqst
->fcls_flows_cnt
,
1605 fqst
->fcls_newflows_cnt
, fqst
->fcls_oldflows_cnt
);
1606 printf(" [ throttle on: %u\toff: %u\tdrop: %u ]\n",
1607 fqst
->fcls_throttle_on
, fqst
->fcls_throttle_off
,
1608 fqst
->fcls_throttle_drops
);
1613 if (fqst
->fcls_flowstats_cnt
> 0) {
1614 printf("Flowhash\tBytes\tMin qdelay\tFlags\t\n");
1615 for (i
= 0; i
< fqst
->fcls_flowstats_cnt
; i
++) {
1616 printf("%u\t%u\t%14s\t",
1617 fqst
->fcls_flowstats
[i
].fqst_flowhash
,
1618 fqst
->fcls_flowstats
[i
].fqst_bytes
,
1619 nsec_to_str(fqst
->fcls_flowstats
[i
].fqst_min_qdelay
));
1620 if (fqst
->fcls_flowstats
[i
].fqst_flags
&
1621 FQ_FLOWSTATS_OLD_FLOW
)
1623 if (fqst
->fcls_flowstats
[i
].fqst_flags
&
1624 FQ_FLOWSTATS_NEW_FLOW
)
1626 if (fqst
->fcls_flowstats
[i
].fqst_flags
&
1627 FQ_FLOWSTATS_LARGE_FLOW
)
1629 if (fqst
->fcls_flowstats
[i
].fqst_flags
&
1630 FQ_FLOWSTATS_DELAY_HIGH
)
1632 if (fqst
->fcls_flowstats
[i
].fqst_flags
&
1633 FQ_FLOWSTATS_FLOWCTL_ON
)
1641 print_sfbstats(struct sfb_stats
*sfb
)
1643 struct sfbstats
*sp
= &sfb
->sfbstats
;
1644 int i
, j
, cur
= sfb
->current
;
1647 printf(" [target delay: %14s ",
1648 nsec_to_str(sfb
->target_qdelay
));
1649 printf("update interval: %14s]\n",
1650 nsec_to_str(sfb
->update_interval
));
1651 printf(" [ early drop: %12llu rlimit drop: %11llu "
1652 "marked: %11llu ]\n",
1653 sp
->drop_early
, sp
->drop_pbox
, sp
->marked_packets
);
1654 printf(" [ penalized: %13llu rehash cnt: %12llu "
1655 "current: %10u ]\n", sp
->pbox_packets
, sp
->num_rehash
, cur
);
1656 printf(" [ deque avg: %13s ", nsec_to_str(sp
->dequeue_avg
));
1657 printf("rehash intvl: %11s]\n", nsec_to_str(sp
->rehash_intval
));
1658 printf(" [ holdtime: %14s ", nsec_to_str(sp
->hold_time
));
1659 printf("pboxtime: %14s ]\n", nsec_to_str(sp
->pbox_time
));
1660 printf(" [ allocation: %12u drop thresh: %11u ]\n",
1661 sfb
->allocation
, sfb
->dropthresh
);
1662 printf(" [ flow controlled: %7llu adv feedback: %10llu ]\n",
1663 sp
->flow_controlled
, sp
->flow_feedback
);
1664 printf(" [ min queue delay: %10s delay_fcthreshold: %12u]\n "
1665 " [stalls: %12llu]\n",
1666 nsec_to_str(sfb
->min_estdelay
), sfb
->delay_fcthreshold
,
1669 printf("\n\t\t\t\tCurrent bins (set %d)", cur
);
1670 for (i
= 0; i
< SFB_LEVELS
; ++i
) {
1674 printf("\n\tLevel: %d\n", i
);
1675 for (j
= 0; j
< SFB_BINS
; ++j
) {
1677 printf("\t%6d:\t", j
+ 1);
1678 p
= sfb
->binstats
[cur
].stats
[i
][j
].pmark
;
1679 q
= sfb
->binstats
[cur
].stats
[i
][j
].pkts
;
1681 p
/= (1 << SFB_FP_SHIFT
);
1682 printf("[%1.4f %4u]", p
, q
);
1686 if (j
> 0 && ((j
+ 1) % 4) == 0)
1692 printf("\n\t\t\t\tWarm up bins (set %d)", cur
);
1693 for (i
= 0; i
< SFB_LEVELS
; ++i
) {
1697 printf("\n\tLevel: %d\n", i
);
1698 for (j
= 0; j
< SFB_BINS
; ++j
) {
1700 printf("\t%6d:\t", j
+ 1);
1701 p
= sfb
->binstats
[cur
].stats
[i
][j
].pmark
;
1702 q
= sfb
->binstats
[cur
].stats
[i
][j
].pkts
;
1704 p
/= (1 << SFB_FP_SHIFT
);
1705 printf("[%1.4f %4u]", p
, q
);
1709 if (j
> 0 && ((j
+ 1) % 4) == 0)
1717 update_avg(struct if_ifclassq_stats
*ifcqs
, struct queue_stats
*qs
)
1724 switch (ifcqs
->ifqs_scheduler
) {
1726 b
= ifcqs
->ifqs_tcq_stats
.xmitcnt
.bytes
;
1727 p
= ifcqs
->ifqs_tcq_stats
.xmitcnt
.packets
;
1730 b
= ifcqs
->ifqs_qfq_stats
.xmitcnt
.bytes
;
1731 p
= ifcqs
->ifqs_qfq_stats
.xmitcnt
.packets
;
1733 case PKTSCHEDT_FQ_CODEL
:
1734 b
= ifcqs
->ifqs_fq_codel_stats
.fcls_dequeue_bytes
;
1735 p
= ifcqs
->ifqs_fq_codel_stats
.fcls_dequeue
;
1745 qs
->prev_packets
= p
;
1750 if (b
>= qs
->prev_bytes
)
1751 qs
->avg_bytes
= ((qs
->avg_bytes
* (n
- 1)) +
1752 (b
- qs
->prev_bytes
)) / n
;
1754 if (p
>= qs
->prev_packets
)
1755 qs
->avg_packets
= ((qs
->avg_packets
* (n
- 1)) +
1756 (p
- qs
->prev_packets
)) / n
;
1759 qs
->prev_packets
= p
;
1765 qtype2str(classq_type_t t
)
1787 #define NSEC_PER_SEC 1000000000 /* nanoseconds per second */
1788 #define USEC_PER_SEC 1000000 /* microseconds per second */
1789 #define MSEC_PER_SEC 1000 /* milliseconds per second */
1792 nsec_to_str(unsigned long long nsec
)
1794 static char buf
[32];
1796 long double n
= nsec
, t
;
1798 if (nsec
>= NSEC_PER_SEC
) {
1799 t
= n
/ NSEC_PER_SEC
;
1801 } else if (n
>= USEC_PER_SEC
) {
1802 t
= n
/ USEC_PER_SEC
;
1804 } else if (n
>= MSEC_PER_SEC
) {
1805 t
= n
/ MSEC_PER_SEC
;
1812 snprintf(buf
, sizeof (buf
), "%-4.2Lf %4s", t
, u
);
1817 sched2str(unsigned int s
)
1822 case PKTSCHEDT_NONE
:
1831 case PKTSCHEDT_FQ_CODEL
:
1843 qid2str(unsigned int s
)
1887 tcqslot2str(unsigned int s
)
1919 pri2str(unsigned int i
)
1961 qstate2str(unsigned int s
)
1981 #define RATESTR_MAX 16
1984 rate2str(long double rate
)
1987 static char r2sbuf
[R2S_BUFS
][RATESTR_MAX
]; /* ring bufer */
1990 static const char unit
[] = " KMG";
1992 buf
= r2sbuf
[idx
++];
1993 if (idx
== R2S_BUFS
)
1996 for (i
= 0; rate
>= 1000 && i
<= 3; i
++)
1999 if ((int)(rate
* 100) % 100)
2000 snprintf(buf
, RATESTR_MAX
, "%.2Lf%cb", rate
, unit
[i
]);
2002 snprintf(buf
, RATESTR_MAX
, "%lld%cb", (int64_t)rate
, unit
[i
]);
2010 struct ifmibdata_supplemental ifmsupp
;
2011 size_t miblen
= sizeof (ifmsupp
);
2012 struct itimerval timer_interval
;
2013 struct if_rxpoll_stats
*sp
;
2014 struct if_netif_stats
*np
;
2015 sigset_t sigset
, oldsigset
;
2016 unsigned int ifindex
;
2019 ifindex
= if_nametoindex(interface
);
2021 fprintf(stderr
, "Invalid interface name\n");
2025 bzero(&ifmsupp
, sizeof (struct ifmibdata_supplemental
));
2029 /* create a timer that fires repeatedly every interval seconds */
2030 timer_interval
.it_value
.tv_sec
= interval
;
2031 timer_interval
.it_value
.tv_usec
= 0;
2032 timer_interval
.it_interval
.tv_sec
= interval
;
2033 timer_interval
.it_interval
.tv_usec
= 0;
2034 (void) signal(SIGALRM
, catchalarm
);
2036 (void) setitimer(ITIMER_REAL
, &timer_interval
, NULL
);
2039 /* Common OID prefix */
2042 name
[2] = NETLINK_GENERIC
;
2043 name
[3] = IFMIB_IFDATA
;
2045 name
[5] = IFDATA_SUPPLEMENTAL
;
2046 if (sysctl(name
, 6, &ifmsupp
, &miblen
, NULL
, 0) == -1)
2047 err(1, "sysctl IFDATA_SUPPLEMENTAL");
2049 sp
= &ifmsupp
.ifmd_rxpoll_stats
;
2051 printf("%-4s [ poll on requests: %15u errors: %27u ]\n",
2052 interface
, sp
->ifi_poll_on_req
, sp
->ifi_poll_on_err
);
2053 printf(" [ poll off requests: %15u errors: %27u ]\n",
2054 sp
->ifi_poll_off_req
, sp
->ifi_poll_off_err
);
2055 printf(" [ polled packets: %18llu per poll limit: %19lu ]\n",
2056 sp
->ifi_poll_packets
, sp
->ifi_poll_packets_limit
);
2057 printf(" [ polled bytes: %20llu ]\n", sp
->ifi_poll_bytes
);
2058 printf(" [ poll interval: %14llu nsec ]\n",
2059 sp
->ifi_poll_interval_time
);
2060 printf(" [ sampled packets avg/min/max: %12u / %12u / %12u ]\n",
2061 sp
->ifi_poll_packets_avg
, sp
->ifi_poll_packets_min
,
2062 sp
->ifi_poll_packets_max
);
2063 printf(" [ sampled bytes avg/min/max: %12u / %12u / %12u ]\n",
2064 sp
->ifi_poll_bytes_avg
, sp
->ifi_poll_bytes_min
,
2065 sp
->ifi_poll_bytes_max
);
2066 printf(" [ sampled wakeups avg: %12u ]\n",
2067 sp
->ifi_poll_wakeups_avg
);
2068 printf(" [ packets lowat/hiwat threshold: %10u / %10u ]\n",
2069 sp
->ifi_poll_packets_lowat
, sp
->ifi_poll_packets_hiwat
);
2070 printf(" [ bytes lowat/hiwat threshold: %10u / %10u ]\n",
2071 sp
->ifi_poll_bytes_lowat
, sp
->ifi_poll_bytes_hiwat
);
2072 printf(" [ wakeups lowat/hiwat threshold: %10u / %10u ]\n",
2073 sp
->ifi_poll_wakeups_lowat
, sp
->ifi_poll_wakeups_hiwat
);
2075 np
= &ifmsupp
.ifmd_netif_stats
;
2076 printf(" [ mit mode: %24U cfg idx: %26u ]\n",
2077 np
->ifn_rx_mit_mode
, np
->ifn_rx_mit_cfg_idx
);
2078 printf(" [ cfg packets lo/hi threshold: %12u / %12u ]\n",
2079 np
->ifn_rx_mit_cfg_packets_lowat
, np
->ifn_rx_mit_cfg_packets_hiwat
);
2080 printf(" [ cfg bytes lo/hi threshold: %12u / %12u ]\n",
2081 np
->ifn_rx_mit_cfg_bytes_lowat
, np
->ifn_rx_mit_cfg_bytes_hiwat
);
2082 printf(" [ cfg interval: %15llu nsec ]\n",
2083 np
->ifn_rx_mit_cfg_interval
);
2084 printf(" [ mit interval: %15llu nsec ]\n",
2085 np
->ifn_rx_mit_interval
);
2086 printf(" [ mit packets avg/min/max: %12u / %12u / %12u ]\n",
2087 np
->ifn_rx_mit_packets_avg
, np
->ifn_rx_mit_packets_min
,
2088 np
->ifn_rx_mit_packets_max
);
2089 printf(" [ mit bytes avg/min/max: %12u / %12u / %12u ]\n",
2090 np
->ifn_rx_mit_bytes_avg
, np
->ifn_rx_mit_bytes_min
,
2091 np
->ifn_rx_mit_bytes_max
);
2096 sigemptyset(&sigset
);
2097 sigaddset(&sigset
, SIGALRM
);
2098 (void) sigprocmask(SIG_BLOCK
, &sigset
, &oldsigset
);
2100 sigemptyset(&sigset
);
2101 sigsuspend(&sigset
);
2103 (void) sigprocmask(SIG_SETMASK
, &oldsigset
, NULL
);
2111 create_control_socket(const char *control_name
)
2113 struct sockaddr_ctl sc
;
2114 struct ctl_info ctl
;
2117 fd
= socket(PF_SYSTEM
, SOCK_DGRAM
, SYSPROTO_CONTROL
);
2119 perror("socket(PF_SYSTEM)");
2123 /* Get the control ID for statistics */
2124 bzero(&ctl
, sizeof(ctl
));
2125 strlcpy(ctl
.ctl_name
, control_name
, sizeof(ctl
.ctl_name
));
2126 if (ioctl(fd
, CTLIOCGINFO
, &ctl
) == -1)
2128 perror("ioctl(CTLIOCGINFO)");
2133 /* Connect to the statistics control */
2134 bzero(&sc
, sizeof(sc
));
2135 sc
.sc_len
= sizeof(sc
);
2136 sc
.sc_family
= AF_SYSTEM
;
2137 sc
.ss_sysaddr
= SYSPROTO_CONTROL
;
2138 sc
.sc_id
= ctl
.ctl_id
;
2140 if (connect(fd
, (struct sockaddr
*)&sc
, sc
.sc_len
) != 0)
2142 perror("connect(SYSPROTO_CONTROL)");
2147 /* Set socket to non-blocking operation */
2148 if (fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFL
, 0) | O_NONBLOCK
) == -1) {
2149 perror("fcnt(F_SETFL,O_NONBLOCK)");
2157 add_nstat_src(int fd
, const nstat_ifnet_add_param
*ifparam
,
2158 nstat_src_ref_t
*outsrc
)
2160 nstat_msg_add_src_req
*addreq
;
2161 nstat_msg_src_added
*addedmsg
;
2162 nstat_ifnet_add_param
*param
;
2163 char buffer
[sizeof(*addreq
) + sizeof(*param
)];
2165 const u_int32_t addreqsize
=
2166 offsetof(struct nstat_msg_add_src
, param
) + sizeof(*param
);
2168 /* Setup the add source request */
2169 addreq
= (nstat_msg_add_src_req
*)buffer
;
2170 param
= (nstat_ifnet_add_param
*)addreq
->param
;
2171 bzero(addreq
, addreqsize
);
2172 addreq
->hdr
.context
= (uintptr_t)&buffer
;
2173 addreq
->hdr
.type
= NSTAT_MSG_TYPE_ADD_SRC
;
2174 addreq
->provider
= NSTAT_PROVIDER_IFNET
;
2175 bzero(param
, sizeof(*param
));
2176 param
->ifindex
= ifparam
->ifindex
;
2177 param
->threshold
= ifparam
->threshold
;
2179 /* Send the add source request */
2180 result
= send(fd
, addreq
, addreqsize
, 0);
2181 if (result
!= addreqsize
)
2184 perror("send(NSTAT_ADD_SRC_REQ)");
2186 fprintf(stderr
, "%s: could only sent %ld out of %d\n",
2187 __func__
, result
, addreqsize
);
2191 /* Receive the response */
2192 addedmsg
= (nstat_msg_src_added
*)buffer
;
2193 result
= recv(fd
, addedmsg
, sizeof(buffer
), 0);
2194 if (result
< sizeof(*addedmsg
))
2197 perror("recv(NSTAT_ADD_SRC_RSP)");
2199 fprintf(stderr
, "%s: recv too small, received %ld, "
2200 "expected %lu\n", __func__
, result
,
2205 if (addedmsg
->hdr
.type
!= NSTAT_MSG_TYPE_SRC_ADDED
)
2207 fprintf(stderr
, "%s: received wrong message type, received %u "
2208 "expected %u\n", __func__
, addedmsg
->hdr
.type
,
2209 NSTAT_MSG_TYPE_SRC_ADDED
);
2213 if (addedmsg
->hdr
.context
!= (uintptr_t)&buffer
)
2215 fprintf(stderr
, "%s: received wrong context, received %llu "
2216 "expected %lu\n", __func__
, addedmsg
->hdr
.context
,
2217 (uintptr_t)&buffer
);
2220 *outsrc
= addedmsg
->srcref
;
2225 rem_nstat_src(int fd
, nstat_src_ref_t sref
)
2227 nstat_msg_rem_src_req
*remreq
;
2228 nstat_msg_src_removed
*remrsp
;
2229 char buffer
[sizeof(*remreq
)];
2232 /* Setup the add source request */
2233 remreq
= (nstat_msg_rem_src_req
*)buffer
;
2234 bzero(remreq
, sizeof(*remreq
));
2235 remreq
->hdr
.type
= NSTAT_MSG_TYPE_REM_SRC
;
2236 remreq
->srcref
= sref
;
2238 /* Send the remove source request */
2239 result
= send(fd
, remreq
, sizeof(*remreq
), 0);
2240 if (result
!= sizeof(*remreq
)) {
2242 perror("send(NSTAT_REM_SRC_REQ)");
2244 fprintf(stderr
, "%s: could only sent %ld out of %lu\n",
2245 __func__
, result
, sizeof(*remreq
));
2249 /* Receive the response */
2250 remrsp
= (nstat_msg_src_removed
*)buffer
;
2251 result
= recv(fd
, remrsp
, sizeof(buffer
), 0);
2252 if (result
< sizeof(*remrsp
)) {
2254 perror("recv(NSTAT_REM_SRC_RSP)");
2256 fprintf(stderr
, "%s: recv too small, received %ld, "
2257 "expected %lu\n", __func__
, result
,
2262 if (remrsp
->hdr
.type
!= NSTAT_MSG_TYPE_SRC_REMOVED
) {
2263 fprintf(stderr
, "%s: received wrong message type, received %u "
2264 "expected %u\n", __func__
, remrsp
->hdr
.type
,
2265 NSTAT_MSG_TYPE_SRC_REMOVED
);
2269 if (remrsp
->srcref
!= sref
) {
2270 fprintf(stderr
, "%s: received invalid srcref, received %llu "
2271 "expected %llu\n", __func__
, remrsp
->srcref
, sref
);
2277 get_src_decsription(int fd
, nstat_src_ref_t srcref
,
2278 struct nstat_ifnet_descriptor
*ifdesc
)
2280 nstat_msg_get_src_description
*dreq
;
2281 nstat_msg_src_description
*drsp
;
2282 char buffer
[sizeof(*drsp
) + sizeof(*ifdesc
)];
2284 const u_int32_t descsize
=
2285 offsetof(struct nstat_msg_src_description
, data
) +
2286 sizeof(nstat_ifnet_descriptor
);
2288 dreq
= (nstat_msg_get_src_description
*)buffer
;
2289 bzero(dreq
, sizeof(*dreq
));
2290 dreq
->hdr
.type
= NSTAT_MSG_TYPE_GET_SRC_DESC
;
2291 dreq
->srcref
= srcref
;
2292 result
= send(fd
, dreq
, sizeof(*dreq
), 0);
2293 if (result
!= sizeof(*dreq
))
2296 perror("send(NSTAT_GET_SRC_DESC_REQ)");
2298 fprintf(stderr
, "%s: sent %ld out of %lu\n",
2299 __func__
, result
, sizeof(*dreq
));
2303 /* Receive the source description response */
2304 drsp
= (nstat_msg_src_description
*)buffer
;
2305 result
= recv(fd
, drsp
, sizeof(buffer
), 0);
2306 if (result
< descsize
)
2309 perror("recv(NSTAT_GET_SRC_DESC_RSP");
2311 fprintf(stderr
, "%s: recv too small, received %ld, "
2312 "expected %u\n", __func__
, result
, descsize
);
2316 if (drsp
->hdr
.type
!= NSTAT_MSG_TYPE_SRC_DESC
)
2318 fprintf(stderr
, "%s: received wrong message type, received %u "
2319 "expected %u\n", __func__
, drsp
->hdr
.type
,
2320 NSTAT_MSG_TYPE_SRC_DESC
);
2324 if (drsp
->srcref
!= srcref
)
2326 fprintf(stderr
, "%s: received message for wrong source, "
2327 "received 0x%llx expected 0x%llx\n",
2328 __func__
, drsp
->srcref
, srcref
);
2332 bcopy(drsp
->data
, ifdesc
, sizeof(*ifdesc
));
2337 print_wifi_status(nstat_ifnet_desc_wifi_status
*status
)
2341 ((status->valid_bitmask & NSTAT_IFNET_DESC_WIFI_ ## f ## _VALID) ?\
2343 #define parg(n, un) #n, val(n, un)
2344 #define pretxtl(n, un) \
2345 (((tmp = val(n, un)) == -1) ? "(not valid)" : \
2346 ((tmp == NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_NONE) ? "(none)" : \
2347 ((tmp == NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_LOW) ? "(low)" : \
2348 ((tmp == NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_MEDIUM) ? "(medium)" : \
2349 ((tmp == NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_HIGH) ? "(high)" : \
2352 printf("\nwifi status:\n");
2373 parg(link_quality_metric
, LINK_QUALITY_METRIC
),
2374 parg(ul_effective_bandwidth
, UL_EFFECTIVE_BANDWIDTH
),
2375 parg(ul_max_bandwidth
, UL_MAX_BANDWIDTH
),
2376 parg(ul_min_latency
, UL_MIN_LATENCY
),
2377 parg(ul_effective_latency
, UL_EFFECTIVE_LATENCY
),
2378 parg(ul_max_latency
, UL_MAX_LATENCY
),
2379 parg(ul_retxt_level
, UL_RETXT_LEVEL
),
2380 pretxtl(ul_retxt_level
, UL_RETXT_LEVEL
),
2381 parg(ul_bytes_lost
, UL_BYTES_LOST
),
2382 parg(ul_error_rate
, UL_ERROR_RATE
),
2383 parg(dl_effective_bandwidth
, DL_EFFECTIVE_BANDWIDTH
),
2384 parg(dl_max_bandwidth
, DL_MAX_BANDWIDTH
),
2385 parg(dl_min_latency
, DL_MIN_LATENCY
),
2386 parg(dl_effective_latency
, DL_EFFECTIVE_LATENCY
),
2387 parg(dl_max_latency
, DL_MAX_LATENCY
),
2388 parg(dl_error_rate
, DL_ERROR_RATE
),
2389 parg(config_frequency
, CONFIG_FREQUENCY
),
2390 parg(config_multicast_rate
, CONFIG_MULTICAST_RATE
),
2391 parg(scan_count
, CONFIG_SCAN_COUNT
),
2392 parg(scan_duration
, CONFIG_SCAN_DURATION
)
2400 print_cellular_status(nstat_ifnet_desc_cellular_status
*status
)
2404 ((status->valid_bitmask & NSTAT_IFNET_DESC_CELL_ ## f ## _VALID) ?\
2406 #define parg(n, un) #n, val(n, un)
2407 #define pretxtl(n, un) \
2408 (((tmp = val(n, un)) == -1) ? "(not valid)" : \
2409 ((tmp == NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_NONE) ? "(none)" : \
2410 ((tmp == NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_LOW) ? "(low)" : \
2411 ((tmp == NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_MEDIUM) ? "(medium)" : \
2412 ((tmp == NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_HIGH) ? "(high)" : \
2414 #define pretxtm(n, un) \
2415 (((tmp_mss = val(n,un)) == -1) ? "(not valid)" : \
2416 ((tmp_mss == NSTAT_IFNET_DESC_MSS_RECOMMENDED_NONE) ? "(none)" : \
2417 ((tmp_mss == NSTAT_IFNET_DESC_MSS_RECOMMENDED_MEDIUM) ? "(medium)" : \
2418 ((tmp_mss == NSTAT_IFNET_DESC_MSS_RECOMMENDED_LOW) ? "(low)" : \
2421 printf("\ncellular status:\n");
2439 parg(link_quality_metric
, LINK_QUALITY_METRIC
),
2440 parg(ul_effective_bandwidth
, UL_EFFECTIVE_BANDWIDTH
),
2441 parg(ul_max_bandwidth
, UL_MAX_BANDWIDTH
),
2442 parg(ul_min_latency
, UL_MIN_LATENCY
),
2443 parg(ul_effective_latency
, UL_EFFECTIVE_LATENCY
),
2444 parg(ul_max_latency
, UL_MAX_LATENCY
),
2445 parg(ul_retxt_level
, UL_RETXT_LEVEL
),
2446 pretxtl(ul_retxt_level
, UL_RETXT_LEVEL
),
2447 parg(ul_bytes_lost
, UL_BYTES_LOST
),
2448 parg(ul_min_queue_size
, UL_MIN_QUEUE_SIZE
),
2449 parg(ul_avg_queue_size
, UL_AVG_QUEUE_SIZE
),
2450 parg(ul_max_queue_size
, UL_MAX_QUEUE_SIZE
),
2451 parg(dl_effective_bandwidth
, DL_EFFECTIVE_BANDWIDTH
),
2452 parg(dl_max_bandwidth
, DL_MAX_BANDWIDTH
),
2453 parg(config_inactivity_time
, CONFIG_INACTIVITY_TIME
),
2454 parg(config_backoff_time
, CONFIG_BACKOFF_TIME
),
2455 parg(mss_recommended
, MSS_RECOMMENDED
),
2456 pretxtm(mss_recommended
, MSS_RECOMMENDED
)
2464 get_interface_state(int fd
, const char *ifname
, struct ifreq
*ifr
)
2466 bzero(ifr
, sizeof(*ifr
));
2467 snprintf(ifr
->ifr_name
, sizeof(ifr
->ifr_name
), "%s", ifname
);
2469 if (ioctl(fd
, SIOCGIFINTERFACESTATE
, ifr
) == -1) {
2470 perror("ioctl(CTLIOCGINFO)");
2477 print_interface_state(struct ifreq
*ifr
)
2479 int lqm
, rrc
, avail
;
2481 printf("\ninterface state:\n");
2483 if (ifr
->ifr_interface_state
.valid_bitmask
&
2484 IF_INTERFACE_STATE_LQM_STATE_VALID
) {
2486 lqm
= ifr
->ifr_interface_state
.lqm_state
;
2487 if (lqm
== IFNET_LQM_THRESH_GOOD
)
2489 else if (lqm
== IFNET_LQM_THRESH_POOR
)
2491 else if (lqm
== IFNET_LQM_THRESH_BAD
)
2493 else if (lqm
== IFNET_LQM_THRESH_UNKNOWN
)
2494 printf("\"unknown\"");
2495 else if (lqm
== IFNET_LQM_THRESH_OFF
)
2498 printf("invalid(%d)", lqm
);
2501 if (ifr
->ifr_interface_state
.valid_bitmask
&
2502 IF_INTERFACE_STATE_RRC_STATE_VALID
) {
2504 rrc
= ifr
->ifr_interface_state
.rrc_state
;
2505 if (rrc
== IF_INTERFACE_STATE_RRC_STATE_CONNECTED
)
2506 printf("\"connected\"");
2507 else if (rrc
== IF_INTERFACE_STATE_RRC_STATE_IDLE
)
2510 printf("\"invalid(%d)\"", rrc
);
2513 if (ifr
->ifr_interface_state
.valid_bitmask
&
2514 IF_INTERFACE_STATE_INTERFACE_AVAILABILITY_VALID
) {
2515 printf("\tavailability: ");
2516 avail
= ifr
->ifr_interface_state
.interface_availability
;
2517 if (avail
== IF_INTERFACE_STATE_INTERFACE_AVAILABLE
)
2519 else if (rrc
== IF_INTERFACE_STATE_INTERFACE_UNAVAILABLE
)
2520 printf("\"false\"");
2522 printf("\"invalid(%d)\"", avail
);
2527 print_link_status(const char *ifname
)
2529 unsigned int ifindex
;
2530 struct itimerval timer_interval
;
2531 sigset_t sigset
, oldsigset
;
2532 struct nstat_ifnet_descriptor ifdesc
;
2533 nstat_ifnet_add_param ifparam
;
2534 nstat_src_ref_t sref
= 0;
2538 ifindex
= if_nametoindex(ifname
);
2540 fprintf(stderr
, "Invalid interface name\n");
2544 if ((ctl_fd
= create_control_socket(NET_STAT_CONTROL_NAME
)) < 0)
2547 ifparam
.ifindex
= ifindex
;
2548 ifparam
.threshold
= UINT64_MAX
;
2549 if (add_nstat_src(ctl_fd
, &ifparam
, &sref
))
2553 /* create a timer that fires repeatedly every interval
2555 timer_interval
.it_value
.tv_sec
= interval
;
2556 timer_interval
.it_value
.tv_usec
= 0;
2557 timer_interval
.it_interval
.tv_sec
= interval
;
2558 timer_interval
.it_interval
.tv_usec
= 0;
2559 (void) signal(SIGALRM
, catchalarm
);
2561 (void) setitimer(ITIMER_REAL
, &timer_interval
, NULL
);
2564 /* get interface state */
2565 if (get_interface_state(ctl_fd
, ifname
, &ifr
))
2568 /* get ntstat interface description */
2569 if (get_src_decsription(ctl_fd
, sref
, &ifdesc
))
2573 printf("\n%s: ", ifname
);
2576 /* print interface state */
2577 print_interface_state(&ifr
);
2579 /* print ntsat interface link status */
2580 if (ifdesc
.link_status
.link_status_type
==
2581 NSTAT_IFNET_DESC_LINK_STATUS_TYPE_CELLULAR
)
2582 print_cellular_status(&ifdesc
.link_status
.u
.cellular
);
2583 else if (ifdesc
.link_status
.link_status_type
==
2584 NSTAT_IFNET_DESC_LINK_STATUS_TYPE_WIFI
)
2585 print_wifi_status(&ifdesc
.link_status
.u
.wifi
);
2590 sigemptyset(&sigset
);
2591 sigaddset(&sigset
, SIGALRM
);
2592 (void) sigprocmask(SIG_BLOCK
, &sigset
, &oldsigset
);
2594 sigemptyset(&sigset
);
2595 sigsuspend(&sigset
);
2597 (void) sigprocmask(SIG_SETMASK
, &oldsigset
, NULL
);
2604 rem_nstat_src(ctl_fd
, sref
);