diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2018-12-11 22:08:58 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2018-12-11 22:08:58 +0000 |
commit | ccab8be4bfb156dcabf996edaa6b432e29f515a2 (patch) | |
tree | a4ed43b1052b8ccc691c2fdd66e23c6a01d8bf76 | |
parent | 179f2332119303131e65b078b78b1fefa916d680 (diff) |
add optional per-cpu counters for interface stats.
these exist so interfaces that want to do mpsafe work outside the
ifq machinery have a place to allocate and update stats in. the
generic ioctl handling for getting stats to userland knows how to
roll the new per cpu stats into the rest before export.
ok visa@
-rw-r--r-- | sys/net/if.c | 42 | ||||
-rw-r--r-- | sys/net/if_var.h | 24 |
2 files changed, 64 insertions, 2 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 0d1c51d0ad8..864bc23d833 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.568 2018/11/29 00:11:49 dlg Exp $ */ +/* $OpenBSD: if.c,v 1.569 2018/12/11 22:08:57 dlg Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -84,6 +84,7 @@ #include <sys/domain.h> #include <sys/task.h> #include <sys/atomic.h> +#include <sys/percpu.h> #include <sys/proc.h> #include <dev/rndvar.h> @@ -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,12 +2366,48 @@ 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]; diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 564b59037fd..f1deddb3994 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_var.h,v 1.90 2018/09/10 16:18:34 sashan Exp $ */ +/* $OpenBSD: if_var.h,v 1.91 2018/12/11 22:08:57 dlg Exp $ */ /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ /* @@ -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, @@ -357,6 +376,9 @@ 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 */ #endif /* _NET_IF_VAR_H_ */ |