From: Magnus Karlsson <magnus.karlsson@intel.com>
Date: Wed, 25 Aug 2021 11:37:16 +0200
Subject: selftests: xsk: Validate tx stats on tx thread
Patch-mainline: v5.15-rc1
Git-commit: b04fdc4ce31fe5ae411737ec6705fcdfc493d6c8
References: jsc#PED-1377
Validate the tx stats on the Tx thread instead of the Rx
thread. Depending on your settings, you might not be allowed to query
the statistics of a socket you do not own, so better to do this on the
correct thread to start with.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20210825093722.10219-11-magnus.karlsson@gmail.com
Acked-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
---
tools/testing/selftests/bpf/xdpxceiver.c | 55 +++++++++++++++++++++++--------
1 file changed, 41 insertions(+), 14 deletions(-)
--- a/tools/testing/selftests/bpf/xdpxceiver.c
+++ b/tools/testing/selftests/bpf/xdpxceiver.c
@@ -642,23 +642,22 @@ static void tx_only_all(struct ifobject
complete_tx_only_all(ifobject);
}
-static void stats_validate(struct ifobject *ifobject)
+static bool rx_stats_are_valid(struct ifobject *ifobject)
{
+ u32 xsk_stat = 0, expected_stat = opt_pkt_count;
+ struct xsk_socket *xsk = ifobject->xsk->xsk;
+ int fd = xsk_socket__fd(xsk);
struct xdp_statistics stats;
socklen_t optlen;
int err;
- struct xsk_socket *xsk = stat_test_type == STAT_TEST_TX_INVALID ?
- ifdict[!ifobject->ifdict_index]->xsk->xsk :
- ifobject->xsk->xsk;
- int fd = xsk_socket__fd(xsk);
- unsigned long xsk_stat = 0, expected_stat = opt_pkt_count;
-
- sigvar = 0;
optlen = sizeof(stats);
err = getsockopt(fd, SOL_XDP, XDP_STATISTICS, &stats, &optlen);
- if (err)
- return;
+ if (err) {
+ ksft_test_result_fail("ERROR: [%s] getsockopt(XDP_STATISTICS) error %u %s\n",
+ __func__, -err, strerror(-err));
+ return true;
+ }
if (optlen == sizeof(struct xdp_statistics)) {
switch (stat_test_type) {
@@ -666,8 +665,7 @@ static void stats_validate(struct ifobje
xsk_stat = stats.rx_dropped;
break;
case STAT_TEST_TX_INVALID:
- xsk_stat = stats.tx_invalid_descs;
- break;
+ return true;
case STAT_TEST_RX_FULL:
xsk_stat = stats.rx_ring_full;
expected_stat -= RX_FULL_RXQSIZE;
@@ -680,8 +678,33 @@ static void stats_validate(struct ifobje
}
if (xsk_stat == expected_stat)
- sigvar = 1;
+ return true;
}
+
+ return false;
+}
+
+static void tx_stats_validate(struct ifobject *ifobject)
+{
+ struct xsk_socket *xsk = ifobject->xsk->xsk;
+ int fd = xsk_socket__fd(xsk);
+ struct xdp_statistics stats;
+ socklen_t optlen;
+ int err;
+
+ optlen = sizeof(stats);
+ err = getsockopt(fd, SOL_XDP, XDP_STATISTICS, &stats, &optlen);
+ if (err) {
+ ksft_test_result_fail("ERROR: [%s] getsockopt(XDP_STATISTICS) error %u %s\n",
+ __func__, -err, strerror(-err));
+ return;
+ }
+
+ if (stats.tx_invalid_descs == opt_pkt_count)
+ return;
+
+ ksft_test_result_fail("ERROR: [%s] tx_invalid_descs incorrect. Got [%u] expected [%u]\n",
+ __func__, stats.tx_invalid_descs, opt_pkt_count);
}
static void thread_common_ops(struct ifobject *ifobject, void *bufs)
@@ -767,6 +790,9 @@ static void *worker_testapp_validate_tx(
print_verbose("Sending %d packets on interface %s\n", opt_pkt_count, ifobject->ifname);
tx_only_all(ifobject);
+ if (stat_test_type == STAT_TEST_TX_INVALID)
+ tx_stats_validate(ifobject);
+
testapp_cleanup_xsk_res(ifobject);
pthread_exit(NULL);
}
@@ -792,7 +818,8 @@ static void *worker_testapp_validate_rx(
if (test_type != TEST_TYPE_STATS) {
rx_pkt(ifobject->xsk, fds);
} else {
- stats_validate(ifobject);
+ if (rx_stats_are_valid(ifobject))
+ break;
}
if (sigvar)
break;