ice(4): add kstat counter

Jan Klemkow <[email protected]>
Newsgroups gmane.os.openbsd.tech
Message-ID <[email protected]>
Hi,

This diff exports most hardware kstat counters from ice(4) interfaces.
So, we improve debugging of these interfaces.

ok?

bye,
jan

Index: dev/pci/if_ice.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_ice.c,v
diff -u -p -r1.69 if_ice.c
--- dev/pci/if_ice.c	23 Jun 2026 14:40:40 -0000	1.69
+++ dev/pci/if_ice.c	7 Jul 2026 21:03:13 -0000
@@ -51,6 +51,7 @@
 
 #include "bpfilter.h"
 #include "vlan.h"
+#include "kstat.h"
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -70,6 +71,10 @@
 #include <machine/bus.h>
 #include <machine/intr.h>
 
+#if NKSTAT > 0
+#include <sys/kstat.h>
+#endif
+
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcidevs.h>
@@ -340,6 +345,8 @@ struct ice_softc {
 	int rebuild_ticks;
 
 	int sw_intr[ICE_MAX_VECTORS];
+	struct kstat *sc_kstat_port;
+	struct kstat *sc_kstat_vsi;
 };
 
 static int ice_rxrinfo(struct ice_softc *, struct if_rxrinfo *);
@@ -24125,7 +24132,7 @@ ice_update_link_status(struct ice_softc 
 				ice_set_default_local_lldp_mib(sc);
 
 			ifp->if_baudrate = baudrate;
-			ifp->if_link_state = LINK_STATE_UP;
+			ifp->if_link_state = LINK_STATE_FULL_DUPLEX;
 			if_link_state_change(ifp);
 #if 0
 			ice_rdma_link_change(sc, LINK_STATE_UP, baudrate);
@@ -28900,6 +28907,279 @@ ice_update_stats(struct ice_softc *sc)
 #endif
 }
 
+#if NKSTAT > 0
+
+/* Synced with struct ice_hw_port_stats */
+struct ice_kstat_port_counters {
+	/* struct ice_eth_stats eth; */
+	struct kstat_kv rx_bytes;
+	struct kstat_kv rx_unicast;
+	struct kstat_kv rx_multicast;
+	struct kstat_kv rx_broadcast;
+	struct kstat_kv rx_discards;
+	/* uint64_t rx_unknown_protocol;	N/A */
+	struct kstat_kv tx_bytes;
+	struct kstat_kv tx_unicast;
+	struct kstat_kv tx_multicast;
+	struct kstat_kv tx_broadcast;
+	/* uint64_t tx_discards;		N/A */
+	/* uint64_t tx_errors;			N/A */
+	/* uint64_t rx_no_desc;			N/A */
+	/* uint64_t rx_errors;			N/A */
+
+	struct kstat_kv tx_dropped_link_down;
+	struct kstat_kv crc_errors;
+	struct kstat_kv illegal_bytes;
+	/* error_bytes				N/A */
+	struct kstat_kv mac_local_faults;
+	struct kstat_kv mac_remote_faults;
+	struct kstat_kv rx_len_errors;
+	struct kstat_kv link_xon_rx;
+	struct kstat_kv link_xoff_rx;
+	struct kstat_kv link_xon_tx;
+	struct kstat_kv link_xoff_tx;
+	/* uint64_t priority_xon_rx[8];		skipped, too verbose */
+	/* uint64_t priority_xoff_rx[8];	skipped, too verbose */
+	/* uint64_t priority_xon_tx[8];		skipped, too verbose */
+	/* uint64_t priority_xoff_tx[8];	skipped, too verbose */
+	/* uint64_t priority_xon_2_xoff[8];	skipped, too verbose */
+	struct kstat_kv rx_size_64;
+	struct kstat_kv rx_size_127;
+	struct kstat_kv rx_size_255;
+	struct kstat_kv rx_size_511;
+	struct kstat_kv rx_size_1023;
+	struct kstat_kv rx_size_1522;
+	struct kstat_kv rx_size_big;
+	struct kstat_kv rx_undersize;
+	struct kstat_kv rx_fragments;
+	struct kstat_kv rx_oversize;
+	struct kstat_kv rx_jabber;
+	struct kstat_kv tx_size_64;
+	struct kstat_kv tx_size_127;
+	struct kstat_kv tx_size_255;
+	struct kstat_kv tx_size_511;
+	struct kstat_kv tx_size_1023;
+	struct kstat_kv tx_size_1522;
+	struct kstat_kv tx_size_big;
+	/* uint64_t mac_short_pkt_dropped;	N/A */
+	/* uint32_t tx_lpi_status;		N/A */
+	/* uint32_t rx_lpi_status;		N/A */
+	/* uint64_t tx_lpi_count;		N/A */
+	/* uint64_t rx_lpi_count;		N/A */
+};
+
+static const struct ice_kstat_port_counters ice_kstat_port_counters_tpl = {
+	KSTAT_KV_UNIT_INITIALIZER("rx bytes", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_BYTES),
+	KSTAT_KV_UNIT_INITIALIZER("rx unicast", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx multicast", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx broadcast", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx discards", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("tx bytes", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_BYTES),
+	KSTAT_KV_UNIT_INITIALIZER("tx unicast", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("tx multicast", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("tx broadcast", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("tx drop no link", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("crc errors", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("illegal bytes", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("mac local errs", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_NONE),
+	KSTAT_KV_UNIT_INITIALIZER("mac remote errs", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_NONE),
+	KSTAT_KV_UNIT_INITIALIZER("rx len errors", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("link xon rx", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("link xoff rx", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("link xon tx", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("link xoff tx", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx size 64", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx size 127", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx size 255", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx size 511", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx size 1023", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx size 1522", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx size big", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx undersize", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx fragments", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx oversize", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx jabber", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("tx size 64", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("tx size 127", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("tx size 255", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("tx size 511", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("tx size 1023", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("tx size 1522", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("tx size big", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+};
+
+int
+ice_kstat_port_counters_copy(struct kstat *ks, void *dst)
+{
+	struct ice_softc *sc = ks->ks_softc;
+	struct ice_kstat_port_counters *data = dst;
+
+	*data = ice_kstat_port_counters_tpl;
+
+#define ICE_COPY_KSTAT_U64_PATH(path, name) \
+	kstat_kv_u64(&data->name) = sc->stats.cur.path.name
+
+#define ICE_COPY_KSTAT_U64(name) \
+	kstat_kv_u64(&data->name) = sc->stats.cur.name
+
+	ICE_COPY_KSTAT_U64_PATH(eth, rx_bytes);
+	ICE_COPY_KSTAT_U64_PATH(eth, rx_unicast);
+	ICE_COPY_KSTAT_U64_PATH(eth, rx_multicast);
+	ICE_COPY_KSTAT_U64_PATH(eth, rx_broadcast);
+	ICE_COPY_KSTAT_U64_PATH(eth, rx_discards);
+	ICE_COPY_KSTAT_U64_PATH(eth, tx_bytes);
+	ICE_COPY_KSTAT_U64_PATH(eth, tx_unicast);
+	ICE_COPY_KSTAT_U64_PATH(eth, tx_multicast);
+	ICE_COPY_KSTAT_U64_PATH(eth, tx_broadcast);
+
+	ICE_COPY_KSTAT_U64(tx_dropped_link_down);
+	ICE_COPY_KSTAT_U64(crc_errors);
+	ICE_COPY_KSTAT_U64(illegal_bytes);
+	ICE_COPY_KSTAT_U64(mac_local_faults);
+	ICE_COPY_KSTAT_U64(mac_remote_faults);
+	ICE_COPY_KSTAT_U64(rx_len_errors);
+	ICE_COPY_KSTAT_U64(link_xon_rx);
+	ICE_COPY_KSTAT_U64(link_xoff_rx);
+	ICE_COPY_KSTAT_U64(link_xon_tx);
+	ICE_COPY_KSTAT_U64(link_xoff_tx);
+	ICE_COPY_KSTAT_U64(rx_size_64);
+	ICE_COPY_KSTAT_U64(rx_size_127);
+	ICE_COPY_KSTAT_U64(rx_size_255);
+	ICE_COPY_KSTAT_U64(rx_size_511);
+	ICE_COPY_KSTAT_U64(rx_size_1023);
+	ICE_COPY_KSTAT_U64(rx_size_1522);
+	ICE_COPY_KSTAT_U64(rx_size_big);
+	ICE_COPY_KSTAT_U64(rx_undersize);
+	ICE_COPY_KSTAT_U64(rx_fragments);
+	ICE_COPY_KSTAT_U64(rx_oversize);
+	ICE_COPY_KSTAT_U64(rx_jabber);
+	ICE_COPY_KSTAT_U64(tx_size_64);
+	ICE_COPY_KSTAT_U64(tx_size_127);
+	ICE_COPY_KSTAT_U64(tx_size_255);
+	ICE_COPY_KSTAT_U64(tx_size_511);
+	ICE_COPY_KSTAT_U64(tx_size_1023);
+	ICE_COPY_KSTAT_U64(tx_size_1522);
+	ICE_COPY_KSTAT_U64(tx_size_big);
+
+#undef ICE_COPY_KSTAT_U64_PATH
+#undef ICE_COPY_KSTAT_U64
+
+	return (0);
+}
+
+/* Synced with struct ice_eth_stats */
+struct ice_kstat_vsi_counters {
+	struct kstat_kv rx_bytes;
+	struct kstat_kv rx_unicast;
+	struct kstat_kv rx_multicast;
+	struct kstat_kv rx_broadcast;
+	struct kstat_kv rx_discards;
+	/* uint64_t rx_unknown_protocol;	N/A */
+	struct kstat_kv tx_bytes;
+	struct kstat_kv tx_unicast;
+	struct kstat_kv tx_multicast;
+	struct kstat_kv tx_broadcast;
+	/* uint64_t tx_discards;		N/A */
+	struct kstat_kv tx_errors;
+	struct kstat_kv rx_no_desc;
+	struct kstat_kv rx_errors;
+};
+
+struct ice_kstat_vsi_counters ice_kstat_vsi_counters_tpl = {
+	KSTAT_KV_UNIT_INITIALIZER("rx bytes", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_BYTES),
+	KSTAT_KV_UNIT_INITIALIZER("rx unicast", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx multicast", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx broadcast", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx discards", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("tx bytes", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_BYTES),
+	KSTAT_KV_UNIT_INITIALIZER("tx unicast", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("tx multicast", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("tx broadcast", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("tx errors", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx no desc", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+	KSTAT_KV_UNIT_INITIALIZER("rx errors", KSTAT_KV_T_COUNTER64,
+	    KSTAT_KV_U_PACKETS),
+};
+
+int
+ice_kstat_vsi_counters_copy(struct kstat *ks, void *dst)
+{
+	struct ice_softc *sc = ks->ks_softc;
+	struct ice_kstat_vsi_counters *data = dst;
+
+	*data = ice_kstat_vsi_counters_tpl;
+
+#define ICE_COPY_KSTAT_U64(name) \
+	kstat_kv_u64(&data->name) = sc->pf_vsi.hw_stats.cur.name
+
+	ICE_COPY_KSTAT_U64(rx_bytes);
+	ICE_COPY_KSTAT_U64(rx_unicast);
+	ICE_COPY_KSTAT_U64(rx_multicast);
+	ICE_COPY_KSTAT_U64(rx_broadcast);
+	ICE_COPY_KSTAT_U64(rx_discards);
+	ICE_COPY_KSTAT_U64(tx_bytes);
+	ICE_COPY_KSTAT_U64(tx_unicast);
+	ICE_COPY_KSTAT_U64(tx_multicast);
+	ICE_COPY_KSTAT_U64(tx_broadcast);
+	ICE_COPY_KSTAT_U64(tx_errors);
+	ICE_COPY_KSTAT_U64(rx_no_desc);
+	ICE_COPY_KSTAT_U64(rx_errors);
+
+#undef ICE_COPY_KSTAT_U64
+
+	return (0);
+}
+
+#endif /* NKSTAT > 0 */
+
 /**
  * ice_if_update_admin_status - update admin status
  * @ctx: iflib ctx structure
@@ -30483,6 +30763,36 @@ ice_init_link_configuration(struct ice_s
 	}
 }
 
+#if NKSTAT > 0
+
+int
+ice_kstat_attach(struct ice_softc *sc)
+{
+	sc->sc_kstat_port = kstat_create(sc->sc_dev.dv_xname, 0, "ice-port", 0,
+	    KSTAT_T_KV, 0);
+	if (sc->sc_kstat_port == NULL)
+		return (-1);
+
+	sc->sc_kstat_port->ks_softc = sc;
+	sc->sc_kstat_port->ks_datalen = sizeof(ice_kstat_port_counters_tpl);
+	sc->sc_kstat_port->ks_copy = ice_kstat_port_counters_copy;
+	kstat_install(sc->sc_kstat_port);
+
+	sc->sc_kstat_vsi = kstat_create(sc->sc_dev.dv_xname, 0, "ice-vsi", 0,
+	    KSTAT_T_KV, 0);
+	if (sc->sc_kstat_vsi == NULL)
+		return (-1);
+
+	sc->sc_kstat_vsi->ks_softc = sc;
+	sc->sc_kstat_vsi->ks_datalen = sizeof(ice_kstat_vsi_counters_tpl);
+	sc->sc_kstat_vsi->ks_copy = ice_kstat_vsi_counters_copy;
+	kstat_install(sc->sc_kstat_vsi);
+
+	return (0);
+}
+
+#endif
+
 void
 ice_attach_hook(struct device *self)
 {
@@ -30727,6 +31037,11 @@ ice_attach_hook(struct device *self)
 	if (err)
 		printf("%s: could not set MAC address (error %d)\n",
 		    sc->sc_dev.dv_xname, err);
+
+#if NKSTAT > 0
+	if (ice_kstat_attach(sc))
+		printf("%s: could not attach to kstat\n", sc->sc_dev.dv_xname);
+#endif
 
 	ice_clear_state(&sc->state, ICE_STATE_ATTACHING);
 	return;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.