summaryrefslogtreecommitdiff
path: root/sys/net/ifq.c
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2020-07-07 00:00:04 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2020-07-07 00:00:04 +0000
commitf435648b783901fc6f430e780bc7c8e0ea202f7c (patch)
treecce54f8f2798c87d25abf645148b233c025c6d2f /sys/net/ifq.c
parent4e526a6aa77e6abcee3f8ea6ff3eab4e57605701 (diff)
add kstats for rx queues (ifiqs) and transmit queues (ifqs).
this means you can observe what the network stack is trying to do when it's working with a nic driver that supports multiple rings. a nic with only one set of rings still gets queues though, and this still exports their stats. here is a small example of what kstat(8) currently outputs for these stats: em0:0:rxq:0 packets: 2292 packets bytes: 229846 bytes qdrops: 0 packets errors: 0 packets qlen: 0 packets em0:0:txq:0 packets: 1297 packets bytes: 193413 bytes qdrops: 0 packets errors: 0 packets qlen: 0 packets maxqlen: 511 packets oactive: false
Diffstat (limited to 'sys/net/ifq.c')
-rw-r--r--sys/net/ifq.c124
1 files changed, 123 insertions, 1 deletions
diff --git a/sys/net/ifq.c b/sys/net/ifq.c
index 2846d23ed03..5e97c4e2e43 100644
--- a/sys/net/ifq.c
+++ b/sys/net/ifq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ifq.c,v 1.40 2020/06/17 06:45:22 dlg Exp $ */
+/* $OpenBSD: ifq.c,v 1.41 2020/07/07 00:00:03 dlg Exp $ */
/*
* Copyright (c) 2015 David Gwynne <dlg@openbsd.org>
@@ -17,6 +17,7 @@
*/
#include "bpfilter.h"
+#include "kstat.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -32,6 +33,10 @@
#include <net/bpf.h>
#endif
+#if NKSTAT > 0
+#include <sys/kstat.h>
+#endif
+
/*
* priq glue
*/
@@ -188,6 +193,52 @@ ifq_barrier_task(void *p)
* ifqueue mbuf queue API
*/
+#if NKSTAT > 0
+struct ifq_kstat_data {
+ struct kstat_kv kd_packets;
+ struct kstat_kv kd_bytes;
+ struct kstat_kv kd_qdrops;
+ struct kstat_kv kd_errors;
+ struct kstat_kv kd_qlen;
+ struct kstat_kv kd_maxqlen;
+ struct kstat_kv kd_oactive;
+};
+
+static const struct ifq_kstat_data ifq_kstat_tpl = {
+ KSTAT_KV_UNIT_INITIALIZER("packets",
+ KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS),
+ KSTAT_KV_UNIT_INITIALIZER("bytes",
+ KSTAT_KV_T_COUNTER64, KSTAT_KV_U_BYTES),
+ KSTAT_KV_UNIT_INITIALIZER("qdrops",
+ KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS),
+ KSTAT_KV_UNIT_INITIALIZER("errors",
+ KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS),
+ KSTAT_KV_UNIT_INITIALIZER("qlen",
+ KSTAT_KV_T_UINT32, KSTAT_KV_U_PACKETS),
+ KSTAT_KV_UNIT_INITIALIZER("maxqlen",
+ KSTAT_KV_T_UINT32, KSTAT_KV_U_PACKETS),
+ KSTAT_KV_INITIALIZER("oactive", KSTAT_KV_T_BOOL),
+};
+
+int
+ifq_kstat_copy(struct kstat *ks, void *dst)
+{
+ struct ifqueue *ifq = ks->ks_softc;
+ struct ifq_kstat_data *kd = dst;
+
+ *kd = ifq_kstat_tpl;
+ kstat_kv_u64(&kd->kd_packets) = ifq->ifq_packets;
+ kstat_kv_u64(&kd->kd_bytes) = ifq->ifq_bytes;
+ kstat_kv_u64(&kd->kd_qdrops) = ifq->ifq_qdrops;
+ kstat_kv_u64(&kd->kd_errors) = ifq->ifq_errors;
+ kstat_kv_u32(&kd->kd_qlen) = ifq->ifq_len;
+ kstat_kv_u32(&kd->kd_maxqlen) = ifq->ifq_maxlen;
+ kstat_kv_bool(&kd->kd_oactive) = ifq->ifq_oactive;
+
+ return (0);
+}
+#endif
+
void
ifq_init(struct ifqueue *ifq, struct ifnet *ifp, unsigned int idx)
{
@@ -222,6 +273,18 @@ ifq_init(struct ifqueue *ifq, struct ifnet *ifp, unsigned int idx)
ifq_set_maxlen(ifq, IFQ_MAXLEN);
ifq->ifq_idx = idx;
+
+#if NKSTAT > 0
+ /* XXX xname vs driver name and unit */
+ ifq->ifq_kstat = kstat_create(ifp->if_xname, 0,
+ "txq", ifq->ifq_idx, KSTAT_T_KV, 0);
+ KASSERT(ifq->ifq_kstat != NULL);
+ kstat_set_mutex(ifq->ifq_kstat, &ifq->ifq_mtx);
+ ifq->ifq_kstat->ks_softc = ifq;
+ ifq->ifq_kstat->ks_datalen = sizeof(ifq_kstat_tpl);
+ ifq->ifq_kstat->ks_copy = ifq_kstat_copy;
+ kstat_install(ifq->ifq_kstat);
+#endif
}
void
@@ -265,6 +328,10 @@ ifq_destroy(struct ifqueue *ifq)
{
struct mbuf_list ml = MBUF_LIST_INITIALIZER();
+#if NKSTAT > 0
+ kstat_destroy(ifq->ifq_kstat);
+#endif
+
NET_ASSERT_UNLOCKED();
if (!task_del(ifq->ifq_softnet, &ifq->ifq_bundle))
taskq_barrier(ifq->ifq_softnet);
@@ -505,6 +572,45 @@ ifq_mfreeml(struct ifqueue *ifq, struct mbuf_list *ml)
* ifiq
*/
+#if NKSTAT > 0
+struct ifiq_kstat_data {
+ struct kstat_kv kd_packets;
+ struct kstat_kv kd_bytes;
+ struct kstat_kv kd_qdrops;
+ struct kstat_kv kd_errors;
+ struct kstat_kv kd_qlen;
+};
+
+static const struct ifiq_kstat_data ifiq_kstat_tpl = {
+ KSTAT_KV_UNIT_INITIALIZER("packets",
+ KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS),
+ KSTAT_KV_UNIT_INITIALIZER("bytes",
+ KSTAT_KV_T_COUNTER64, KSTAT_KV_U_BYTES),
+ KSTAT_KV_UNIT_INITIALIZER("qdrops",
+ KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS),
+ KSTAT_KV_UNIT_INITIALIZER("errors",
+ KSTAT_KV_T_COUNTER64, KSTAT_KV_U_PACKETS),
+ KSTAT_KV_UNIT_INITIALIZER("qlen",
+ KSTAT_KV_T_UINT32, KSTAT_KV_U_PACKETS),
+};
+
+int
+ifiq_kstat_copy(struct kstat *ks, void *dst)
+{
+ struct ifiqueue *ifiq = ks->ks_softc;
+ struct ifiq_kstat_data *kd = dst;
+
+ *kd = ifiq_kstat_tpl;
+ kstat_kv_u64(&kd->kd_packets) = ifiq->ifiq_packets;
+ kstat_kv_u64(&kd->kd_bytes) = ifiq->ifiq_bytes;
+ kstat_kv_u64(&kd->kd_qdrops) = ifiq->ifiq_qdrops;
+ kstat_kv_u64(&kd->kd_errors) = ifiq->ifiq_errors;
+ kstat_kv_u32(&kd->kd_qlen) = ml_len(&ifiq->ifiq_ml);
+
+ return (0);
+}
+#endif
+
static void ifiq_process(void *);
void
@@ -525,11 +631,27 @@ ifiq_init(struct ifiqueue *ifiq, struct ifnet *ifp, unsigned int idx)
ifiq->ifiq_errors = 0;
ifiq->ifiq_idx = idx;
+
+#if NKSTAT > 0
+ /* XXX xname vs driver name and unit */
+ ifiq->ifiq_kstat = kstat_create(ifp->if_xname, 0,
+ "rxq", ifiq->ifiq_idx, KSTAT_T_KV, 0);
+ KASSERT(ifiq->ifiq_kstat != NULL);
+ kstat_set_mutex(ifiq->ifiq_kstat, &ifiq->ifiq_mtx);
+ ifiq->ifiq_kstat->ks_softc = ifiq;
+ ifiq->ifiq_kstat->ks_datalen = sizeof(ifiq_kstat_tpl);
+ ifiq->ifiq_kstat->ks_copy = ifiq_kstat_copy;
+ kstat_install(ifiq->ifiq_kstat);
+#endif
}
void
ifiq_destroy(struct ifiqueue *ifiq)
{
+#if NKSTAT > 0
+ kstat_destroy(ifiq->ifiq_kstat);
+#endif
+
NET_ASSERT_UNLOCKED();
if (!task_del(ifiq->ifiq_softnet, &ifiq->ifiq_task))
taskq_barrier(ifiq->ifiq_softnet);