Skip to contentSkip to conversation

net/mlx5: add hardware query for basic stats

PATCH In review Rayane Boussanni 2 participants 2 messages Apr 16 – Nov 8 Network drivers

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 net/mlx5: add hardware query for basic stats

When MLX5_PMD_SOFT_COUNTERS is not defined, the basic dev statistics (rte_eth_stats) previously fell back to returning zeroed values for all packet and byte metrics.

This patch resolves the FIXMEs in mlx5_stats_get and mlx5_stats_reset by falling back to the target's dev counters map. It utilizes mlx5_os_read_dev_counters to retrieve the bulk arrays from the hardware and strategically filters them against the xstats_ctrl index to summarize the basic opackets, obytes, ipackets, ibytes, oerrors, and ierrors without duplicating the context-switch overhead.

---
 drivers/net/mlx5/mlx5_stats.c | 57 +++++++++++++++++++++++++++++++++--
 1 file changed, 55 insertions(+), 2 deletions(-)
drivers/net/mlx5/mlx5_stats.c +55 -2
index 5cd3e303cc..198f231559 100644
@@ -280,7 +280,46 @@ mlx5_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats,
 		tmp.imissed = stats_ctrl->imissed;
 	}
 #ifndef MLX5_PMD_SOFT_COUNTERS
-	/* FIXME: retrieve and add hardware counters. */
+	{
+		uint64_t counters[MLX5_MAX_XSTATS];
+		struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
+		bool bond_master = (priv->master && priv->pf_bond >= 0);
+
+		ret = mlx5_os_read_dev_counters(dev, bond_master, counters);
+		if (ret) {
+			DRV_LOG(WARNING, "port %u unable to read device counters",
+				dev->data->port_id);
+			return ret;
+		}
+		for (i = 0; i != xstats_ctrl->mlx5_stats_n; ++i) {
+			const char *name = xstats_ctrl->info[i].dpdk_name;
+			uint64_t val = (counters[i] - xstats_ctrl->base[i]);
+
+			if (!strcmp(name, "rx_unicast_packets") ||
+			    !strcmp(name, "rx_multicast_packets") ||
+			    !strcmp(name, "rx_broadcast_packets"))
+				tmp.ipackets += val;
+			else if (!strcmp(name, "rx_unicast_bytes") ||
+				 !strcmp(name, "rx_multicast_bytes") ||
+				 !strcmp(name, "rx_broadcast_bytes"))
+				tmp.ibytes += val;
+			else if (!strcmp(name, "tx_unicast_packets") ||
+				 !strcmp(name, "tx_multicast_packets") ||
+				 !strcmp(name, "tx_broadcast_packets"))
+				tmp.opackets += val;
+			else if (!strcmp(name, "tx_unicast_bytes") ||
+				 !strcmp(name, "tx_multicast_bytes") ||
+				 !strcmp(name, "tx_broadcast_bytes"))
+				tmp.obytes += val;
+			else if (!strcmp(name, "rx_wqe_errors") ||
+				 !strcmp(name, "rx_phy_crc_errors") ||
+				 !strcmp(name, "rx_phy_in_range_len_errors") ||
+				 !strcmp(name, "rx_phy_symbol_errors"))
+				tmp.ierrors += val;
+			else if (!strcmp(name, "tx_phy_errors"))
+				tmp.oerrors += val;
+		}
+	}
 #endif
 	*stats = tmp;
 	return 0;
@@ -319,7 +358,21 @@ mlx5_stats_reset(struct rte_eth_dev *dev)
 	mlx5_os_read_dev_stat(priv, "out_of_buffer", &stats_ctrl->imissed_base);
 	stats_ctrl->imissed = 0;
 #ifndef MLX5_PMD_SOFT_COUNTERS
-	/* FIXME: reset hardware counters. */
+	{
+		uint64_t counters[MLX5_MAX_XSTATS];
+		struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
+		bool bond_master = (priv->master && priv->pf_bond >= 0);
+		int ret;
+
+		ret = mlx5_os_read_dev_counters(dev, bond_master, counters);
+		if (ret) {
+			DRV_LOG(WARNING, "port %u unable to read device counters",
+				dev->data->port_id);
+			return ret;
+		}
+		for (i = 0; i != xstats_ctrl->mlx5_stats_n; ++i)
+			xstats_ctrl->base[i] = counters[i];
+	}
 #endif
 
 	return 0;
Signature · 1 line
2.34.1
#1 lore raw

Hi Rayane,

Thanks for working on this. Unfortunately the patch cannot be accepted in its current form. Please see the comments below.

Quoted 32 lines

-----Original Message-----
From: Rayane Boussanni <[email protected]>
Sent: Friday, April 17, 2026 6:40 AM
To: [email protected]
Cc: Raslan Darawsheh <[email protected]>; Rayane Boussanni <[email protected]>
Subject: [PATCH] net/mlx5: add hardware query for basic stats

External email: Use caution opening links or attachments

When MLX5_PMD_SOFT_COUNTERS is not defined, the basic dev statistics (rte_eth_stats) previously fell back to returning zeroed values for all packet and byte metrics.

This patch resolves the FIXMEs in mlx5_stats_get and mlx5_stats_reset by falling back to the target's dev counters map. It utilizes mlx5_os_read_dev_counters to retrieve the bulk arrays from the hardware and strategically filters them against the xstats_ctrl index to summarize the basic opackets, obytes, ipackets, ibytes, oerrors, and ierrors without duplicating the context-switch overhead.

---
 drivers/net/mlx5/mlx5_stats.c | 57 +++++++++++++++++++++++++++++++++--
 1 file changed, 55 insertions(+), 2 deletions(-)
drivers/net/mlx5/mlx5_stats.c +0 -0
index 5cd3e303cc..198f231559 100644

drivers/net/mlx5/mlx5_stats.c mlx5_stats_get(struct rte_eth_dev *dev, struct · line 285

Quoted 7 lines
drivers/net/mlx5/mlx5_stats.c +2 -1
@@ -280,7 +280,46 @@ mlx5_stats_get(struct rte_eth_dev *dev, struct
 rte_eth_stats *stats,
                tmp.imissed = stats_ctrl->imissed;
        }
 #ifndef MLX5_PMD_SOFT_COUNTERS
-       /* FIXME: retrieve and add hardware counters. */
+       {
+               uint64_t counters[MLX5_MAX_XSTATS];

1. The new code is never compiled. drivers/net/mlx5/mlx5_defs.h defines MLX5_PMD_SOFT_COUNTERS to 1 whenever it is not already defined, so both new #ifndef blocks are always excluded. Neither -DMLX5_PMD_SOFT_COUNTERS=0 nor -UMLX5_PMD_SOFT_COUNTERS changes this, so the patch has no effect in any supported build.

A supported way to select hardware counters is needed first. Note also that the non-soft-counter configuration already fails with -Werror, because of the unused "ntcp" variables in mlx5_tx_packet_multi_tso() and mlx5_tx_burst_tso() in mlx5_tx.h. That is not caused by your patch, but it shows this mode is not currently built or tested.

Quoted 5 lines
drivers/net/mlx5/mlx5_stats.c +4 -0
+               struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
+               bool bond_master = (priv->master && priv->pf_bond >= 0);
+
+               ret = mlx5_os_read_dev_counters(dev, bond_master,
 counters);

drivers/net/mlx5/mlx5_stats.c mlx5_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats,

Quoted 10 lines
drivers/net/mlx5/mlx5_stats.c +9 -0
+               if (ret) {
+                       DRV_LOG(WARNING, "port %u unable to read device
 counters",
+                               dev->data->port_id);
+                       return ret;
+               }
+               for (i = 0; i != xstats_ctrl->mlx5_stats_n; ++i) {
+                       const char *name = xstats_ctrl->info[i].dpdk_name;
+                       uint64_t val = (counters[i] -
+ xstats_ctrl->base[i]);

2. mlx5_stats_reset() overwrites the xstats baselines but does not reset xstats_ctrl->hw_stats[], which mlx5_xstats_get() uses for 32-bit wrap tracking of device counters. After a basic stats reset with unchanged hardware counters, rx_out_of_buffer is reported as 4294967296. Please either perform a complete, consistent reset (as in mlx5_xstats_reset()) or keep separate baselines for the basic statistics.

Quoted 40 lines
drivers/net/mlx5/mlx5_stats.c +20 -0
+
+                       if (!strcmp(name, "rx_unicast_packets") ||
+                           !strcmp(name, "rx_multicast_packets") ||
+                           !strcmp(name, "rx_broadcast_packets"))
+                               tmp.ipackets += val;
+                       else if (!strcmp(name, "rx_unicast_bytes") ||
+                                !strcmp(name, "rx_multicast_bytes") ||
+                                !strcmp(name, "rx_broadcast_bytes"))
+                               tmp.ibytes += val;
+                       else if (!strcmp(name, "tx_unicast_packets") ||
+                                !strcmp(name, "tx_multicast_packets") ||
+                                !strcmp(name, "tx_broadcast_packets"))
+                               tmp.opackets += val;
+                       else if (!strcmp(name, "tx_unicast_bytes") ||
+                                !strcmp(name, "tx_multicast_bytes") ||
+                                !strcmp(name, "tx_broadcast_bytes"))
+                               tmp.obytes += val;
+                       else if (!strcmp(name, "rx_wqe_errors") ||
+                                !strcmp(name, "rx_phy_crc_errors") ||
+                                !strcmp(name,

"rx_phy_in_range_len_errors") ||

drivers/net/mlx5/mlx5_stats.c +10 -1
+                                !strcmp(name, "rx_phy_symbol_errors"))
+                               tmp.ierrors += val;
+                       else if (!strcmp(name, "tx_phy_errors"))
+                               tmp.oerrors += val;
+               }
+       }
 #endif
        *stats = tmp;
        return 0;
@@ -319,7 +358,21 @@ mlx5_stats_reset(struct rte_eth_dev *dev)
        mlx5_os_read_dev_stat(priv, "out_of_buffer", &stats_ctrl-
 >imissed_base);
        stats_ctrl->imissed = 0;
 #ifndef MLX5_PMD_SOFT_COUNTERS
-       /* FIXME: reset hardware counters. */
+       {
+               uint64_t counters[MLX5_MAX_XSTATS];
+               struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
+               bool bond_master = (priv->master && priv->pf_bond >= 0);

drivers/net/mlx5/mlx5_stats.c mlx5_stats_reset(struct rte_eth_dev *dev) · line 375

Quoted 10 lines
drivers/net/mlx5/mlx5_stats.c +8 -0
+               int ret;
+
+               ret = mlx5_os_read_dev_counters(dev, bond_master,
 counters);
+               if (ret) {
+                       DRV_LOG(WARNING, "port %u unable to read device
 counters",
+                               dev->data->port_id);
+                       return ret;
+               }

3. On Windows, mlx5_os_read_dev_counters() always returns -ENOTSUP. Once this path is enabled, rte_eth_stats_get() and rte_eth_stats_reset() would fail completely there, instead of still returning the statistics that are available today. An unsupported backend should be handled gracefully.

Quoted 4 lines
drivers/net/mlx5/mlx5_stats.c +3 -0
+               for (i = 0; i != xstats_ctrl->mlx5_stats_n; ++i)
+                       xstats_ctrl->base[i] = counters[i];
+       }

#endif

4. This changes what the basic statistics mean. The vport counters also include traffic received or sent by the Linux kernel (bifurcated driver), while doc/guides/nics/mlx5.rst says the basic Rx/Tx statistics count only packets handled by the PMD. If this is intended, the documentation must be updated and the change in behaviour explained in the commit message.

My AI tool checked this by compiling mlx5_stats.c in both the default configuration and with the hardware branch forced on, and by running the patched get/reset callbacks in a small harness with the device reads stubbed out. I did not run it on hardware.

For a v2, I'd suggest agreeing first on how hardware basic statistics should be selected, then addressing the points above. Please include the documentation update and test results on Linux (including bonding) and Windows.

Quoted 4 lines
        return 0;

--
2.34.1