The forwarding loop was bounded by a fixed interval of 0.5ms
but on slow or emulated platforms with a low-frequency timebase
(e.g. RISC-V rdtime) this fails because the loop only ran once.
The test needs two iterations to get any samples.

Rearrange the forwarding loop so that a minimum number of iterations
are required. The loop still has an upper bound on packets and time
interval which is expanded to 10 ms.

If no samples are collected, mark the test as skipped.
Refactor the forwarding loop test so that cleanup happens on
failure.

Reported-by: Luca Boccassi <[email protected]>
Fixes: b34508b9cbcd ("test/latency: update with more checks")
Cc: [email protected]

Signed-off-by: Stephen Hemminger <[email protected]>
---
 app/test/test_latencystats.c | 75 ++++++++++++++++++++++--------------
 1 file changed, 46 insertions(+), 29 deletions(-)

diff --git a/app/test/test_latencystats.c b/app/test/test_latencystats.c
index e0483e3e4f..76498b66b4 100644
--- a/app/test/test_latencystats.c
+++ b/app/test/test_latencystats.c
@@ -16,6 +16,10 @@
 
 #define NUM_STATS 5
 #define LATENCY_NUM_PACKETS 10
+#define LATENCY_FORWARD_ITERATIONS 10000u
+#define LATENCY_FORWARD_MS 10u
+#define MIN_ITERATIONS 10u
+
 #define QUEUE_ID 0
 
 static uint16_t portid;
@@ -140,28 +144,13 @@ static void test_latency_ring_free(void)
        test_vdev_uninit("net_ring_net_ringa");
 }
 
-static int test_latency_packet_forward(void)
+static int test_forward_loop(uint16_t portid, struct rte_mbuf 
*pbuf[LATENCY_NUM_PACKETS])
 {
-       unsigned int i;
-       int ret;
-       struct rte_mbuf *pbuf[LATENCY_NUM_PACKETS] = { };
-       struct rte_mempool *mp;
-       char poolname[] = "mbuf_pool";
+       unsigned int i, iters = 0;
        uint64_t end_cycles;
        struct rte_metric_value values[NUM_STATS] = { };
        struct rte_metric_name names[NUM_STATS] = { };
-
-       ret = test_get_mbuf_from_pool(&mp, pbuf, poolname);
-       if (ret < 0) {
-               printf("allocate mbuf pool Failed\n");
-               return TEST_FAILED;
-       }
-       ret = test_dev_start(portid, mp);
-       if (ret < 0) {
-               printf("test_dev_start(%hu, %p) failed, error code: %d\n",
-                       portid, mp, ret);
-               return TEST_FAILED;
-       }
+       int ret;
 
        ret = rte_latencystats_get_names(names, NUM_STATS);
        TEST_ASSERT((ret == NUM_STATS), "Test Failed to get metrics names");
@@ -170,37 +159,65 @@ static int test_latency_packet_forward(void)
        TEST_ASSERT(ret == NUM_STATS, "Test failed to get results before 
forwarding");
        TEST_ASSERT(values[4].value == 0, "Samples not zero at start of test");
 
-       /*
-        * Want test to run long enough to collect sufficient samples
-        * but not so long that scheduler decides to reschedule it (1000 hz).
-        */
-       end_cycles = rte_rdtsc() + rte_get_tsc_hz() / 2000;
-       do {
+       /* Want test to run long enough to collect sufficient samples */
+       end_cycles = rte_rdtsc() + rte_get_tsc_hz() / MS_PER_S * 
LATENCY_FORWARD_MS;
+       for (i = 0; i < LATENCY_FORWARD_ITERATIONS; i++) {
                ret = test_packet_forward(pbuf, portid, QUEUE_ID);
                if (ret < 0)
                        printf("send pkts Failed\n");
-       } while (rte_rdtsc() < end_cycles);
+
+               if (++iters >= MIN_ITERATIONS && rte_rdtsc() >= end_cycles)
+                       break;
+       }
 
        ret = rte_latencystats_get(values, NUM_STATS);
        TEST_ASSERT(ret == NUM_STATS, "Test failed to get results after 
forwarding");
 
+       if (values[4].value == 0) {
+               printf("No latency samples collected after %u iterations, 
skipping\n", iters);
+               return TEST_SKIPPED;
+       }
+
        for (i = 0; i < NUM_STATS; i++) {
                uint16_t k = values[i].key;
 
-               printf("%s = %"PRIu64"\n",
-                      names[k].name, values[i].value);
+               printf("%s = %"PRIu64"\n", names[k].name, values[i].value);
        }
-
+       fflush(stdout);
        TEST_ASSERT(values[4].value > 0, "No samples taken");
 
        TEST_ASSERT(values[0].value < values[1].value, "Min latency > Avg 
latency");
        TEST_ASSERT(values[0].value < values[2].value, "Min latency > Max 
latency");
        TEST_ASSERT(values[1].value < values[2].value, "Avg latency > Max 
latency");
+       return TEST_SUCCESS;
+}
+
+static int test_latency_packet_forward(void)
+{
+       struct rte_mempool *mp = NULL;
+       char poolname[] = "mbuf_pool";
+       struct rte_mbuf *pbuf[LATENCY_NUM_PACKETS] = { };
+       int ret;
+
+       ret = test_get_mbuf_from_pool(&mp, pbuf, poolname);
+       if (ret < 0) {
+               printf("allocate mbuf pool Failed\n");
+               return TEST_FAILED;
+       }
+
+       ret = test_dev_start(portid, mp);
+       if (ret < 0) {
+               printf("test_dev_start(%hu, %p) failed, error code: %d\n",
+                       portid, mp, ret);
+               ret = TEST_FAILED;
+       } else {
+               ret = test_forward_loop(portid, pbuf);
+       }
 
        rte_eth_dev_stop(portid);
        test_put_mbuf_to_pool(mp, pbuf);
 
-       return (ret >= 0) ? TEST_SUCCESS : TEST_FAILED;
+       return ret;
 }
 
 static struct
-- 
2.53.0

Reply via email to