DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Stephen Hemminger <stephen@networkplumber.org>
To: dev@dpdk.org
Cc: Stephen Hemminger <stephen@networkplumber.org>,
	Bruce Richardson <bruce.richardson@intel.com>
Subject: [PATCH v3 16/16] test/pmd_ring: test per-queue xstats
Date: Thu, 13 Aug 2026 10:55:15 -0700	[thread overview]
Message-ID: <20260813180402.622784-17-stephen@networkplumber.org> (raw)
In-Reply-To: <20260813180402.622784-1-stephen@networkplumber.org>

Add a test that per-queue xstats are reported for every configured
queue, and only for those. Uses different Rx and Tx queue counts so
that each direction is checked independently.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test/test_pmd_ring.c | 145 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 145 insertions(+)

diff --git a/app/test/test_pmd_ring.c b/app/test/test_pmd_ring.c
index cb08dcf1d9..e7682906df 100644
--- a/app/test/test_pmd_ring.c
+++ b/app/test/test_pmd_ring.c
@@ -4,7 +4,10 @@
 #include "test.h"
 #include <string.h>
 
+#include <inttypes.h>
+#include <stdbool.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 #include <rte_eth_ring.h>
 #include <rte_ethdev.h>
@@ -557,6 +560,147 @@ test_ethdev_configure_ports(void)
 	return TEST_SUCCESS;
 }
 
+/*
+ * Per-queue xstats are added by ethdev for all configured queues.
+ * Use a port with different Rx and Tx queue counts to check that each
+ * direction is reported independently.
+ */
+#define QSTATS_NB_RXQ 3
+#define QSTATS_NB_TXQ 5
+#define QSTATS_NB_RINGS RTE_MAX(QSTATS_NB_RXQ, QSTATS_NB_TXQ)
+
+static int
+test_queue_xstats(void)
+{
+	struct rte_ring *qrings[QSTATS_NB_RINGS] = { };
+	struct rte_eth_xstat_name *names = NULL;
+	struct rte_eth_xstat *xstats = NULL;
+	struct rte_eth_conf null_conf;
+	unsigned int i, nb_names, found;
+	char expected[RTE_ETH_XSTATS_NAME_SIZE];
+	int port = -1, nb_xstats, ret = -1;
+	uint16_t q;
+
+	for (q = 0; q < QSTATS_NB_RINGS; q++) {
+		char name[RTE_RING_NAMESIZE];
+
+		snprintf(name, sizeof(name), "RQ%u", q);
+		qrings[q] = rte_ring_create(name, RING_SIZE, SOCKET0,
+				RING_F_SP_ENQ | RING_F_SC_DEQ);
+		if (qrings[q] == NULL) {
+			printf("rte_ring_create %s failed\n", name);
+			goto out;
+		}
+	}
+
+	port = rte_eth_from_rings("net_ringq", qrings, QSTATS_NB_RXQ,
+			qrings, QSTATS_NB_TXQ, SOCKET0);
+	if (port < 0) {
+		printf("failed to create port\n");
+		goto out;
+	}
+
+	memset(&null_conf, 0, sizeof(null_conf));
+	if (rte_eth_dev_configure(port, QSTATS_NB_RXQ, QSTATS_NB_TXQ,
+			&null_conf) < 0) {
+		printf("configure failed\n");
+		goto out;
+	}
+
+	for (q = 0; q < QSTATS_NB_RXQ; q++) {
+		if (rte_eth_rx_queue_setup(port, q, RING_SIZE, SOCKET0,
+				NULL, mp) < 0) {
+			printf("Rx queue %u setup failed\n", q);
+			goto out;
+		}
+	}
+	for (q = 0; q < QSTATS_NB_TXQ; q++) {
+		if (rte_eth_tx_queue_setup(port, q, RING_SIZE, SOCKET0,
+				NULL) < 0) {
+			printf("Tx queue %u setup failed\n", q);
+			goto out;
+		}
+	}
+
+	nb_xstats = rte_eth_xstats_get_names(port, NULL, 0);
+	if (nb_xstats <= 0) {
+		printf("no xstats reported\n");
+		goto out;
+	}
+
+	names = calloc(nb_xstats, sizeof(*names));
+	xstats = calloc(nb_xstats, sizeof(*xstats));
+	if (names == NULL || xstats == NULL) {
+		printf("out of memory\n");
+		goto out;
+	}
+
+	nb_names = rte_eth_xstats_get_names(port, names, nb_xstats);
+	if (nb_names != (unsigned int)nb_xstats) {
+		printf("got %u names, expected %d\n", nb_names, nb_xstats);
+		goto out;
+	}
+
+	if (rte_eth_xstats_get(port, xstats, nb_xstats) != nb_xstats) {
+		printf("xstats count does not match names count\n");
+		goto out;
+	}
+
+	/* No traffic has passed, so every counter must still be zero. */
+	for (i = 0; i < (unsigned int)nb_xstats; i++) {
+		if (xstats[i].value != 0) {
+			printf("xstat '%s' is %"PRIu64", expected 0\n",
+					names[xstats[i].id].name, xstats[i].value);
+			goto out;
+		}
+	}
+
+	/* Every configured queue must have its counters, in both directions. */
+	for (q = 0; q < QSTATS_NB_RXQ + QSTATS_NB_TXQ; q++) {
+		bool rx = q < QSTATS_NB_RXQ;
+
+		snprintf(expected, sizeof(expected), "%s_q%u_packets",
+				rx ? "rx" : "tx", rx ? q : q - QSTATS_NB_RXQ);
+
+		for (i = 0, found = 0; i < nb_names; i++)
+			if (strcmp(names[i].name, expected) == 0)
+				found++;
+
+		if (found != 1) {
+			printf("expected one '%s', got %u\n", expected, found);
+			goto out;
+		}
+	}
+
+	/* Queues beyond the configured count must not be reported. */
+	snprintf(expected, sizeof(expected), "rx_q%u_packets", QSTATS_NB_RXQ);
+	for (i = 0; i < nb_names; i++) {
+		if (strcmp(names[i].name, expected) == 0) {
+			printf("unexpected stat '%s'\n", expected);
+			goto out;
+		}
+	}
+
+	snprintf(expected, sizeof(expected), "tx_q%u_packets", QSTATS_NB_TXQ);
+	for (i = 0; i < nb_names; i++) {
+		if (strcmp(names[i].name, expected) == 0) {
+			printf("unexpected stat '%s'\n", expected);
+			goto out;
+		}
+	}
+
+	ret = TEST_SUCCESS;
+out:
+	free(names);
+	free(xstats);
+	if (port >= 0)
+		rte_eth_dev_close(port);
+	for (q = 0; q < QSTATS_NB_RINGS; q++)
+		rte_ring_free(qrings[q]);
+
+	return ret;
+}
+
 static int
 test_get_stats_for_port(void)
 {
@@ -581,6 +725,7 @@ unit_test_suite test_pmd_ring_suite  = {
 		TEST_CASE(test_send_basic_packets),
 		TEST_CASE(test_get_stats_for_port),
 		TEST_CASE(test_stats_reset_for_port),
+		TEST_CASE(test_queue_xstats),
 		TEST_CASE(test_pmd_ring_pair_create_attach),
 		TEST_CASE(test_command_line_ring_port),
 		TEST_CASES_END()
-- 
2.53.0


      parent reply	other threads:[~2026-08-13 18:05 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-30 16:09 [RFC 0/7] Complete removal of queue stats mapping Stephen Hemminger
2026-05-30 16:09 ` [RFC 1/7] net/virtio: remove unused " Stephen Hemminger
2026-05-30 16:09 ` [RFC 2/7] net/enic: remove queue_stats_mapping ethdev_op Stephen Hemminger
2026-05-30 16:09 ` [RFC 3/7] net/cnxk: remove queue stats mapping Stephen Hemminger
2026-05-30 16:09 ` [RFC 4/7] net/e1000: " Stephen Hemminger
2026-05-30 16:10 ` [RFC 5/7] net/ixgbe: " Stephen Hemminger
2026-05-30 16:10 ` [RFC 6/7] net/txgbe: " Stephen Hemminger
2026-05-30 16:10 ` [RFC 7/7] ethdev: remove support for " Stephen Hemminger
2026-06-01  1:56   ` fengchengwen
2026-06-01  8:45   ` Andrew Rybchenko
2026-07-23 20:28 ` [PATCH v2 0/9] Complete removal of " Stephen Hemminger
2026-07-23 20:28   ` [PATCH v2 1/9] net/virtio: remove unused " Stephen Hemminger
2026-07-23 20:28   ` [PATCH v2 2/9] app/testpmd: remove unused function prototype Stephen Hemminger
2026-07-23 20:28   ` [PATCH v2 3/9] net/enic: remove unneeded ops initialization Stephen Hemminger
2026-07-24  1:52     ` Hyong Youb Kim (hyonkim)
2026-07-23 20:28   ` [PATCH v2 4/9] net/cnxk: remove queue stats mapping Stephen Hemminger
2026-07-24  7:26     ` David Marchand
2026-07-24 15:20       ` Stephen Hemminger
2026-07-23 20:28   ` [PATCH v2 5/9] net/e1000: " Stephen Hemminger
2026-07-24  7:31     ` David Marchand
2026-08-13 12:26       ` Bruce Richardson
2026-07-23 20:28   ` [PATCH v2 6/9] net/ixgbe: " Stephen Hemminger
2026-07-23 20:28   ` [PATCH v2 7/9] net/txgbe: " Stephen Hemminger
2026-07-23 20:28   ` [PATCH v2 8/9] net/sxe2: " Stephen Hemminger
2026-07-23 20:28   ` [PATCH v2 9/9] ethdev: remove support for " Stephen Hemminger
2026-07-24  7:39   ` [PATCH v2 0/9] Complete removal of " David Marchand
2026-07-24  7:42   ` David Marchand
2026-07-24 15:28     ` Stephen Hemminger
2026-08-13 17:54 ` [PATCH v3 00/16] remove stats mapping an RTE_ETHDEV_QUEUE_STAT_CNTRS Stephen Hemminger
2026-08-13 17:55   ` [PATCH v3 01/16] net/virtio: remove unused queue stats mapping Stephen Hemminger
2026-08-13 17:55   ` [PATCH v3 02/16] app/testpmd: remove leftover set qmap Stephen Hemminger
2026-08-13 17:55   ` [PATCH v3 03/16] net/enic: remove unneeded ops initialization Stephen Hemminger
2026-08-13 17:55   ` [PATCH v3 04/16] net/cnxk: fix Tx drops added to Rx queue errors Stephen Hemminger
2026-08-13 17:55   ` [PATCH v3 05/16] net/cnxk: remove queue stats mapping Stephen Hemminger
2026-08-13 17:55   ` [PATCH v3 06/16] net/e1000: " Stephen Hemminger
2026-08-13 17:55   ` [PATCH v3 07/16] net/ixgbe: " Stephen Hemminger
2026-08-13 17:55   ` [PATCH v3 08/16] net/txgbe: " Stephen Hemminger
2026-08-13 17:55   ` [PATCH v3 09/16] net/sxe2: fix null dereference in stats get Stephen Hemminger
2026-08-13 17:55   ` [PATCH v3 10/16] net/sxe2: remove queue stats mapping Stephen Hemminger
2026-08-13 17:55   ` [PATCH v3 11/16] ethdev: remove support for " Stephen Hemminger
2026-08-13 17:55   ` [PATCH v3 12/16] net/mvpp2: fix out of range Tx queue stats write Stephen Hemminger
2026-08-13 17:55   ` [PATCH v3 13/16] net/ntnic: fix Tx errors reported as Rx queue errors Stephen Hemminger
2026-08-13 17:55   ` [PATCH v3 14/16] net/xsc: fix Tx errors added to " Stephen Hemminger
2026-08-13 17:55   ` [PATCH v3 15/16] ethdev: remove queue stats counter limit Stephen Hemminger
2026-08-13 17:55   ` Stephen Hemminger [this message]

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=20260813180402.622784-17-stephen@networkplumber.org \
    --to=stephen@networkplumber.org \
    --cc=bruce.richardson@intel.com \
    --cc=dev@dpdk.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox