netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jason Xing <kerneljasonxing@gmail.com>
To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, bjorn@kernel.org, magnus.karlsson@intel.com,
	maciej.fijalkowski@intel.com, jonathan.lemon@gmail.com,
	sdf@fomichev.me, ast@kernel.org, daniel@iogearbox.net,
	hawk@kernel.org, john.fastabend@gmail.com, joe@dama.to,
	willemdebruijn.kernel@gmail.com
Cc: bpf@vger.kernel.org, netdev@vger.kernel.org,
	Jason Xing <kernelxing@tencent.com>
Subject: [PATCH net-next v4 2/2] selftests/bpf: check if the global consumer updates in time
Date: Fri, 27 Jun 2025 16:57:45 +0800	[thread overview]
Message-ID: <20250627085745.53173-3-kerneljasonxing@gmail.com> (raw)
In-Reply-To: <20250627085745.53173-1-kerneljasonxing@gmail.com>

From: Jason Xing <kernelxing@tencent.com>

This patch only checks non-zc mode and non STAT_TX_INVALID testcase. The
conditions are included in check_consumer().

The policy of testing the issue is to recognize the max budget case where
the number of descs in the tx queue is larger than the default max budget,
namely, 32, to make sure that 1) the max_batch error is triggered in
__xsk_generic_xmit(), 2) xskq_cons_peek_desc() doesn't have the chance
to update the global state of consumer at last. Hitting max budget case
is just one of premature exit cases but has the same result/action in
__xsk_generic_xmit().

Signed-off-by: Jason Xing <kernelxing@tencent.com>
---
 tools/testing/selftests/bpf/xskxceiver.c | 60 +++++++++++++++++++-----
 1 file changed, 48 insertions(+), 12 deletions(-)

diff --git a/tools/testing/selftests/bpf/xskxceiver.c b/tools/testing/selftests/bpf/xskxceiver.c
index 0ced4026ee44..694b0c0e1217 100644
--- a/tools/testing/selftests/bpf/xskxceiver.c
+++ b/tools/testing/selftests/bpf/xskxceiver.c
@@ -109,6 +109,8 @@
 
 #include <network_helpers.h>
 
+#define MAX_TX_BUDGET_DEFAULT 32
+
 static bool opt_verbose;
 static bool opt_print_tests;
 static enum test_mode opt_mode = TEST_MODE_ALL;
@@ -1091,11 +1093,34 @@ static bool is_pkt_valid(struct pkt *pkt, void *buffer, u64 addr, u32 len)
 	return true;
 }
 
-static int kick_tx(struct xsk_socket_info *xsk)
+static u32 load_value(u32 *a)
 {
-	int ret;
+	return __atomic_load_n(a, __ATOMIC_ACQUIRE);
+}
+
+static int kick_tx_with_check(struct xsk_socket_info *xsk)
+{
+	int ret, cons_delta;
+	u32 prev_cons;
 
+	prev_cons = load_value(xsk->tx.consumer);
 	ret = sendto(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0);
+	cons_delta = load_value(xsk->tx.consumer) - prev_cons;
+	if (cons_delta != MAX_TX_BUDGET_DEFAULT)
+		return TEST_FAILURE;
+
+	return ret;
+}
+
+static int kick_tx(struct xsk_socket_info *xsk, bool check_cons)
+{
+	u32 ready_to_send = load_value(xsk->tx.producer) - load_value(xsk->tx.consumer);
+	int ret;
+
+	if (!check_cons || ready_to_send <= MAX_TX_BUDGET_DEFAULT)
+		ret = sendto(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0);
+	else
+		ret = kick_tx_with_check(xsk);
 	if (ret >= 0)
 		return TEST_PASS;
 	if (errno == ENOBUFS || errno == EAGAIN || errno == EBUSY || errno == ENETDOWN) {
@@ -1116,14 +1141,14 @@ static int kick_rx(struct xsk_socket_info *xsk)
 	return TEST_PASS;
 }
 
-static int complete_pkts(struct xsk_socket_info *xsk, int batch_size)
+static int complete_pkts(struct xsk_socket_info *xsk, int batch_size, bool check_cons)
 {
 	unsigned int rcvd;
 	u32 idx;
 	int ret;
 
 	if (xsk_ring_prod__needs_wakeup(&xsk->tx)) {
-		ret = kick_tx(xsk);
+		ret = kick_tx(xsk, check_cons);
 		if (ret)
 			return TEST_FAILURE;
 	}
@@ -1323,7 +1348,17 @@ static int receive_pkts(struct test_spec *test)
 	return TEST_PASS;
 }
 
-static int __send_pkts(struct ifobject *ifobject, struct xsk_socket_info *xsk, bool timeout)
+bool check_consumer(struct test_spec *test)
+{
+	if (test->mode & TEST_MODE_ZC ||
+	    !strncmp("STAT_TX_INVALID", test->name, MAX_TEST_NAME_SIZE))
+		return false;
+
+	return true;
+}
+
+static int __send_pkts(struct test_spec *test, struct ifobject *ifobject,
+		       struct xsk_socket_info *xsk, bool timeout)
 {
 	u32 i, idx = 0, valid_pkts = 0, valid_frags = 0, buffer_len;
 	struct pkt_stream *pkt_stream = xsk->pkt_stream;
@@ -1336,7 +1371,7 @@ static int __send_pkts(struct ifobject *ifobject, struct xsk_socket_info *xsk, b
 	/* pkts_in_flight might be negative if many invalid packets are sent */
 	if (pkts_in_flight >= (int)((umem_size(umem) - xsk->batch_size * buffer_len) /
 	    buffer_len)) {
-		ret = kick_tx(xsk);
+		ret = kick_tx(xsk, check_consumer(test));
 		if (ret)
 			return TEST_FAILURE;
 		return TEST_CONTINUE;
@@ -1365,7 +1400,7 @@ static int __send_pkts(struct ifobject *ifobject, struct xsk_socket_info *xsk, b
 			}
 		}
 
-		complete_pkts(xsk, xsk->batch_size);
+		complete_pkts(xsk, xsk->batch_size, check_consumer(test));
 	}
 
 	for (i = 0; i < xsk->batch_size; i++) {
@@ -1437,7 +1472,7 @@ static int __send_pkts(struct ifobject *ifobject, struct xsk_socket_info *xsk, b
 	}
 
 	if (!timeout) {
-		if (complete_pkts(xsk, i))
+		if (complete_pkts(xsk, i, check_consumer(test)))
 			return TEST_FAILURE;
 
 		usleep(10);
@@ -1447,7 +1482,7 @@ static int __send_pkts(struct ifobject *ifobject, struct xsk_socket_info *xsk, b
 	return TEST_CONTINUE;
 }
 
-static int wait_for_tx_completion(struct xsk_socket_info *xsk)
+static int wait_for_tx_completion(struct xsk_socket_info *xsk, bool check_cons)
 {
 	struct timeval tv_end, tv_now, tv_timeout = {THREAD_TMOUT, 0};
 	int ret;
@@ -1466,7 +1501,7 @@ static int wait_for_tx_completion(struct xsk_socket_info *xsk)
 			return TEST_FAILURE;
 		}
 
-		complete_pkts(xsk, xsk->batch_size);
+		complete_pkts(xsk, xsk->batch_size, check_cons);
 	}
 
 	return TEST_PASS;
@@ -1492,7 +1527,7 @@ static int send_pkts(struct test_spec *test, struct ifobject *ifobject)
 				__set_bit(i, bitmap);
 				continue;
 			}
-			ret = __send_pkts(ifobject, &ifobject->xsk_arr[i], timeout);
+			ret = __send_pkts(test, ifobject, &ifobject->xsk_arr[i], timeout);
 			if (ret == TEST_CONTINUE && !test->fail)
 				continue;
 
@@ -1502,7 +1537,8 @@ static int send_pkts(struct test_spec *test, struct ifobject *ifobject)
 			if (ret == TEST_PASS && timeout)
 				return ret;
 
-			ret = wait_for_tx_completion(&ifobject->xsk_arr[i]);
+			ret = wait_for_tx_completion(&ifobject->xsk_arr[i],
+						     check_consumer(test));
 			if (ret)
 				return TEST_FAILURE;
 		}
-- 
2.41.3


  parent reply	other threads:[~2025-06-27  8:58 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-27  8:57 [PATCH net-next v4 0/2] net: xsk: update tx queue consumer Jason Xing
2025-06-27  8:57 ` [PATCH net-next v4 1/2] net: xsk: update tx queue consumer immediately after transmission Jason Xing
2025-06-30 11:49   ` Maciej Fijalkowski
2025-06-30 15:23     ` Stanislav Fomichev
2025-06-27  8:57 ` Jason Xing [this message]
2025-06-30 12:06   ` [PATCH net-next v4 2/2] selftests/bpf: check if the global consumer updates in time Maciej Fijalkowski
2025-06-30 12:28     ` Jason Xing

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=20250627085745.53173-3-kerneljasonxing@gmail.com \
    --to=kerneljasonxing@gmail.com \
    --cc=ast@kernel.org \
    --cc=bjorn@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=hawk@kernel.org \
    --cc=joe@dama.to \
    --cc=john.fastabend@gmail.com \
    --cc=jonathan.lemon@gmail.com \
    --cc=kernelxing@tencent.com \
    --cc=kuba@kernel.org \
    --cc=maciej.fijalkowski@intel.com \
    --cc=magnus.karlsson@intel.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=sdf@fomichev.me \
    --cc=willemdebruijn.kernel@gmail.com \
    /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;
as well as URLs for NNTP newsgroup(s).