From: Jan Klemkow Subject: ice(4): add kstat counter To: tech@openbsd.org Date: Tue, 7 Jul 2026 23:10:09 +0200 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 #include @@ -70,6 +71,10 @@ #include #include +#if NKSTAT > 0 +#include +#endif + #include #include #include @@ -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;