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 <[email protected]>
---
 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

Reply via email to