Index: if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.568 diff -u -p -r1.568 if.c --- if.c 29 Nov 2018 00:11:49 -0000 1.568 +++ if.c 11 Dec 2018 01:40:40 -0000 @@ -84,6 +84,7 @@ #include #include #include +#include #include #include @@ -1103,6 +1104,9 @@ if_detach(struct ifnet *ifp) splx(s); NET_UNLOCK(); + if (ifp->if_counters != NULL) + if_counters_free(ifp); + for (i = 0; i < ifp->if_nifqs; i++) ifq_destroy(ifp->if_ifqs[i]); if (ifp->if_ifqs != ifp->if_snd.ifq_ifqs) { @@ -2362,11 +2366,47 @@ ifconf(caddr_t data) } void +if_counters_alloc(struct ifnet *ifp) +{ + KASSERT(ifp->if_counters == NULL); + + ifp->if_counters = counters_alloc(ifc_ncounters); +} + +void +if_counters_free(struct ifnet *ifp) +{ + KASSERT(ifp->if_counters != NULL); + + counters_free(ifp->if_counters, ifc_ncounters); + ifp->if_counters = NULL; +} + +void if_getdata(struct ifnet *ifp, struct if_data *data) { unsigned int i; *data = ifp->if_data; + + if (ifp->if_counters != NULL) { + uint64_t counters[ifc_ncounters]; + + counters_read(ifp->if_counters, counters, nitems(counters)); + + data->ifi_ipackets += counters[ifc_ipackets]; + data->ifi_ierrors += counters[ifc_ierrors]; + data->ifi_opackets += counters[ifc_opackets]; + data->ifi_oerrors += counters[ifc_oerrors]; + data->ifi_collisions += counters[ifc_collisions]; + data->ifi_ibytes += counters[ifc_ibytes]; + data->ifi_obytes += counters[ifc_obytes]; + data->ifi_imcasts += counters[ifc_imcasts]; + data->ifi_omcasts += counters[ifc_omcasts]; + data->ifi_iqdrops += counters[ifc_iqdrops]; + data->ifi_oqdrops += counters[ifc_oqdrops]; + data->ifi_noproto += counters[ifc_noproto]; + } for (i = 0; i < ifp->if_nifqs; i++) { struct ifqueue *ifq = ifp->if_ifqs[i]; Index: if_var.h =================================================================== RCS file: /cvs/src/sys/net/if_var.h,v retrieving revision 1.90 diff -u -p -r1.90 if_var.h --- if_var.h 10 Sep 2018 16:18:34 -0000 1.90 +++ if_var.h 11 Dec 2018 01:40:40 -0000 @@ -76,6 +76,7 @@ struct rtentry; struct ifnet; struct task; +struct cpumem; /* * Structure describing a `cloning' interface. @@ -144,6 +145,7 @@ struct ifnet { /* and the entries */ unsigned short if_flags; /* [N] up/down, broadcast, etc. */ int if_xflags; /* [N] extra softnet flags */ struct if_data if_data; /* stats and other data about if */ + struct cpumem *if_counters; /* per cpu stats */ uint32_t if_hardmtu; /* [d] maximum MTU device supports */ char if_description[IFDESCRSIZE]; /* [c] interface description */ u_short if_rtlabelid; /* [c] next route label */ @@ -202,6 +204,23 @@ struct ifnet { /* and the entries */ #define if_capabilities if_data.ifi_capabilities #define if_rdomain if_data.ifi_rdomain +enum if_counters { + ifc_ipackets, /* packets received on interface */ + ifc_ierrors, /* input errors on interface */ + ifc_opackets, /* packets sent on interface */ + ifc_oerrors, /* output errors on interface */ + ifc_collisions, /* collisions on csma interfaces */ + ifc_ibytes, /* total number of octets received */ + ifc_obytes, /* total number of octets sent */ + ifc_imcasts, /* packets received via multicast */ + ifc_omcasts, /* packets sent via multicast */ + ifc_iqdrops, /* dropped on input, this interface */ + ifc_oqdrops, /* dropped on output, this interface */ + ifc_noproto, /* destined for unsupported protocol */ + + ifc_ncounters +}; + /* * The ifaddr structure contains information about one address * of an interface. They are maintained by the different address families, @@ -356,6 +375,9 @@ u_int if_rxr_get(struct if_rxring *, u_i int if_rxr_info_ioctl(struct if_rxrinfo *, u_int, struct if_rxring_info *); int if_rxr_ioctl(struct if_rxrinfo *, const char *, u_int, struct if_rxring *); + +void if_counters_alloc(struct ifnet *); +void if_counters_free(struct ifnet *); #endif /* _KERNEL */