summaryrefslogtreecommitdiffstats
path: root/sys/net/if.c
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2018-12-11 22:08:57 +0000
committerdlg <dlg@openbsd.org>2018-12-11 22:08:57 +0000
commit5cf301f03442516757a4c40addc8e70524aa39bd (patch)
tree9ac769fb91aedaf7fbbd74ad7abaf06095187eee /sys/net/if.c
parentthe world is not ready for dnssec enabled by default (diff)
downloadwireguard-openbsd-5cf301f03442516757a4c40addc8e70524aa39bd.tar.xz
wireguard-openbsd-5cf301f03442516757a4c40addc8e70524aa39bd.zip
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@
Diffstat (limited to 'sys/net/if.c')
-rw-r--r--sys/net/if.c42
1 files changed, 41 insertions, 1 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];