Commit 01af0001 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-xsk-update-tx-queue-consumer'

Jason Xing says:

====================
net: xsk: update tx queue consumer

Patch 1 makes sure the consumer is updated at the end of generic xmit.
Patch 2 adds corresponding test.
====================

Link: https://patch.msgid.link/20250703141712.33190-1-kerneljasonxing@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 042ef6aa 680acde1
Loading
Loading
Loading
Loading
+10 −7
Original line number Diff line number Diff line
@@ -300,6 +300,13 @@ static bool xsk_tx_writeable(struct xdp_sock *xs)
	return true;
}

static void __xsk_tx_release(struct xdp_sock *xs)
{
	__xskq_cons_release(xs->tx);
	if (xsk_tx_writeable(xs))
		xs->sk.sk_write_space(&xs->sk);
}

static bool xsk_is_bound(struct xdp_sock *xs)
{
	if (READ_ONCE(xs->state) == XSK_BOUND) {
@@ -407,11 +414,8 @@ void xsk_tx_release(struct xsk_buff_pool *pool)
	struct xdp_sock *xs;

	rcu_read_lock();
	list_for_each_entry_rcu(xs, &pool->xsk_tx_list, tx_list) {
		__xskq_cons_release(xs->tx);
		if (xsk_tx_writeable(xs))
			xs->sk.sk_write_space(&xs->sk);
	}
	list_for_each_entry_rcu(xs, &pool->xsk_tx_list, tx_list)
		__xsk_tx_release(xs);
	rcu_read_unlock();
}
EXPORT_SYMBOL(xsk_tx_release);
@@ -858,8 +862,7 @@ static int __xsk_generic_xmit(struct sock *sk)

out:
	if (sent_frame)
		if (xsk_tx_writeable(xs))
			sk->sk_write_space(sk);
		__xsk_tx_release(xs);

	mutex_unlock(&xs->mutex);
	return err;
+55 −1
Original line number Diff line number Diff line
@@ -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,45 @@ static bool is_pkt_valid(struct pkt *pkt, void *buffer, u64 addr, u32 len)
	return true;
}

static u32 load_value(u32 *counter)
{
	return __atomic_load_n(counter, __ATOMIC_ACQUIRE);
}

static bool kick_tx_with_check(struct xsk_socket_info *xsk, int *ret)
{
	u32 max_budget = MAX_TX_BUDGET_DEFAULT;
	u32 cons, ready_to_send;
	int delta;

	cons = load_value(xsk->tx.consumer);
	ready_to_send = load_value(xsk->tx.producer) - cons;
	*ret = sendto(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0);

	delta = load_value(xsk->tx.consumer) - cons;
	/* By default, xsk should consume exact @max_budget descs at one
	 * send in this case where hitting the max budget limit in while
	 * loop is triggered in __xsk_generic_xmit(). Please make sure that
	 * the number of descs to be sent is larger than @max_budget, or
	 * else the tx.consumer will be updated in xskq_cons_peek_desc()
	 * in time which hides the issue we try to verify.
	 */
	if (ready_to_send > max_budget && delta != max_budget)
		return false;

	return true;
}

static int kick_tx(struct xsk_socket_info *xsk)
{
	int ret;

	if (xsk->check_consumer) {
		if (!kick_tx_with_check(xsk, &ret))
			return TEST_FAILURE;
	} else {
		ret = sendto(xsk_socket__fd(xsk->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0);
	}
	if (ret >= 0)
		return TEST_PASS;
	if (errno == ENOBUFS || errno == EAGAIN || errno == EBUSY || errno == ENETDOWN) {
@@ -2613,6 +2649,23 @@ static int testapp_adjust_tail_grow_mb(struct test_spec *test)
				   XSK_UMEM__LARGE_FRAME_SIZE * 2);
}

static int testapp_tx_queue_consumer(struct test_spec *test)
{
	int nr_packets;

	if (test->mode == TEST_MODE_ZC) {
		ksft_test_result_skip("Can not run TX_QUEUE_CONSUMER test for ZC mode\n");
		return TEST_SKIP;
	}

	nr_packets = MAX_TX_BUDGET_DEFAULT + 1;
	pkt_stream_replace(test, nr_packets, MIN_PKT_SIZE);
	test->ifobj_tx->xsk->batch_size = nr_packets;
	test->ifobj_tx->xsk->check_consumer = true;

	return testapp_validate_traffic(test);
}

static void run_pkt_test(struct test_spec *test)
{
	int ret;
@@ -2723,6 +2776,7 @@ static const struct test_spec tests[] = {
	{.name = "XDP_ADJUST_TAIL_SHRINK_MULTI_BUFF", .test_func = testapp_adjust_tail_shrink_mb},
	{.name = "XDP_ADJUST_TAIL_GROW", .test_func = testapp_adjust_tail_grow},
	{.name = "XDP_ADJUST_TAIL_GROW_MULTI_BUFF", .test_func = testapp_adjust_tail_grow_mb},
	{.name = "TX_QUEUE_CONSUMER", .test_func = testapp_tx_queue_consumer},
	};

static void print_tests(void)
+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ struct xsk_socket_info {
	u32 batch_size;
	u8 dst_mac[ETH_ALEN];
	u8 src_mac[ETH_ALEN];
	bool check_consumer;
};

struct pkt {