Add support for MP-safe network interface statistics by maintaining them in per-cpu storage, and collecting them for export in an if_data structure when user-space wants them. The new if_stat API is structured to make a gradual transition to the new way in network drivers possible, and per-cpu stats are currently disabled (thus there is no kernel ABI change). Once all drivers have been converted, the old ABI will be removed, and per-cpu stats will be enabled universally.diff -r1.41 -r1.42 src/sys/net/Makefile
(thorpej)
--- src/sys/net/Makefile 2020/01/20 18:38:18 1.41
+++ src/sys/net/Makefile 2020/01/29 03:16:28 1.42
@@ -1,17 +1,17 @@ | @@ -1,17 +1,17 @@ | |||
1 | # $NetBSD: Makefile,v 1.41 2020/01/20 18:38:18 thorpej Exp $ | 1 | # $NetBSD: Makefile,v 1.42 2020/01/29 03:16:28 thorpej Exp $ | |
2 | 2 | |||
3 | INCSDIR= /usr/include/net | 3 | INCSDIR= /usr/include/net | |
4 | 4 | |||
5 | INCS= bpf.h bpfjit.h bpfdesc.h dlt.h ethertypes.h if.h if_arc.h if_arp.h \ | 5 | INCS= bpf.h bpfjit.h bpfdesc.h dlt.h ethertypes.h if.h if_arc.h if_arp.h \ | |
6 | if_bridgevar.h if_dl.h if_ether.h if_gif.h \ | 6 | if_bridgevar.h if_dl.h if_ether.h if_gif.h \ | |
7 | if_gre.h if_ieee1394.h if_ipsec.h if_llc.h if_media.h if_mpls.h \ | 7 | if_gre.h if_ieee1394.h if_ipsec.h if_llc.h if_media.h if_mpls.h \ | |
8 | if_pflog.h if_ppp.h if_pppoe.h if_l2tp.h if_sppp.h if_srt.h if_stf.h \ | 8 | if_pflog.h if_ppp.h if_pppoe.h if_l2tp.h if_sppp.h if_srt.h if_stats.h \ | |
9 | if_tap.h if_tun.h if_types.h if_vlanvar.h net_stats.h \ | 9 | if_stf.h if_tap.h if_tun.h if_types.h if_vlanvar.h net_stats.h \ | |
10 | netisr.h pfil.h pfkeyv2.h pfvar.h ppp-comp.h ppp_defs.h radix.h \ | 10 | netisr.h pfil.h pfkeyv2.h pfvar.h ppp-comp.h ppp_defs.h radix.h \ | |
11 | raw_cb.h route.h slcompress.h slip.h zlib.h | 11 | raw_cb.h route.h slcompress.h slip.h zlib.h | |
12 | 12 | |||
13 | SUBDIR= agr npf | 13 | SUBDIR= agr npf | |
14 | 14 | |||
15 | .include <bsd.kinc.mk> | 15 | .include <bsd.kinc.mk> | |
16 | 16 | |||
17 | .PATH: ${NETBSDSRCDIR}/sys/dist/pf/net | 17 | .PATH: ${NETBSDSRCDIR}/sys/dist/pf/net |
--- src/sys/net/files.net 2020/01/20 18:38:18 1.24
+++ src/sys/net/files.net 2020/01/29 03:16:28 1.25
@@ -1,40 +1,41 @@ | @@ -1,40 +1,41 @@ | |||
1 | # $NetBSD: files.net,v 1.24 2020/01/20 18:38:18 thorpej Exp $ | 1 | # $NetBSD: files.net,v 1.25 2020/01/29 03:16:28 thorpej Exp $ | |
2 | 2 | |||
3 | # XXX CLEANUP | 3 | # XXX CLEANUP | |
4 | define net | 4 | define net | |
5 | file net/bpf.c bpfilter | 5 | file net/bpf.c bpfilter | |
6 | file net/bpf_filter.c bpf_filter | 6 | file net/bpf_filter.c bpf_filter | |
7 | file net/bpf_stub.c net | 7 | file net/bpf_stub.c net | |
8 | file net/bsd-comp.c ppp & ppp_bsdcomp | 8 | file net/bsd-comp.c ppp & ppp_bsdcomp | |
9 | file net/dl_print.c | 9 | file net/dl_print.c | |
10 | file net/ether_sw_offload.c bridge | 10 | file net/ether_sw_offload.c bridge | |
11 | file net/if.c net | 11 | file net/if.c net | |
12 | file net/if_arcsubr.c arcnet needs-flag | 12 | file net/if_arcsubr.c arcnet needs-flag | |
13 | file net/if_bridge.c bridge needs-flag | 13 | file net/if_bridge.c bridge needs-flag | |
14 | file net/bridgestp.c bridge | 14 | file net/bridgestp.c bridge | |
15 | file net/if_ethersubr.c ether | netatalk | wlan needs-flag | 15 | file net/if_ethersubr.c ether | netatalk | wlan needs-flag | |
16 | file net/if_faith.c faith & (inet | inet6) needs-flag | 16 | file net/if_faith.c faith & (inet | inet6) needs-flag | |
17 | file net/if_gif.c gif needs-flag | 17 | file net/if_gif.c gif needs-flag | |
18 | file net/if_gre.c gre needs-flag | 18 | file net/if_gre.c gre needs-flag | |
19 | file net/if_ieee1394subr.c ieee1394 | 19 | file net/if_ieee1394subr.c ieee1394 | |
20 | file net/if_ipsec.c ipsec & ipsecif | 20 | file net/if_ipsec.c ipsec & ipsecif | |
21 | file net/if_llatbl.c inet | inet6 | 21 | file net/if_llatbl.c inet | inet6 | |
22 | file net/if_l2tp.c l2tp needs-flag | 22 | file net/if_l2tp.c l2tp needs-flag | |
23 | file net/if_loop.c loop | 23 | file net/if_loop.c loop | |
24 | file net/if_media.c net | 24 | file net/if_media.c net | |
25 | file net/if_mpls.c mpls needs-flag | 25 | file net/if_mpls.c mpls needs-flag | |
26 | file net/if_ppp.c ppp needs-flag | 26 | file net/if_ppp.c ppp needs-flag | |
27 | file net/if_srt.c srt | 27 | file net/if_srt.c srt | |
28 | file net/if_stats.c net | |||
28 | file net/if_stf.c stf & inet & inet6 needs-flag | 29 | file net/if_stf.c stf & inet & inet6 needs-flag | |
29 | file net/if_sl.c sl needs-flag | 30 | file net/if_sl.c sl needs-flag | |
30 | file net/if_spppsubr.c sppp | 31 | file net/if_spppsubr.c sppp | |
31 | file net/if_tap.c tap | 32 | file net/if_tap.c tap | |
32 | file net/if_tun.c tun | 33 | file net/if_tun.c tun | |
33 | file net/if_vlan.c vlan needs-flag | 34 | file net/if_vlan.c vlan needs-flag | |
34 | file net/if_pppoe.c pppoe needs-flag | 35 | file net/if_pppoe.c pppoe needs-flag | |
35 | file net/pfil.c net | 36 | file net/pfil.c net | |
36 | file net/ppp-deflate.c ppp & ppp_deflate | 37 | file net/ppp-deflate.c ppp & ppp_deflate | |
37 | file net/ppp_tty.c ppp | 38 | file net/ppp_tty.c ppp | |
38 | file net/pktqueue.c net | 39 | file net/pktqueue.c net | |
39 | file net/net_stats.c net | 40 | file net/net_stats.c net | |
40 | file net/radix.c net | 41 | file net/radix.c net |
--- src/sys/net/if.c 2020/01/20 18:38:18 1.468
+++ src/sys/net/if.c 2020/01/29 03:16:28 1.469
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: if.c,v 1.468 2020/01/20 18:38:18 thorpej Exp $ */ | 1 | /* $NetBSD: if.c,v 1.469 2020/01/29 03:16:28 thorpej Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by William Studenmund and Jason R. Thorpe. | 8 | * by William Studenmund and Jason R. Thorpe. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -80,27 +80,27 @@ | @@ -80,27 +80,27 @@ | |||
80 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 80 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
81 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 81 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
82 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 82 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
83 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 83 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
84 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 84 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
85 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 85 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
86 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 86 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
87 | * SUCH DAMAGE. | 87 | * SUCH DAMAGE. | |
88 | * | 88 | * | |
89 | * @(#)if.c 8.5 (Berkeley) 1/9/95 | 89 | * @(#)if.c 8.5 (Berkeley) 1/9/95 | |
90 | */ | 90 | */ | |
91 | 91 | |||
92 | #include <sys/cdefs.h> | 92 | #include <sys/cdefs.h> | |
93 | __KERNEL_RCSID(0, "$NetBSD: if.c,v 1.468 2020/01/20 18:38:18 thorpej Exp $"); | 93 | __KERNEL_RCSID(0, "$NetBSD: if.c,v 1.469 2020/01/29 03:16:28 thorpej Exp $"); | |
94 | 94 | |||
95 | #if defined(_KERNEL_OPT) | 95 | #if defined(_KERNEL_OPT) | |
96 | #include "opt_inet.h" | 96 | #include "opt_inet.h" | |
97 | #include "opt_ipsec.h" | 97 | #include "opt_ipsec.h" | |
98 | #include "opt_atalk.h" | 98 | #include "opt_atalk.h" | |
99 | #include "opt_wlan.h" | 99 | #include "opt_wlan.h" | |
100 | #include "opt_net_mpsafe.h" | 100 | #include "opt_net_mpsafe.h" | |
101 | #include "opt_mrouting.h" | 101 | #include "opt_mrouting.h" | |
102 | #endif | 102 | #endif | |
103 | 103 | |||
104 | #include <sys/param.h> | 104 | #include <sys/param.h> | |
105 | #include <sys/mbuf.h> | 105 | #include <sys/mbuf.h> | |
106 | #include <sys/systm.h> | 106 | #include <sys/systm.h> | |
@@ -723,26 +723,29 @@ if_initialize(ifnet_t *ifp) | @@ -723,26 +723,29 @@ if_initialize(ifnet_t *ifp) | |||
723 | ifp->if_link_si = softint_establish(flags, | 723 | ifp->if_link_si = softint_establish(flags, | |
724 | if_link_state_change_si, ifp); | 724 | if_link_state_change_si, ifp); | |
725 | if (ifp->if_link_si == NULL) { | 725 | if (ifp->if_link_si == NULL) { | |
726 | rv = ENOMEM; | 726 | rv = ENOMEM; | |
727 | goto fail; | 727 | goto fail; | |
728 | } | 728 | } | |
729 | } | 729 | } | |
730 | 730 | |||
731 | PSLIST_ENTRY_INIT(ifp, if_pslist_entry); | 731 | PSLIST_ENTRY_INIT(ifp, if_pslist_entry); | |
732 | PSLIST_INIT(&ifp->if_addr_pslist); | 732 | PSLIST_INIT(&ifp->if_addr_pslist); | |
733 | psref_target_init(&ifp->if_psref, ifnet_psref_class); | 733 | psref_target_init(&ifp->if_psref, ifnet_psref_class); | |
734 | ifp->if_ioctl_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); | 734 | ifp->if_ioctl_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); | |
735 | LIST_INIT(&ifp->if_multiaddrs); | 735 | LIST_INIT(&ifp->if_multiaddrs); | |
736 | if ((rv = if_stats_init(ifp)) != 0) { | |||
737 | goto fail; | |||
738 | } | |||
736 | 739 | |||
737 | IFNET_GLOBAL_LOCK(); | 740 | IFNET_GLOBAL_LOCK(); | |
738 | if_getindex(ifp); | 741 | if_getindex(ifp); | |
739 | IFNET_GLOBAL_UNLOCK(); | 742 | IFNET_GLOBAL_UNLOCK(); | |
740 | 743 | |||
741 | return 0; | 744 | return 0; | |
742 | 745 | |||
743 | fail: | 746 | fail: | |
744 | IF_AFDATA_LOCK_DESTROY(ifp); | 747 | IF_AFDATA_LOCK_DESTROY(ifp); | |
745 | 748 | |||
746 | pfil_run_ifhooks(if_pfil, PFIL_IFNET_DETACH, ifp); | 749 | pfil_run_ifhooks(if_pfil, PFIL_IFNET_DETACH, ifp); | |
747 | (void)pfil_head_destroy(ifp->if_pfil); | 750 | (void)pfil_head_destroy(ifp->if_pfil); | |
748 | 751 | |||
@@ -806,27 +809,27 @@ if_register(ifnet_t *ifp) | @@ -806,27 +809,27 @@ if_register(ifnet_t *ifp) | |||
806 | * - You can use if_percpuq_* directly in your driver | 809 | * - You can use if_percpuq_* directly in your driver | |
807 | * - In this case, you need to allocate struct if_percpuq in driver's softc | 810 | * - In this case, you need to allocate struct if_percpuq in driver's softc | |
808 | * - See wm(4) as a reference implementation | 811 | * - See wm(4) as a reference implementation | |
809 | */ | 812 | */ | |
810 | 813 | |||
811 | static void | 814 | static void | |
812 | if_percpuq_softint(void *arg) | 815 | if_percpuq_softint(void *arg) | |
813 | { | 816 | { | |
814 | struct if_percpuq *ipq = arg; | 817 | struct if_percpuq *ipq = arg; | |
815 | struct ifnet *ifp = ipq->ipq_ifp; | 818 | struct ifnet *ifp = ipq->ipq_ifp; | |
816 | struct mbuf *m; | 819 | struct mbuf *m; | |
817 | 820 | |||
818 | while ((m = if_percpuq_dequeue(ipq)) != NULL) { | 821 | while ((m = if_percpuq_dequeue(ipq)) != NULL) { | |
819 | ifp->if_ipackets++; | 822 | if_statinc(ifp, if_ipackets); | |
820 | bpf_mtap(ifp, m, BPF_D_IN); | 823 | bpf_mtap(ifp, m, BPF_D_IN); | |
821 | 824 | |||
822 | ifp->_if_input(ifp, m); | 825 | ifp->_if_input(ifp, m); | |
823 | } | 826 | } | |
824 | } | 827 | } | |
825 | 828 | |||
826 | static void | 829 | static void | |
827 | if_percpuq_init_ifq(void *p, void *arg __unused, struct cpu_info *ci __unused) | 830 | if_percpuq_init_ifq(void *p, void *arg __unused, struct cpu_info *ci __unused) | |
828 | { | 831 | { | |
829 | struct ifqueue *const ifq = p; | 832 | struct ifqueue *const ifq = p; | |
830 | 833 | |||
831 | memset(ifq, 0, sizeof(*ifq)); | 834 | memset(ifq, 0, sizeof(*ifq)); | |
832 | ifq->ifq_maxlen = IFQ_MAXLEN; | 835 | ifq->ifq_maxlen = IFQ_MAXLEN; | |
@@ -1100,27 +1103,27 @@ if_deferred_start_destroy(struct ifnet * | @@ -1100,27 +1103,27 @@ if_deferred_start_destroy(struct ifnet * | |||
1100 | 1103 | |||
1101 | /* | 1104 | /* | |
1102 | * The common interface input routine that is called by device drivers, | 1105 | * The common interface input routine that is called by device drivers, | |
1103 | * which should be used only when the driver's rx handler already runs | 1106 | * which should be used only when the driver's rx handler already runs | |
1104 | * in softint. | 1107 | * in softint. | |
1105 | */ | 1108 | */ | |
1106 | void | 1109 | void | |
1107 | if_input(struct ifnet *ifp, struct mbuf *m) | 1110 | if_input(struct ifnet *ifp, struct mbuf *m) | |
1108 | { | 1111 | { | |
1109 | 1112 | |||
1110 | KASSERT(ifp->if_percpuq == NULL); | 1113 | KASSERT(ifp->if_percpuq == NULL); | |
1111 | KASSERT(!cpu_intr_p()); | 1114 | KASSERT(!cpu_intr_p()); | |
1112 | 1115 | |||
1113 | ifp->if_ipackets++; | 1116 | if_statinc(ifp, if_ipackets); | |
1114 | bpf_mtap(ifp, m, BPF_D_IN); | 1117 | bpf_mtap(ifp, m, BPF_D_IN); | |
1115 | 1118 | |||
1116 | ifp->_if_input(ifp, m); | 1119 | ifp->_if_input(ifp, m); | |
1117 | } | 1120 | } | |
1118 | 1121 | |||
1119 | /* | 1122 | /* | |
1120 | * DEPRECATED. Use if_initialize and if_register instead. | 1123 | * DEPRECATED. Use if_initialize and if_register instead. | |
1121 | * See the above comment of if_initialize. | 1124 | * See the above comment of if_initialize. | |
1122 | * | 1125 | * | |
1123 | * Note that it implicitly enables if_percpuq to make drivers easy to | 1126 | * Note that it implicitly enables if_percpuq to make drivers easy to | |
1124 | * migrate softint-based if_input without much changes. If you don't | 1127 | * migrate softint-based if_input without much changes. If you don't | |
1125 | * want to enable it, use if_initialize instead. | 1128 | * want to enable it, use if_initialize instead. | |
1126 | */ | 1129 | */ | |
@@ -1511,26 +1514,27 @@ restart: | @@ -1511,26 +1514,27 @@ restart: | |||
1511 | if (in6_present) | 1514 | if (in6_present) | |
1512 | pktq_barrier(ip6_pktq); | 1515 | pktq_barrier(ip6_pktq); | |
1513 | #endif | 1516 | #endif | |
1514 | xc_barrier(0); | 1517 | xc_barrier(0); | |
1515 | 1518 | |||
1516 | if (ifp->if_percpuq != NULL) { | 1519 | if (ifp->if_percpuq != NULL) { | |
1517 | if_percpuq_destroy(ifp->if_percpuq); | 1520 | if_percpuq_destroy(ifp->if_percpuq); | |
1518 | ifp->if_percpuq = NULL; | 1521 | ifp->if_percpuq = NULL; | |
1519 | } | 1522 | } | |
1520 | 1523 | |||
1521 | mutex_obj_free(ifp->if_ioctl_lock); | 1524 | mutex_obj_free(ifp->if_ioctl_lock); | |
1522 | ifp->if_ioctl_lock = NULL; | 1525 | ifp->if_ioctl_lock = NULL; | |
1523 | mutex_obj_free(ifp->if_snd.ifq_lock); | 1526 | mutex_obj_free(ifp->if_snd.ifq_lock); | |
1527 | if_stats_fini(ifp); | |||
1524 | 1528 | |||
1525 | splx(s); | 1529 | splx(s); | |
1526 | 1530 | |||
1527 | #ifdef IFAREF_DEBUG | 1531 | #ifdef IFAREF_DEBUG | |
1528 | if_check_and_free_ifa_list(ifp); | 1532 | if_check_and_free_ifa_list(ifp); | |
1529 | #endif | 1533 | #endif | |
1530 | } | 1534 | } | |
1531 | 1535 | |||
1532 | static void | 1536 | static void | |
1533 | if_detach_queues(struct ifnet *ifp, struct ifqueue *q) | 1537 | if_detach_queues(struct ifnet *ifp, struct ifqueue *q) | |
1534 | { | 1538 | { | |
1535 | struct mbuf *m, *prev, *next; | 1539 | struct mbuf *m, *prev, *next; | |
1536 | 1540 | |||
@@ -2949,26 +2953,42 @@ if_tunnel_rtcache_free_pc(void *p, void | @@ -2949,26 +2953,42 @@ if_tunnel_rtcache_free_pc(void *p, void | |||
2949 | struct tunnel_ro *tro = p; | 2953 | struct tunnel_ro *tro = p; | |
2950 | 2954 | |||
2951 | mutex_enter(tro->tr_lock); | 2955 | mutex_enter(tro->tr_lock); | |
2952 | rtcache_free(tro->tr_ro); | 2956 | rtcache_free(tro->tr_ro); | |
2953 | mutex_exit(tro->tr_lock); | 2957 | mutex_exit(tro->tr_lock); | |
2954 | } | 2958 | } | |
2955 | 2959 | |||
2956 | void if_tunnel_ro_percpu_rtcache_free(percpu_t *ro_percpu) | 2960 | void if_tunnel_ro_percpu_rtcache_free(percpu_t *ro_percpu) | |
2957 | { | 2961 | { | |
2958 | 2962 | |||
2959 | percpu_foreach(ro_percpu, if_tunnel_rtcache_free_pc, NULL); | 2963 | percpu_foreach(ro_percpu, if_tunnel_rtcache_free_pc, NULL); | |
2960 | } | 2964 | } | |
2961 | 2965 | |||
2966 | void | |||
2967 | if_export_if_data(ifnet_t * const ifp, struct if_data *ifi, bool zero_stats) | |||
2968 | { | |||
2969 | ||||
2970 | /* Collet the volatile stats first; this zeros *ifi. */ | |||
2971 | if_stats_to_if_data(ifp, ifi, zero_stats); | |||
2972 | ||||
2973 | ifi->ifi_type = ifp->if_type; | |||
2974 | ifi->ifi_addrlen = ifp->if_addrlen; | |||
2975 | ifi->ifi_hdrlen = ifp->if_hdrlen; | |||
2976 | ifi->ifi_link_state = ifp->if_link_state; | |||
2977 | ifi->ifi_mtu = ifp->if_mtu; | |||
2978 | ifi->ifi_metric = ifp->if_metric; | |||
2979 | ifi->ifi_baudrate = ifp->if_baudrate; | |||
2980 | ifi->ifi_lastchange = ifp->if_lastchange; | |||
2981 | } | |||
2962 | 2982 | |||
2963 | /* common */ | 2983 | /* common */ | |
2964 | int | 2984 | int | |
2965 | ifioctl_common(struct ifnet *ifp, u_long cmd, void *data) | 2985 | ifioctl_common(struct ifnet *ifp, u_long cmd, void *data) | |
2966 | { | 2986 | { | |
2967 | int s; | 2987 | int s; | |
2968 | struct ifreq *ifr; | 2988 | struct ifreq *ifr; | |
2969 | struct ifcapreq *ifcr; | 2989 | struct ifcapreq *ifcr; | |
2970 | struct ifdatareq *ifdr; | 2990 | struct ifdatareq *ifdr; | |
2971 | unsigned short flags; | 2991 | unsigned short flags; | |
2972 | char *descr; | 2992 | char *descr; | |
2973 | int error; | 2993 | int error; | |
2974 | 2994 | |||
@@ -3073,50 +3093,37 @@ ifioctl_common(struct ifnet *ifp, u_long | @@ -3073,50 +3093,37 @@ ifioctl_common(struct ifnet *ifp, u_long | |||
3073 | case SIOCGIFCAP: | 3093 | case SIOCGIFCAP: | |
3074 | ifcr = data; | 3094 | ifcr = data; | |
3075 | ifcr->ifcr_capabilities = ifp->if_capabilities; | 3095 | ifcr->ifcr_capabilities = ifp->if_capabilities; | |
3076 | ifcr->ifcr_capenable = ifp->if_capenable; | 3096 | ifcr->ifcr_capenable = ifp->if_capenable; | |
3077 | break; | 3097 | break; | |
3078 | 3098 | |||
3079 | case SIOCSIFMETRIC: | 3099 | case SIOCSIFMETRIC: | |
3080 | ifr = data; | 3100 | ifr = data; | |
3081 | ifp->if_metric = ifr->ifr_metric; | 3101 | ifp->if_metric = ifr->ifr_metric; | |
3082 | break; | 3102 | break; | |
3083 | 3103 | |||
3084 | case SIOCGIFDATA: | 3104 | case SIOCGIFDATA: | |
3085 | ifdr = data; | 3105 | ifdr = data; | |
3086 | ifdr->ifdr_data = ifp->if_data; | 3106 | if_export_if_data(ifp, &ifdr->ifdr_data, false); | |
3087 | break; | 3107 | break; | |
3088 | 3108 | |||
3089 | case SIOCGIFINDEX: | 3109 | case SIOCGIFINDEX: | |
3090 | ifr = data; | 3110 | ifr = data; | |
3091 | ifr->ifr_index = ifp->if_index; | 3111 | ifr->ifr_index = ifp->if_index; | |
3092 | break; | 3112 | break; | |
3093 | 3113 | |||
3094 | case SIOCZIFDATA: | 3114 | case SIOCZIFDATA: | |
3095 | ifdr = data; | 3115 | ifdr = data; | |
3096 | ifdr->ifdr_data = ifp->if_data; | 3116 | if_export_if_data(ifp, &ifdr->ifdr_data, true); | |
3097 | /* | |||
3098 | * Assumes that the volatile counters that can be | |||
3099 | * zero'ed are at the end of if_data. | |||
3100 | */ | |||
3101 | memset(&ifp->if_data.ifi_ipackets, 0, sizeof(ifp->if_data) - | |||
3102 | offsetof(struct if_data, ifi_ipackets)); | |||
3103 | /* | |||
3104 | * The memset() clears to the bottm of if_data. In the area, | |||
3105 | * if_lastchange is included. Please be careful if new entry | |||
3106 | * will be added into if_data or rewite this. | |||
3107 | * | |||
3108 | * And also, update if_lastchnage. | |||
3109 | */ | |||
3110 | getnanotime(&ifp->if_lastchange); | 3117 | getnanotime(&ifp->if_lastchange); | |
3111 | break; | 3118 | break; | |
3112 | case SIOCSIFMTU: | 3119 | case SIOCSIFMTU: | |
3113 | ifr = data; | 3120 | ifr = data; | |
3114 | if (ifp->if_mtu == ifr->ifr_mtu) | 3121 | if (ifp->if_mtu == ifr->ifr_mtu) | |
3115 | break; | 3122 | break; | |
3116 | ifp->if_mtu = ifr->ifr_mtu; | 3123 | ifp->if_mtu = ifr->ifr_mtu; | |
3117 | /* | 3124 | /* | |
3118 | * If the link MTU changed, do network layer specific procedure. | 3125 | * If the link MTU changed, do network layer specific procedure. | |
3119 | */ | 3126 | */ | |
3120 | #ifdef INET6 | 3127 | #ifdef INET6 | |
3121 | KERNEL_LOCK_UNLESS_NET_MPSAFE(); | 3128 | KERNEL_LOCK_UNLESS_NET_MPSAFE(); | |
3122 | if (in6_present) | 3129 | if (in6_present) | |
@@ -3585,29 +3592,31 @@ if_transmit(struct ifnet *ifp, struct mb | @@ -3585,29 +3592,31 @@ if_transmit(struct ifnet *ifp, struct mb | |||
3585 | { | 3592 | { | |
3586 | int s, error; | 3593 | int s, error; | |
3587 | size_t pktlen = m->m_pkthdr.len; | 3594 | size_t pktlen = m->m_pkthdr.len; | |
3588 | bool mcast = (m->m_flags & M_MCAST) != 0; | 3595 | bool mcast = (m->m_flags & M_MCAST) != 0; | |
3589 | 3596 | |||
3590 | s = splnet(); | 3597 | s = splnet(); | |
3591 | 3598 | |||
3592 | IFQ_ENQUEUE(&ifp->if_snd, m, error); | 3599 | IFQ_ENQUEUE(&ifp->if_snd, m, error); | |
3593 | if (error != 0) { | 3600 | if (error != 0) { | |
3594 | /* mbuf is already freed */ | 3601 | /* mbuf is already freed */ | |
3595 | goto out; | 3602 | goto out; | |
3596 | } | 3603 | } | |
3597 | 3604 | |||
3598 | ifp->if_obytes += pktlen; | 3605 | net_stat_ref_t nsr = IF_STAT_GETREF(ifp); | |
3606 | if_statadd_ref(nsr, if_obytes, pktlen); | |||
3599 | if (mcast) | 3607 | if (mcast) | |
3600 | ifp->if_omcasts++; | 3608 | if_statinc_ref(nsr, if_omcasts); | |
3609 | IF_STAT_PUTREF(ifp); | |||
3601 | 3610 | |||
3602 | if ((ifp->if_flags & IFF_OACTIVE) == 0) | 3611 | if ((ifp->if_flags & IFF_OACTIVE) == 0) | |
3603 | if_start_lock(ifp); | 3612 | if_start_lock(ifp); | |
3604 | out: | 3613 | out: | |
3605 | splx(s); | 3614 | splx(s); | |
3606 | 3615 | |||
3607 | return error; | 3616 | return error; | |
3608 | } | 3617 | } | |
3609 | 3618 | |||
3610 | int | 3619 | int | |
3611 | if_transmit_lock(struct ifnet *ifp, struct mbuf *m) | 3620 | if_transmit_lock(struct ifnet *ifp, struct mbuf *m) | |
3612 | { | 3621 | { | |
3613 | int error; | 3622 | int error; | |
@@ -3656,27 +3665,27 @@ ifq_enqueue2(struct ifnet *ifp, struct i | @@ -3656,27 +3665,27 @@ ifq_enqueue2(struct ifnet *ifp, struct i | |||
3656 | && ALTQ_IS_ENABLED(&ifp->if_snd) == 0 | 3665 | && ALTQ_IS_ENABLED(&ifp->if_snd) == 0 | |
3657 | #endif | 3666 | #endif | |
3658 | ) { | 3667 | ) { | |
3659 | if (IF_QFULL(ifq)) { | 3668 | if (IF_QFULL(ifq)) { | |
3660 | IF_DROP(&ifp->if_snd); | 3669 | IF_DROP(&ifp->if_snd); | |
3661 | m_freem(m); | 3670 | m_freem(m); | |
3662 | if (error == 0) | 3671 | if (error == 0) | |
3663 | error = ENOBUFS; | 3672 | error = ENOBUFS; | |
3664 | } else | 3673 | } else | |
3665 | IF_ENQUEUE(ifq, m); | 3674 | IF_ENQUEUE(ifq, m); | |
3666 | } else | 3675 | } else | |
3667 | IFQ_ENQUEUE(&ifp->if_snd, m, error); | 3676 | IFQ_ENQUEUE(&ifp->if_snd, m, error); | |
3668 | if (error != 0) { | 3677 | if (error != 0) { | |
3669 | ++ifp->if_oerrors; | 3678 | if_statinc(ifp, if_oerrors); | |
3670 | return error; | 3679 | return error; | |
3671 | } | 3680 | } | |
3672 | return 0; | 3681 | return 0; | |
3673 | } | 3682 | } | |
3674 | 3683 | |||
3675 | int | 3684 | int | |
3676 | if_addr_init(ifnet_t *ifp, struct ifaddr *ifa, const bool src) | 3685 | if_addr_init(ifnet_t *ifp, struct ifaddr *ifa, const bool src) | |
3677 | { | 3686 | { | |
3678 | int rc; | 3687 | int rc; | |
3679 | 3688 | |||
3680 | KASSERT(IFNET_LOCKED(ifp)); | 3689 | KASSERT(IFNET_LOCKED(ifp)); | |
3681 | if (ifp->if_initaddr != NULL) | 3690 | if (ifp->if_initaddr != NULL) | |
3682 | rc = (*ifp->if_initaddr)(ifp, ifa, src); | 3691 | rc = (*ifp->if_initaddr)(ifp, ifa, src); |
--- src/sys/net/if.h 2019/09/19 06:07:24 1.277
+++ src/sys/net/if.h 2020/01/29 03:16:28 1.278
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: if.h,v 1.277 2019/09/19 06:07:24 knakahara Exp $ */ | 1 | /* $NetBSD: if.h,v 1.278 2020/01/29 03:16:28 thorpej Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by William Studenmund and Jason R. Thorpe. | 8 | * by William Studenmund and Jason R. Thorpe. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -163,26 +163,28 @@ struct if_clone { | @@ -163,26 +163,28 @@ struct if_clone { | |||
163 | 163 | |||
164 | /* | 164 | /* | |
165 | * Structure used to query names of interface cloners. | 165 | * Structure used to query names of interface cloners. | |
166 | */ | 166 | */ | |
167 | struct if_clonereq { | 167 | struct if_clonereq { | |
168 | int ifcr_total; /* total cloners (out) */ | 168 | int ifcr_total; /* total cloners (out) */ | |
169 | int ifcr_count; /* room for this many in user buffer */ | 169 | int ifcr_count; /* room for this many in user buffer */ | |
170 | char *ifcr_buffer; /* buffer for cloner names */ | 170 | char *ifcr_buffer; /* buffer for cloner names */ | |
171 | }; | 171 | }; | |
172 | 172 | |||
173 | /* | 173 | /* | |
174 | * Structure defining statistics and other data kept regarding a network | 174 | * Structure defining statistics and other data kept regarding a network | |
175 | * interface. | 175 | * interface. | |
176 | * | |||
177 | * Only used for exporting data from the interface. | |||
176 | */ | 178 | */ | |
177 | struct if_data { | 179 | struct if_data { | |
178 | /* generic interface information */ | 180 | /* generic interface information */ | |
179 | u_char ifi_type; /* ethernet, tokenring, etc. */ | 181 | u_char ifi_type; /* ethernet, tokenring, etc. */ | |
180 | u_char ifi_addrlen; /* media address length */ | 182 | u_char ifi_addrlen; /* media address length */ | |
181 | u_char ifi_hdrlen; /* media header length */ | 183 | u_char ifi_hdrlen; /* media header length */ | |
182 | int ifi_link_state; /* current link state */ | 184 | int ifi_link_state; /* current link state */ | |
183 | uint64_t ifi_mtu; /* maximum transmission unit */ | 185 | uint64_t ifi_mtu; /* maximum transmission unit */ | |
184 | uint64_t ifi_metric; /* routing metric (external only) */ | 186 | uint64_t ifi_metric; /* routing metric (external only) */ | |
185 | uint64_t ifi_baudrate; /* linespeed */ | 187 | uint64_t ifi_baudrate; /* linespeed */ | |
186 | /* volatile statistics */ | 188 | /* volatile statistics */ | |
187 | uint64_t ifi_ipackets; /* packets received on interface */ | 189 | uint64_t ifi_ipackets; /* packets received on interface */ | |
188 | uint64_t ifi_ierrors; /* input errors on interface */ | 190 | uint64_t ifi_ierrors; /* input errors on interface */ | |
@@ -263,27 +265,40 @@ typedef struct ifnet { | @@ -263,27 +265,40 @@ typedef struct ifnet { | |||
263 | /* DEPRECATED. Keep it to avoid breaking kvm(3) users */ | 265 | /* DEPRECATED. Keep it to avoid breaking kvm(3) users */ | |
264 | TAILQ_ENTRY(ifnet) | 266 | TAILQ_ENTRY(ifnet) | |
265 | if_list; /* i: all struct ifnets are chained */ | 267 | if_list; /* i: all struct ifnets are chained */ | |
266 | TAILQ_HEAD(, ifaddr) | 268 | TAILQ_HEAD(, ifaddr) | |
267 | if_addrlist; /* i: linked list of addresses per if */ | 269 | if_addrlist; /* i: linked list of addresses per if */ | |
268 | char if_xname[IFNAMSIZ]; | 270 | char if_xname[IFNAMSIZ]; | |
269 | /* :: external name (name + unit) */ | 271 | /* :: external name (name + unit) */ | |
270 | int if_pcount; /* i: number of promiscuous listeners */ | 272 | int if_pcount; /* i: number of promiscuous listeners */ | |
271 | struct bpf_if *if_bpf; /* :: packet filter structure */ | 273 | struct bpf_if *if_bpf; /* :: packet filter structure */ | |
272 | if_index_t if_index; /* :: numeric abbreviation for this if */ | 274 | if_index_t if_index; /* :: numeric abbreviation for this if */ | |
273 | short if_timer; /* ?: time 'til if_slowtimo called */ | 275 | short if_timer; /* ?: time 'til if_slowtimo called */ | |
274 | unsigned short if_flags; /* i: up/down, broadcast, etc. */ | 276 | unsigned short if_flags; /* i: up/down, broadcast, etc. */ | |
275 | short if_extflags; /* :: if_output MP-safe, etc. */ | 277 | short if_extflags; /* :: if_output MP-safe, etc. */ | |
276 | struct if_data if_data; /* ?: statistics and other data about if */ | 278 | #ifdef __IF_STATS_PERCPU | |
279 | u_char if_type; /* :: ethernet, tokenring, etc. */ | |||
280 | u_char if_addrlen; /* :: media address length */ | |||
281 | u_char if_hdrlen; /* :: media header length */ | |||
282 | /* XXX audit :? fields here. */ | |||
283 | int if_link_state; /* :? current link state */ | |||
284 | uint64_t if_mtu; /* :? maximum transmission unit */ | |||
285 | uint64_t if_metric; /* :? routing metric (external only) */ | |||
286 | uint64_t if_baudrate; /* :? linespeed */ | |||
287 | struct timespec if_lastchange; /* :? last operational state change */ | |||
288 | percpu_t *if_stats; /* :: statistics */ | |||
289 | #else /* ! __IF_STATS_PERCPU */ | |||
290 | struct if_data if_data; /* ?: statistics and other data */ | |||
291 | #endif /* __IF_STATS_PERCPU */ | |||
277 | /* | 292 | /* | |
278 | * Procedure handles. If you add more of these, don't forget the | 293 | * Procedure handles. If you add more of these, don't forget the | |
279 | * corresponding NULL stub in if.c. | 294 | * corresponding NULL stub in if.c. | |
280 | */ | 295 | */ | |
281 | int (*if_output) /* :: output routine (enqueue) */ | 296 | int (*if_output) /* :: output routine (enqueue) */ | |
282 | (struct ifnet *, struct mbuf *, const struct sockaddr *, | 297 | (struct ifnet *, struct mbuf *, const struct sockaddr *, | |
283 | const struct rtentry *); | 298 | const struct rtentry *); | |
284 | void (*_if_input) /* :: input routine (from h/w driver) */ | 299 | void (*_if_input) /* :: input routine (from h/w driver) */ | |
285 | (struct ifnet *, struct mbuf *); | 300 | (struct ifnet *, struct mbuf *); | |
286 | void (*if_start) /* :: initiate output routine */ | 301 | void (*if_start) /* :: initiate output routine */ | |
287 | (struct ifnet *); | 302 | (struct ifnet *); | |
288 | int (*if_transmit) /* :: output routine, must be MP-safe */ | 303 | int (*if_transmit) /* :: output routine, must be MP-safe */ | |
289 | (struct ifnet *, struct mbuf *); | 304 | (struct ifnet *, struct mbuf *); | |
@@ -383,46 +398,50 @@ typedef struct ifnet { | @@ -383,46 +398,50 @@ typedef struct ifnet { | |||
383 | if_pslist_entry;/* i: */ | 398 | if_pslist_entry;/* i: */ | |
384 | struct psref_target | 399 | struct psref_target | |
385 | if_psref; /* :: */ | 400 | if_psref; /* :: */ | |
386 | struct pslist_head | 401 | struct pslist_head | |
387 | if_addr_pslist; /* i: */ | 402 | if_addr_pslist; /* i: */ | |
388 | struct if_deferred_start | 403 | struct if_deferred_start | |
389 | *if_deferred_start; | 404 | *if_deferred_start; | |
390 | /* :: */ | 405 | /* :: */ | |
391 | /* XXX should be protocol independent */ | 406 | /* XXX should be protocol independent */ | |
392 | LIST_HEAD(, in6_multi) | 407 | LIST_HEAD(, in6_multi) | |
393 | if_multiaddrs; /* 6: */ | 408 | if_multiaddrs; /* 6: */ | |
394 | #endif | 409 | #endif | |
395 | } ifnet_t; | 410 | } ifnet_t; | |
411 | ||||
412 | #include <net/if_stats.h> | |||
396 | 413 | |||
414 | #ifndef __IF_STATS_PERCPU | |||
397 | #define if_mtu if_data.ifi_mtu | 415 | #define if_mtu if_data.ifi_mtu | |
398 | #define if_type if_data.ifi_type | 416 | #define if_type if_data.ifi_type | |
399 | #define if_addrlen if_data.ifi_addrlen | 417 | #define if_addrlen if_data.ifi_addrlen | |
400 | #define if_hdrlen if_data.ifi_hdrlen | 418 | #define if_hdrlen if_data.ifi_hdrlen | |
401 | #define if_metric if_data.ifi_metric | 419 | #define if_metric if_data.ifi_metric | |
402 | #define if_link_state if_data.ifi_link_state | 420 | #define if_link_state if_data.ifi_link_state | |
403 | #define if_baudrate if_data.ifi_baudrate | 421 | #define if_baudrate if_data.ifi_baudrate | |
404 | #define if_ipackets if_data.ifi_ipackets | 422 | #define if_ipackets if_data.ifi_ipackets | |
405 | #define if_ierrors if_data.ifi_ierrors | 423 | #define if_ierrors if_data.ifi_ierrors | |
406 | #define if_opackets if_data.ifi_opackets | 424 | #define if_opackets if_data.ifi_opackets | |
407 | #define if_oerrors if_data.ifi_oerrors | 425 | #define if_oerrors if_data.ifi_oerrors | |
408 | #define if_collisions if_data.ifi_collisions | 426 | #define if_collisions if_data.ifi_collisions | |
409 | #define if_ibytes if_data.ifi_ibytes | 427 | #define if_ibytes if_data.ifi_ibytes | |
410 | #define if_obytes if_data.ifi_obytes | 428 | #define if_obytes if_data.ifi_obytes | |
411 | #define if_imcasts if_data.ifi_imcasts | 429 | #define if_imcasts if_data.ifi_imcasts | |
412 | #define if_omcasts if_data.ifi_omcasts | 430 | #define if_omcasts if_data.ifi_omcasts | |
413 | #define if_iqdrops if_data.ifi_iqdrops | 431 | #define if_iqdrops if_data.ifi_iqdrops | |
414 | #define if_noproto if_data.ifi_noproto | 432 | #define if_noproto if_data.ifi_noproto | |
415 | #define if_lastchange if_data.ifi_lastchange | 433 | #define if_lastchange if_data.ifi_lastchange | |
434 | #endif /* __IF_STATS_PERCPU */ | |||
416 | #define if_name(ifp) ((ifp)->if_xname) | 435 | #define if_name(ifp) ((ifp)->if_xname) | |
417 | 436 | |||
418 | #define IFF_UP 0x0001 /* interface is up */ | 437 | #define IFF_UP 0x0001 /* interface is up */ | |
419 | #define IFF_BROADCAST 0x0002 /* broadcast address valid */ | 438 | #define IFF_BROADCAST 0x0002 /* broadcast address valid */ | |
420 | #define IFF_DEBUG 0x0004 /* turn on debugging */ | 439 | #define IFF_DEBUG 0x0004 /* turn on debugging */ | |
421 | #define IFF_LOOPBACK 0x0008 /* is a loopback net */ | 440 | #define IFF_LOOPBACK 0x0008 /* is a loopback net */ | |
422 | #define IFF_POINTOPOINT 0x0010 /* interface is point-to-point link */ | 441 | #define IFF_POINTOPOINT 0x0010 /* interface is point-to-point link */ | |
423 | /* 0x0020 was IFF_NOTRAILERS */ | 442 | /* 0x0020 was IFF_NOTRAILERS */ | |
424 | #define IFF_RUNNING 0x0040 /* resources allocated */ | 443 | #define IFF_RUNNING 0x0040 /* resources allocated */ | |
425 | #define IFF_NOARP 0x0080 /* no address resolution protocol */ | 444 | #define IFF_NOARP 0x0080 /* no address resolution protocol */ | |
426 | #define IFF_PROMISC 0x0100 /* receive all packets */ | 445 | #define IFF_PROMISC 0x0100 /* receive all packets */ | |
427 | #define IFF_ALLMULTI 0x0200 /* receive all multicast packets */ | 446 | #define IFF_ALLMULTI 0x0200 /* receive all multicast packets */ | |
428 | #define IFF_OACTIVE 0x0400 /* transmission in progress */ | 447 | #define IFF_OACTIVE 0x0400 /* transmission in progress */ | |
@@ -1080,26 +1099,27 @@ void if_free(struct ifnet *); | @@ -1080,26 +1099,27 @@ void if_free(struct ifnet *); | |||
1080 | void if_initname(struct ifnet *, const char *, int); | 1099 | void if_initname(struct ifnet *, const char *, int); | |
1081 | struct ifaddr *if_dl_create(const struct ifnet *, const struct sockaddr_dl **); | 1100 | struct ifaddr *if_dl_create(const struct ifnet *, const struct sockaddr_dl **); | |
1082 | void if_activate_sadl(struct ifnet *, struct ifaddr *, | 1101 | void if_activate_sadl(struct ifnet *, struct ifaddr *, | |
1083 | const struct sockaddr_dl *); | 1102 | const struct sockaddr_dl *); | |
1084 | void if_set_sadl(struct ifnet *, const void *, u_char, bool); | 1103 | void if_set_sadl(struct ifnet *, const void *, u_char, bool); | |
1085 | void if_alloc_sadl(struct ifnet *); | 1104 | void if_alloc_sadl(struct ifnet *); | |
1086 | void if_free_sadl(struct ifnet *, int); | 1105 | void if_free_sadl(struct ifnet *, int); | |
1087 | int if_initialize(struct ifnet *); | 1106 | int if_initialize(struct ifnet *); | |
1088 | void if_register(struct ifnet *); | 1107 | void if_register(struct ifnet *); | |
1089 | int if_attach(struct ifnet *); /* Deprecated. Use if_initialize and if_register */ | 1108 | int if_attach(struct ifnet *); /* Deprecated. Use if_initialize and if_register */ | |
1090 | void if_attachdomain(void); | 1109 | void if_attachdomain(void); | |
1091 | void if_deactivate(struct ifnet *); | 1110 | void if_deactivate(struct ifnet *); | |
1092 | bool if_is_deactivated(const struct ifnet *); | 1111 | bool if_is_deactivated(const struct ifnet *); | |
1112 | void if_export_if_data(struct ifnet *, struct if_data *, bool); | |||
1093 | void if_purgeaddrs(struct ifnet *, int, void (*)(struct ifaddr *)); | 1113 | void if_purgeaddrs(struct ifnet *, int, void (*)(struct ifaddr *)); | |
1094 | void if_detach(struct ifnet *); | 1114 | void if_detach(struct ifnet *); | |
1095 | void if_down(struct ifnet *); | 1115 | void if_down(struct ifnet *); | |
1096 | void if_down_locked(struct ifnet *); | 1116 | void if_down_locked(struct ifnet *); | |
1097 | void if_link_state_change(struct ifnet *, int); | 1117 | void if_link_state_change(struct ifnet *, int); | |
1098 | void if_link_state_change_softint(struct ifnet *, int); | 1118 | void if_link_state_change_softint(struct ifnet *, int); | |
1099 | void if_up(struct ifnet *); | 1119 | void if_up(struct ifnet *); | |
1100 | void ifinit(void); | 1120 | void ifinit(void); | |
1101 | void ifinit1(void); | 1121 | void ifinit1(void); | |
1102 | void ifinit_post(void); | 1122 | void ifinit_post(void); | |
1103 | int ifaddrpref_ioctl(struct socket *, u_long, void *, struct ifnet *); | 1123 | int ifaddrpref_ioctl(struct socket *, u_long, void *, struct ifnet *); | |
1104 | extern int (*ifioctl)(struct socket *, u_long, void *, struct lwp *); | 1124 | extern int (*ifioctl)(struct socket *, u_long, void *, struct lwp *); | |
1105 | int ifioctl_common(struct ifnet *, u_long, void *); | 1125 | int ifioctl_common(struct ifnet *, u_long, void *); |
/* $NetBSD: if_stats.c,v 1.1 2020/01/29 03:16:28 thorpej Exp $ */
/*-
* Copyright (c) 2020 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_stats.c,v 1.1 2020/01/29 03:16:28 thorpej Exp $");
#include <sys/param.h>
#include <sys/mbuf.h>
#include <sys/systm.h>
#include <net/if.h>
#define IF_STATS_SIZE (sizeof(uint64_t) * IF_NSTATS)
/*
* if_stats_init --
* Initialize statistics storage for a network interface.
*/
int
if_stats_init(ifnet_t * const ifp)
{
#ifdef __IF_STATS_PERCPU
ifp->if_stats = percpu_alloc(IF_STATS_SIZE);
if (ifp->if_stats == NULL)
return ENOMEM;
#endif /* __IF_STATS_PERCPU */
return 0;
}
/*
* if_stats_fini --
* Tear down statistics storage for a network interface.
*/
void
if_stats_fini(ifnet_t * const ifp)
{
#ifdef __IF_STATS_PERCPU
percpu_t *pc = ifp->if_stats;
ifp->if_stats = NULL;
if (pc) {
percpu_free(pc, IF_STATS_SIZE);
}
#endif /* __IF_STATS_PERCPU */
}
#ifdef __IF_STATS_PERCPU
struct if_stats_to_if_data_ctx {
struct if_data * const ifi;
const bool zero_stats;
};
static void
if_stats_to_if_data_cb(void *v1, void *v2, struct cpu_info *ci)
{
const uint64_t * const local_counters = v1;
struct if_stats_to_if_data_ctx *ctx = v2;
int s = splnet();
if (ctx->ifi) {
ctx->ifi->ifi_ipackets += local_counters[if_ipackets];
ctx->ifi->ifi_ierrors += local_counters[if_ierrors];
ctx->ifi->ifi_opackets += local_counters[if_opackets];
ctx->ifi->ifi_oerrors += local_counters[if_oerrors];
ctx->ifi->ifi_collisions += local_counters[if_collisions];
ctx->ifi->ifi_ibytes += local_counters[if_ibytes];
ctx->ifi->ifi_obytes += local_counters[if_obytes];
ctx->ifi->ifi_imcasts += local_counters[if_imcasts];
ctx->ifi->ifi_omcasts += local_counters[if_omcasts];
ctx->ifi->ifi_iqdrops += local_counters[if_iqdrops];
ctx->ifi->ifi_noproto += local_counters[if_noproto];
}
if (ctx->zero_stats) {
memset(v1, 0, IF_STATS_SIZE);
}
splx(s);
}
/*
* if_stats_to_if_data --
* Collect the interface statistics and place them into the
* legacy if_data structure for reportig to user space.
* Optionally zeros the stats after collection.
*/
void
if_stats_to_if_data(ifnet_t * const ifp, struct if_data * const ifi,
const bool zero_stats)
{
struct if_stats_to_if_data_ctx ctx = {
.ifi = ifi,
.zero_stats = zero_stats,
};
memset(ifi, 0, sizeof(*ifi));
percpu_foreach(ifp->if_stats, if_stats_to_if_data_cb, &ctx);
}
#else /* ! __IF_STATS_PERCPU */
/*
* if_stats_to_if_data --
* Collect the interface statistics and place them into the
* legacy if_data structure for reportig to user space.
* Optionally zeros the stats after collection.
*/
void
if_stats_to_if_data(ifnet_t * const ifp, struct if_data * const ifi,
const bool zero_stats)
{
memset(ifi, 0, sizeof(*ifi));
int s = splnet();
if (ifi) {
memcpy(&ifi->ifi_ipackets, &ifp->if_data.ifi_ipackets,
offsetof(struct if_data, ifi_lastchange) -
offsetof(struct if_data, ifi_ipackets));
}
if (zero_stats) {
memset(&ifp->if_data.ifi_ipackets, 0,
offsetof(struct if_data, ifi_lastchange) -
offsetof(struct if_data, ifi_ipackets));
}
splx(s);
}
#endif /* __IF_STATS_PERCPU */
/* $NetBSD: if_stats.h,v 1.1 2020/01/29 03:16:28 thorpej Exp $ */
/*-
* Copyright (c) 2020 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _NET_IF_STATS_H_
#define _NET_IF_STATS_H_
#include <net/net_stats.h>
#ifdef __IF_STATS_PERCPU
/*
* Interface statistics. All values are unsigned 64-bit.
*/
typedef enum {
if_ipackets = 0, /* packets received on interface */
if_ierrors = 1, /* input errors on interface */
if_opackets = 2, /* packets sent on interface */
if_oerrors = 3, /* output errors on interface */
if_collisions = 4, /* collisions on csma interfaces */
if_ibytes = 5, /* total number of octets received */
if_obytes = 6, /* total number of octets sent */
if_imcasts = 7, /* packets received via multicast */
if_omcasts = 8, /* packets sent via multicast */
if_iqdrops = 9, /* dropped on input, this interface */
if_noproto = 10, /* destined for unsupported protocol */
IF_NSTATS = 11
} if_stat_t;
#ifdef _KERNEL
#define IF_STAT_GETREF(ifp) _NET_STAT_GETREF((ifp)->if_stats)
#define IF_STAT_PUTREF(ifp) _NET_STAT_PUTREF((ifp)->if_stats)
static inline void
if_statinc(ifnet_t *ifp, if_stat_t x)
{
_NET_STATINC((ifp)->if_stats, x);
}
static inline void
if_statinc_ref(net_stat_ref_t nsr, if_stat_t x)
{
_NET_STATINC_REF(nsr, x);
}
static inline void
if_statdec(ifnet_t *ifp, if_stat_t x)
{
_NET_STATDEC((ifp)->if_stats, x);
}
static inline void
if_statdec_ref(net_stat_ref_t nsr, if_stat_t x)
{
_NET_STATDEC_REF(nsr, x);
}
static inline void
if_statadd(ifnet_t *ifp, if_stat_t x, uint64_t v)
{
_NET_STATADD((ifp)->if_stats, x, v);
}
static inline void
if_statadd_ref(net_stat_ref_t nsr, if_stat_t x, uint64_t v)
{
_NET_STATADD_REF(nsr, x, v);
}
static inline void
if_statadd2(ifnet_t *ifp, if_stat_t x1, uint64_t v1, if_stat_t x2, uint64_t v2)
{
net_stat_ref_t _nsr_ = IF_STAT_GETREF(ifp);
_NET_STATADD_REF(_nsr_, x1, v1);
_NET_STATADD_REF(_nsr_, x2, v2);
IF_STAT_PUTREF(ifp);
}
static inline void
if_statsub(ifnet_t *ifp, if_stat_t x, uint64_t v)
{
_NET_STATSUB((ifp)->if_stats, x, v);
}
static inline void
if_statsub_ref(net_stat_ref_t nsr, if_stat_t x, uint64_t v)
{
_NET_STATSUB_REF(nsr, x, v);
}
#endif /* _KERNEL */
#else /* ! __IF_STATS_PERCPU */
#ifdef _KERNEL
/*
* Transitional aid to allow drivers to migrate to the new API. Once
* all drivers are transitioned, the implementation will be replaced
* with per-cpu counters.
*/
static inline net_stat_ref_t
IF_STAT_GETREF(ifnet_t *ifp)
{
return (net_stat_ref_t)ifp;
}
#define IF_STAT_PUTREF(ifp) __nothing
#define if_statinc(ifp, x) do { ++(ifp)->x; } while (/*CONSTCOND*/0)
#define if_statdec(ifp, x) do { --(ifp)->x; } while (/*CONSTCOND*/0)
#define if_statadd(ifp, x, v) do { (ifp)->x += (v); } while (/*CONSTCOND*/0)
#define if_statsub(ifp, x, v) do { (ifp)->x -= (v); } while (/*CONSTCOND*/0)
#define if_statadd2(ifp, x1, v1, x2, v2) \
do { \
(ifp)->x1 += (v1); \
(ifp)->x2 += (v2); \
} while (/*CONSTCOND*/0)
#define if_statinc_ref(r, x) if_statinc((ifnet_t *)(r), x)
#define if_statdec_ref(r, x) if_statdec((ifnet_t *)(r), x)
#define if_statadd_ref(r, x, v) if_statadd((ifnet_t *)(r), x, v)
#define if_statsub_ref(r, x, v) if_statsub((ifnet_t *)(r), x, v)
#endif /* _KERNEL */
#endif /* __IF_STATS_PERCPU */
#ifdef _KERNEL
int if_stats_init(ifnet_t *);
void if_stats_fini(ifnet_t *);
void if_stats_to_if_data(ifnet_t *, struct if_data *, bool);
#endif /* _KERNEL */
#endif /* !_NET_IF_STATS_H_ */