2 * Copyright (c) 2008-2015 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>
101 #define ROUNDUP(a, size) (((a) & ((size) - 1)) ? (1 + ((a)|(size - 1))) : (a))
103 #define NEXT_SA(p) (struct sockaddr *) \
104 ((caddr_t)p + (p->sa_len ? ROUNDUP(p->sa_len, sizeof(uint32_t)) : \
107 static void sidewaysintpr ();
108 static void catchalarm (int);
109 static char *sec2str(time_t);
110 static void llreach_sysctl(uint32_t);
111 static char *nsec_to_str(unsigned long long);
112 static char *qtype2str(classq_type_t
);
113 static char *sched2str(unsigned int);
114 static char *qid2str(unsigned int);
115 static char *qstate2str(unsigned int);
116 static char *tcqslot2str(unsigned int);
117 static char *rate2str(long double);
118 static char *pri2str(unsigned int i
);
126 u_int64_t prev_bytes
;
127 u_int64_t prev_packets
;
128 unsigned int printed
;
132 static void print_tcqstats(int slot
, struct tcq_classstats
*,
133 struct queue_stats
*);
134 static void print_qfqstats(int slot
, struct qfq_classstats
*,
135 struct queue_stats
*);
136 static void print_sfbstats(struct sfb_stats
*);
137 static void update_avg(struct if_ifclassq_stats
*, struct queue_stats
*);
138 static void print_fq_codel_stats(int slot
, struct fq_codel_classstats
*,
139 struct queue_stats
*);
141 struct queue_stats qstats
[IFCQ_SC_MAX
];
144 char *netname6 (struct sockaddr_in6
*, struct sockaddr
*);
145 static char ntop_buf
[INET6_ADDRSTRLEN
]; /* for inet_ntop() */
149 * Display a formatted value, or a '-' in the same space.
152 show_stat(const char *fmt
, int width
, u_int64_t value
, short showvalue
)
156 /* Construct the format string */
158 snprintf(newfmt
, sizeof(newfmt
), "%%%d%s", width
, fmt
);
159 printf(newfmt
, value
);
161 snprintf(newfmt
, sizeof(newfmt
), "%%%ds", width
);
167 get_rti_info(int addrs
, struct sockaddr
*sa
, struct sockaddr
**rti_info
)
172 for (i
= 0; i
< RTAX_MAX
; i
++) {
173 if (addrs
& (1 << i
)) {
175 if (sa
->sa_len
< sizeof(struct sockaddr
))
176 len
+= sizeof(struct sockaddr
);
188 multipr(int family
, char *buf
, char *lim
)
192 for (next
= buf
; next
< lim
; ) {
193 struct ifma_msghdr2
*ifmam
= (struct ifma_msghdr2
*)next
;
194 struct sockaddr
*rti_info
[RTAX_MAX
];
198 next
+= ifmam
->ifmam_msglen
;
199 if (ifmam
->ifmam_type
== RTM_IFINFO2
)
201 else if (ifmam
->ifmam_type
!= RTM_NEWMADDR2
)
203 get_rti_info(ifmam
->ifmam_addrs
, (struct sockaddr
*)(ifmam
+ 1), rti_info
);
204 sa
= rti_info
[RTAX_IFA
];
206 if (sa
->sa_family
!= family
)
208 switch (sa
->sa_family
) {
210 struct sockaddr_in
*sin
= (struct sockaddr_in
*)sa
;
212 fmt
= routename(sin
->sin_addr
.s_addr
);
217 struct sockaddr_in6 sin6
;
219 memcpy(&sin6
, sa
, sizeof(struct sockaddr_in6
));
221 if (IN6_IS_ADDR_LINKLOCAL(&sin6
.sin6_addr
) ||
222 IN6_IS_ADDR_MC_NODELOCAL(&sin6
.sin6_addr
) ||
223 IN6_IS_ADDR_MC_LINKLOCAL(&sin6
.sin6_addr
)) {
224 sin6
.sin6_scope_id
= ntohs(*(u_int16_t
*)&sin6
.sin6_addr
.s6_addr
[2]);
225 sin6
.sin6_addr
.s6_addr
[2] = 0;
226 sin6
.sin6_addr
.s6_addr
[3] = 0;
229 printf("%23s %-19.19s(refs: %d)\n", "",
230 inet_ntop(AF_INET6
, &sin6
.sin6_addr
,
231 ntop_buf
, sizeof(ntop_buf
)),
232 ifmam
->ifmam_refcount
);
237 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)sa
;
239 switch (sdl
->sdl_type
) {
242 fmt
= ether_ntoa((struct ether_addr
*)
250 printf("%23s %s\n", "", fmt
);
255 * Print a description of the network interfaces.
258 intpr(void (*pfunc
)(char *))
260 u_int64_t opackets
= 0;
261 u_int64_t ipackets
= 0;
262 u_int64_t obytes
= 0;
263 u_int64_t ibytes
= 0;
264 u_int64_t oerrors
= 0;
265 u_int64_t ierrors
= 0;
266 u_int64_t collisions
= 0;
267 u_int64_t fpackets
= 0;
268 u_int64_t fbytes
= 0;
272 struct sockaddr
*sa
= NULL
;
277 char *buf
= NULL
, *lim
, *next
;
279 struct if_msghdr
*ifm
;
280 struct sockaddr
*rti_info
[RTAX_MAX
];
281 unsigned int ifindex
= 0;
289 ifindex
= if_nametoindex(interface
);
291 mib
[0] = CTL_NET
; // networking subsystem
292 mib
[1] = PF_ROUTE
; // type of information
293 mib
[2] = 0; // protocol (IPPROTO_xxx)
294 mib
[3] = 0; // address family
295 mib
[4] = NET_RT_IFLIST2
; // operation
297 if (sysctl(mib
, 6, NULL
, &len
, NULL
, 0) < 0)
299 if ((buf
= malloc(len
)) == NULL
) {
300 printf("malloc failed\n");
303 if (sysctl(mib
, 6, buf
, &len
, NULL
, 0) < 0) {
310 printf("%-5.5s %-5.5s %-13.13s %-15.15s %8.8s %5.5s",
311 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs");
313 printf(" %8.8s %8.8s", "Itcpkts", "Ipvpkts");
315 printf(" %10.10s","Ibytes");
317 printf(" %8.8s %8.8s", "Itcbytes", "Ipvbytes");
319 printf(" %8.8s %5.5s", "Opkts", "Oerrs");
321 printf(" %8.8s %8.8s", "Otcpkts", "Opvpkts");
323 printf(" %10.10s","Obytes");
325 printf(" %8.8s %8.8s", "Otcbytes", "Opvbytes");
327 printf(" %5s", "Coll");
329 printf(" %s", "Time");
331 printf(" %s", "Drop");
333 printf(" %8.8s", "Fpkts");
335 printf(" %10.10s", "Fbytes");
340 for (next
= buf
; next
< lim
; ) {
343 struct ifmibdata_supplemental ifmsupp
;
344 u_int64_t ift_itcp
= 0; /* input tc packets */
345 u_int64_t ift_itcb
= 0; /* input tc bytes */
346 u_int64_t ift_otcp
= 0; /* output tc packets */
347 u_int64_t ift_otcb
= 0; /* output tc bytes */
348 u_int64_t ift_ipvp
= 0; /* input priv tc packets */
349 u_int64_t ift_ipvb
= 0; /* input priv tc bytes */
350 u_int64_t ift_opvp
= 0; /* output priv tc packets */
351 u_int64_t ift_opvb
= 0; /* output priv tc bytes */
353 bzero(&ifmsupp
, sizeof(struct ifmibdata_supplemental
));
357 ifm
= (struct if_msghdr
*)next
;
358 next
+= ifm
->ifm_msglen
;
360 if (ifm
->ifm_type
== RTM_IFINFO2
) {
361 struct if_msghdr2
*if2m
= (struct if_msghdr2
*)ifm
;
362 struct sockaddr_dl
*sdl
=
363 (struct sockaddr_dl
*)(if2m
+ 1);
365 size_t miblen
= sizeof(struct ifmibdata_supplemental
);
367 strncpy(name
, sdl
->sdl_data
, sdl
->sdl_nlen
);
368 name
[sdl
->sdl_nlen
] = 0;
369 if (interface
!= 0 && if2m
->ifm_index
!= ifindex
)
371 cp
= index(name
, '\0');
378 if ((if2m
->ifm_flags
& IFF_UP
) == 0)
383 * Get the interface stats. These may get
384 * overriden below on a per-interface basis.
386 opackets
= if2m
->ifm_data
.ifi_opackets
;
387 ipackets
= if2m
->ifm_data
.ifi_ipackets
;
388 obytes
= if2m
->ifm_data
.ifi_obytes
;
389 ibytes
= if2m
->ifm_data
.ifi_ibytes
;
390 oerrors
=if2m
->ifm_data
.ifi_oerrors
;
391 ierrors
= if2m
->ifm_data
.ifi_ierrors
;
392 collisions
= if2m
->ifm_data
.ifi_collisions
;
393 timer
= if2m
->ifm_timer
;
394 drops
= if2m
->ifm_snd_drops
;
395 mtu
= if2m
->ifm_data
.ifi_mtu
;
397 /* Common OID prefix */
398 mibname
[0] = CTL_NET
;
399 mibname
[1] = PF_LINK
;
400 mibname
[2] = NETLINK_GENERIC
;
401 mibname
[3] = IFMIB_IFDATA
;
402 mibname
[4] = if2m
->ifm_index
;
403 mibname
[5] = IFDATA_SUPPLEMENTAL
;
404 if (sysctl(mibname
, 6, &ifmsupp
, &miblen
, NULL
, 0) == -1)
405 err(1, "sysctl IFDATA_SUPPLEMENTAL");
407 fpackets
= ifmsupp
.ifmd_data_extended
.ifi_fpackets
;
408 fbytes
= ifmsupp
.ifmd_data_extended
.ifi_fbytes
;
413 ift_itcp
= ifmsupp
.ifmd_traffic_class
.ifi_ibepackets
;
414 ift_itcb
= ifmsupp
.ifmd_traffic_class
.ifi_ibebytes
;
415 ift_otcp
= ifmsupp
.ifmd_traffic_class
.ifi_obepackets
;
416 ift_otcb
= ifmsupp
.ifmd_traffic_class
.ifi_obebytes
;
419 ift_itcp
= ifmsupp
.ifmd_traffic_class
.ifi_ibkpackets
;
420 ift_itcb
= ifmsupp
.ifmd_traffic_class
.ifi_ibkbytes
;
421 ift_otcp
= ifmsupp
.ifmd_traffic_class
.ifi_obkpackets
;
422 ift_otcb
= ifmsupp
.ifmd_traffic_class
.ifi_obkbytes
;
425 ift_itcp
= ifmsupp
.ifmd_traffic_class
.ifi_ivipackets
;
426 ift_itcb
= ifmsupp
.ifmd_traffic_class
.ifi_ivibytes
;
427 ift_otcp
= ifmsupp
.ifmd_traffic_class
.ifi_ovipackets
;
428 ift_otcb
= ifmsupp
.ifmd_traffic_class
.ifi_ovibytes
;
431 ift_itcp
= ifmsupp
.ifmd_traffic_class
.ifi_ivopackets
;
432 ift_itcb
= ifmsupp
.ifmd_traffic_class
.ifi_ivobytes
;
433 ift_otcp
= ifmsupp
.ifmd_traffic_class
.ifi_ovopackets
;
434 ift_otcb
= ifmsupp
.ifmd_traffic_class
.ifi_ovobytes
;
447 ift_ipvp
= ifmsupp
.ifmd_traffic_class
.ifi_ipvpackets
;
448 ift_ipvb
= ifmsupp
.ifmd_traffic_class
.ifi_ipvbytes
;
449 ift_opvp
= ifmsupp
.ifmd_traffic_class
.ifi_opvpackets
;
450 ift_opvb
= ifmsupp
.ifmd_traffic_class
.ifi_opvbytes
;
453 get_rti_info(if2m
->ifm_addrs
,
454 (struct sockaddr
*)(if2m
+ 1), rti_info
);
455 sa
= rti_info
[RTAX_IFP
];
456 } else if (ifm
->ifm_type
== RTM_NEWADDR
) {
457 struct ifa_msghdr
*ifam
= (struct ifa_msghdr
*)ifm
;
459 if (interface
!= 0 && ifam
->ifam_index
!= ifindex
)
461 get_rti_info(ifam
->ifam_addrs
,
462 (struct sockaddr
*)(ifam
+ 1), rti_info
);
463 sa
= rti_info
[RTAX_IFA
];
467 printf("%-5.5s %-5u ", name
, mtu
);
470 printf("%-13.13s ", "none");
471 printf("%-15.15s ", "none");
473 switch (sa
->sa_family
) {
475 printf("%-13.13s ", "none");
476 printf("%-15.15s ", "none");
480 struct sockaddr_in
*sin
=
481 (struct sockaddr_in
*)sa
;
482 struct sockaddr_in mask
;
484 mask
.sin_addr
.s_addr
= 0;
485 memcpy(&mask
, rti_info
[RTAX_NETMASK
],
486 ((struct sockaddr_in
*)
487 rti_info
[RTAX_NETMASK
])->sin_len
);
490 netname(sin
->sin_addr
.s_addr
&
491 mask
.sin_addr
.s_addr
,
492 ntohl(mask
.sin_addr
.s_addr
)));
495 routename(sin
->sin_addr
.s_addr
));
502 struct sockaddr_in6
*sin6
=
503 (struct sockaddr_in6
*)sa
;
504 struct sockaddr
*mask
=
505 (struct sockaddr
*)rti_info
[RTAX_NETMASK
];
507 printf("%-11.11s ", netname6(sin6
, mask
));
508 printf("%-17.17s ", (char *)inet_ntop(AF_INET6
,
509 &sin6
->sin6_addr
, ntop_buf
,
517 struct sockaddr_dl
*sdl
=
518 (struct sockaddr_dl
*)sa
;
520 cp
= (char *)LLADDR(sdl
);
522 snprintf(linknum
, sizeof(linknum
),
523 "<Link#%d>", sdl
->sdl_index
);
524 m
= printf("%-11.11s ", linknum
);
529 m
= printf("(%d)", sa
->sa_family
);
530 for (cp
= sa
->sa_len
+ (char *)sa
;
531 --cp
> sa
->sa_data
&& (*cp
== 0);) {}
532 n
= cp
- sa
->sa_data
+ 1;
536 m
+= printf("%02x%c", *cp
++ & 0xff,
547 show_stat("llu", 8, ipackets
, link_layer
|network_layer
);
549 show_stat("llu", 5, ierrors
, link_layer
);
552 show_stat("llu", 8, ift_itcp
, link_layer
|network_layer
);
554 show_stat("llu", 8, ift_ipvp
, link_layer
|network_layer
);
558 show_stat("llu", 10, ibytes
, link_layer
|network_layer
);
561 show_stat("llu", 8, ift_itcb
, link_layer
|network_layer
);
563 show_stat("llu", 8, ift_ipvb
, link_layer
|network_layer
);
567 show_stat("llu", 8, opackets
, link_layer
|network_layer
);
569 show_stat("llu", 5, oerrors
, link_layer
);
572 show_stat("llu", 8, ift_otcp
, link_layer
|network_layer
);
574 show_stat("llu", 8, ift_opvp
, link_layer
|network_layer
);
578 show_stat("llu", 10, obytes
, link_layer
|network_layer
);
581 show_stat("llu", 8, ift_otcb
, link_layer
|network_layer
);
583 show_stat("llu", 8, ift_opvb
, link_layer
|network_layer
);
587 show_stat("llu", 5, collisions
, link_layer
);
590 show_stat("d", 3, timer
, link_layer
);
594 show_stat("d", 3, drops
, link_layer
);
598 show_stat("llu", 8, fpackets
, link_layer
|network_layer
);
601 show_stat("llu", 10, fbytes
,
602 link_layer
|network_layer
);
608 multipr(sa
->sa_family
, next
, lim
);
614 SLIST_ENTRY(iftot
) chain
;
615 char ift_name
[16]; /* interface name */
616 u_int64_t ift_ip
; /* input packets */
617 u_int64_t ift_ie
; /* input errors */
618 u_int64_t ift_op
; /* output packets */
619 u_int64_t ift_oe
; /* output errors */
620 u_int64_t ift_co
; /* collisions */
621 u_int64_t ift_dr
; /* drops */
622 u_int64_t ift_ib
; /* input bytes */
623 u_int64_t ift_ob
; /* output bytes */
624 u_int64_t ift_itcp
; /* input tc packets */
625 u_int64_t ift_itcb
; /* input tc bytes */
626 u_int64_t ift_otcp
; /* output tc packets */
627 u_int64_t ift_otcb
; /* output tc bytes */
628 u_int64_t ift_ipvp
; /* input priv tc packets */
629 u_int64_t ift_ipvb
; /* input priv tc bytes */
630 u_int64_t ift_opvp
; /* output priv tc packets */
631 u_int64_t ift_opvb
; /* output priv tc bytes */
632 u_int64_t ift_fp
; /* forwarded packets */
633 u_int64_t ift_fb
; /* forwarded bytes */
636 u_char signalled
; /* set if alarm goes off "early" */
639 * Print a running summary of interface statistics.
640 * Repeat display every interval seconds, showing statistics
641 * collected over that interval. Assumes that interval is non-zero.
642 * First line printed at top of screen is always cumulative.
643 * XXX - should be rewritten to use ifmib(4).
648 struct iftot
*total
, *sum
, *interesting
;
653 unsigned int ifcount
, i
;
654 struct ifmibdata
*ifmdall
= 0;
656 sigset_t sigset
, oldsigset
;
657 struct itimerval timer_interval
;
659 /* Common OID prefix */
662 name
[2] = NETLINK_GENERIC
;
665 name
[3] = IFMIB_SYSTEM
;
666 name
[4] = IFMIB_IFCOUNT
;
667 if (sysctl(name
, 5, &ifcount
, &len
, 0, 0) == 1)
668 err(1, "sysctl IFMIB_IFCOUNT");
670 len
= ifcount
* sizeof(struct ifmibdata
);
671 ifmdall
= malloc(len
);
673 err(1, "malloc failed");
674 name
[3] = IFMIB_IFALLDATA
;
676 name
[5] = IFDATA_GENERAL
;
677 if (sysctl(name
, 6, ifmdall
, &len
, (void *)0, 0) == -1)
678 err(1, "sysctl IFMIB_IFALLDATA");
682 for (i
= 0; i
< ifcount
; i
++) {
683 struct ifmibdata
*ifmd
= ifmdall
+ i
;
685 if (interface
&& strcmp(ifmd
->ifmd_name
, interface
) == 0) {
686 if ((interesting
= calloc(ifcount
,
687 sizeof(struct iftot
))) == NULL
)
688 err(1, "malloc failed");
689 interesting_row
= if_nametoindex(interface
);
690 snprintf(interesting
->ift_name
, 16, "(%s)",
694 if ((total
= calloc(1, sizeof(struct iftot
))) == NULL
)
695 err(1, "malloc failed");
697 if ((sum
= calloc(1, sizeof(struct iftot
))) == NULL
)
698 err(1, "malloc failed");
700 /* create a timer that fires repeatedly every interval seconds */
701 timer_interval
.it_value
.tv_sec
= interval
;
702 timer_interval
.it_value
.tv_usec
= 0;
703 timer_interval
.it_interval
.tv_sec
= interval
;
704 timer_interval
.it_interval
.tv_usec
= 0;
705 (void)signal(SIGALRM
, catchalarm
);
707 (void)setitimer(ITIMER_REAL
, &timer_interval
, NULL
);
714 printf("%39s %39s %36s", "input",
715 interesting
? interesting
->ift_name
: "(Total)", "output");
717 printf("%17s %14s %16s", "input",
718 interesting
? interesting
->ift_name
: "(Total)", "output");
724 printf("%10s %5s %10s ", "packets", "errs", "bytes");
726 printf(" %10s %10s %10s %10s",
727 "tcpkts", "tcbytes", "pvpkts", "pvbytes");
728 printf("%10s %5s %10s %5s", "packets", "errs", "bytes", "colls");
730 printf(" %5.5s", "drops");
732 printf(" %10s %10s %10s %10s",
733 "tcpkts", "tcbytes", "pvpkts", "pvbytes");
735 printf(" %10s %10s", "fpackets", "fbytes");
743 if (interesting
!= NULL
) {
744 struct ifmibdata ifmd
;
745 struct ifmibdata_supplemental ifmsupp
;
747 len
= sizeof(struct ifmibdata
);
748 name
[3] = IFMIB_IFDATA
;
749 name
[4] = interesting_row
;
750 name
[5] = IFDATA_GENERAL
;
751 if (sysctl(name
, 6, &ifmd
, &len
, (void *)0, 0) == -1)
752 err(1, "sysctl IFDATA_GENERAL %d", interesting_row
);
754 len
= sizeof(struct ifmibdata_supplemental
);
755 name
[3] = IFMIB_IFDATA
;
756 name
[4] = interesting_row
;
757 name
[5] = IFDATA_SUPPLEMENTAL
;
758 if (sysctl(name
, 6, &ifmsupp
, &len
, (void *)0, 0) == -1)
759 err(1, "sysctl IFDATA_SUPPLEMENTAL %d",
763 printf("%10llu %5llu %10llu ",
764 ifmd
.ifmd_data
.ifi_ipackets
- interesting
->ift_ip
,
765 ifmd
.ifmd_data
.ifi_ierrors
- interesting
->ift_ie
,
766 ifmd
.ifmd_data
.ifi_ibytes
- interesting
->ift_ib
);
769 printf("%10llu %10llu ",
770 ifmsupp
.ifmd_traffic_class
.ifi_ibepackets
-
771 interesting
->ift_itcp
,
772 ifmsupp
.ifmd_traffic_class
.ifi_ibebytes
-
773 interesting
->ift_itcb
);
776 printf("%10llu %10llu ",
777 ifmsupp
.ifmd_traffic_class
.ifi_ibkpackets
-
778 interesting
->ift_itcp
,
779 ifmsupp
.ifmd_traffic_class
.ifi_ibkbytes
-
780 interesting
->ift_itcb
);
783 printf("%10llu %10llu ",
784 ifmsupp
.ifmd_traffic_class
.ifi_ivipackets
-
785 interesting
->ift_itcp
,
786 ifmsupp
.ifmd_traffic_class
.ifi_ivibytes
-
787 interesting
->ift_itcb
);
790 printf("%10llu %10llu ",
791 ifmsupp
.ifmd_traffic_class
.ifi_ivopackets
-
792 interesting
->ift_itcp
,
793 ifmsupp
.ifmd_traffic_class
.ifi_ivobytes
-
794 interesting
->ift_itcb
);
800 printf("%10llu %10llu ",
801 ifmsupp
.ifmd_traffic_class
.ifi_ipvpackets
-
802 interesting
->ift_ipvp
,
803 ifmsupp
.ifmd_traffic_class
.ifi_ipvbytes
-
804 interesting
->ift_ipvb
);
806 printf("%10llu %5llu %10llu %5llu",
807 ifmd
.ifmd_data
.ifi_opackets
- interesting
->ift_op
,
808 ifmd
.ifmd_data
.ifi_oerrors
- interesting
->ift_oe
,
809 ifmd
.ifmd_data
.ifi_obytes
- interesting
->ift_ob
,
810 ifmd
.ifmd_data
.ifi_collisions
- interesting
->ift_co
);
813 ifmd
.ifmd_snd_drops
- interesting
->ift_dr
);
816 printf(" %10llu %10llu",
817 ifmsupp
.ifmd_traffic_class
.ifi_obepackets
-
818 interesting
->ift_otcp
,
819 ifmsupp
.ifmd_traffic_class
.ifi_obebytes
-
820 interesting
->ift_otcb
);
823 printf(" %10llu %10llu",
824 ifmsupp
.ifmd_traffic_class
.ifi_obkpackets
-
825 interesting
->ift_otcp
,
826 ifmsupp
.ifmd_traffic_class
.ifi_obkbytes
-
827 interesting
->ift_otcb
);
830 printf(" %10llu %10llu",
831 ifmsupp
.ifmd_traffic_class
.ifi_ovipackets
-
832 interesting
->ift_otcp
,
833 ifmsupp
.ifmd_traffic_class
.ifi_ovibytes
-
834 interesting
->ift_otcb
);
837 printf(" %10llu %10llu",
838 ifmsupp
.ifmd_traffic_class
.ifi_ovopackets
-
839 interesting
->ift_otcp
,
840 ifmsupp
.ifmd_traffic_class
.ifi_ovobytes
-
841 interesting
->ift_otcb
);
847 printf("%10llu %10llu ",
848 ifmsupp
.ifmd_traffic_class
.ifi_opvpackets
-
849 interesting
->ift_opvp
,
850 ifmsupp
.ifmd_traffic_class
.ifi_opvbytes
-
851 interesting
->ift_opvb
);
854 printf("%10llu %10llu",
855 ifmsupp
.ifmd_data_extended
.ifi_fpackets
-
857 ifmsupp
.ifmd_data_extended
.ifi_fbytes
-
858 interesting
->ift_fb
);
861 interesting
->ift_ip
= ifmd
.ifmd_data
.ifi_ipackets
;
862 interesting
->ift_ie
= ifmd
.ifmd_data
.ifi_ierrors
;
863 interesting
->ift_ib
= ifmd
.ifmd_data
.ifi_ibytes
;
864 interesting
->ift_op
= ifmd
.ifmd_data
.ifi_opackets
;
865 interesting
->ift_oe
= ifmd
.ifmd_data
.ifi_oerrors
;
866 interesting
->ift_ob
= ifmd
.ifmd_data
.ifi_obytes
;
867 interesting
->ift_co
= ifmd
.ifmd_data
.ifi_collisions
;
868 interesting
->ift_dr
= ifmd
.ifmd_snd_drops
;
870 /* private counters */
873 interesting
->ift_itcp
=
874 ifmsupp
.ifmd_traffic_class
.ifi_ibepackets
;
875 interesting
->ift_itcb
=
876 ifmsupp
.ifmd_traffic_class
.ifi_ibebytes
;
877 interesting
->ift_otcp
=
878 ifmsupp
.ifmd_traffic_class
.ifi_obepackets
;
879 interesting
->ift_otcb
=
880 ifmsupp
.ifmd_traffic_class
.ifi_obebytes
;
883 interesting
->ift_itcp
=
884 ifmsupp
.ifmd_traffic_class
.ifi_ibkpackets
;
885 interesting
->ift_itcb
=
886 ifmsupp
.ifmd_traffic_class
.ifi_ibkbytes
;
887 interesting
->ift_otcp
=
888 ifmsupp
.ifmd_traffic_class
.ifi_obkpackets
;
889 interesting
->ift_otcb
=
890 ifmsupp
.ifmd_traffic_class
.ifi_obkbytes
;
893 interesting
->ift_itcp
=
894 ifmsupp
.ifmd_traffic_class
.ifi_ivipackets
;
895 interesting
->ift_itcb
=
896 ifmsupp
.ifmd_traffic_class
.ifi_ivibytes
;
897 interesting
->ift_otcp
=
898 ifmsupp
.ifmd_traffic_class
.ifi_ovipackets
;
899 interesting
->ift_otcb
=
900 ifmsupp
.ifmd_traffic_class
.ifi_ovibytes
;
903 interesting
->ift_itcp
=
904 ifmsupp
.ifmd_traffic_class
.ifi_ivopackets
;
905 interesting
->ift_itcb
=
906 ifmsupp
.ifmd_traffic_class
.ifi_ivobytes
;
907 interesting
->ift_otcp
=
908 ifmsupp
.ifmd_traffic_class
.ifi_ovopackets
;
909 interesting
->ift_otcb
=
910 ifmsupp
.ifmd_traffic_class
.ifi_ovobytes
;
916 interesting
->ift_ipvp
=
917 ifmsupp
.ifmd_traffic_class
.ifi_ipvpackets
;
918 interesting
->ift_ipvb
=
919 ifmsupp
.ifmd_traffic_class
.ifi_ipvbytes
;
920 interesting
->ift_opvp
=
921 ifmsupp
.ifmd_traffic_class
.ifi_opvpackets
;
922 interesting
->ift_opvb
=
923 ifmsupp
.ifmd_traffic_class
.ifi_opvbytes
;
925 interesting
->ift_fp
= ifmsupp
.ifmd_data_extended
.ifi_fpackets
;
926 interesting
->ift_fb
= ifmsupp
.ifmd_data_extended
.ifi_fbytes
;
928 unsigned int latest_ifcount
;
929 struct ifmibdata_supplemental
*ifmsuppall
= NULL
;
932 name
[3] = IFMIB_SYSTEM
;
933 name
[4] = IFMIB_IFCOUNT
;
934 if (sysctl(name
, 5, &latest_ifcount
, &len
, 0, 0) == 1)
935 err(1, "sysctl IFMIB_IFCOUNT");
936 if (latest_ifcount
> ifcount
) {
937 ifcount
= latest_ifcount
;
938 len
= ifcount
* sizeof(struct ifmibdata
);
940 ifmdall
= malloc(len
);
942 err(1, "malloc ifmdall failed");
943 } else if (latest_ifcount
> ifcount
) {
944 ifcount
= latest_ifcount
;
945 len
= ifcount
* sizeof(struct ifmibdata
);
947 len
= ifcount
* sizeof(struct ifmibdata
);
948 name
[3] = IFMIB_IFALLDATA
;
950 name
[5] = IFDATA_GENERAL
;
951 if (sysctl(name
, 6, ifmdall
, &len
, (void *)0, 0) == -1)
952 err(1, "sysctl IFMIB_IFALLDATA");
954 len
= ifcount
* sizeof(struct ifmibdata_supplemental
);
955 ifmsuppall
= malloc(len
);
956 if (ifmsuppall
== NULL
)
957 err(1, "malloc ifmsuppall failed");
958 name
[3] = IFMIB_IFALLDATA
;
960 name
[5] = IFDATA_SUPPLEMENTAL
;
961 if (sysctl(name
, 6, ifmsuppall
, &len
, (void *)0, 0) == -1)
962 err(1, "sysctl IFMIB_IFALLDATA SUPPLEMENTAL");
982 for (i
= 0; i
< ifcount
; i
++) {
983 struct ifmibdata
*ifmd
= ifmdall
+ i
;
984 struct ifmibdata_supplemental
*ifmsupp
= ifmsuppall
+ i
;
986 sum
->ift_ip
+= ifmd
->ifmd_data
.ifi_ipackets
;
987 sum
->ift_ie
+= ifmd
->ifmd_data
.ifi_ierrors
;
988 sum
->ift_ib
+= ifmd
->ifmd_data
.ifi_ibytes
;
989 sum
->ift_op
+= ifmd
->ifmd_data
.ifi_opackets
;
990 sum
->ift_oe
+= ifmd
->ifmd_data
.ifi_oerrors
;
991 sum
->ift_ob
+= ifmd
->ifmd_data
.ifi_obytes
;
992 sum
->ift_co
+= ifmd
->ifmd_data
.ifi_collisions
;
993 sum
->ift_dr
+= ifmd
->ifmd_snd_drops
;
994 /* private counters */
998 sum
->ift_itcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ibepackets
;
999 sum
->ift_itcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ibebytes
;
1000 sum
->ift_otcp
+= ifmsupp
->ifmd_traffic_class
.ifi_obepackets
;
1001 sum
->ift_otcb
+= ifmsupp
->ifmd_traffic_class
.ifi_obebytes
;
1004 sum
->ift_itcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ibkpackets
;
1005 sum
->ift_itcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ibkbytes
;
1006 sum
->ift_otcp
+= ifmsupp
->ifmd_traffic_class
.ifi_obkpackets
;
1007 sum
->ift_otcb
+= ifmsupp
->ifmd_traffic_class
.ifi_obkbytes
;
1010 sum
->ift_itcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ivipackets
;
1011 sum
->ift_itcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ivibytes
;
1012 sum
->ift_otcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ovipackets
;
1013 sum
->ift_otcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ovibytes
;
1016 sum
->ift_itcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ivopackets
;
1017 sum
->ift_itcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ivobytes
;
1018 sum
->ift_otcp
+= ifmsupp
->ifmd_traffic_class
.ifi_ovopackets
;
1019 sum
->ift_otcb
+= ifmsupp
->ifmd_traffic_class
.ifi_ovobytes
;
1024 sum
->ift_ipvp
+= ifmsupp
->ifmd_traffic_class
.ifi_ipvpackets
;
1025 sum
->ift_ipvb
+= ifmsupp
->ifmd_traffic_class
.ifi_ipvbytes
;
1026 sum
->ift_opvp
+= ifmsupp
->ifmd_traffic_class
.ifi_opvpackets
;
1027 sum
->ift_opvb
+= ifmsupp
->ifmd_traffic_class
.ifi_opvbytes
;
1029 sum
->ift_fp
+= ifmsupp
->ifmd_data_extended
.ifi_fpackets
;
1030 sum
->ift_fb
+= ifmsupp
->ifmd_data_extended
.ifi_fbytes
;
1033 printf("%10llu %5llu %10llu ",
1034 sum
->ift_ip
- total
->ift_ip
,
1035 sum
->ift_ie
- total
->ift_ie
,
1036 sum
->ift_ib
- total
->ift_ib
);
1038 printf(" %10llu %10llu %10llu %10llu",
1039 sum
->ift_itcp
- total
->ift_itcp
,
1040 sum
->ift_itcb
- total
->ift_itcb
,
1041 sum
->ift_ipvp
- total
->ift_ipvp
,
1042 sum
->ift_ipvb
- total
->ift_ipvb
);
1043 printf("%10llu %5llu %10llu %5llu",
1044 sum
->ift_op
- total
->ift_op
,
1045 sum
->ift_oe
- total
->ift_oe
,
1046 sum
->ift_ob
- total
->ift_ob
,
1047 sum
->ift_co
- total
->ift_co
);
1049 printf(" %5llu", sum
->ift_dr
- total
->ift_dr
);
1051 printf(" %10llu %10llu %10llu %10llu",
1052 sum
->ift_otcp
- total
->ift_otcp
,
1053 sum
->ift_otcb
- total
->ift_otcb
,
1054 sum
->ift_opvp
- total
->ift_opvp
,
1055 sum
->ift_opvb
- total
->ift_opvb
);
1057 printf(" %10llu %10llu",
1058 sum
->ift_fp
- total
->ift_fp
,
1059 sum
->ift_fb
- total
->ift_fb
);
1068 sigemptyset(&sigset
);
1069 sigaddset(&sigset
, SIGALRM
);
1070 (void)sigprocmask(SIG_BLOCK
, &sigset
, &oldsigset
);
1072 sigemptyset(&sigset
);
1073 sigsuspend(&sigset
);
1075 (void)sigprocmask(SIG_SETMASK
, &oldsigset
, NULL
);
1088 intervalpr(void (*pr
)(uint32_t, char *, int), uint32_t off
, char *name
, int af
)
1090 struct itimerval timer_interval
;
1091 sigset_t sigset
, oldsigset
;
1093 /* create a timer that fires repeatedly every interval seconds */
1094 timer_interval
.it_value
.tv_sec
= interval
;
1095 timer_interval
.it_value
.tv_usec
= 0;
1096 timer_interval
.it_interval
.tv_sec
= interval
;
1097 timer_interval
.it_interval
.tv_usec
= 0;
1098 (void) signal(SIGALRM
, catchalarm
);
1100 (void) setitimer(ITIMER_REAL
, &timer_interval
, NULL
);
1106 sigemptyset(&sigset
);
1107 sigaddset(&sigset
, SIGALRM
);
1108 (void) sigprocmask(SIG_BLOCK
, &sigset
, &oldsigset
);
1110 sigemptyset(&sigset
);
1111 sigsuspend(&sigset
);
1113 (void) sigprocmask(SIG_SETMASK
, &oldsigset
, NULL
);
1119 * Called if an interval expires before sidewaysintpr has completed a loop.
1120 * Sets a flag to not wait for the alarm.
1123 catchalarm(int signo
)
1132 static char result
[256];
1133 int days
, hours
, mins
, secs
;
1137 days
= total
/ 3600 / 24;
1138 hours
= (total
/ 3600) % 24;
1139 mins
= (total
/ 60) % 60;
1144 p
+= snprintf(p
, sizeof(result
) - (p
- result
), "%dd", days
);
1146 if (!first
|| hours
) {
1148 p
+= snprintf(p
, sizeof(result
) - (p
- result
), "%dh", hours
);
1150 if (!first
|| mins
) {
1152 p
+= snprintf(p
, sizeof(result
) - (p
- result
), "%dm", mins
);
1154 snprintf(p
, sizeof(result
) - (p
- result
), "%ds", secs
);
1160 intpr_ri(void (*pfunc
)(char *))
1163 char *buf
= NULL
, *lim
, *next
;
1165 unsigned int ifindex
= 0;
1166 struct if_msghdr2
*if2m
;
1168 if (interface
!= 0) {
1169 ifindex
= if_nametoindex(interface
);
1171 printf("interface name is not valid: %s\n", interface
);
1176 mib
[0] = CTL_NET
; /* networking subsystem */
1177 mib
[1] = PF_ROUTE
; /* type of information */
1178 mib
[2] = 0; /* protocol (IPPROTO_xxx) */
1179 mib
[3] = 0; /* address family */
1180 mib
[4] = NET_RT_IFLIST2
; /* operation */
1182 if (sysctl(mib
, 6, NULL
, &len
, NULL
, 0) < 0)
1184 if ((buf
= malloc(len
)) == NULL
) {
1185 printf("malloc failed\n");
1188 if (sysctl(mib
, 6, buf
, &len
, NULL
, 0) < 0) {
1193 printf("%-6s %-17s %8.8s %-9.9s %4s %4s",
1194 "Proto", "Linklayer Address", "Netif", "Expire", "Refs",
1197 printf(" %7s %7s %7s", "RSSI", "LQM", "NPM");
1201 if2m
= (struct if_msghdr2
*)buf
;
1203 for (next
= buf
; next
< lim
; ) {
1204 if2m
= (struct if_msghdr2
*)next
;
1205 next
+= if2m
->ifm_msglen
;
1207 if (if2m
->ifm_type
!= RTM_IFINFO2
)
1209 else if (interface
!= 0 && if2m
->ifm_index
!= ifindex
)
1212 llreach_sysctl(if2m
->ifm_index
);
1218 llreach_sysctl(uint32_t ifindex
)
1220 #define MAX_SYSCTL_TRY 5
1221 int mib
[6], i
, ntry
= 0;
1222 size_t mibsize
, len
, needed
, cnt
;
1223 struct if_llreach_info
*lri
;
1224 struct timeval time
;
1226 char ifname
[IF_NAMESIZE
];
1228 bzero(&mib
, sizeof (mib
));
1229 mibsize
= sizeof (mib
) / sizeof (mib
[0]);
1230 if (sysctlnametomib("net.link.generic.system.llreach_info", mib
,
1232 perror("sysctlnametomib");
1239 mibsize
= sizeof (mib
) / sizeof (mib
[0]);
1241 if (sysctl(mib
, mibsize
, NULL
, &needed
, NULL
, 0) == -1) {
1242 perror("sysctl net.link.generic.system.llreach_info");
1245 if ((buf
= malloc(needed
)) == NULL
) {
1249 if (sysctl(mib
, mibsize
, buf
, &needed
, NULL
, 0) == -1) {
1250 if (errno
!= ENOMEM
|| ++ntry
>= MAX_SYSCTL_TRY
) {
1257 } while (buf
== NULL
);
1260 cnt
= len
/ sizeof (*lri
);
1261 lri
= (struct if_llreach_info
*)buf
;
1263 gettimeofday(&time
, 0);
1264 if (if_indextoname(ifindex
, ifname
) == NULL
)
1265 snprintf(ifname
, sizeof (ifname
), "%s", "?");
1267 for (i
= 0; i
< cnt
; i
++, lri
++) {
1268 printf("0x%-4x %-17s %8.8s ", lri
->lri_proto
,
1269 ether_ntoa((struct ether_addr
*)lri
->lri_addr
), ifname
);
1271 if (lri
->lri_expire
> time
.tv_sec
)
1272 printf("%-9.9s", sec2str(lri
->lri_expire
- time
.tv_sec
));
1273 else if (lri
->lri_expire
== 0)
1274 printf("%-9.9s", "permanent");
1276 printf("%-9.9s", "expired");
1278 printf(" %4d", lri
->lri_refcnt
);
1279 if (lri
->lri_probes
)
1280 printf(" %4d", lri
->lri_probes
);
1283 if (!lri
->lri_probes
)
1284 printf(" %-4.4s", "none");
1286 if (lri
->lri_rssi
!= IFNET_RSSI_UNKNOWN
)
1287 printf(" %7d", lri
->lri_rssi
);
1289 printf(" %-7.7s", "unknown");
1291 switch (lri
->lri_lqm
)
1293 case IFNET_LQM_THRESH_OFF
:
1294 printf(" %-7.7s", "off");
1296 case IFNET_LQM_THRESH_UNKNOWN
:
1297 printf(" %-7.7s", "unknown");
1299 case IFNET_LQM_THRESH_POOR
:
1300 printf(" %-7.7s", "poor");
1302 case IFNET_LQM_THRESH_GOOD
:
1303 printf(" %-7.7s", "good");
1306 printf(" %7d", lri
->lri_lqm
);
1310 switch (lri
->lri_npm
)
1312 case IFNET_NPM_THRESH_UNKNOWN
:
1313 printf(" %-7.7s", "unknown");
1315 case IFNET_NPM_THRESH_NEAR
:
1316 printf(" %-7.7s", "near");
1318 case IFNET_NPM_THRESH_GENERAL
:
1319 printf(" %-7.7s", "general");
1321 case IFNET_NPM_THRESH_FAR
:
1322 printf(" %-7.7s", "far");
1325 printf(" %7d", lri
->lri_npm
);
1331 len
-= sizeof (*lri
);
1335 fprintf(stderr
, "warning: %u trailing bytes from %s\n",
1336 (unsigned int)len
, "net.link.generic.system.llreach_info");
1341 #undef MAX_SYSCTL_TRY
1347 unsigned int ifindex
;
1348 struct itimerval timer_interval
;
1349 struct if_qstatsreq ifqr
;
1350 struct if_ifclassq_stats
*ifcqs
;
1351 sigset_t sigset
, oldsigset
;
1352 u_int32_t scheduler
;
1355 if (cq
< -1 || cq
>= IFCQ_SC_MAX
) {
1356 fprintf(stderr
, "Invalid classq index (range is 0-%d)\n",
1360 ifindex
= if_nametoindex(interface
);
1362 fprintf(stderr
, "Invalid interface name\n");
1366 ifcqs
= malloc(sizeof (*ifcqs
));
1367 if (ifcqs
== NULL
) {
1368 fprintf(stderr
, "Unable to allocate memory\n");
1372 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
1373 perror("Warning: socket(AF_INET)");
1378 bzero(&ifqr
, sizeof (ifqr
));
1379 strlcpy(ifqr
.ifqr_name
, interface
, sizeof (ifqr
.ifqr_name
));
1380 ifqr
.ifqr_buf
= ifcqs
;
1381 ifqr
.ifqr_len
= sizeof (*ifcqs
);
1385 /* create a timer that fires repeatedly every interval seconds */
1386 timer_interval
.it_value
.tv_sec
= interval
;
1387 timer_interval
.it_value
.tv_usec
= 0;
1388 timer_interval
.it_interval
.tv_sec
= interval
;
1389 timer_interval
.it_interval
.tv_usec
= 0;
1390 (void) signal(SIGALRM
, catchalarm
);
1392 (void) setitimer(ITIMER_REAL
, &timer_interval
, NULL
);
1396 if (ioctl(s
, SIOCGIFQUEUESTATS
, (char *)&ifqr
) < 0) {
1397 if (errno
== ENXIO
) {
1398 printf("Queue statistics are not available on %s\n",
1401 perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
1405 scheduler
= ifcqs
->ifqs_scheduler
;
1406 tcq
= (scheduler
== PKTSCHEDT_TCQ
);
1409 "%s [ sched: %9s %sqlength: %3d/%3d ]\n",
1410 interface
, tcq
? " " : "", sched2str(ifcqs
->ifqs_scheduler
),
1411 tcq
? "" : " ", ifcqs
->ifqs_len
, ifcqs
->ifqs_maxlen
);
1412 printf("%s [ pkts: %10llu %sbytes: %10llu "
1413 "%sdropped pkts: %6llu bytes: %6llu ]\n",
1414 (scheduler
!= PKTSCHEDT_TCQ
) ? "" : " ",
1415 ifcqs
->ifqs_xmitcnt
.packets
, tcq
? "" : " ",
1416 ifcqs
->ifqs_xmitcnt
.bytes
, tcq
? "" : " ",
1417 ifcqs
->ifqs_dropcnt
.packets
, ifcqs
->ifqs_dropcnt
.bytes
);
1419 for (n
= 0; n
< IFCQ_SC_MAX
; n
++) {
1420 qstats
[n
].printed
= 0;
1424 if (ioctl(s
, SIOCGIFQUEUESTATS
, (char *)&ifqr
) < 0) {
1425 perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
1428 qstats
[n
].handle
= ifcqs
->ifqs_tcq_stats
.class_handle
;
1431 for (n
= 0; n
< IFCQ_SC_MAX
&& scheduler
!= PKTSCHEDT_NONE
; n
++) {
1432 if (cq
>= 0 && cq
!= n
)
1436 if (ioctl(s
, SIOCGIFQUEUESTATS
, (char *)&ifqr
) < 0) {
1437 perror("Warning: ioctl(SIOCGIFQUEUESTATS)");
1441 update_avg(ifcqs
, &qstats
[n
]);
1443 switch (scheduler
) {
1445 print_tcqstats(n
, &ifcqs
->ifqs_tcq_stats
,
1449 print_qfqstats(n
, &ifcqs
->ifqs_qfq_stats
,
1452 case PKTSCHEDT_FQ_CODEL
:
1453 print_fq_codel_stats(n
,
1454 &ifcqs
->ifqs_fq_codel_stats
,
1457 case PKTSCHEDT_NONE
:
1466 sigemptyset(&sigset
);
1467 sigaddset(&sigset
, SIGALRM
);
1468 (void) sigprocmask(SIG_BLOCK
, &sigset
, &oldsigset
);
1470 sigemptyset(&sigset
);
1471 sigsuspend(&sigset
);
1473 (void) sigprocmask(SIG_SETMASK
, &oldsigset
, NULL
);
1485 print_tcqstats(int slot
, struct tcq_classstats
*cs
, struct queue_stats
*qs
)
1492 qs
->handle
= cs
->class_handle
;
1495 for (n
= 0; n
< IFCQ_SC_MAX
; n
++) {
1496 if (&qstats
[n
] != qs
&& qstats
[n
].handle
== qs
->handle
)
1497 qstats
[n
].printed
++;
1500 printf("%5s: [ pkts: %10llu bytes: %10llu "
1501 "dropped pkts: %6llu bytes: %6llu ]\n", tcqslot2str(slot
),
1502 (unsigned long long)cs
->xmitcnt
.packets
,
1503 (unsigned long long)cs
->xmitcnt
.bytes
,
1504 (unsigned long long)cs
->dropcnt
.packets
,
1505 (unsigned long long)cs
->dropcnt
.bytes
);
1506 printf(" [ qlength: %3d/%3d qalg: %11s "
1507 "svc class: %9s %-13s ]\n", cs
->qlength
, cs
->qlimit
,
1508 qtype2str(cs
->qtype
), qid2str(cs
->class_handle
),
1509 qstate2str(cs
->qstate
));
1511 if (qs
->avgn
>= 2) {
1512 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1513 qs
->avg_packets
/ interval
,
1514 rate2str((8 * qs
->avg_bytes
) / interval
));
1520 switch (cs
->qtype
) {
1522 print_sfbstats(&cs
->sfb
);
1530 print_qfqstats(int slot
, struct qfq_classstats
*cs
, struct queue_stats
*qs
)
1532 printf(" %2d: [ pkts: %10llu bytes: %10llu "
1533 "dropped pkts: %6llu bytes: %6llu ]\n", slot
,
1534 (unsigned long long)cs
->xmitcnt
.packets
,
1535 (unsigned long long)cs
->xmitcnt
.bytes
,
1536 (unsigned long long)cs
->dropcnt
.packets
,
1537 (unsigned long long)cs
->dropcnt
.bytes
);
1538 printf(" [ qlength: %3d/%3d index: %10u weight: %12u "
1539 "lmax: %7u ]\n", cs
->qlength
, cs
->qlimit
, cs
->index
,
1540 cs
->weight
, cs
->lmax
);
1541 printf(" [ qalg: %10s svc class: %6s %-35s ]\n",
1542 qtype2str(cs
->qtype
), qid2str(cs
->class_handle
),
1543 qstate2str(cs
->qstate
));
1545 if (qs
->avgn
>= 2) {
1546 printf(" [ measured: %7.1f packets/s, %s/s ]\n",
1547 qs
->avg_packets
/ interval
,
1548 rate2str((8 * qs
->avg_bytes
) / interval
));
1554 switch (cs
->qtype
) {
1556 print_sfbstats(&cs
->sfb
);
1564 print_fq_codel_stats(int pri
, struct fq_codel_classstats
*fqst
,
1565 struct queue_stats
*qs
)
1569 if (fqst
->fcls_service_class
== 0 && fqst
->fcls_pri
== 0)
1571 printf("=====================================================\n");
1572 printf(" [ pri: %s (%d)\tsrv_cl: 0x%x\tquantum: %d\tdrr_max: %d ]\n",
1573 pri2str(fqst
->fcls_pri
), fqst
->fcls_pri
,
1574 fqst
->fcls_service_class
, fqst
->fcls_quantum
,
1575 fqst
->fcls_drr_max
);
1576 printf(" [ queued pkts: %llu\tbytes: %llu ]\n",
1577 fqst
->fcls_pkt_cnt
, fqst
->fcls_byte_cnt
);
1578 printf(" [ dequeued pkts: %llu\tbytes: %llu ]\n",
1579 fqst
->fcls_dequeue
, fqst
->fcls_dequeue_bytes
);
1580 printf(" [ budget: %lld\ttarget qdelay: %10s\t",
1581 fqst
->fcls_budget
, nsec_to_str(fqst
->fcls_target_qdelay
));
1582 printf("update interval:%10s ]\n",
1583 nsec_to_str(fqst
->fcls_update_interval
));
1584 printf(" [ flow control: %u\tfeedback: %u\tstalls: %u\tfailed: %u ]\n",
1585 fqst
->fcls_flow_control
, fqst
->fcls_flow_feedback
,
1586 fqst
->fcls_dequeue_stall
, fqst
->fcls_flow_control_fail
);
1587 printf(" [ drop overflow: %llu\tearly: %llu\tmemfail: %u\tduprexmt:%u ]\n",
1588 fqst
->fcls_drop_overflow
, fqst
->fcls_drop_early
,
1589 fqst
->fcls_drop_memfailure
, fqst
->fcls_dup_rexmts
);
1590 printf(" [ flows total: %u\tnew: %u\told: %u ]\n",
1591 fqst
->fcls_flows_cnt
,
1592 fqst
->fcls_newflows_cnt
, fqst
->fcls_oldflows_cnt
);
1593 printf(" [ throttle on: %u\toff: %u\tdrop: %u ]\n",
1594 fqst
->fcls_throttle_on
, fqst
->fcls_throttle_off
,
1595 fqst
->fcls_throttle_drops
);
1600 if (fqst
->fcls_flowstats_cnt
> 0) {
1601 printf("Flowhash\tBytes\tMin qdelay\tFlags\t\n");
1602 for (i
= 0; i
< fqst
->fcls_flowstats_cnt
; i
++) {
1603 printf("%u\t%u\t%14s\t",
1604 fqst
->fcls_flowstats
[i
].fqst_flowhash
,
1605 fqst
->fcls_flowstats
[i
].fqst_bytes
,
1606 nsec_to_str(fqst
->fcls_flowstats
[i
].fqst_min_qdelay
));
1607 if (fqst
->fcls_flowstats
[i
].fqst_flags
&
1608 FQ_FLOWSTATS_OLD_FLOW
)
1610 if (fqst
->fcls_flowstats
[i
].fqst_flags
&
1611 FQ_FLOWSTATS_NEW_FLOW
)
1613 if (fqst
->fcls_flowstats
[i
].fqst_flags
&
1614 FQ_FLOWSTATS_LARGE_FLOW
)
1616 if (fqst
->fcls_flowstats
[i
].fqst_flags
&
1617 FQ_FLOWSTATS_DELAY_HIGH
)
1619 if (fqst
->fcls_flowstats
[i
].fqst_flags
&
1620 FQ_FLOWSTATS_FLOWCTL_ON
)
1628 print_sfbstats(struct sfb_stats
*sfb
)
1630 struct sfbstats
*sp
= &sfb
->sfbstats
;
1631 int i
, j
, cur
= sfb
->current
;
1634 printf(" [target delay: %14s ",
1635 nsec_to_str(sfb
->target_qdelay
));
1636 printf("update interval: %14s]\n",
1637 nsec_to_str(sfb
->update_interval
));
1638 printf(" [ early drop: %12llu rlimit drop: %11llu "
1639 "marked: %11llu ]\n",
1640 sp
->drop_early
, sp
->drop_pbox
, sp
->marked_packets
);
1641 printf(" [ penalized: %13llu rehash cnt: %12llu "
1642 "current: %10u ]\n", sp
->pbox_packets
, sp
->num_rehash
, cur
);
1643 printf(" [ deque avg: %13s ", nsec_to_str(sp
->dequeue_avg
));
1644 printf("rehash intvl: %11s]\n", nsec_to_str(sp
->rehash_intval
));
1645 printf(" [ holdtime: %14s ", nsec_to_str(sp
->hold_time
));
1646 printf("pboxtime: %14s ]\n", nsec_to_str(sp
->pbox_time
));
1647 printf(" [ allocation: %12u drop thresh: %11u ]\n",
1648 sfb
->allocation
, sfb
->dropthresh
);
1649 printf(" [ flow controlled: %7llu adv feedback: %10llu ]\n",
1650 sp
->flow_controlled
, sp
->flow_feedback
);
1651 printf(" [ min queue delay: %10s delay_fcthreshold: %12u]\n "
1652 " [stalls: %12llu]\n",
1653 nsec_to_str(sfb
->min_estdelay
), sfb
->delay_fcthreshold
,
1656 printf("\n\t\t\t\tCurrent bins (set %d)", cur
);
1657 for (i
= 0; i
< SFB_LEVELS
; ++i
) {
1661 printf("\n\tLevel: %d\n", i
);
1662 for (j
= 0; j
< SFB_BINS
; ++j
) {
1664 printf("\t%6d:\t", j
+ 1);
1665 p
= sfb
->binstats
[cur
].stats
[i
][j
].pmark
;
1666 q
= sfb
->binstats
[cur
].stats
[i
][j
].pkts
;
1668 p
/= (1 << SFB_FP_SHIFT
);
1669 printf("[%1.4f %4u]", p
, q
);
1673 if (j
> 0 && ((j
+ 1) % 4) == 0)
1679 printf("\n\t\t\t\tWarm up bins (set %d)", cur
);
1680 for (i
= 0; i
< SFB_LEVELS
; ++i
) {
1684 printf("\n\tLevel: %d\n", i
);
1685 for (j
= 0; j
< SFB_BINS
; ++j
) {
1687 printf("\t%6d:\t", j
+ 1);
1688 p
= sfb
->binstats
[cur
].stats
[i
][j
].pmark
;
1689 q
= sfb
->binstats
[cur
].stats
[i
][j
].pkts
;
1691 p
/= (1 << SFB_FP_SHIFT
);
1692 printf("[%1.4f %4u]", p
, q
);
1696 if (j
> 0 && ((j
+ 1) % 4) == 0)
1704 update_avg(struct if_ifclassq_stats
*ifcqs
, struct queue_stats
*qs
)
1711 switch (ifcqs
->ifqs_scheduler
) {
1713 b
= ifcqs
->ifqs_tcq_stats
.xmitcnt
.bytes
;
1714 p
= ifcqs
->ifqs_tcq_stats
.xmitcnt
.packets
;
1717 b
= ifcqs
->ifqs_qfq_stats
.xmitcnt
.bytes
;
1718 p
= ifcqs
->ifqs_qfq_stats
.xmitcnt
.packets
;
1720 case PKTSCHEDT_FQ_CODEL
:
1721 b
= ifcqs
->ifqs_fq_codel_stats
.fcls_dequeue_bytes
;
1722 p
= ifcqs
->ifqs_fq_codel_stats
.fcls_dequeue
;
1732 qs
->prev_packets
= p
;
1737 if (b
>= qs
->prev_bytes
)
1738 qs
->avg_bytes
= ((qs
->avg_bytes
* (n
- 1)) +
1739 (b
- qs
->prev_bytes
)) / n
;
1741 if (p
>= qs
->prev_packets
)
1742 qs
->avg_packets
= ((qs
->avg_packets
* (n
- 1)) +
1743 (p
- qs
->prev_packets
)) / n
;
1746 qs
->prev_packets
= p
;
1752 qtype2str(classq_type_t t
)
1774 #define NSEC_PER_SEC 1000000000 /* nanoseconds per second */
1775 #define USEC_PER_SEC 1000000 /* microseconds per second */
1776 #define MSEC_PER_SEC 1000 /* milliseconds per second */
1779 nsec_to_str(unsigned long long nsec
)
1781 static char buf
[32];
1783 long double n
= nsec
, t
;
1785 if (nsec
>= NSEC_PER_SEC
) {
1786 t
= n
/ NSEC_PER_SEC
;
1788 } else if (n
>= USEC_PER_SEC
) {
1789 t
= n
/ USEC_PER_SEC
;
1791 } else if (n
>= MSEC_PER_SEC
) {
1792 t
= n
/ MSEC_PER_SEC
;
1799 snprintf(buf
, sizeof (buf
), "%-4.2Lf %4s", t
, u
);
1804 sched2str(unsigned int s
)
1809 case PKTSCHEDT_NONE
:
1818 case PKTSCHEDT_FQ_CODEL
:
1830 qid2str(unsigned int s
)
1874 tcqslot2str(unsigned int s
)
1906 pri2str(unsigned int i
)
1948 qstate2str(unsigned int s
)
1968 #define RATESTR_MAX 16
1971 rate2str(long double rate
)
1974 static char r2sbuf
[R2S_BUFS
][RATESTR_MAX
]; /* ring bufer */
1977 static const char unit
[] = " KMG";
1979 buf
= r2sbuf
[idx
++];
1980 if (idx
== R2S_BUFS
)
1983 for (i
= 0; rate
>= 1000 && i
<= 3; i
++)
1986 if ((int)(rate
* 100) % 100)
1987 snprintf(buf
, RATESTR_MAX
, "%.2Lf%cb", rate
, unit
[i
]);
1989 snprintf(buf
, RATESTR_MAX
, "%lld%cb", (int64_t)rate
, unit
[i
]);
1997 struct ifmibdata_supplemental ifmsupp
;
1998 size_t miblen
= sizeof (ifmsupp
);
1999 struct itimerval timer_interval
;
2000 struct if_rxpoll_stats
*sp
;
2001 sigset_t sigset
, oldsigset
;
2002 unsigned int ifindex
;
2005 ifindex
= if_nametoindex(interface
);
2007 fprintf(stderr
, "Invalid interface name\n");
2011 bzero(&ifmsupp
, sizeof (struct ifmibdata_supplemental
));
2015 /* create a timer that fires repeatedly every interval seconds */
2016 timer_interval
.it_value
.tv_sec
= interval
;
2017 timer_interval
.it_value
.tv_usec
= 0;
2018 timer_interval
.it_interval
.tv_sec
= interval
;
2019 timer_interval
.it_interval
.tv_usec
= 0;
2020 (void) signal(SIGALRM
, catchalarm
);
2022 (void) setitimer(ITIMER_REAL
, &timer_interval
, NULL
);
2025 /* Common OID prefix */
2028 name
[2] = NETLINK_GENERIC
;
2029 name
[3] = IFMIB_IFDATA
;
2031 name
[5] = IFDATA_SUPPLEMENTAL
;
2032 if (sysctl(name
, 6, &ifmsupp
, &miblen
, NULL
, 0) == -1)
2033 err(1, "sysctl IFDATA_SUPPLEMENTAL");
2035 sp
= &ifmsupp
.ifmd_rxpoll_stats
;
2037 printf("%-4s [ poll on requests: %15u errors: %27u ]\n",
2038 interface
, sp
->ifi_poll_on_req
, sp
->ifi_poll_on_err
);
2039 printf(" [ poll off requests: %15u errors: %27u ]\n",
2040 sp
->ifi_poll_off_req
, sp
->ifi_poll_off_err
);
2041 printf(" [ polled packets: %18llu polled bytes: %21llu ]\n",
2042 sp
->ifi_poll_packets
, sp
->ifi_poll_bytes
);
2043 printf(" [ sampled packets avg/min/max: %12u / %12u / %12u ]\n",
2044 sp
->ifi_poll_packets_avg
, sp
->ifi_poll_packets_min
,
2045 sp
->ifi_poll_packets_max
);
2046 printf(" [ sampled bytes avg/min/max: %12u / %12u / %12u ]\n",
2047 sp
->ifi_poll_bytes_avg
, sp
->ifi_poll_bytes_min
,
2048 sp
->ifi_poll_bytes_max
);
2049 printf(" [ sampled wakeups avg: %12u ]\n",
2050 sp
->ifi_poll_wakeups_avg
);
2051 printf(" [ packets lowat/hiwat threshold: %10u / %10u ]\n",
2052 sp
->ifi_poll_packets_lowat
, sp
->ifi_poll_packets_hiwat
);
2053 printf(" [ bytes lowat/hiwat threshold: %10u / %10u ]\n",
2054 sp
->ifi_poll_bytes_lowat
, sp
->ifi_poll_bytes_hiwat
);
2055 printf(" [ wakeups lowat/hiwat threshold: %10u / %10u ]\n",
2056 sp
->ifi_poll_wakeups_lowat
, sp
->ifi_poll_wakeups_hiwat
);
2061 sigemptyset(&sigset
);
2062 sigaddset(&sigset
, SIGALRM
);
2063 (void) sigprocmask(SIG_BLOCK
, &sigset
, &oldsigset
);
2065 sigemptyset(&sigset
);
2066 sigsuspend(&sigset
);
2068 (void) sigprocmask(SIG_SETMASK
, &oldsigset
, NULL
);
2076 create_control_socket(const char *control_name
)
2078 struct sockaddr_ctl sc
;
2079 struct ctl_info ctl
;
2082 fd
= socket(PF_SYSTEM
, SOCK_DGRAM
, SYSPROTO_CONTROL
);
2084 perror("socket(PF_SYSTEM)");
2088 /* Get the control ID for statistics */
2089 bzero(&ctl
, sizeof(ctl
));
2090 strlcpy(ctl
.ctl_name
, control_name
, sizeof(ctl
.ctl_name
));
2091 if (ioctl(fd
, CTLIOCGINFO
, &ctl
) == -1)
2093 perror("ioctl(CTLIOCGINFO)");
2098 /* Connect to the statistics control */
2099 bzero(&sc
, sizeof(sc
));
2100 sc
.sc_len
= sizeof(sc
);
2101 sc
.sc_family
= AF_SYSTEM
;
2102 sc
.ss_sysaddr
= SYSPROTO_CONTROL
;
2103 sc
.sc_id
= ctl
.ctl_id
;
2105 if (connect(fd
, (struct sockaddr
*)&sc
, sc
.sc_len
) != 0)
2107 perror("connect(SYSPROTO_CONTROL)");
2112 /* Set socket to non-blocking operation */
2113 if (fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFL
, 0) | O_NONBLOCK
) == -1) {
2114 perror("fcnt(F_SETFL,O_NONBLOCK)");
2122 add_nstat_src(int fd
, const nstat_ifnet_add_param
*ifparam
,
2123 nstat_src_ref_t
*outsrc
)
2125 nstat_msg_add_src_req
*addreq
;
2126 nstat_msg_src_added
*addedmsg
;
2127 nstat_ifnet_add_param
*param
;
2128 char buffer
[sizeof(*addreq
) + sizeof(*param
)];
2130 const u_int32_t addreqsize
=
2131 offsetof(struct nstat_msg_add_src
, param
) + sizeof(*param
);
2133 /* Setup the add source request */
2134 addreq
= (nstat_msg_add_src_req
*)buffer
;
2135 param
= (nstat_ifnet_add_param
*)addreq
->param
;
2136 bzero(addreq
, addreqsize
);
2137 addreq
->hdr
.context
= (uintptr_t)&buffer
;
2138 addreq
->hdr
.type
= NSTAT_MSG_TYPE_ADD_SRC
;
2139 addreq
->provider
= NSTAT_PROVIDER_IFNET
;
2140 bzero(param
, sizeof(*param
));
2141 param
->ifindex
= ifparam
->ifindex
;
2142 param
->threshold
= ifparam
->threshold
;
2144 /* Send the add source request */
2145 result
= send(fd
, addreq
, addreqsize
, 0);
2146 if (result
!= addreqsize
)
2149 perror("send(NSTAT_ADD_SRC_REQ)");
2151 fprintf(stderr
, "%s: could only sent %ld out of %d\n",
2152 __func__
, result
, addreqsize
);
2156 /* Receive the response */
2157 addedmsg
= (nstat_msg_src_added
*)buffer
;
2158 result
= recv(fd
, addedmsg
, sizeof(buffer
), 0);
2159 if (result
< sizeof(*addedmsg
))
2162 perror("recv(NSTAT_ADD_SRC_RSP)");
2164 fprintf(stderr
, "%s: recv too small, received %ld, "
2165 "expected %lu\n", __func__
, result
,
2170 if (addedmsg
->hdr
.type
!= NSTAT_MSG_TYPE_SRC_ADDED
)
2172 fprintf(stderr
, "%s: received wrong message type, received %u "
2173 "expected %u\n", __func__
, addedmsg
->hdr
.type
,
2174 NSTAT_MSG_TYPE_SRC_ADDED
);
2178 if (addedmsg
->hdr
.context
!= (uintptr_t)&buffer
)
2180 fprintf(stderr
, "%s: received wrong context, received %llu "
2181 "expected %lu\n", __func__
, addedmsg
->hdr
.context
,
2182 (uintptr_t)&buffer
);
2185 *outsrc
= addedmsg
->srcref
;
2190 rem_nstat_src(int fd
, nstat_src_ref_t sref
)
2192 nstat_msg_rem_src_req
*remreq
;
2193 nstat_msg_src_removed
*remrsp
;
2194 char buffer
[sizeof(*remreq
)];
2197 /* Setup the add source request */
2198 remreq
= (nstat_msg_rem_src_req
*)buffer
;
2199 bzero(remreq
, sizeof(*remreq
));
2200 remreq
->hdr
.type
= NSTAT_MSG_TYPE_REM_SRC
;
2201 remreq
->srcref
= sref
;
2203 /* Send the remove source request */
2204 result
= send(fd
, remreq
, sizeof(*remreq
), 0);
2205 if (result
!= sizeof(*remreq
)) {
2207 perror("send(NSTAT_REM_SRC_REQ)");
2209 fprintf(stderr
, "%s: could only sent %ld out of %lu\n",
2210 __func__
, result
, sizeof(*remreq
));
2214 /* Receive the response */
2215 remrsp
= (nstat_msg_src_removed
*)buffer
;
2216 result
= recv(fd
, remrsp
, sizeof(buffer
), 0);
2217 if (result
< sizeof(*remrsp
)) {
2219 perror("recv(NSTAT_REM_SRC_RSP)");
2221 fprintf(stderr
, "%s: recv too small, received %ld, "
2222 "expected %lu\n", __func__
, result
,
2227 if (remrsp
->hdr
.type
!= NSTAT_MSG_TYPE_SRC_REMOVED
) {
2228 fprintf(stderr
, "%s: received wrong message type, received %u "
2229 "expected %u\n", __func__
, remrsp
->hdr
.type
,
2230 NSTAT_MSG_TYPE_SRC_REMOVED
);
2234 if (remrsp
->srcref
!= sref
) {
2235 fprintf(stderr
, "%s: received invalid srcref, received %llu "
2236 "expected %llu\n", __func__
, remrsp
->srcref
, sref
);
2242 get_src_decsription(int fd
, nstat_src_ref_t srcref
,
2243 struct nstat_ifnet_descriptor
*ifdesc
)
2245 nstat_msg_get_src_description
*dreq
;
2246 nstat_msg_src_description
*drsp
;
2247 char buffer
[sizeof(*drsp
) + sizeof(*ifdesc
)];
2249 const u_int32_t descsize
=
2250 offsetof(struct nstat_msg_src_description
, data
) +
2251 sizeof(nstat_ifnet_descriptor
);
2253 dreq
= (nstat_msg_get_src_description
*)buffer
;
2254 bzero(dreq
, sizeof(*dreq
));
2255 dreq
->hdr
.type
= NSTAT_MSG_TYPE_GET_SRC_DESC
;
2256 dreq
->srcref
= srcref
;
2257 result
= send(fd
, dreq
, sizeof(*dreq
), 0);
2258 if (result
!= sizeof(*dreq
))
2261 perror("send(NSTAT_GET_SRC_DESC_REQ)");
2263 fprintf(stderr
, "%s: sent %ld out of %lu\n",
2264 __func__
, result
, sizeof(*dreq
));
2268 /* Receive the source description response */
2269 drsp
= (nstat_msg_src_description
*)buffer
;
2270 result
= recv(fd
, drsp
, sizeof(buffer
), 0);
2271 if (result
< descsize
)
2274 perror("recv(NSTAT_GET_SRC_DESC_RSP");
2276 fprintf(stderr
, "%s: recv too small, received %ld, "
2277 "expected %u\n", __func__
, result
, descsize
);
2281 if (drsp
->hdr
.type
!= NSTAT_MSG_TYPE_SRC_DESC
)
2283 fprintf(stderr
, "%s: received wrong message type, received %u "
2284 "expected %u\n", __func__
, drsp
->hdr
.type
,
2285 NSTAT_MSG_TYPE_SRC_DESC
);
2289 if (drsp
->srcref
!= srcref
)
2291 fprintf(stderr
, "%s: received message for wrong source, "
2292 "received 0x%llx expected 0x%llx\n",
2293 __func__
, drsp
->srcref
, srcref
);
2297 bcopy(drsp
->data
, ifdesc
, sizeof(*ifdesc
));
2302 print_wifi_status(nstat_ifnet_desc_wifi_status
*status
)
2306 ((status->valid_bitmask & NSTAT_IFNET_DESC_WIFI_ ## f ## _VALID) ?\
2308 #define parg(n, un) #n, val(n, un)
2309 #define pretxtl(n, un) \
2310 (((tmp = val(n, un)) == -1) ? "(not valid)" : \
2311 ((tmp == NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_NONE) ? "(none)" : \
2312 ((tmp == NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_LOW) ? "(low)" : \
2313 ((tmp == NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_MEDIUM) ? "(medium)" : \
2314 ((tmp == NSTAT_IFNET_DESC_WIFI_UL_RETXT_LEVEL_HIGH) ? "(high)" : \
2317 printf("\nwifi status:\n");
2338 parg(link_quality_metric
, LINK_QUALITY_METRIC
),
2339 parg(ul_effective_bandwidth
, UL_EFFECTIVE_BANDWIDTH
),
2340 parg(ul_max_bandwidth
, UL_MAX_BANDWIDTH
),
2341 parg(ul_min_latency
, UL_MIN_LATENCY
),
2342 parg(ul_effective_latency
, UL_EFFECTIVE_LATENCY
),
2343 parg(ul_max_latency
, UL_MAX_LATENCY
),
2344 parg(ul_retxt_level
, UL_RETXT_LEVEL
),
2345 pretxtl(ul_retxt_level
, UL_RETXT_LEVEL
),
2346 parg(ul_bytes_lost
, UL_BYTES_LOST
),
2347 parg(ul_error_rate
, UL_ERROR_RATE
),
2348 parg(dl_effective_bandwidth
, DL_EFFECTIVE_BANDWIDTH
),
2349 parg(dl_max_bandwidth
, DL_MAX_BANDWIDTH
),
2350 parg(dl_min_latency
, DL_MIN_LATENCY
),
2351 parg(dl_effective_latency
, DL_EFFECTIVE_LATENCY
),
2352 parg(dl_max_latency
, DL_MAX_LATENCY
),
2353 parg(dl_error_rate
, DL_ERROR_RATE
),
2354 parg(config_frequency
, CONFIG_FREQUENCY
),
2355 parg(config_multicast_rate
, CONFIG_MULTICAST_RATE
),
2356 parg(scan_count
, CONFIG_SCAN_COUNT
),
2357 parg(scan_duration
, CONFIG_SCAN_DURATION
)
2365 print_cellular_status(nstat_ifnet_desc_cellular_status
*status
)
2369 ((status->valid_bitmask & NSTAT_IFNET_DESC_CELL_ ## f ## _VALID) ?\
2371 #define parg(n, un) #n, val(n, un)
2372 #define pretxtl(n, un) \
2373 (((tmp = val(n, un)) == -1) ? "(not valid)" : \
2374 ((tmp == NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_NONE) ? "(none)" : \
2375 ((tmp == NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_LOW) ? "(low)" : \
2376 ((tmp == NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_MEDIUM) ? "(medium)" : \
2377 ((tmp == NSTAT_IFNET_DESC_CELL_UL_RETXT_LEVEL_HIGH) ? "(high)" : \
2379 #define pretxtm(n, un) \
2380 (((tmp_mss = val(n,un)) == -1) ? "(not valid)" : \
2381 ((tmp_mss == NSTAT_IFNET_DESC_MSS_RECOMMENDED_NONE) ? "(none)" : \
2382 ((tmp_mss == NSTAT_IFNET_DESC_MSS_RECOMMENDED_MEDIUM) ? "(medium)" : \
2383 ((tmp_mss == NSTAT_IFNET_DESC_MSS_RECOMMENDED_LOW) ? "(low)" : \
2386 printf("\ncellular status:\n");
2404 parg(link_quality_metric
, LINK_QUALITY_METRIC
),
2405 parg(ul_effective_bandwidth
, UL_EFFECTIVE_BANDWIDTH
),
2406 parg(ul_max_bandwidth
, UL_MAX_BANDWIDTH
),
2407 parg(ul_min_latency
, UL_MIN_LATENCY
),
2408 parg(ul_effective_latency
, UL_EFFECTIVE_LATENCY
),
2409 parg(ul_max_latency
, UL_MAX_LATENCY
),
2410 parg(ul_retxt_level
, UL_RETXT_LEVEL
),
2411 pretxtl(ul_retxt_level
, UL_RETXT_LEVEL
),
2412 parg(ul_bytes_lost
, UL_BYTES_LOST
),
2413 parg(ul_min_queue_size
, UL_MIN_QUEUE_SIZE
),
2414 parg(ul_avg_queue_size
, UL_AVG_QUEUE_SIZE
),
2415 parg(ul_max_queue_size
, UL_MAX_QUEUE_SIZE
),
2416 parg(dl_effective_bandwidth
, DL_EFFECTIVE_BANDWIDTH
),
2417 parg(dl_max_bandwidth
, DL_MAX_BANDWIDTH
),
2418 parg(config_inactivity_time
, CONFIG_INACTIVITY_TIME
),
2419 parg(config_backoff_time
, CONFIG_BACKOFF_TIME
),
2420 parg(mss_recommended
, MSS_RECOMMENDED
),
2421 pretxtm(mss_recommended
, MSS_RECOMMENDED
)
2429 get_interface_state(int fd
, const char *ifname
, struct ifreq
*ifr
)
2431 bzero(ifr
, sizeof(*ifr
));
2432 snprintf(ifr
->ifr_name
, sizeof(ifr
->ifr_name
), "%s", ifname
);
2434 if (ioctl(fd
, SIOCGIFINTERFACESTATE
, ifr
) == -1) {
2435 perror("ioctl(CTLIOCGINFO)");
2442 print_interface_state(struct ifreq
*ifr
)
2444 int lqm
, rrc
, avail
;
2446 printf("\ninterface state:\n");
2448 if (ifr
->ifr_interface_state
.valid_bitmask
&
2449 IF_INTERFACE_STATE_LQM_STATE_VALID
) {
2451 lqm
= ifr
->ifr_interface_state
.lqm_state
;
2452 if (lqm
== IFNET_LQM_THRESH_GOOD
)
2454 else if (lqm
== IFNET_LQM_THRESH_POOR
)
2456 else if (lqm
== IFNET_LQM_THRESH_BAD
)
2458 else if (lqm
== IFNET_LQM_THRESH_UNKNOWN
)
2459 printf("\"unknown\"");
2460 else if (lqm
== IFNET_LQM_THRESH_OFF
)
2463 printf("invalid(%d)", lqm
);
2466 if (ifr
->ifr_interface_state
.valid_bitmask
&
2467 IF_INTERFACE_STATE_RRC_STATE_VALID
) {
2469 rrc
= ifr
->ifr_interface_state
.rrc_state
;
2470 if (rrc
== IF_INTERFACE_STATE_RRC_STATE_CONNECTED
)
2471 printf("\"connected\"");
2472 else if (rrc
== IF_INTERFACE_STATE_RRC_STATE_IDLE
)
2475 printf("\"invalid(%d)\"", rrc
);
2478 if (ifr
->ifr_interface_state
.valid_bitmask
&
2479 IF_INTERFACE_STATE_INTERFACE_AVAILABILITY_VALID
) {
2480 printf("\tavailability: ");
2481 avail
= ifr
->ifr_interface_state
.interface_availability
;
2482 if (avail
== IF_INTERFACE_STATE_INTERFACE_AVAILABLE
)
2484 else if (rrc
== IF_INTERFACE_STATE_INTERFACE_UNAVAILABLE
)
2485 printf("\"false\"");
2487 printf("\"invalid(%d)\"", avail
);
2492 print_link_status(const char *ifname
)
2494 unsigned int ifindex
;
2495 struct itimerval timer_interval
;
2496 sigset_t sigset
, oldsigset
;
2497 struct nstat_ifnet_descriptor ifdesc
;
2498 nstat_ifnet_add_param ifparam
;
2499 nstat_src_ref_t sref
= 0;
2503 ifindex
= if_nametoindex(ifname
);
2505 fprintf(stderr
, "Invalid interface name\n");
2509 if ((ctl_fd
= create_control_socket(NET_STAT_CONTROL_NAME
)) < 0)
2512 ifparam
.ifindex
= ifindex
;
2513 ifparam
.threshold
= UINT64_MAX
;
2514 if (add_nstat_src(ctl_fd
, &ifparam
, &sref
))
2518 /* create a timer that fires repeatedly every interval
2520 timer_interval
.it_value
.tv_sec
= interval
;
2521 timer_interval
.it_value
.tv_usec
= 0;
2522 timer_interval
.it_interval
.tv_sec
= interval
;
2523 timer_interval
.it_interval
.tv_usec
= 0;
2524 (void) signal(SIGALRM
, catchalarm
);
2526 (void) setitimer(ITIMER_REAL
, &timer_interval
, NULL
);
2529 /* get interface state */
2530 if (get_interface_state(ctl_fd
, ifname
, &ifr
))
2533 /* get ntstat interface description */
2534 if (get_src_decsription(ctl_fd
, sref
, &ifdesc
))
2538 printf("\n%s: ", ifname
);
2541 /* print interface state */
2542 print_interface_state(&ifr
);
2544 /* print ntsat interface link status */
2545 if (ifdesc
.link_status
.link_status_type
==
2546 NSTAT_IFNET_DESC_LINK_STATUS_TYPE_CELLULAR
)
2547 print_cellular_status(&ifdesc
.link_status
.u
.cellular
);
2548 else if (ifdesc
.link_status
.link_status_type
==
2549 NSTAT_IFNET_DESC_LINK_STATUS_TYPE_WIFI
)
2550 print_wifi_status(&ifdesc
.link_status
.u
.wifi
);
2555 sigemptyset(&sigset
);
2556 sigaddset(&sigset
, SIGALRM
);
2557 (void) sigprocmask(SIG_BLOCK
, &sigset
, &oldsigset
);
2559 sigemptyset(&sigset
);
2560 sigsuspend(&sigset
);
2562 (void) sigprocmask(SIG_SETMASK
, &oldsigset
, NULL
);
2569 rem_nstat_src(ctl_fd
, sref
);