this is a first pass at converting the stats gathering in em(4) to
kstat instead of a disabled printf.
there are some semantic differences. the most obvious is that hardware
counters are not fed into the stacks counters on struct ifnet. i also
don't collect ring based counters (yet).
they look like this:
em0:0:em-stats:0
rx crc errs: 0 packets
rx align errs: 0 packets
rx align errs: 0 packets
rx errs: 0 packets
rx missed: 0 packets
tx single coll: 0 packets
tx excess coll: 0 packets
tx multi coll: 0 packets
tx late coll: 0 packets
tx coll: 0
tx defers: 0
tx no CRS: 0 packets
seq errs: 0
carr ext errs: 0 packets
rx len errs: 0 packets
rx xon: 0 packets
tx xon: 0 packets
rx xoff: 0 packets
tx xoff: 0 packets
FC unsupported: 0 packets
rx 64B: 6 packets
rx 65-127B: 223 packets
rx 128-255B: 15 packets
rx 256-511B: 7 packets
rx 512-1023B: 2 packets
rx 1024-maxB: 1234584 packets
rx good: 1234837 packets
rx bcast: 19 packets
rx mcast: 0 packets
tx good: 630873 packets
rx good: 1874122399 bytes
tx good: 44180108 bytes
rx no buffers: 0 packets
rx undersize: 0 packets
rx fragments: 0 packets
rx oversize: 0 packets
rx jabbers: 0 packets
rx mgmt: 0 packets
rx mgmt drops: 0 packets
tx mgmt: 0 packets
rx total: 1874146525 bytes
tx total: 44180108 bytes
rx total: 1235017 packets
tx total: 630873 packets
tx 64B: 113 packets
tx 65-127B: 630681 packets
tx 128-255B: 47 packets
tx 256-511B: 29 packets
tx 512-1023B: 2 packets
tx 1024-maxB: 1 packets
tx mcast: 0 packets
tx bcast: 10 packets
unfortunately em(4) covers a lot of chips of different vintages, so if
anyone has a super old one they can try this diff on with kstat enabled
in their kernel config, that would be appreciated.
Index: if_em.c
===
RCS file: /cvs/src/sys/dev/pci/if_em.c,v
retrieving revision 1.354
diff -u -p -r1.354 if_em.c
--- if_em.c 22 Jun 2020 02:31:32 - 1.354
+++ if_em.c 7 Jul 2020 08:48:37 -
@@ -270,9 +270,6 @@ void em_receive_checksum(struct em_softc
u_int em_transmit_checksum_setup(struct em_queue *, struct mbuf *, u_int,
u_int32_t *, u_int32_t *);
void em_iff(struct em_softc *);
-#ifdef EM_DEBUG
-void em_print_hw_stats(struct em_softc *);
-#endif
void em_update_link_status(struct em_softc *);
int em_get_buf(struct em_queue *, int);
void em_enable_hw_vlans(struct em_softc *);
@@ -302,6 +299,12 @@ void em_enable_queue_intr_msix(struct em
#define em_allocate_msix(_sc) (-1)
#endif
+#if NKSTAT > 0
+void em_kstat_attach(struct em_softc *);
+intem_kstat_read(struct kstat *);
+void em_tbi_adjust_stats(struct em_softc *, uint32_t, uint8_t *);
+#endif
+
/*
* OpenBSD Device Interface Entry Points
*/
@@ -561,8 +564,8 @@ em_attach(struct device *parent, struct
/* Initialize statistics */
em_clear_hw_cntrs(&sc->hw);
-#ifndef SMALL_KERNEL
- em_update_stats_counters(sc);
+#if NKSTAT > 0
+ em_kstat_attach(sc);
#endif
sc->hw.get_link_status = 1;
if (!defer)
@@ -1467,26 +1470,21 @@ em_iff(struct em_softc *sc)
void
em_local_timer(void *arg)
{
- struct ifnet *ifp;
struct em_softc *sc = arg;
int s;
- ifp = &sc->sc_ac.ac_if;
+ timeout_add_sec(&sc->timer_handle, 1);
s = splnet();
-
-#ifndef SMALL_KERNEL
- em_update_stats_counters(sc);
-#ifdef EM_DEBUG
- if (ifp->if_flags & IFF_DEBUG && ifp->if_flags & IFF_RUNNING)
- em_print_hw_stats(sc);
-#endif
-#endif
em_smartspeed(sc);
-
- timeout_add_sec(&sc->timer_handle, 1);
-
splx(s);
+
+#if NKSTAT > 0
+ if (sc->kstat != NULL && mtx_enter_try(&sc->kstat_mtx)) {
+ em_kstat_read(sc->kstat);
+ mtx_leave(&sc->kstat_mtx);
+ }
+#endif
}
void
@@ -2934,8 +2932,8 @@ em_rxeof(struct em_queue *que)
last_byte = *(mtod(m, caddr_t) + desc_len - 1);
if (TBI_ACCEPT(&sc->hw, status, desc->errors,
pkt_len, last_byte)) {
-#ifndef SMALL_KERNEL
- em_tbi_adjust_stats(&sc->hw, &sc->stats,
+#if NKSTAT > 0
+ em_tbi_adjust_stats(sc,
pkt_len, sc->hw.mac_addr);
#endif
if (len > 0)
@@ -3396,228 +3394,365 @@ em_allocate_legacy(struct em_softc *sc)
return (0);
}
+#if NKSTAT > 0
+/* this is used to look up the array of kstats quickly */
+enum em_stat {
+ em_stat_crcerrs,
+