summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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_ */