Download raw body.
kstats for igc(4)
the subject says it all. they work pretty much the same as the em(4)
counters, but with less quirks (so far).
the interesting ones for me are the rx no bufs, tx discards, rxd min
thresh and tx tso ctx counters.
igc0:0:igc-stats:0
crc errs: 0
alignment errs: 0
rx errs: 0
missed pkts: 0
single colls: 0
excessive colls: 0
multiple colls: 0
late colls: 0
collisions: 0
recv errs: 0
defers: 0
tx no crs: 0
host tx discard: 0
recv len errs: 0
xon rx: 0
xon tx: 0
xoff rx: 0
xoff tx: 0
fc rx unsupp: 0
rx 64B: 204 packets
rx 65-127B: 497 packets
rx 128-255B: 200 packets
rx 256-511B: 35 packets
rx 512-1023B: 5 packets
rx 1024-maxB: 11 packets
rx good: 952 packets
rx bcast: 103 packets
rx mcast: 0 packets
tx good: 859 packets
rx good bytes: 125964 bytes
tx good bytes: 374936 bytes
rx no bufs: 0
rx undersize: 0
rx frags: 0
rx oversize: 0
rx jabbers: 0
rx mgmt: 0 packets
rx mgmt drops: 0 packets
tx mgmt: 0 packets
rx total bytes: 179498 bytes
tx total bytes: 374936 bytes
rx total: 1207 packets
tx total: 859 packets
tx 64B: 88 packets
tx 65-127B: 366 packets
tx 128-255B: 111 packets
tx 256-511B: 62 packets
tx 512-1023B: 69 packets
tx 1024-maxB: 163 packets
tx mcast: 0 packets
tx bcast: 9 packets
tx tso ctx: 0
interrupts: 1424
rx to host: 952 packets
eee tx lpi: 0
eee rx lpi: 0
host rx: 859 packets
rxd min thresh: 0
host good rx: 125964 bytes
host good tx: 374936 bytes
len errs: 0
Index: igc_regs.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/igc_regs.h,v
retrieving revision 1.2
diff -u -p -r1.2 igc_regs.h
--- igc_regs.h 15 Aug 2023 08:27:30 -0000 1.2
+++ igc_regs.h 26 Mar 2024 03:49:37 -0000
@@ -164,6 +164,7 @@
/* Statistics Register Descriptions */
#define IGC_CRCERRS 0x04000 /* CRC Error Count - R/clr */
#define IGC_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
+#define IGC_RXERRC 0x04004 /* Receive Error Count - R/clr */
#define IGC_MPC 0x04010 /* Missed Packet Count - R/clr */
#define IGC_SCC 0x04014 /* Single Collision Count - R/clr */
#define IGC_ECOL 0x04018 /* Excessive Collision Count - R/clr */
@@ -218,7 +219,14 @@
#define IGC_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */
#define IGC_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */
#define IGC_IAC 0x04100 /* Interrupt Assertion Count */
+#define IGC_RPTHC 0x04104 /* Rx Packets To Host */
+#define IGC_HGPTC 0x04118 /* Host Good Packets Tx Count */
#define IGC_RXDMTC 0x04120 /* Rx Descriptor Minimum Threshold Count */
+#define IGC_HGORCL 0x04128 /* Host Good Octets Received Count Low */
+#define IGC_HGORCH 0x0412C /* Host Good Octets Received Count High */
+#define IGC_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */
+#define IGC_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */
+#define IGC_LENERRS 0x04138 /* Length Errors Count */
#define IGC_VFGPRC 0x00F10
#define IGC_VFGORC 0x00F18
@@ -229,11 +237,7 @@
#define IGC_VFGPTLBC 0x00F44
#define IGC_VFGORLBC 0x00F48
#define IGC_VFGPRLBC 0x00F40
-#define IGC_HGORCL 0x04128 /* Host Good Octets Received Count Low */
-#define IGC_HGORCH 0x0412C /* Host Good Octets Received Count High */
-#define IGC_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */
-#define IGC_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */
-#define IGC_LENERRS 0x04138 /* Length Errors Count */
+
#define IGC_PCS_ANADV 0x04218 /* AN advertisement - RW */
#define IGC_PCS_LPAB 0x0421C /* Link Partner Ability - RW */
#define IGC_RXCSUM 0x05000 /* Rx Checksum Control - RW */
Index: if_igc.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_igc.c,v
retrieving revision 1.18
diff -u -p -r1.18 if_igc.c
--- if_igc.c 23 Feb 2024 01:06:18 -0000 1.18
+++ if_igc.c 26 Mar 2024 03:49:37 -0000
@@ -30,6 +30,7 @@
#include "bpfilter.h"
#include "vlan.h"
+#include "kstat.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -41,6 +42,7 @@
#include <sys/device.h>
#include <sys/endian.h>
#include <sys/intrmap.h>
+#include <sys/kstat.h>
#include <net/if.h>
#include <net/if_media.h>
@@ -145,6 +147,10 @@ void igc_get_hw_control(struct igc_softc
void igc_release_hw_control(struct igc_softc *);
int igc_is_valid_ether_addr(uint8_t *);
+#if NKSTAT > 0
+void igc_kstat_attach(struct igc_softc *);
+#endif
+
/*********************************************************************
* OpenBSD Device Interface Entry Points
*********************************************************************/
@@ -279,6 +285,10 @@ igc_attach(struct device *parent, struct
igc_get_hw_control(sc);
printf(", address %s\n", ether_sprintf(sc->hw.mac.addr));
+
+#if NKSTAT > 0
+ igc_kstat_attach(sc);
+#endif
return;
err_late:
@@ -2453,3 +2463,328 @@ igc_is_valid_ether_addr(uint8_t *addr)
return 1;
}
+
+#if NKSTAT > 0
+
+/*
+ * the below are read to clear, so they need to be accumulated for
+ * userland to see counters. periodically fetch the counters from a
+ * timeout to avoid a 32 roll-over between kstat reads.
+ */
+
+enum igc_stat {
+ igc_stat_crcerrs,
+ igc_stat_algnerrc,
+ igc_stat_rxerrc,
+ igc_stat_mpc,
+ igc_stat_scc,
+ igc_stat_ecol,
+ igc_stat_mcc,
+ igc_stat_latecol,
+ igc_stat_colc,
+ igc_stat_rerc,
+ igc_stat_dc,
+ igc_stat_tncrs,
+ igc_stat_htdpmc,
+ igc_stat_rlec,
+ igc_stat_xonrxc,
+ igc_stat_xontxc,
+ igc_stat_xoffrxc,
+ igc_stat_xofftxc,
+ igc_stat_fcruc,
+ igc_stat_prc64,
+ igc_stat_prc127,
+ igc_stat_prc255,
+ igc_stat_prc511,
+ igc_stat_prc1023,
+ igc_stat_prc1522,
+ igc_stat_gprc,
+ igc_stat_bprc,
+ igc_stat_mprc,
+ igc_stat_gptc,
+ igc_stat_gorc,
+ igc_stat_gotc,
+ igc_stat_rnbc,
+ igc_stat_ruc,
+ igc_stat_rfc,
+ igc_stat_roc,
+ igc_stat_rjc,
+ igc_stat_mgtprc,
+ igc_stat_mgtpdc,
+ igc_stat_mgtptc,
+ igc_stat_tor,
+ igc_stat_tot,
+ igc_stat_tpr,
+ igc_stat_tpt,
+ igc_stat_ptc64,
+ igc_stat_ptc127,
+ igc_stat_ptc255,
+ igc_stat_ptc511,
+ igc_stat_ptc1023,
+ igc_stat_ptc1522,
+ igc_stat_mptc,
+ igc_stat_bptc,
+ igc_stat_tsctc,
+
+ igc_stat_iac,
+ igc_stat_rpthc,
+ igc_stat_tlpic,
+ igc_stat_rlpic,
+ igc_stat_hgptc,
+ igc_stat_rxdmtc,
+ igc_stat_hgorc,
+ igc_stat_hgotc,
+ igc_stat_lenerrs,
+
+ igc_stat_count
+};
+
+struct igc_counter {
+ const char *name;
+ enum kstat_kv_unit unit;
+ uint32_t reg;
+};
+
+static const struct igc_counter igc_counters[igc_stat_count] = {
+ [igc_stat_crcerrs] =
+ { "crc errs", KSTAT_KV_U_NONE, IGC_CRCERRS },
+ [igc_stat_algnerrc] =
+ { "alignment errs", KSTAT_KV_U_NONE, IGC_ALGNERRC },
+ [igc_stat_rxerrc] =
+ { "rx errs", KSTAT_KV_U_NONE, IGC_RXERRC },
+ [igc_stat_mpc] =
+ { "missed pkts", KSTAT_KV_U_NONE, IGC_MPC },
+ [igc_stat_scc] =
+ { "single colls", KSTAT_KV_U_NONE, IGC_SCC },
+ [igc_stat_ecol] =
+ { "excessive colls", KSTAT_KV_U_NONE, IGC_ECOL },
+ [igc_stat_mcc] =
+ { "multiple colls", KSTAT_KV_U_NONE, IGC_MCC },
+ [igc_stat_latecol] =
+ { "late colls", KSTAT_KV_U_NONE, IGC_LATECOL },
+ [igc_stat_colc] =
+ { "collisions", KSTAT_KV_U_NONE, IGC_COLC },
+ [igc_stat_rerc] =
+ { "recv errs", KSTAT_KV_U_NONE, IGC_RERC },
+ [igc_stat_dc] =
+ { "defers", KSTAT_KV_U_NONE, IGC_DC },
+ [igc_stat_tncrs] =
+ { "tx no crs", KSTAT_KV_U_NONE, IGC_TNCRS},
+ [igc_stat_htdpmc] =
+ { "host tx discards", KSTAT_KV_U_NONE, IGC_HTDPMC },
+ [igc_stat_rlec] =
+ { "recv len errs", KSTAT_KV_U_NONE, IGC_RLEC },
+ [igc_stat_xonrxc] =
+ { "xon rx", KSTAT_KV_U_NONE, IGC_XONRXC },
+ [igc_stat_xontxc] =
+ { "xon tx", KSTAT_KV_U_NONE, IGC_XONTXC },
+ [igc_stat_xoffrxc] =
+ { "xoff rx", KSTAT_KV_U_NONE, IGC_XOFFRXC },
+ [igc_stat_xofftxc] =
+ { "xoff tx", KSTAT_KV_U_NONE, IGC_XOFFTXC },
+ [igc_stat_fcruc] =
+ { "fc rx unsupp", KSTAT_KV_U_NONE, IGC_FCRUC },
+ [igc_stat_prc64] =
+ { "rx 64B", KSTAT_KV_U_PACKETS, IGC_PRC64 },
+ [igc_stat_prc127] =
+ { "rx 65-127B", KSTAT_KV_U_PACKETS, IGC_PRC127 },
+ [igc_stat_prc255] =
+ { "rx 128-255B", KSTAT_KV_U_PACKETS, IGC_PRC255 },
+ [igc_stat_prc511] =
+ { "rx 256-511B", KSTAT_KV_U_PACKETS, IGC_PRC511 },
+ [igc_stat_prc1023] =
+ { "rx 512-1023B", KSTAT_KV_U_PACKETS, IGC_PRC1023 },
+ [igc_stat_prc1522] =
+ { "rx 1024-maxB", KSTAT_KV_U_PACKETS, IGC_PRC1522 },
+ [igc_stat_gprc] =
+ { "rx good", KSTAT_KV_U_PACKETS, IGC_GPRC },
+ [igc_stat_bprc] =
+ { "rx bcast", KSTAT_KV_U_PACKETS, IGC_BPRC },
+ [igc_stat_mprc] =
+ { "rx mcast", KSTAT_KV_U_PACKETS, IGC_MPRC },
+ [igc_stat_gptc] =
+ { "tx good", KSTAT_KV_U_PACKETS, IGC_GPTC },
+ [igc_stat_gorc] =
+ { "rx good bytes", KSTAT_KV_U_BYTES, 0 },
+ [igc_stat_gotc] =
+ { "tx good bytes", KSTAT_KV_U_BYTES, 0 },
+ [igc_stat_rnbc] =
+ { "rx no bufs", KSTAT_KV_U_NONE, IGC_RNBC },
+ [igc_stat_ruc] =
+ { "rx undersize", KSTAT_KV_U_NONE, IGC_RUC },
+ [igc_stat_rfc] =
+ { "rx frags", KSTAT_KV_U_NONE, IGC_RFC },
+ [igc_stat_roc] =
+ { "rx oversize", KSTAT_KV_U_NONE, IGC_ROC },
+ [igc_stat_rjc] =
+ { "rx jabbers", KSTAT_KV_U_NONE, IGC_RJC },
+ [igc_stat_mgtprc] =
+ { "rx mgmt", KSTAT_KV_U_PACKETS, IGC_MGTPRC },
+ [igc_stat_mgtpdc] =
+ { "rx mgmt drops", KSTAT_KV_U_PACKETS, IGC_MGTPDC },
+ [igc_stat_mgtptc] =
+ { "tx mgmt", KSTAT_KV_U_PACKETS, IGC_MGTPTC },
+ [igc_stat_tor] =
+ { "rx total bytes", KSTAT_KV_U_BYTES, 0 },
+ [igc_stat_tot] =
+ { "tx total bytes", KSTAT_KV_U_BYTES, 0 },
+ [igc_stat_tpr] =
+ { "rx total", KSTAT_KV_U_PACKETS, IGC_TPR },
+ [igc_stat_tpt] =
+ { "tx total", KSTAT_KV_U_PACKETS, IGC_TPT },
+ [igc_stat_ptc64] =
+ { "tx 64B", KSTAT_KV_U_PACKETS, IGC_PTC64 },
+ [igc_stat_ptc127] =
+ { "tx 65-127B", KSTAT_KV_U_PACKETS, IGC_PTC127 },
+ [igc_stat_ptc255] =
+ { "tx 128-255B", KSTAT_KV_U_PACKETS, IGC_PTC255 },
+ [igc_stat_ptc511] =
+ { "tx 256-511B", KSTAT_KV_U_PACKETS, IGC_PTC511 },
+ [igc_stat_ptc1023] =
+ { "tx 512-1023B", KSTAT_KV_U_PACKETS, IGC_PTC1023 },
+ [igc_stat_ptc1522] =
+ { "tx 1024-maxB", KSTAT_KV_U_PACKETS, IGC_PTC1522 },
+ [igc_stat_mptc] =
+ { "tx mcast", KSTAT_KV_U_PACKETS, IGC_MPTC },
+ [igc_stat_bptc] =
+ { "tx bcast", KSTAT_KV_U_PACKETS, IGC_BPTC },
+ [igc_stat_tsctc] =
+ { "tx tso ctx", KSTAT_KV_U_NONE, IGC_TSCTC },
+
+ [igc_stat_iac] =
+ { "interrupts", KSTAT_KV_U_NONE, IGC_IAC },
+ [igc_stat_rpthc] =
+ { "rx to host", KSTAT_KV_U_PACKETS, IGC_RPTHC },
+ [igc_stat_tlpic] =
+ { "eee tx lpi", KSTAT_KV_U_NONE, IGC_TLPIC },
+ [igc_stat_rlpic] =
+ { "eee rx lpi", KSTAT_KV_U_NONE, IGC_RLPIC },
+ [igc_stat_hgptc] =
+ { "host rx", KSTAT_KV_U_PACKETS, IGC_HGPTC },
+ [igc_stat_rxdmtc] =
+ { "rxd min thresh", KSTAT_KV_U_NONE, IGC_RXDMTC },
+ [igc_stat_hgorc] =
+ { "host good rx", KSTAT_KV_U_BYTES, 0 },
+ [igc_stat_hgotc] =
+ { "host good tx", KSTAT_KV_U_BYTES, 0 },
+ [igc_stat_lenerrs] =
+ { "len errs", KSTAT_KV_U_NONE, IGC_LENERRS },
+};
+
+static void
+igc_stat_read(struct igc_softc *sc)
+{
+ struct igc_hw *hw = &sc->hw;
+ struct kstat *ks = sc->ks;
+ struct kstat_kv *kvs = ks->ks_data;
+ uint32_t hi, lo;
+ unsigned int i;
+
+ for (i = 0; i < nitems(igc_counters); i++) {
+ const struct igc_counter *c = &igc_counters[i];
+ if (c->reg == 0)
+ continue;
+
+ kstat_kv_u64(&kvs[i]) += IGC_READ_REG(hw, c->reg);
+ }
+
+ lo = IGC_READ_REG(hw, IGC_GORCL);
+ hi = IGC_READ_REG(hw, IGC_GORCH);
+ kstat_kv_u64(&kvs[igc_stat_gorc]) +=
+ ((uint64_t)hi << 32) | ((uint64_t)lo << 0);
+
+ lo = IGC_READ_REG(hw, IGC_GOTCL);
+ hi = IGC_READ_REG(hw, IGC_GOTCH);
+ kstat_kv_u64(&kvs[igc_stat_gotc]) +=
+ ((uint64_t)hi << 32) | ((uint64_t)lo << 0);
+
+ lo = IGC_READ_REG(hw, IGC_TORL);
+ hi = IGC_READ_REG(hw, IGC_TORH);
+ kstat_kv_u64(&kvs[igc_stat_tor]) +=
+ ((uint64_t)hi << 32) | ((uint64_t)lo << 0);
+
+ lo = IGC_READ_REG(hw, IGC_TOTL);
+ hi = IGC_READ_REG(hw, IGC_TOTH);
+ kstat_kv_u64(&kvs[igc_stat_tot]) +=
+ ((uint64_t)hi << 32) | ((uint64_t)lo << 0);
+
+ lo = IGC_READ_REG(hw, IGC_HGORCL);
+ hi = IGC_READ_REG(hw, IGC_HGORCH);
+ kstat_kv_u64(&kvs[igc_stat_hgorc]) +=
+ ((uint64_t)hi << 32) | ((uint64_t)lo << 0);
+
+ lo = IGC_READ_REG(hw, IGC_HGOTCL);
+ hi = IGC_READ_REG(hw, IGC_HGOTCH);
+ kstat_kv_u64(&kvs[igc_stat_hgotc]) +=
+ ((uint64_t)hi << 32) | ((uint64_t)lo << 0);
+}
+
+static void
+igc_kstat_tick(void *arg)
+{
+ struct igc_softc *sc = arg;
+
+ if (mtx_enter_try(&sc->ks_mtx)) {
+ igc_stat_read(sc);
+ mtx_leave(&sc->ks_mtx);
+ }
+
+ timeout_add_sec(&sc->ks_tmo, 4);
+}
+
+static int
+igc_kstat_read(struct kstat *ks)
+{
+ struct igc_softc *sc = ks->ks_softc;
+
+ igc_stat_read(sc);
+ nanouptime(&ks->ks_updated);
+
+ return (0);
+}
+
+void
+igc_kstat_attach(struct igc_softc *sc)
+{
+ struct kstat *ks;
+ struct kstat_kv *kvs;
+ size_t len;
+ unsigned int i;
+
+ mtx_init(&sc->ks_mtx, IPL_SOFTCLOCK);
+ timeout_set(&sc->ks_tmo, igc_kstat_tick, sc);
+
+ kvs = mallocarray(sizeof(*kvs), nitems(igc_counters), M_DEVBUF,
+ M_WAITOK|M_ZERO|M_CANFAIL);
+ if (kvs == NULL) {
+ printf("%s: unable to allocate igc kstats\n", DEVNAME(sc));
+ return;
+ }
+ len = sizeof(*kvs) * nitems(igc_counters);
+
+ ks = kstat_create(DEVNAME(sc), 0, "igc-stats", 0, KSTAT_T_KV, 0);
+ if (ks == NULL) {
+ printf("%s: unable to create igc kstats\n", DEVNAME(sc));
+ free(kvs, M_DEVBUF, len);
+ return;
+ }
+
+ for (i = 0; i < nitems(igc_counters); i++) {
+ const struct igc_counter *c = &igc_counters[i];
+ kstat_kv_unit_init(&kvs[i], c->name,
+ KSTAT_KV_T_COUNTER64, c->unit);
+ }
+
+ ks->ks_softc = sc;
+ ks->ks_data = kvs;
+ ks->ks_datalen = len;
+ ks->ks_read = igc_kstat_read;
+ kstat_set_mutex(ks, &sc->ks_mtx);
+
+ kstat_install(ks);
+
+ sc->ks = ks;
+
+ igc_kstat_tick(sc); /* let's gooo */
+}
+#endif /* NKSTAT > 0 */
Index: if_igc.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_igc.h,v
retrieving revision 1.2
diff -u -p -r1.2 if_igc.h
--- if_igc.h 9 Jan 2022 05:42:50 -0000 1.2
+++ if_igc.h 26 Mar 2024 03:49:37 -0000
@@ -199,6 +199,7 @@
/* Forward declaration. */
struct igc_hw;
+struct kstat;
struct igc_osdep {
bus_dma_tag_t os_dmat;
@@ -320,6 +321,11 @@ struct igc_softc {
/* Multicast array memory */
uint8_t *mta;
+
+ /* Counters */
+ struct mutex ks_mtx;
+ struct timeout ks_tmo;
+ struct kstat *ks;
};
#define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname)
kstats for igc(4)