summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2018-12-11 22:08:58 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2018-12-11 22:08:58 +0000
commitccab8be4bfb156dcabf996edaa6b432e29f515a2 (patch)
treea4ed43b1052b8ccc691c2fdd66e23c6a01d8bf76
parent179f2332119303131e65b078b78b1fefa916d680 (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.c42
-rw-r--r--sys/net/if_var.h24
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_ */