From 0e1eadd0d682725ba9cc1fb5c35ae3946eb104e5 Mon Sep 17 00:00:00 2001 From: Harry van Haaren Date: Thu, 11 May 2017 10:56:26 +0100 Subject: [PATCH] event/sw: add queue-to-port stats This commit adds a new statistic to the SW eventdev PMD. The statistic shows how many packets were sent from a queue to a port. This provides information on how traffic from a specific queue is being load-balanced to worker cores. Note that these numbers should be compared across all queue stages - the load-balancing does not try to perfectly share each queue's traffic, rather it balances the overall traffic from all queues to the ports. The statistic is printed from the rte_eventdev_dump() function, as well as being made available via the xstats API. Unit tests have been updated to expect more per-queue statistics, and the correctness of counts and counts after reset is verified. Signed-off-by: Harry van Haaren --- drivers/event/sw/sw_evdev.c | 13 +++---- drivers/event/sw/sw_evdev.h | 1 + drivers/event/sw/sw_evdev_scheduler.c | 1 + drivers/event/sw/sw_evdev_xstats.c | 13 +++++-- test/test/test_eventdev_sw.c | 51 +++++++++++++++++---------- 5 files changed, 52 insertions(+), 27 deletions(-) diff --git a/drivers/event/sw/sw_evdev.c b/drivers/event/sw/sw_evdev.c index a31aaa6625..7f69e38832 100644 --- a/drivers/event/sw/sw_evdev.c +++ b/drivers/event/sw/sw_evdev.c @@ -559,12 +559,13 @@ sw_dump(struct rte_eventdev *dev, FILE *f) inflights += qid->fids[flow].pcount; } - uint32_t cq; - fprintf(f, "\tInflights: %u\tFlows pinned per port: ", - inflights); - for (cq = 0; cq < sw->port_count; cq++) - fprintf(f, "%d ", affinities_per_port[cq]); - fprintf(f, "\n"); + uint32_t port; + fprintf(f, "\tPer Port Stats:\n"); + for (port = 0; port < sw->port_count; port++) { + fprintf(f, "\t Port %d: Pkts: %"PRIu64, port, + qid->to_port[port]); + fprintf(f, "\tFlows: %d\n", affinities_per_port[port]); + } uint32_t iq; uint32_t iq_printed = 0; diff --git a/drivers/event/sw/sw_evdev.h b/drivers/event/sw/sw_evdev.h index 61c671d622..b3929f4a7d 100644 --- a/drivers/event/sw/sw_evdev.h +++ b/drivers/event/sw/sw_evdev.h @@ -149,6 +149,7 @@ struct sw_qid { uint32_t cq_num_mapped_cqs; uint32_t cq_next_tx; /* cq to write next (non-atomic) packet */ uint32_t cq_map[SW_PORTS_MAX]; + uint64_t to_port[SW_PORTS_MAX]; /* Track flow ids for atomic load balancing */ struct sw_fid_t fids[SW_QID_NUM_FIDS]; diff --git a/drivers/event/sw/sw_evdev_scheduler.c b/drivers/event/sw/sw_evdev_scheduler.c index 35f8f175ad..fe15517061 100644 --- a/drivers/event/sw/sw_evdev_scheduler.c +++ b/drivers/event/sw/sw_evdev_scheduler.c @@ -119,6 +119,7 @@ sw_schedule_atomic_to_cq(struct sw_evdev *sw, struct sw_qid * const qid, p->stats.tx_pkts++; qid->stats.tx_pkts++; + qid->to_port[cq]++; /* if we just filled in the last slot, flush the buffer */ if (sw->cq_ring_space[cq] == 0) { diff --git a/drivers/event/sw/sw_evdev_xstats.c b/drivers/event/sw/sw_evdev_xstats.c index c7b1abe882..7b66fbb154 100644 --- a/drivers/event/sw/sw_evdev_xstats.c +++ b/drivers/event/sw/sw_evdev_xstats.c @@ -57,6 +57,7 @@ enum xstats_type { iq_used, /* qid port mapping specific */ pinned, + pkts, /* note: qid-to-port pkts */ }; typedef uint64_t (*xstats_fn)(const struct sw_evdev *dev, @@ -179,6 +180,8 @@ get_qid_port_stat(const struct sw_evdev *sw, uint16_t obj_idx, return pin; } while (0); break; + case pkts: + return qid->to_port[port]; default: return -1; } } @@ -246,8 +249,11 @@ sw_xstats_init(struct sw_evdev *sw) static const enum xstats_type qid_iq_types[] = { iq_used }; /* reset allowed */ - static const char * const qid_port_stats[] = { "pinned_flows" }; - static const enum xstats_type qid_port_types[] = { pinned }; + static const char * const qid_port_stats[] = { "pinned_flows", + "packets" + }; + static const enum xstats_type qid_port_types[] = { pinned, pkts }; + static const uint8_t qid_port_reset_allowed[] = {0, 1}; /* reset allowed */ /* ---- end of stat definitions ---- */ @@ -376,7 +382,8 @@ sw_xstats_init(struct sw_evdev *sw) .stat = qid_port_types[i], .mode = RTE_EVENT_DEV_XSTATS_QUEUE, .extra_arg = port, - .reset_allowed = 0, + .reset_allowed = + qid_port_reset_allowed[i], }; snprintf(sname, sizeof(sname), "qid_%u_port_%u_%s", diff --git a/test/test/test_eventdev_sw.c b/test/test/test_eventdev_sw.c index b187d02903..c37e345b63 100644 --- a/test/test/test_eventdev_sw.c +++ b/test/test/test_eventdev_sw.c @@ -877,8 +877,8 @@ xstats_tests(struct test *t) ret = rte_event_dev_xstats_names_get(evdev, RTE_EVENT_DEV_XSTATS_QUEUE, 0, xstats_names, ids, XSTATS_MAX); - if (ret != 13) { - printf("%d: expected 13 stats, got return %d\n", __LINE__, ret); + if (ret != 17) { + printf("%d: expected 17 stats, got return %d\n", __LINE__, ret); return -1; } @@ -894,8 +894,8 @@ xstats_tests(struct test *t) ret = rte_event_dev_xstats_get(evdev, RTE_EVENT_DEV_XSTATS_QUEUE, 0, ids, values, ret); - if (ret != 13) { - printf("%d: expected 13 stats, got return %d\n", __LINE__, ret); + if (ret != 17) { + printf("%d: expected 17 stats, got return %d\n", __LINE__, ret); return -1; } @@ -1059,7 +1059,11 @@ xstats_tests(struct test *t) 3 /* inflights */, 512 /* iq size */, 0, 0, 0, 0, /* iq 0, 1, 2, 3 used */ - 0, 0, 1, 0, /* qid_0_port_X_pinned_flows */ + /* QID-to-Port: pinned_flows, packets */ + 0, 0, + 0, 0, + 1, 3, + 0, 0, }; for (i = 0; (signed int)i < ret; i++) { if (queue_expected[i] != values[i]) { @@ -1086,7 +1090,11 @@ xstats_tests(struct test *t) 3 /* inflight */, 512 /* iq size */, 0, 0, 0, 0, /* 4 iq used */ - 0, 0, 1, 0, /* qid to port pinned flows */ + /* QID-to-Port: pinned_flows, packets */ + 0, 0, + 0, 0, + 1, 0, + 0, 0, }; ret = rte_event_dev_xstats_get(evdev, RTE_EVENT_DEV_XSTATS_QUEUE, 0, @@ -1634,7 +1642,7 @@ xstats_id_reset_tests(struct test *t) goto fail; /* num queue stats */ -#define NUM_Q_STATS 13 +#define NUM_Q_STATS 17 /* queue offset from start of the devices whole xstats. * This will break every time we add a statistic to a device/port/queue */ @@ -1665,9 +1673,13 @@ xstats_id_reset_tests(struct test *t) "qid_0_iq_2_used", "qid_0_iq_3_used", "qid_0_port_0_pinned_flows", + "qid_0_port_0_packets", "qid_0_port_1_pinned_flows", + "qid_0_port_1_packets", "qid_0_port_2_pinned_flows", + "qid_0_port_2_packets", "qid_0_port_3_pinned_flows", + "qid_0_port_3_packets", }; uint64_t queue_expected[] = { 7, /* rx */ @@ -1679,10 +1691,11 @@ xstats_id_reset_tests(struct test *t) 0, /* iq 1 used */ 0, /* iq 2 used */ 0, /* iq 3 used */ - 0, /* qid 0 port 0 pinned flows */ - 0, /* qid 0 port 1 pinned flows */ - 1, /* qid 0 port 2 pinned flows */ - 0, /* qid 0 port 4 pinned flows */ + /* QID-to-Port: pinned_flows, packets */ + 0, 0, + 0, 0, + 1, 7, + 0, 0, }; uint64_t queue_expected_zero[] = { 0, /* rx */ @@ -1694,12 +1707,14 @@ xstats_id_reset_tests(struct test *t) 0, /* iq 1 used */ 0, /* iq 2 used */ 0, /* iq 3 used */ - 0, /* qid 0 port 0 pinned flows */ - 0, /* qid 0 port 1 pinned flows */ - 1, /* qid 0 port 2 pinned flows */ - 0, /* qid 0 port 4 pinned flows */ + /* QID-to-Port: pinned_flows, packets */ + 0, 0, + 0, 0, + 1, 0, + 0, 0, }; if (RTE_DIM(queue_expected) != NUM_Q_STATS || + RTE_DIM(queue_expected_zero) != NUM_Q_STATS || RTE_DIM(queue_names) != NUM_Q_STATS) { printf("%d : queue array of wrong size\n", __LINE__); goto fail; @@ -1718,9 +1733,9 @@ xstats_id_reset_tests(struct test *t) failed = 1; } if (val != queue_expected[i]) { - printf("%d: %s value incorrect, expected %"PRIu64 - " got %d\n", __LINE__, queue_names[i], - queue_expected[i], id); + printf("%d: %d: %s value , expected %"PRIu64 + " got %"PRIu64"\n", i, __LINE__, + queue_names[i], queue_expected[i], val); failed = 1; } /* reset to zero */ -- 2.20.1