* [PATCH net-next v3 0/4] selftests/xsk: simplify UMEM setup
@ 2026-06-08 13:09 Tushar Vyavahare
2026-06-08 13:09 ` [PATCH net-next v3 1/4] selftests/xsk: Introduce helpers for setting UMEM properties Tushar Vyavahare
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Tushar Vyavahare @ 2026-06-08 13:09 UTC (permalink / raw)
To: netdev, magnus.karlsson, maciej.fijalkowski, stfomichev,
kernelxing, davem, kuba, pabeni, ast, daniel, tirthendu.sarkar,
tushar.vyavahare
Cc: bpf
This series simplifies UMEM handling in selftests/xsk.
It centralizes UMEM property setup through helpers, moves UMEM ownership
from ifobject to socket-owned state, and normalizes umem_size/mmap_size
usage across the touched paths.
v1 -> v2:
- Applied helper usage consistently across the touched test paths.
- Moved UMEM ownership to socket-owned state and switched to one
heap-backed umem_real object at xsk_arr[0] with explicit reset/cleanup.
- Kept shared-UMEM TX behavior unchanged via TX-local UMEM state
copy/reset during TX configuration.
- Folded pkt_generate() umem parameter removal into the ownership
refactor patch (no standalone cleanup patch). [Maciej]
- Updated mmap_size teardown handling to join the RX worker thread in
single-thread mode before cleanup to synchronize UMEM mapping state.
v2 -> v3:
- Reverted the unnecessary pkt_generate() interface change. [Maciej]
- Removed the unneeded umem_rx/umem_tx locals in
testapp_validate_traffic(). [Maciej]
- No functional changes, only review-driven cleanup.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
Signed-off-by: Tushar Vyavahare <tushar.vyavahare@intel.com>
Tushar Vyavahare (4):
selftests/xsk: Introduce helpers for setting UMEM properties
selftests/xsk: Move UMEM state from ifobject to xsk_socket_info
selftests/xsk: Use umem_size() helper consistently
selftests/xsk: Introduce mmap_size in umem struct
.../selftests/bpf/prog_tests/test_xsk.c | 193 ++++++++++--------
.../selftests/bpf/prog_tests/test_xsk.h | 3 +-
2 files changed, 111 insertions(+), 85 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH net-next v3 1/4] selftests/xsk: Introduce helpers for setting UMEM properties
2026-06-08 13:09 [PATCH net-next v3 0/4] selftests/xsk: simplify UMEM setup Tushar Vyavahare
@ 2026-06-08 13:09 ` Tushar Vyavahare
2026-06-08 13:09 ` [PATCH net-next v3 2/4] selftests/xsk: Move UMEM state from ifobject to xsk_socket_info Tushar Vyavahare
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Tushar Vyavahare @ 2026-06-08 13:09 UTC (permalink / raw)
To: netdev, magnus.karlsson, maciej.fijalkowski, stfomichev,
kernelxing, davem, kuba, pabeni, ast, daniel, tirthendu.sarkar,
tushar.vyavahare
Cc: bpf
UMEM properties are set via open-coded field assignments in multiple test
paths, which makes updates noisy and error-prone.
Introduce two helpers to set UMEM properties through a single interface.
This keeps setup logic consistent across tests and makes future refactoring
simpler.
No functional behavior change is intended.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
Signed-off-by: Tushar Vyavahare <tushar.vyavahare@intel.com>
Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
---
.../selftests/bpf/prog_tests/test_xsk.c | 36 ++++++++++---------
1 file changed, 20 insertions(+), 16 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/test_xsk.c b/tools/testing/selftests/bpf/prog_tests/test_xsk.c
index 7950c504ed28..3369450da974 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_xsk.c
+++ b/tools/testing/selftests/bpf/prog_tests/test_xsk.c
@@ -303,6 +303,18 @@ static void test_spec_reset(struct test_spec *test)
__test_spec_init(test, test->ifobj_tx, test->ifobj_rx);
}
+static void test_spec_set_unaligned(struct test_spec *test)
+{
+ test->ifobj_tx->umem->unaligned_mode = true;
+ test->ifobj_rx->umem->unaligned_mode = true;
+}
+
+static void test_spec_set_frame_size(struct test_spec *test, u32 size)
+{
+ test->ifobj_tx->umem->frame_size = size;
+ test->ifobj_rx->umem->frame_size = size;
+}
+
static void test_spec_set_xdp_prog(struct test_spec *test, struct bpf_program *xdp_prog_rx,
struct bpf_program *xdp_prog_tx, struct bpf_map *xskmap_rx,
struct bpf_map *xskmap_tx)
@@ -2025,8 +2037,7 @@ int testapp_stats_fill_empty(struct test_spec *test)
int testapp_send_receive_unaligned(struct test_spec *test)
{
- test->ifobj_tx->umem->unaligned_mode = true;
- test->ifobj_rx->umem->unaligned_mode = true;
+ test_spec_set_unaligned(test);
/* Let half of the packets straddle a 4K buffer boundary */
if (pkt_stream_replace_half(test, MIN_PKT_SIZE, -MIN_PKT_SIZE / 2))
return TEST_FAILURE;
@@ -2037,8 +2048,7 @@ int testapp_send_receive_unaligned(struct test_spec *test)
int testapp_send_receive_unaligned_mb(struct test_spec *test)
{
test->mtu = MAX_ETH_JUMBO_SIZE;
- test->ifobj_tx->umem->unaligned_mode = true;
- test->ifobj_rx->umem->unaligned_mode = true;
+ test_spec_set_unaligned(test);
if (pkt_stream_replace(test, DEFAULT_PKT_CNT, MAX_ETH_JUMBO_SIZE))
return TEST_FAILURE;
return testapp_validate_traffic(test);
@@ -2337,8 +2347,7 @@ int testapp_send_receive(struct test_spec *test)
int testapp_send_receive_2k_frame(struct test_spec *test)
{
- test->ifobj_tx->umem->frame_size = 2048;
- test->ifobj_rx->umem->frame_size = 2048;
+ test_spec_set_frame_size(test, 2048);
if (pkt_stream_replace(test, DEFAULT_PKT_CNT, MIN_PKT_SIZE))
return TEST_FAILURE;
return testapp_validate_traffic(test);
@@ -2363,15 +2372,13 @@ int testapp_aligned_inv_desc(struct test_spec *test)
int testapp_aligned_inv_desc_2k_frame(struct test_spec *test)
{
- test->ifobj_tx->umem->frame_size = 2048;
- test->ifobj_rx->umem->frame_size = 2048;
+ test_spec_set_frame_size(test, 2048);
return testapp_invalid_desc(test);
}
int testapp_unaligned_inv_desc(struct test_spec *test)
{
- test->ifobj_tx->umem->unaligned_mode = true;
- test->ifobj_rx->umem->unaligned_mode = true;
+ test_spec_set_unaligned(test);
return testapp_invalid_desc(test);
}
@@ -2380,10 +2387,8 @@ int testapp_unaligned_inv_desc_4001_frame(struct test_spec *test)
u64 page_size, umem_size;
/* Odd frame size so the UMEM doesn't end near a page boundary. */
- test->ifobj_tx->umem->frame_size = 4001;
- test->ifobj_rx->umem->frame_size = 4001;
- test->ifobj_tx->umem->unaligned_mode = true;
- test->ifobj_rx->umem->unaligned_mode = true;
+ test_spec_set_frame_size(test, 4001);
+ test_spec_set_unaligned(test);
/* This test exists to test descriptors that staddle the end of
* the UMEM but not a page.
*/
@@ -2402,8 +2407,7 @@ int testapp_aligned_inv_desc_mb(struct test_spec *test)
int testapp_unaligned_inv_desc_mb(struct test_spec *test)
{
- test->ifobj_tx->umem->unaligned_mode = true;
- test->ifobj_rx->umem->unaligned_mode = true;
+ test_spec_set_unaligned(test);
return testapp_invalid_desc_mb(test);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net-next v3 2/4] selftests/xsk: Move UMEM state from ifobject to xsk_socket_info
2026-06-08 13:09 [PATCH net-next v3 0/4] selftests/xsk: simplify UMEM setup Tushar Vyavahare
2026-06-08 13:09 ` [PATCH net-next v3 1/4] selftests/xsk: Introduce helpers for setting UMEM properties Tushar Vyavahare
@ 2026-06-08 13:09 ` Tushar Vyavahare
2026-06-08 13:09 ` [PATCH net-next v3 3/4] selftests/xsk: Use umem_size() helper consistently Tushar Vyavahare
2026-06-08 13:09 ` [PATCH net-next v3 4/4] selftests/xsk: Introduce mmap_size in umem struct Tushar Vyavahare
3 siblings, 0 replies; 6+ messages in thread
From: Tushar Vyavahare @ 2026-06-08 13:09 UTC (permalink / raw)
To: netdev, magnus.karlsson, maciej.fijalkowski, stfomichev,
kernelxing, davem, kuba, pabeni, ast, daniel, tirthendu.sarkar,
tushar.vyavahare
Cc: bpf
Move UMEM ownership from ifobject to xsk_socket_info and access it
through xsk->umem.
Allocate one shared umem_real in ifobject_create() and let all
sockets reference it through xsk->umem, while keeping ownership in
xsk_arr[0]. Keep the existing goto-based error path in
ifobject_create() and free the allocation once in ifobject_delete().
Reset the existing umem_real in __test_spec_init() with memset()
instead of reallocating it.
Preserve shared-UMEM behavior by copying RX UMEM state into a TX-local
UMEM state in thread_common_ops_tx() and reset base_addr/next_buffer
before TX socket configuration.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
Signed-off-by: Tushar Vyavahare <tushar.vyavahare@intel.com>
---
.../selftests/bpf/prog_tests/test_xsk.c | 123 +++++++++++-------
.../selftests/bpf/prog_tests/test_xsk.h | 2 +-
2 files changed, 74 insertions(+), 51 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/test_xsk.c b/tools/testing/selftests/bpf/prog_tests/test_xsk.c
index 3369450da974..8356a4bb6d4c 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_xsk.c
+++ b/tools/testing/selftests/bpf/prog_tests/test_xsk.c
@@ -65,9 +65,9 @@ static void gen_eth_hdr(struct xsk_socket_info *xsk, struct ethhdr *eth_hdr)
eth_hdr->h_proto = htons(ETH_P_LOOPBACK);
}
-static bool is_umem_valid(struct ifobject *ifobj)
+static bool is_umem_valid(struct xsk_socket_info *xsk)
{
- return !!ifobj->umem->umem;
+ return !!xsk->umem->umem;
}
static u32 mode_to_xdp_flags(enum test_mode mode)
@@ -213,6 +213,7 @@ static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx,
for (i = 0; i < MAX_INTERFACES; i++) {
struct ifobject *ifobj = i ? ifobj_rx : ifobj_tx;
+ struct xsk_umem_info *umem_real;
ifobj->xsk = &ifobj->xsk_arr[0];
ifobj->use_poll = false;
@@ -229,24 +230,30 @@ static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx,
ifobj->tx_on = false;
}
- memset(ifobj->umem, 0, sizeof(*ifobj->umem));
- ifobj->umem->num_frames = DEFAULT_UMEM_BUFFERS;
- ifobj->umem->frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE;
-
+ umem_real = ifobj->xsk_arr[0].umem_real;
+ memset(umem_real, 0, sizeof(*umem_real));
for (j = 0; j < MAX_SOCKETS; j++) {
- memset(&ifobj->xsk_arr[j], 0, sizeof(ifobj->xsk_arr[j]));
- ifobj->xsk_arr[j].rxqsize = XSK_RING_CONS__DEFAULT_NUM_DESCS;
- ifobj->xsk_arr[j].batch_size = DEFAULT_BATCH_SIZE;
+ struct xsk_socket_info *xsk = &ifobj->xsk_arr[j];
+
+ memset(xsk, 0, sizeof(*xsk));
+ xsk->rxqsize = XSK_RING_CONS__DEFAULT_NUM_DESCS;
+ if (j == 0)
+ xsk->umem_real = umem_real;
+ xsk->umem = umem_real;
+ xsk->batch_size = DEFAULT_BATCH_SIZE;
if (i == 0)
- ifobj->xsk_arr[j].pkt_stream = test->tx_pkt_stream_default;
+ xsk->pkt_stream = test->tx_pkt_stream_default;
else
- ifobj->xsk_arr[j].pkt_stream = test->rx_pkt_stream_default;
+ xsk->pkt_stream = test->rx_pkt_stream_default;
- memcpy(ifobj->xsk_arr[j].src_mac, g_mac, ETH_ALEN);
- memcpy(ifobj->xsk_arr[j].dst_mac, g_mac, ETH_ALEN);
- ifobj->xsk_arr[j].src_mac[5] += ((j * 2) + 0);
- ifobj->xsk_arr[j].dst_mac[5] += ((j * 2) + 1);
+ memcpy(xsk->src_mac, g_mac, ETH_ALEN);
+ memcpy(xsk->dst_mac, g_mac, ETH_ALEN);
+ xsk->src_mac[5] += ((j * 2) + 0);
+ xsk->dst_mac[5] += ((j * 2) + 1);
}
+
+ ifobj->xsk->umem->num_frames = DEFAULT_UMEM_BUFFERS;
+ ifobj->xsk->umem->frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE;
}
if (ifobj_tx->hw_ring_size_supp)
@@ -305,14 +312,14 @@ static void test_spec_reset(struct test_spec *test)
static void test_spec_set_unaligned(struct test_spec *test)
{
- test->ifobj_tx->umem->unaligned_mode = true;
- test->ifobj_rx->umem->unaligned_mode = true;
+ test->ifobj_tx->xsk->umem->unaligned_mode = true;
+ test->ifobj_rx->xsk->umem->unaligned_mode = true;
}
static void test_spec_set_frame_size(struct test_spec *test, u32 size)
{
- test->ifobj_tx->umem->frame_size = size;
- test->ifobj_rx->umem->frame_size = size;
+ test->ifobj_tx->xsk->umem->frame_size = size;
+ test->ifobj_rx->xsk->umem->frame_size = size;
}
static void test_spec_set_xdp_prog(struct test_spec *test, struct bpf_program *xdp_prog_rx,
@@ -1003,7 +1010,7 @@ static int __receive_pkts(struct test_spec *test, struct xsk_socket_info *xsk)
return TEST_FAILURE;
if (!ret) {
- if (!is_umem_valid(test->ifobj_tx))
+ if (!is_umem_valid(test->ifobj_tx->xsk))
return TEST_PASS;
ksft_print_msg("ERROR: [%s] Poll timed out\n", __func__);
@@ -1163,7 +1170,7 @@ static int __send_pkts(struct ifobject *ifobject, struct xsk_socket_info *xsk, b
{
u32 i, idx = 0, valid_pkts = 0, valid_frags = 0, buffer_len;
struct pkt_stream *pkt_stream = xsk->pkt_stream;
- struct xsk_umem_info *umem = ifobject->umem;
+ struct xsk_umem_info *umem = xsk->umem;
bool use_poll = ifobject->use_poll;
struct pollfd fds = { };
int ret;
@@ -1222,7 +1229,7 @@ static int __send_pkts(struct ifobject *ifobject, struct xsk_socket_info *xsk, b
while (nb_frags_left--) {
struct xdp_desc *tx_desc = xsk_ring_prod__tx_desc(&xsk->tx, idx + i);
- tx_desc->addr = pkt_get_addr(pkt, ifobject->umem);
+ tx_desc->addr = pkt_get_addr(pkt, umem);
if (pkt_stream->verbatim) {
tx_desc->len = pkt->len;
tx_desc->options = pkt->options;
@@ -1315,7 +1322,7 @@ bool all_packets_sent(struct test_spec *test, unsigned long *bitmap)
static int send_pkts(struct test_spec *test, struct ifobject *ifobject)
{
- bool timeout = !is_umem_valid(test->ifobj_rx);
+ bool timeout = !is_umem_valid(test->ifobj_rx->xsk);
DECLARE_BITMAP(bitmap, test->nb_sockets);
u32 i, ret;
@@ -1500,14 +1507,25 @@ static int xsk_configure(struct test_spec *test, struct ifobject *ifobject,
static int thread_common_ops_tx(struct test_spec *test, struct ifobject *ifobject)
{
- int ret = xsk_configure(test, ifobject, test->ifobj_rx->umem, true);
+ struct xsk_umem_info *umem_rx, *umem_tx;
+ int ret;
+
+ if (!test->ifobj_rx || !test->ifobj_rx->xsk_arr[0].umem->umem) {
+ ksft_print_msg("Error: RX UMEM is not initialized before shared-UMEM TX setup\n");
+ return -EINVAL;
+ }
+
+ umem_rx = test->ifobj_rx->xsk_arr[0].umem;
+ umem_tx = ifobject->xsk_arr[0].umem_real;
+ memcpy(umem_tx, umem_rx, sizeof(*umem_tx));
+ umem_tx->base_addr = 0;
+ umem_tx->next_buffer = 0;
+ ret = xsk_configure(test, ifobject, umem_tx, true);
if (ret)
return ret;
ifobject->xsk = &ifobject->xsk_arr[0];
ifobject->xskmap = test->ifobj_rx->xskmap;
- memcpy(ifobject->umem, test->ifobj_rx->umem, sizeof(struct xsk_umem_info));
- ifobject->umem->base_addr = 0;
return 0;
}
@@ -1560,6 +1578,7 @@ static int xsk_populate_fill_ring(struct xsk_umem_info *umem, struct pkt_stream
static int thread_common_ops(struct test_spec *test, struct ifobject *ifobject)
{
+ struct xsk_umem_info *umem = ifobject->xsk->umem;
LIBBPF_OPTS(bpf_xdp_query_opts, opts);
int mmap_flags;
u64 umem_sz;
@@ -1567,10 +1586,10 @@ static int thread_common_ops(struct test_spec *test, struct ifobject *ifobject)
int ret;
u32 i;
- umem_sz = ifobject->umem->num_frames * ifobject->umem->frame_size;
+ umem_sz = umem->num_frames * umem->frame_size;
mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
- if (ifobject->umem->unaligned_mode)
+ if (umem->unaligned_mode)
mmap_flags |= MAP_HUGETLB | MAP_HUGE_2MB;
if (ifobject->shared_umem)
@@ -1580,11 +1599,11 @@ static int thread_common_ops(struct test_spec *test, struct ifobject *ifobject)
if (bufs == MAP_FAILED)
return -errno;
- ret = xsk_configure_umem(ifobject, ifobject->umem, bufs, umem_sz);
+ ret = xsk_configure_umem(ifobject, umem, bufs, umem_sz);
if (ret)
return ret;
- ret = xsk_configure(test, ifobject, ifobject->umem, false);
+ ret = xsk_configure(test, ifobject, umem, false);
if (ret)
return ret;
@@ -1593,14 +1612,13 @@ static int thread_common_ops(struct test_spec *test, struct ifobject *ifobject)
if (!ifobject->rx_on)
return 0;
- ret = xsk_populate_fill_ring(ifobject->umem, ifobject->xsk->pkt_stream,
+ ret = xsk_populate_fill_ring(umem, ifobject->xsk->pkt_stream,
ifobject->use_fill_ring);
if (ret)
return ret;
for (i = 0; i < test->nb_sockets; i++) {
- ifobject->xsk = &ifobject->xsk_arr[i];
- ret = xsk_update_xskmap(ifobject->xskmap, ifobject->xsk->xsk, i);
+ ret = xsk_update_xskmap(ifobject->xskmap, ifobject->xsk_arr[i].xsk, i);
if (ret)
return ret;
}
@@ -1687,14 +1705,15 @@ void *worker_testapp_validate_rx(void *arg)
static void testapp_clean_xsk_umem(struct ifobject *ifobj)
{
- u64 umem_sz = ifobj->umem->num_frames * ifobj->umem->frame_size;
+ struct xsk_umem_info *umem = ifobj->xsk->umem;
+ u64 umem_sz = umem->num_frames * umem->frame_size;
if (ifobj->shared_umem)
umem_sz *= 2;
umem_sz = ceil_u64(umem_sz, HUGEPAGE_SIZE) * HUGEPAGE_SIZE;
- xsk_umem__delete(ifobj->umem->umem);
- munmap(ifobj->umem->buffer, umem_sz);
+ xsk_umem__delete(umem->umem);
+ munmap(umem->buffer, umem_sz);
}
static void handler(int signum)
@@ -1857,8 +1876,8 @@ static int testapp_validate_traffic(struct test_spec *test)
struct ifobject *ifobj_rx = test->ifobj_rx;
struct ifobject *ifobj_tx = test->ifobj_tx;
- if ((ifobj_rx->umem->unaligned_mode && !ifobj_rx->unaligned_supp) ||
- (ifobj_tx->umem->unaligned_mode && !ifobj_tx->unaligned_supp)) {
+ if ((ifobj_rx->xsk->umem->unaligned_mode && !ifobj_rx->unaligned_supp) ||
+ (ifobj_tx->xsk->umem->unaligned_mode && !ifobj_tx->unaligned_supp)) {
ksft_print_msg("No huge pages present.\n");
return TEST_SKIP;
}
@@ -1965,12 +1984,13 @@ int testapp_xdp_prog_cleanup(struct test_spec *test)
int testapp_headroom(struct test_spec *test)
{
- test->ifobj_rx->umem->frame_headroom = UMEM_HEADROOM_TEST_SIZE;
+ test->ifobj_rx->xsk->umem->frame_headroom = UMEM_HEADROOM_TEST_SIZE;
return testapp_validate_traffic(test);
}
int testapp_stats_rx_dropped(struct test_spec *test)
{
+ struct xsk_umem_info *umem = test->ifobj_rx->xsk->umem;
u32 umem_tr = test->ifobj_tx->umem_tailroom;
if (test->mode == TEST_MODE_ZC) {
@@ -1980,7 +2000,7 @@ int testapp_stats_rx_dropped(struct test_spec *test)
if (pkt_stream_replace_half(test, (MIN_PKT_SIZE * 3) + umem_tr, 0))
return TEST_FAILURE;
- test->ifobj_rx->umem->frame_headroom = test->ifobj_rx->umem->frame_size -
+ umem->frame_headroom = umem->frame_size -
XDP_PACKET_HEADROOM - (MIN_PKT_SIZE * 2) - umem_tr;
if (pkt_stream_receive_half(test))
return TEST_FAILURE;
@@ -2074,7 +2094,7 @@ int testapp_send_receive_mb(struct test_spec *test)
int testapp_invalid_desc_mb(struct test_spec *test)
{
- struct xsk_umem_info *umem = test->ifobj_tx->umem;
+ struct xsk_umem_info *umem = test->ifobj_tx->xsk->umem;
u64 umem_size = umem->num_frames * umem->frame_size;
struct pkt pkts[] = {
/* Valid packet for synch to start with */
@@ -2115,7 +2135,7 @@ int testapp_invalid_desc_mb(struct test_spec *test)
int testapp_invalid_desc(struct test_spec *test)
{
- struct xsk_umem_info *umem = test->ifobj_tx->umem;
+ struct xsk_umem_info *umem = test->ifobj_tx->xsk->umem;
u64 umem_size = umem->num_frames * umem->frame_size;
struct pkt pkts[] = {
/* Zero packet address allowed */
@@ -2214,7 +2234,7 @@ int testapp_poll_txq_tmout(struct test_spec *test)
{
test->ifobj_tx->use_poll = true;
/* create invalid frame by set umem frame_size and pkt length equal to 2048 */
- test->ifobj_tx->umem->frame_size = 2048;
+ test->ifobj_tx->xsk->umem->frame_size = 2048;
if (pkt_stream_replace(test, 2 * DEFAULT_PKT_CNT, 2048))
return TEST_FAILURE;
return testapp_validate_traffic_single_thread(test, test->ifobj_tx);
@@ -2393,7 +2413,8 @@ int testapp_unaligned_inv_desc_4001_frame(struct test_spec *test)
* the UMEM but not a page.
*/
page_size = sysconf(_SC_PAGESIZE);
- umem_size = test->ifobj_tx->umem->num_frames * test->ifobj_tx->umem->frame_size;
+ umem_size = test->ifobj_tx->xsk->umem->num_frames *
+ test->ifobj_tx->xsk->umem->frame_size;
assert(umem_size % page_size > MIN_PKT_SIZE);
assert(umem_size % page_size < page_size - MIN_PKT_SIZE);
@@ -2451,9 +2472,9 @@ int testapp_hw_sw_max_ring_size(struct test_spec *test)
test->total_steps = 2;
test->ifobj_tx->ring.tx_pending = test->ifobj_tx->ring.tx_max_pending;
test->ifobj_tx->ring.rx_pending = test->ifobj_tx->ring.rx_max_pending;
- test->ifobj_rx->umem->num_frames = max_descs;
- test->ifobj_rx->umem->fill_size = max_descs;
- test->ifobj_rx->umem->comp_size = max_descs;
+ test->ifobj_rx->xsk->umem->num_frames = max_descs;
+ test->ifobj_rx->xsk->umem->fill_size = max_descs;
+ test->ifobj_rx->xsk->umem->comp_size = max_descs;
test->ifobj_tx->xsk->batch_size = XSK_RING_PROD__DEFAULT_NUM_DESCS;
test->ifobj_rx->xsk->batch_size = XSK_RING_PROD__DEFAULT_NUM_DESCS;
@@ -2594,8 +2615,8 @@ struct ifobject *ifobject_create(void)
if (!ifobj->xsk_arr)
goto out_xsk_arr;
- ifobj->umem = calloc(1, sizeof(*ifobj->umem));
- if (!ifobj->umem)
+ ifobj->xsk_arr[0].umem_real = calloc(1, sizeof(struct xsk_umem_info));
+ if (!ifobj->xsk_arr[0].umem_real)
goto out_umem;
return ifobj;
@@ -2609,7 +2630,9 @@ struct ifobject *ifobject_create(void)
void ifobject_delete(struct ifobject *ifobj)
{
- free(ifobj->umem);
+ if (ifobj->xsk_arr)
+ free(ifobj->xsk_arr[0].umem_real);
+
free(ifobj->xsk_arr);
free(ifobj);
}
diff --git a/tools/testing/selftests/bpf/prog_tests/test_xsk.h b/tools/testing/selftests/bpf/prog_tests/test_xsk.h
index 1ab8aee4ce56..99003995d7c3 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_xsk.h
+++ b/tools/testing/selftests/bpf/prog_tests/test_xsk.h
@@ -83,6 +83,7 @@ typedef int (*test_func_t)(struct test_spec *test);
struct xsk_socket_info {
struct xsk_ring_cons rx;
struct xsk_ring_prod tx;
+ struct xsk_umem_info *umem_real;
struct xsk_umem_info *umem;
struct xsk_socket *xsk;
struct pkt_stream *pkt_stream;
@@ -123,7 +124,6 @@ struct ifobject {
char ifname[MAX_INTERFACE_NAME_CHARS];
struct xsk_socket_info *xsk;
struct xsk_socket_info *xsk_arr;
- struct xsk_umem_info *umem;
thread_func_t func_ptr;
validation_func_t validation_func;
struct xsk_xdp_progs *xdp_progs;
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net-next v3 3/4] selftests/xsk: Use umem_size() helper consistently
2026-06-08 13:09 [PATCH net-next v3 0/4] selftests/xsk: simplify UMEM setup Tushar Vyavahare
2026-06-08 13:09 ` [PATCH net-next v3 1/4] selftests/xsk: Introduce helpers for setting UMEM properties Tushar Vyavahare
2026-06-08 13:09 ` [PATCH net-next v3 2/4] selftests/xsk: Move UMEM state from ifobject to xsk_socket_info Tushar Vyavahare
@ 2026-06-08 13:09 ` Tushar Vyavahare
2026-06-08 13:09 ` [PATCH net-next v3 4/4] selftests/xsk: Introduce mmap_size in umem struct Tushar Vyavahare
3 siblings, 0 replies; 6+ messages in thread
From: Tushar Vyavahare @ 2026-06-08 13:09 UTC (permalink / raw)
To: netdev, magnus.karlsson, maciej.fijalkowski, stfomichev,
kernelxing, davem, kuba, pabeni, ast, daniel, tirthendu.sarkar,
tushar.vyavahare
Cc: bpf
Replace remaining open-coded `umem->num_frames * umem->frame_size`
calculations in test_xsk.c with the existing `umem_size()` helper.
This keeps UMEM size computation centralized, avoids duplicated arithmetic,
and improves readability with no intended behavior change.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
Signed-off-by: Tushar Vyavahare <tushar.vyavahare@intel.com>
Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
---
.../selftests/bpf/prog_tests/test_xsk.c | 36 +++++++++----------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/test_xsk.c b/tools/testing/selftests/bpf/prog_tests/test_xsk.c
index 8356a4bb6d4c..17a467a7dd7f 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_xsk.c
+++ b/tools/testing/selftests/bpf/prog_tests/test_xsk.c
@@ -829,11 +829,11 @@ static bool is_frag_valid(struct xsk_umem_info *umem, u64 addr, u32 len, u32 exp
{
u32 seqnum, pkt_nb, *pkt_data, words_to_end, expected_seqnum;
void *data = xsk_umem__get_data(umem->buffer, addr);
+ u64 umem_sz = umem_size(umem);
addr -= umem->base_addr;
- if (addr >= umem->num_frames * umem->frame_size ||
- addr + len > umem->num_frames * umem->frame_size) {
+ if (addr >= umem_sz || addr + len > umem_sz) {
ksft_print_msg("Frag invalid addr: %llx len: %u\n",
(unsigned long long)addr, len);
return false;
@@ -1586,7 +1586,7 @@ static int thread_common_ops(struct test_spec *test, struct ifobject *ifobject)
int ret;
u32 i;
- umem_sz = umem->num_frames * umem->frame_size;
+ umem_sz = umem_size(umem);
mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
if (umem->unaligned_mode)
@@ -1706,12 +1706,13 @@ void *worker_testapp_validate_rx(void *arg)
static void testapp_clean_xsk_umem(struct ifobject *ifobj)
{
struct xsk_umem_info *umem = ifobj->xsk->umem;
- u64 umem_sz = umem->num_frames * umem->frame_size;
+ u64 umem_sz = umem_size(umem);
if (ifobj->shared_umem)
umem_sz *= 2;
umem_sz = ceil_u64(umem_sz, HUGEPAGE_SIZE) * HUGEPAGE_SIZE;
+
xsk_umem__delete(umem->umem);
munmap(umem->buffer, umem_sz);
}
@@ -2095,7 +2096,7 @@ int testapp_send_receive_mb(struct test_spec *test)
int testapp_invalid_desc_mb(struct test_spec *test)
{
struct xsk_umem_info *umem = test->ifobj_tx->xsk->umem;
- u64 umem_size = umem->num_frames * umem->frame_size;
+ u64 umem_sz = umem_size(umem);
struct pkt pkts[] = {
/* Valid packet for synch to start with */
{0, MIN_PKT_SIZE, 0, true, 0},
@@ -2105,7 +2106,7 @@ int testapp_invalid_desc_mb(struct test_spec *test)
{0, 0, 0, false, 0},
/* Invalid address in the second frame */
{0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD},
- {umem_size, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD},
+ {umem_sz, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD},
/* Invalid len in the middle */
{0, XSK_UMEM__LARGE_FRAME_SIZE, 0, false, XDP_PKT_CONTD},
{0, XSK_UMEM__INVALID_FRAME_SIZE, 0, false, XDP_PKT_CONTD},
@@ -2136,7 +2137,7 @@ int testapp_invalid_desc_mb(struct test_spec *test)
int testapp_invalid_desc(struct test_spec *test)
{
struct xsk_umem_info *umem = test->ifobj_tx->xsk->umem;
- u64 umem_size = umem->num_frames * umem->frame_size;
+ u64 umem_sz = umem_size(umem);
struct pkt pkts[] = {
/* Zero packet address allowed */
{0, MIN_PKT_SIZE, 0, true},
@@ -2147,11 +2148,11 @@ int testapp_invalid_desc(struct test_spec *test)
/* Packet too large */
{0, XSK_UMEM__INVALID_FRAME_SIZE, 0, false},
/* Up to end of umem allowed */
- {umem_size - MIN_PKT_SIZE - 2 * umem->frame_size, MIN_PKT_SIZE, 0, true},
+ {umem_sz - MIN_PKT_SIZE - 2 * umem->frame_size, MIN_PKT_SIZE, 0, true},
/* After umem ends */
- {umem_size, MIN_PKT_SIZE, 0, false},
+ {umem_sz, MIN_PKT_SIZE, 0, false},
/* Straddle the end of umem */
- {umem_size - MIN_PKT_SIZE / 2, MIN_PKT_SIZE, 0, false},
+ {umem_sz - MIN_PKT_SIZE / 2, MIN_PKT_SIZE, 0, false},
/* Straddle a 4K boundary */
{0x1000 - MIN_PKT_SIZE / 2, MIN_PKT_SIZE, 0, false},
/* Straddle a 2K boundary */
@@ -2169,9 +2170,9 @@ int testapp_invalid_desc(struct test_spec *test)
}
if (test->ifobj_tx->shared_umem) {
- pkts[4].offset += umem_size;
- pkts[5].offset += umem_size;
- pkts[6].offset += umem_size;
+ pkts[4].offset += umem_sz;
+ pkts[5].offset += umem_sz;
+ pkts[6].offset += umem_sz;
}
if (pkt_stream_generate_custom(test, pkts, ARRAY_SIZE(pkts)))
@@ -2404,7 +2405,7 @@ int testapp_unaligned_inv_desc(struct test_spec *test)
int testapp_unaligned_inv_desc_4001_frame(struct test_spec *test)
{
- u64 page_size, umem_size;
+ u64 page_size, umem_sz;
/* Odd frame size so the UMEM doesn't end near a page boundary. */
test_spec_set_frame_size(test, 4001);
@@ -2413,10 +2414,9 @@ int testapp_unaligned_inv_desc_4001_frame(struct test_spec *test)
* the UMEM but not a page.
*/
page_size = sysconf(_SC_PAGESIZE);
- umem_size = test->ifobj_tx->xsk->umem->num_frames *
- test->ifobj_tx->xsk->umem->frame_size;
- assert(umem_size % page_size > MIN_PKT_SIZE);
- assert(umem_size % page_size < page_size - MIN_PKT_SIZE);
+ umem_sz = umem_size(test->ifobj_tx->xsk->umem);
+ assert(umem_sz % page_size > MIN_PKT_SIZE);
+ assert(umem_sz % page_size < page_size - MIN_PKT_SIZE);
return testapp_invalid_desc(test);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net-next v3 4/4] selftests/xsk: Introduce mmap_size in umem struct
2026-06-08 13:09 [PATCH net-next v3 0/4] selftests/xsk: simplify UMEM setup Tushar Vyavahare
` (2 preceding siblings ...)
2026-06-08 13:09 ` [PATCH net-next v3 3/4] selftests/xsk: Use umem_size() helper consistently Tushar Vyavahare
@ 2026-06-08 13:09 ` Tushar Vyavahare
2026-06-09 13:10 ` sashiko-bot
3 siblings, 1 reply; 6+ messages in thread
From: Tushar Vyavahare @ 2026-06-08 13:09 UTC (permalink / raw)
To: netdev, magnus.karlsson, maciej.fijalkowski, stfomichev,
kernelxing, davem, kuba, pabeni, ast, daniel, tirthendu.sarkar,
tushar.vyavahare
Cc: bpf
UMEM teardown currently recomputes the munmap() length from frame
geometry, shared-UMEM adjustment, and hugepage rounding. This duplicates
setup-time logic in cleanup and relies on re-deriving the mapping size
instead of using the size originally established for the mapping.
Store the final mapping length in xsk_umem_info as mmap_size when the
UMEM mapping is created, and use that value during teardown.
Also join the RX worker thread before cleanup in the single-thread
path. This establishes synchronization before reading umem->mmap_size
in teardown and avoids a potential visibility race.
This removes duplicated size arithmetic in cleanup and makes munmap()
use the canonical mapping size recorded at setup time.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
Signed-off-by: Tushar Vyavahare <tushar.vyavahare@intel.com>
Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
---
.../selftests/bpf/prog_tests/test_xsk.c | 20 +++++++++----------
.../selftests/bpf/prog_tests/test_xsk.h | 1 +
2 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/test_xsk.c b/tools/testing/selftests/bpf/prog_tests/test_xsk.c
index 17a467a7dd7f..72875071d4f1 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_xsk.c
+++ b/tools/testing/selftests/bpf/prog_tests/test_xsk.c
@@ -1581,7 +1581,7 @@ static int thread_common_ops(struct test_spec *test, struct ifobject *ifobject)
struct xsk_umem_info *umem = ifobject->xsk->umem;
LIBBPF_OPTS(bpf_xdp_query_opts, opts);
int mmap_flags;
- u64 umem_sz;
+ u64 umem_sz, mmap_sz;
void *bufs;
int ret;
u32 i;
@@ -1595,10 +1595,15 @@ static int thread_common_ops(struct test_spec *test, struct ifobject *ifobject)
if (ifobject->shared_umem)
umem_sz *= 2;
- bufs = mmap(NULL, umem_sz, PROT_READ | PROT_WRITE, mmap_flags, -1, 0);
+ mmap_sz = umem->unaligned_mode ?
+ ceil_u64(umem_sz, HUGEPAGE_SIZE) * HUGEPAGE_SIZE : umem_sz;
+
+ bufs = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE, mmap_flags, -1, 0);
if (bufs == MAP_FAILED)
return -errno;
+ umem->mmap_size = mmap_sz;
+
ret = xsk_configure_umem(ifobject, umem, bufs, umem_sz);
if (ret)
return ret;
@@ -1706,15 +1711,9 @@ void *worker_testapp_validate_rx(void *arg)
static void testapp_clean_xsk_umem(struct ifobject *ifobj)
{
struct xsk_umem_info *umem = ifobj->xsk->umem;
- u64 umem_sz = umem_size(umem);
-
- if (ifobj->shared_umem)
- umem_sz *= 2;
-
- umem_sz = ceil_u64(umem_sz, HUGEPAGE_SIZE) * HUGEPAGE_SIZE;
xsk_umem__delete(umem->umem);
- munmap(umem->buffer, umem_sz);
+ munmap(umem->buffer, umem->mmap_size);
}
static void handler(int signum)
@@ -1857,8 +1856,7 @@ static int __testapp_validate_traffic(struct test_spec *test, struct ifobject *i
if (!ifobj2)
pthread_kill(t0, SIGUSR1);
- else
- pthread_join(t0, NULL);
+ pthread_join(t0, NULL);
if (test->total_steps == test->current_step || test->fail) {
clean_sockets(test, ifobj1);
diff --git a/tools/testing/selftests/bpf/prog_tests/test_xsk.h b/tools/testing/selftests/bpf/prog_tests/test_xsk.h
index 99003995d7c3..4313d0d87235 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_xsk.h
+++ b/tools/testing/selftests/bpf/prog_tests/test_xsk.h
@@ -103,6 +103,7 @@ struct xsk_umem_info {
struct xsk_ring_cons cq;
struct xsk_umem *umem;
u64 next_buffer;
+ u64 mmap_size;
u32 num_frames;
u32 frame_headroom;
void *buffer;
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH net-next v3 4/4] selftests/xsk: Introduce mmap_size in umem struct
2026-06-08 13:09 ` [PATCH net-next v3 4/4] selftests/xsk: Introduce mmap_size in umem struct Tushar Vyavahare
@ 2026-06-09 13:10 ` sashiko-bot
0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-06-09 13:10 UTC (permalink / raw)
To: Tushar Vyavahare; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Unconditional `pthread_join` in the single-thread path can cause the test suite to hang indefinitely due to a deadlock with an unsafe signal handler.
--
commit 2b44f1770c5b4b9bb0b75f25f4cfb408f2d008dd
Author: Tushar Vyavahare <tushar.vyavahare@intel.com>
Subject: selftests/xsk: Introduce mmap_size in umem struct
This commit stores the final mapping length in xsk_umem_info as mmap_size when
the UMEM mapping is created, and uses that value during teardown. It also
joins the RX worker thread before cleanup in the single-thread path.
> diff --git a/tools/testing/selftests/bpf/prog_tests/test_xsk.c b/tools/testing/selftests/bpf/prog_tests/test_xsk.c
> index 17a467a7dd7f6..72875071d4f12 100644
> --- a/tools/testing/selftests/bpf/prog_tests/test_xsk.c
> +++ b/tools/testing/selftests/bpf/prog_tests/test_xsk.c
[ ... ]
> @@ -1857,8 +1856,7 @@ static int __testapp_validate_traffic(struct test_spec *test, struct ifobject *i
>
> if (!ifobj2)
> pthread_kill(t0, SIGUSR1);
> - else
> - pthread_join(t0, NULL);
> + pthread_join(t0, NULL);
[Severity: Medium]
Will this unconditional pthread_join() cause the test suite to hang
indefinitely if the worker thread self-deadlocks?
The worker thread t0 is terminated by sending SIGUSR1 asynchronously, which is
caught by handler():
tools/testing/selftests/bpf/prog_tests/test_xsk.c:handler() {
pthread_exit(NULL);
}
Since pthread_exit() is not async-signal-safe, if the signal interrupts the
worker thread while it holds an internal libc lock (such as during memory
allocation or mutex acquisition), pthread_exit() can self-deadlock when
attempting to acquire the same lock during thread-local teardown.
Before this patch, the deadlocked thread was leaked but did not block the main
test thread. By adding an unconditional pthread_join(t0, NULL) here, won't the
main thread now block forever waiting for the deadlocked thread, causing the
entire test suite to hang?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260608130938.958793-1-tushar.vyavahare@intel.com?part=4
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-06-09 13:10 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-08 13:09 [PATCH net-next v3 0/4] selftests/xsk: simplify UMEM setup Tushar Vyavahare
2026-06-08 13:09 ` [PATCH net-next v3 1/4] selftests/xsk: Introduce helpers for setting UMEM properties Tushar Vyavahare
2026-06-08 13:09 ` [PATCH net-next v3 2/4] selftests/xsk: Move UMEM state from ifobject to xsk_socket_info Tushar Vyavahare
2026-06-08 13:09 ` [PATCH net-next v3 3/4] selftests/xsk: Use umem_size() helper consistently Tushar Vyavahare
2026-06-08 13:09 ` [PATCH net-next v3 4/4] selftests/xsk: Introduce mmap_size in umem struct Tushar Vyavahare
2026-06-09 13:10 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.