All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephen Hemminger <stephen@networkplumber.org>
To: dev@dpdk.org
Cc: Stephen Hemminger <stephen@networkplumber.org>,
	Chas Williams <3chas3@gmail.com>,
	"Min Hu (Connor)" <humin29@huawei.com>
Subject: [PATCH 6/8] net/bonding: add extended statistics
Date: Sun, 30 Aug 2026 13:23:48 -0700	[thread overview]
Message-ID: <20260830202636.760014-7-stephen@networkplumber.org> (raw)
In-Reply-To: <20260830202636.760014-1-stephen@networkplumber.org>

The bonding device reported only the sum of its members, so there was
no way to see how traffic was distributed across them.
This patch adds xstats which reports per-member packets/bytes/errors.

Also drop RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS since driver never
implemented per-queue stats.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 doc/guides/rel_notes/release_26_11.rst |   6 ++
 drivers/net/bonding/rte_eth_bond_pmd.c | 113 ++++++++++++++++++++++++-
 2 files changed, 117 insertions(+), 2 deletions(-)

diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index 87c7e81bde..83d70872af 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -55,6 +55,12 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Added extended statistics to bonding PMD.**
+
+  Extended statistics now report the packets, bytes and errors
+  of each member as ``rx_memberN_*`` and ``tx_memberN_*``.
+  The per-queue entries, which were always zero, are no longer reported.
+
 
 Removed Items
 -------------
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index 0e18ded4a5..46bc1db120 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -2764,6 +2764,111 @@ bond_ethdev_stats_reset(struct rte_eth_dev *dev)
 	return err;
 }
 
+#define BOND_MEMBER_STAT_PREFIX_LEN (sizeof("rx_member") - 1 + 5 + 1)
+
+struct bond_member_stats_name_off {
+	char name[RTE_ETH_XSTATS_NAME_SIZE - BOND_MEMBER_STAT_PREFIX_LEN];
+	size_t offset;
+};
+
+static const struct bond_member_stats_name_off bond_member_rxq_stats_strings[] = {
+	{ "packets", offsetof(struct rte_eth_stats, ipackets) },
+	{ "bytes", offsetof(struct rte_eth_stats, ibytes) },
+	{ "errors", offsetof(struct rte_eth_stats, ierrors) },
+};
+
+#define BOND_NB_MEMBER_RX_STATS RTE_DIM(bond_member_rxq_stats_strings)
+
+static const struct bond_member_stats_name_off bond_member_txq_stats_strings[] = {
+	{ "packets", offsetof(struct rte_eth_stats, opackets) },
+	{ "bytes", offsetof(struct rte_eth_stats, obytes) },
+	{ "errors", offsetof(struct rte_eth_stats, oerrors) },
+};
+
+#define BOND_NB_MEMBER_TX_STATS RTE_DIM(bond_member_txq_stats_strings)
+
+#define BOND_NB_MEMBER_STATS (BOND_NB_MEMBER_RX_STATS + BOND_NB_MEMBER_TX_STATS)
+
+static int
+bond_ethdev_xstats_get_names(struct rte_eth_dev *dev,
+			     struct rte_eth_xstat_name *xstats_names,
+			     unsigned int limit)
+{
+	struct bond_dev_private *internals = dev->data->dev_private;
+	unsigned int count = internals->member_count * BOND_NB_MEMBER_STATS;
+	unsigned int i, j;
+
+	if (xstats_names == NULL || limit < count)
+		return count;
+
+	count = 0;
+	for (i = 0; i < internals->member_count; i++) {
+		uint16_t member_id = internals->members[i].port_id;
+
+		for (j = 0; j < BOND_NB_MEMBER_RX_STATS; j++)
+			snprintf(xstats_names[count++].name,
+				 RTE_ETH_XSTATS_NAME_SIZE, "rx_member%u_%s",
+				 member_id, bond_member_rxq_stats_strings[j].name);
+
+		for (j = 0; j < BOND_NB_MEMBER_TX_STATS; j++)
+			snprintf(xstats_names[count++].name,
+				 RTE_ETH_XSTATS_NAME_SIZE, "tx_member%u_%s",
+				 member_id, bond_member_txq_stats_strings[j].name);
+	}
+
+	return count;
+}
+
+static int
+bond_ethdev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
+		       unsigned int n)
+{
+	const struct bond_dev_private *internals = dev->data->dev_private;
+	unsigned int count = internals->member_count * BOND_NB_MEMBER_STATS;
+	unsigned int i, j;
+
+	if (xstats == NULL || n < count)
+		return count;
+
+	count = 0;
+	for (i = 0; i < internals->member_count; i++) {
+		struct rte_eth_stats member_stats;
+		uint16_t member_id = internals->members[i].port_id;
+
+		/* If member query fails just report zero. */
+		if (rte_eth_stats_get(member_id, &member_stats) < 0)
+			memset(&member_stats, 0, sizeof(member_stats));
+
+		for (j = 0; j < BOND_NB_MEMBER_RX_STATS; j++) {
+			xstats[count].id = count;
+			xstats[count].value = *(const uint64_t *)((const char *)&member_stats +
+					bond_member_rxq_stats_strings[j].offset);
+			count++;
+		}
+
+		for (j = 0; j < BOND_NB_MEMBER_TX_STATS; j++) {
+			xstats[count].id = count;
+			xstats[count].value = *(const uint64_t *)((const char *)&member_stats +
+					bond_member_txq_stats_strings[j].offset);
+			count++;
+		}
+	}
+
+	return count;
+}
+
+static int
+bond_ethdev_xstats_reset(struct rte_eth_dev *dev)
+{
+	const struct bond_dev_private *internals = dev->data->dev_private;
+	uint16_t i;
+
+	for (i = 0; i < internals->member_count; i++)
+		rte_eth_stats_reset(internals->members[i].port_id);
+
+	return 0;
+}
+
 static int
 bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev)
 {
@@ -3710,6 +3815,8 @@ static const struct eth_dev_ops secondary_dev_ops = {
 	.dev_infos_get        = bond_ethdev_info,
 	.link_update          = bond_ethdev_link_update,
 	.stats_get            = bond_ethdev_stats_get,
+	.xstats_get           = bond_ethdev_xstats_get,
+	.xstats_get_names     = bond_ethdev_xstats_get_names,
 	.reta_query           = bond_ethdev_rss_reta_query,
 	.rss_hash_conf_get    = bond_ethdev_rss_hash_conf_get,
 	.eth_dev_priv_dump    = bond_ethdev_priv_dump,
@@ -3729,6 +3836,9 @@ const struct eth_dev_ops default_dev_ops = {
 	.link_update          = bond_ethdev_link_update,
 	.stats_get            = bond_ethdev_stats_get,
 	.stats_reset          = bond_ethdev_stats_reset,
+	.xstats_get           = bond_ethdev_xstats_get,
+	.xstats_get_names     = bond_ethdev_xstats_get_names,
+	.xstats_reset         = bond_ethdev_xstats_reset,
 	.promiscuous_enable   = bond_ethdev_promiscuous_enable,
 	.promiscuous_disable  = bond_ethdev_promiscuous_disable,
 	.allmulticast_enable  = bond_ethdev_allmulticast_enable,
@@ -3780,8 +3890,7 @@ bond_alloc(struct rte_vdev_device *dev, uint8_t mode)
 	}
 
 	eth_dev->dev_ops = &default_dev_ops;
-	eth_dev->data->dev_flags = RTE_ETH_DEV_INTR_LSC |
-					RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
+	eth_dev->data->dev_flags = RTE_ETH_DEV_INTR_LSC;
 
 	rte_spinlock_init(&internals->lock);
 	rte_spinlock_init(&internals->lsc_lock);
-- 
2.53.0


  parent reply	other threads:[~2026-08-30 20:27 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-08 17:42 [RFC PATCH] net/bonding: reject control operations in secondary Weijun Pan
2026-07-22 23:10 ` Stephen Hemminger
2026-07-26 17:32 ` Stephen Hemminger
2026-08-23 15:16 ` [RFC PATCH v2] net/bonding: restrict secondary control operations Weijun Pan
2026-08-23 15:43   ` Stephen Hemminger
2026-08-24  2:39     ` Weijun Pan
2026-08-24 16:15   ` Stephen Hemminger
2026-08-26 16:10   ` [RFC PATCH v3] " Weijun Pan
2026-08-26 17:53     ` Stephen Hemminger
2026-08-30  1:14     ` [RFC PATCH v4 1/2] net/bonding: skip unavailable member stats Weijun Pan
2026-08-30  1:14       ` [RFC PATCH v4 2/2] net/bonding: restrict secondary control operations Weijun Pan
2026-08-30  4:29         ` Stephen Hemminger
2026-08-30  4:22       ` [RFC PATCH v4 1/2] net/bonding: skip unavailable member stats Stephen Hemminger
2026-08-30 16:35       ` [RFC PATCH v5 " Weijun Pan
2026-08-30 16:35         ` [RFC PATCH v5 2/2] net/bonding: restrict secondary control operations Weijun Pan
2026-08-30 20:23 ` [PATCH 0/8] net/bonding: fixes and per-member statistics Stephen Hemminger
2026-08-30 20:23   ` [PATCH 1/8] net/bonding: fix TLB member ordering with unusable member Stephen Hemminger
2026-08-30 20:23   ` [PATCH 2/8] net/bonding: skip unavailable member stats Stephen Hemminger
2026-08-30 20:23   ` [PATCH 3/8] net/bonding: skip unavailable members in device info Stephen Hemminger
2026-08-30 20:23   ` [PATCH 4/8] net/bonding: use atomic link status accessors Stephen Hemminger
2026-08-30 20:23   ` [PATCH 5/8] net/bonding: restrict control operations in secondary process Stephen Hemminger
2026-08-30 20:23   ` Stephen Hemminger [this message]
2026-08-30 20:23   ` [PATCH 7/8] test/bonding: add extended statistics test Stephen Hemminger
2026-08-30 20:23   ` [PATCH 8/8] doc: add bonding features matrix Stephen Hemminger
2026-08-31 16:06 ` [PATCH v2 0/8] net/bonding: fixes and per-member stats Stephen Hemminger
2026-08-31 16:06   ` [PATCH v2 1/8] net/bonding: fix TLB member ordering with unusable member Stephen Hemminger
2026-08-31 16:06   ` [PATCH v2 2/8] net/bonding: skip unavailable member stats Stephen Hemminger
2026-08-31 16:06   ` [PATCH v2 3/8] net/bonding: skip unavailable members in device info Stephen Hemminger
2026-08-31 16:06   ` [PATCH v2 4/8] net/bonding: use atomic link status accessors Stephen Hemminger
2026-08-31 16:06   ` [PATCH v2 5/8] net/bonding: restrict control ops in secondary process Stephen Hemminger
2026-08-31 16:06   ` [PATCH v2 6/8] net/bonding: add extended statistics Stephen Hemminger
2026-08-31 16:06   ` [PATCH v2 7/8] test/bonding: add extended statistics test Stephen Hemminger
2026-08-31 16:06   ` [PATCH v2 8/8] doc: add bonding features matrix Stephen Hemminger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260830202636.760014-7-stephen@networkplumber.org \
    --to=stephen@networkplumber.org \
    --cc=3chas3@gmail.com \
    --cc=dev@dpdk.org \
    --cc=humin29@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.