* [PATCH net-next v2 1/4] selftests/xsk: Introduce helpers for setting UMEM properties
2026-06-03 6:03 [PATCH net-next v2 0/4] selftests/xsk: simplify UMEM setup Tushar Vyavahare
@ 2026-06-03 6:03 ` Tushar Vyavahare
2026-06-03 14:52 ` Maciej Fijalkowski
2026-06-03 6:03 ` [PATCH net-next v2 2/4] selftests/xsk: Move UMEM state from ifobject to xsk_socket_info Tushar Vyavahare
` (2 subsequent siblings)
3 siblings, 1 reply; 11+ messages in thread
From: Tushar Vyavahare @ 2026-06-03 6:03 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>
---
.../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] 11+ messages in thread* Re: [PATCH net-next v2 1/4] selftests/xsk: Introduce helpers for setting UMEM properties
2026-06-03 6:03 ` [PATCH net-next v2 1/4] selftests/xsk: Introduce helpers for setting UMEM properties Tushar Vyavahare
@ 2026-06-03 14:52 ` Maciej Fijalkowski
0 siblings, 0 replies; 11+ messages in thread
From: Maciej Fijalkowski @ 2026-06-03 14:52 UTC (permalink / raw)
To: Tushar Vyavahare
Cc: netdev, magnus.karlsson, stfomichev, kernelxing, davem, kuba,
pabeni, ast, daniel, tirthendu.sarkar, bpf
On Wed, Jun 03, 2026 at 11:33:24AM +0530, Tushar Vyavahare wrote:
> 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 [flat|nested] 11+ messages in thread
* [PATCH net-next v2 2/4] selftests/xsk: Move UMEM state from ifobject to xsk_socket_info
2026-06-03 6:03 [PATCH net-next v2 0/4] selftests/xsk: simplify UMEM setup Tushar Vyavahare
2026-06-03 6:03 ` [PATCH net-next v2 1/4] selftests/xsk: Introduce helpers for setting UMEM properties Tushar Vyavahare
@ 2026-06-03 6:03 ` Tushar Vyavahare
2026-06-03 14:51 ` Maciej Fijalkowski
2026-06-03 6:03 ` [PATCH net-next v2 3/4] selftests/xsk: Use umem_size() helper consistently Tushar Vyavahare
2026-06-03 6:03 ` [PATCH net-next v2 4/4] selftests/xsk: Introduce mmap_size in umem struct Tushar Vyavahare
3 siblings, 1 reply; 11+ messages in thread
From: Tushar Vyavahare @ 2026-06-03 6:03 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 | 133 +++++++++++-------
.../selftests/bpf/prog_tests/test_xsk.h | 2 +-
2 files changed, 80 insertions(+), 55 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..7e0d34111b2f 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,
@@ -623,10 +630,10 @@ static void pkt_stream_cancel(struct pkt_stream *pkt_stream)
pkt_stream->current_pkt_nb--;
}
-static void pkt_generate(struct xsk_socket_info *xsk, struct xsk_umem_info *umem, u64 addr, u32 len,
- u32 pkt_nb, u32 bytes_written)
+static void pkt_generate(struct xsk_socket_info *xsk, u64 addr, u32 len, u32 pkt_nb,
+ u32 bytes_written)
{
- void *data = xsk_umem__get_data(umem->buffer, addr);
+ void *data = xsk_umem__get_data(xsk->umem->buffer, addr);
if (len < MIN_PKT_SIZE)
return;
@@ -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;
@@ -1234,7 +1241,7 @@ static int __send_pkts(struct ifobject *ifobject, struct xsk_socket_info *xsk, b
tx_desc->options = 0;
}
if (pkt->valid)
- pkt_generate(xsk, umem, tx_desc->addr, tx_desc->len, pkt->pkt_nb,
+ pkt_generate(xsk, tx_desc->addr, tx_desc->len, pkt->pkt_nb,
bytes_written);
bytes_written += tx_desc->len;
@@ -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)
@@ -1856,9 +1875,11 @@ static int testapp_validate_traffic(struct test_spec *test)
{
struct ifobject *ifobj_rx = test->ifobj_rx;
struct ifobject *ifobj_tx = test->ifobj_tx;
+ struct xsk_umem_info *umem_rx = ifobj_rx->xsk->umem;
+ struct xsk_umem_info *umem_tx = ifobj_tx->xsk->umem;
- if ((ifobj_rx->umem->unaligned_mode && !ifobj_rx->unaligned_supp) ||
- (ifobj_tx->umem->unaligned_mode && !ifobj_tx->unaligned_supp)) {
+ if ((umem_rx->unaligned_mode && !ifobj_rx->unaligned_supp) ||
+ (umem_tx->unaligned_mode && !ifobj_tx->unaligned_supp)) {
ksft_print_msg("No huge pages present.\n");
return TEST_SKIP;
}
@@ -1965,12 +1986,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 +2002,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 +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->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 +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->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 +2236,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 +2415,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 +2474,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 +2617,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 +2632,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] 11+ messages in thread* Re: [PATCH net-next v2 2/4] selftests/xsk: Move UMEM state from ifobject to xsk_socket_info
2026-06-03 6:03 ` [PATCH net-next v2 2/4] selftests/xsk: Move UMEM state from ifobject to xsk_socket_info Tushar Vyavahare
@ 2026-06-03 14:51 ` Maciej Fijalkowski
2026-06-04 6:51 ` Vyavahare, Tushar
0 siblings, 1 reply; 11+ messages in thread
From: Maciej Fijalkowski @ 2026-06-03 14:51 UTC (permalink / raw)
To: Tushar Vyavahare
Cc: netdev, magnus.karlsson, stfomichev, kernelxing, davem, kuba,
pabeni, ast, daniel, tirthendu.sarkar, bpf
On Wed, Jun 03, 2026 at 11:33:25AM +0530, Tushar Vyavahare wrote:
> 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 | 133 +++++++++++-------
> .../selftests/bpf/prog_tests/test_xsk.h | 2 +-
> 2 files changed, 80 insertions(+), 55 deletions(-)
...
> -static void pkt_generate(struct xsk_socket_info *xsk, struct xsk_umem_info *umem, u64 addr, u32 len,
> - u32 pkt_nb, u32 bytes_written)
> +static void pkt_generate(struct xsk_socket_info *xsk, u64 addr, u32 len, u32 pkt_nb,
> + u32 bytes_written)
> {
> - void *data = xsk_umem__get_data(umem->buffer, addr);
> + void *data = xsk_umem__get_data(xsk->umem->buffer, addr);
>
> if (len < MIN_PKT_SIZE)
> return;
> @@ -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;
> @@ -1234,7 +1241,7 @@ static int __send_pkts(struct ifobject *ifobject, struct xsk_socket_info *xsk, b
> tx_desc->options = 0;
> }
> if (pkt->valid)
> - pkt_generate(xsk, umem, tx_desc->addr, tx_desc->len, pkt->pkt_nb,
> + pkt_generate(xsk, tx_desc->addr, tx_desc->len, pkt->pkt_nb,
Nit: you have the umem pointer handy, what's the point to change
pkt_generate() interface?
> bytes_written);
> bytes_written += tx_desc->len;
>
...
> @@ -1856,9 +1875,11 @@ static int testapp_validate_traffic(struct test_spec *test)
> {
> struct ifobject *ifobj_rx = test->ifobj_rx;
> struct ifobject *ifobj_tx = test->ifobj_tx;
> + struct xsk_umem_info *umem_rx = ifobj_rx->xsk->umem;
> + struct xsk_umem_info *umem_tx = ifobj_tx->xsk->umem;
>
> - if ((ifobj_rx->umem->unaligned_mode && !ifobj_rx->unaligned_supp) ||
> - (ifobj_tx->umem->unaligned_mode && !ifobj_tx->unaligned_supp)) {
> + if ((umem_rx->unaligned_mode && !ifobj_rx->unaligned_supp) ||
> + (umem_tx->unaligned_mode && !ifobj_tx->unaligned_supp)) {
> ksft_print_msg("No huge pages present.\n");
> return TEST_SKIP;
> }
this hunk does not add any value IMHO.
^ permalink raw reply [flat|nested] 11+ messages in thread* RE: [PATCH net-next v2 2/4] selftests/xsk: Move UMEM state from ifobject to xsk_socket_info
2026-06-03 14:51 ` Maciej Fijalkowski
@ 2026-06-04 6:51 ` Vyavahare, Tushar
0 siblings, 0 replies; 11+ messages in thread
From: Vyavahare, Tushar @ 2026-06-04 6:51 UTC (permalink / raw)
To: Fijalkowski, Maciej
Cc: netdev@vger.kernel.org, Karlsson, Magnus, stfomichev@gmail.com,
kernelxing@tencent.com, davem@davemloft.net, kuba@kernel.org,
pabeni@redhat.com, ast@kernel.org, daniel@iogearbox.net,
Sarkar, Tirthendu, bpf@vger.kernel.org
> -----Original Message-----
> From: Fijalkowski, Maciej <maciej.fijalkowski@intel.com>
> Sent: Wednesday, June 3, 2026 8:22 PM
> To: Vyavahare, Tushar <tushar.vyavahare@intel.com>
> Cc: netdev@vger.kernel.org; Karlsson, Magnus
> <magnus.karlsson@intel.com>; stfomichev@gmail.com;
> kernelxing@tencent.com; davem@davemloft.net; kuba@kernel.org;
> pabeni@redhat.com; ast@kernel.org; daniel@iogearbox.net; Sarkar,
> Tirthendu <tirthendu.sarkar@intel.com>; bpf@vger.kernel.org
> Subject: Re: [PATCH net-next v2 2/4] selftests/xsk: Move UMEM state from
> ifobject to xsk_socket_info
>
> On Wed, Jun 03, 2026 at 11:33:25AM +0530, Tushar Vyavahare wrote:
> > 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 | 133 +++++++++++-------
> > .../selftests/bpf/prog_tests/test_xsk.h | 2 +-
> > 2 files changed, 80 insertions(+), 55 deletions(-)
>
> ...
>
> > -static void pkt_generate(struct xsk_socket_info *xsk, struct xsk_umem_info
> *umem, u64 addr, u32 len,
> > - u32 pkt_nb, u32 bytes_written)
> > +static void pkt_generate(struct xsk_socket_info *xsk, u64 addr, u32 len,
> u32 pkt_nb,
> > + u32 bytes_written)
> > {
> > - void *data = xsk_umem__get_data(umem->buffer, addr);
> > + void *data = xsk_umem__get_data(xsk->umem->buffer, addr);
> >
> > if (len < MIN_PKT_SIZE)
> > return;
> > @@ -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;
> > @@ -1234,7 +1241,7 @@ static int __send_pkts(struct ifobject *ifobject,
> struct xsk_socket_info *xsk, b
> > tx_desc->options = 0;
> > }
> > if (pkt->valid)
> > - pkt_generate(xsk, umem, tx_desc->addr,
> tx_desc->len, pkt->pkt_nb,
> > + pkt_generate(xsk, tx_desc->addr, tx_desc-
> >len, pkt->pkt_nb,
>
> Nit: you have the umem pointer handy, what's the point to change
> pkt_generate() interface?
>
Thanks for the catch; I've reverted that part and kept pkt_generate() using a local
umem pointer to avoid unnecessary interface churn.
-Tushar
> > bytes_written);
> > bytes_written += tx_desc->len;
> >
>
> ...
>
> > @@ -1856,9 +1875,11 @@ static int testapp_validate_traffic(struct
> > test_spec *test) {
> > struct ifobject *ifobj_rx = test->ifobj_rx;
> > struct ifobject *ifobj_tx = test->ifobj_tx;
> > + struct xsk_umem_info *umem_rx = ifobj_rx->xsk->umem;
> > + struct xsk_umem_info *umem_tx = ifobj_tx->xsk->umem;
> >
> > - if ((ifobj_rx->umem->unaligned_mode && !ifobj_rx->unaligned_supp)
> ||
> > - (ifobj_tx->umem->unaligned_mode && !ifobj_tx->unaligned_supp))
> {
> > + if ((umem_rx->unaligned_mode && !ifobj_rx->unaligned_supp) ||
> > + (umem_tx->unaligned_mode && !ifobj_tx->unaligned_supp)) {
> > ksft_print_msg("No huge pages present.\n");
> > return TEST_SKIP;
> > }
>
> this hunk does not add any value IMHO.
Agreed, this was unnecessary indirection. I've removed umem_rx/umem_tx and
now use direct ifobj_{rx,tx}->xsk->umem access. I'll send v3 with this fix.
-Tushar
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH net-next v2 3/4] selftests/xsk: Use umem_size() helper consistently
2026-06-03 6:03 [PATCH net-next v2 0/4] selftests/xsk: simplify UMEM setup Tushar Vyavahare
2026-06-03 6:03 ` [PATCH net-next v2 1/4] selftests/xsk: Introduce helpers for setting UMEM properties Tushar Vyavahare
2026-06-03 6:03 ` [PATCH net-next v2 2/4] selftests/xsk: Move UMEM state from ifobject to xsk_socket_info Tushar Vyavahare
@ 2026-06-03 6:03 ` Tushar Vyavahare
2026-06-03 15:34 ` Maciej Fijalkowski
2026-06-03 6:03 ` [PATCH net-next v2 4/4] selftests/xsk: Introduce mmap_size in umem struct Tushar Vyavahare
3 siblings, 1 reply; 11+ messages in thread
From: Tushar Vyavahare @ 2026-06-03 6:03 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>
---
.../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 7e0d34111b2f..f1730466ffd9 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);
}
@@ -2097,7 +2098,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},
@@ -2107,7 +2108,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},
@@ -2138,7 +2139,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},
@@ -2149,11 +2150,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 */
@@ -2171,9 +2172,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)))
@@ -2406,7 +2407,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);
@@ -2415,10 +2416,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] 11+ messages in thread* Re: [PATCH net-next v2 3/4] selftests/xsk: Use umem_size() helper consistently
2026-06-03 6:03 ` [PATCH net-next v2 3/4] selftests/xsk: Use umem_size() helper consistently Tushar Vyavahare
@ 2026-06-03 15:34 ` Maciej Fijalkowski
0 siblings, 0 replies; 11+ messages in thread
From: Maciej Fijalkowski @ 2026-06-03 15:34 UTC (permalink / raw)
To: Tushar Vyavahare
Cc: netdev, magnus.karlsson, stfomichev, kernelxing, davem, kuba,
pabeni, ast, daniel, tirthendu.sarkar, bpf
On Wed, Jun 03, 2026 at 11:33:26AM +0530, Tushar Vyavahare wrote:
> 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 7e0d34111b2f..f1730466ffd9 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);
> }
> @@ -2097,7 +2098,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},
> @@ -2107,7 +2108,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},
> @@ -2138,7 +2139,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},
> @@ -2149,11 +2150,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 */
> @@ -2171,9 +2172,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)))
> @@ -2406,7 +2407,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);
> @@ -2415,10 +2416,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 [flat|nested] 11+ messages in thread
* [PATCH net-next v2 4/4] selftests/xsk: Introduce mmap_size in umem struct
2026-06-03 6:03 [PATCH net-next v2 0/4] selftests/xsk: simplify UMEM setup Tushar Vyavahare
` (2 preceding siblings ...)
2026-06-03 6:03 ` [PATCH net-next v2 3/4] selftests/xsk: Use umem_size() helper consistently Tushar Vyavahare
@ 2026-06-03 6:03 ` Tushar Vyavahare
2026-06-03 15:35 ` Maciej Fijalkowski
2026-06-04 6:48 ` sashiko-bot
3 siblings, 2 replies; 11+ messages in thread
From: Tushar Vyavahare @ 2026-06-03 6:03 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>
---
.../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 f1730466ffd9..e94c38a1faf4 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] 11+ messages in thread* Re: [PATCH net-next v2 4/4] selftests/xsk: Introduce mmap_size in umem struct
2026-06-03 6:03 ` [PATCH net-next v2 4/4] selftests/xsk: Introduce mmap_size in umem struct Tushar Vyavahare
@ 2026-06-03 15:35 ` Maciej Fijalkowski
2026-06-04 6:48 ` sashiko-bot
1 sibling, 0 replies; 11+ messages in thread
From: Maciej Fijalkowski @ 2026-06-03 15:35 UTC (permalink / raw)
To: Tushar Vyavahare
Cc: netdev, magnus.karlsson, stfomichev, kernelxing, davem, kuba,
pabeni, ast, daniel, tirthendu.sarkar, bpf
On Wed, Jun 03, 2026 at 11:33:27AM +0530, Tushar Vyavahare wrote:
> 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 f1730466ffd9..e94c38a1faf4 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 [flat|nested] 11+ messages in thread* Re: [PATCH net-next v2 4/4] selftests/xsk: Introduce mmap_size in umem struct
2026-06-03 6:03 ` [PATCH net-next v2 4/4] selftests/xsk: Introduce mmap_size in umem struct Tushar Vyavahare
2026-06-03 15:35 ` Maciej Fijalkowski
@ 2026-06-04 6:48 ` sashiko-bot
1 sibling, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-06-04 6:48 UTC (permalink / raw)
To: Tushar Vyavahare; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
Pre-existing issues:
- [High] Worker thread calls `pthread_barrier_wait` on an uninitialized barrier during single-thread tests.
- [High] Async-signal-unsafe call to `pthread_exit()` in `SIGUSR1` handler exposes the framework to deadlocks.
- [High] Single-thread tests are instantly aborted and completely bypass their testing logic.
- [Medium] Missing `pthread_join()` on the `pthread_barrier_destroy()` error path leads to a use-after-free race.
- [Medium] Missing error check for `pthread_create` leads to undefined behavior.
- [Low] Unmapped memory leak when `xsk_configure_umem` fails.
--
commit 154c93204cd9eb3588c96c98454860ecbe0e819c
Author: Tushar Vyavahare <tushar.vyavahare@intel.com>
Subject: selftests/xsk: Introduce mmap_size in umem struct
This patch stores the final mapping length in xsk_umem_info as mmap_size
when the UMEM mapping is created. This value is then used during teardown,
avoiding duplicated size arithmetic in cleanup. 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 f1730466ffd9c..e94c38a1faf47 100644
> --- a/tools/testing/selftests/bpf/prog_tests/test_xsk.c
> +++ b/tools/testing/selftests/bpf/prog_tests/test_xsk.c
> @@ -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;
[Severity: Low]
This isn't a bug introduced by this patch, but does this leak the memory
mapped into bufs if xsk_configure_umem() fails?
If xsk_umem__create() fails inside xsk_configure_umem(), umem->buffer is
never assigned. The teardown logic in testapp_clean_xsk_umem() will later
call munmap(NULL, mmap_size) which fails with EINVAL, leaking the memory.
While a test suite memory leak is minor, could repeated failures exhaust
hugepages across test runs?
[ ... ]
> @@ -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)
[Severity: High]
This is a pre-existing issue, but does this async-signal-unsafe call to
pthread_exit() in the SIGUSR1 handler expose the framework to deadlocks?
pthread_exit() is explicitly documented by POSIX as async-signal-unsafe.
The test suite uses SIGUSR1 to asynchronously kill worker threads. If a
thread is interrupted while holding an internal libc lock (e.g., during
malloc(), mmap(), or BPF map ops), the lock is abandoned.
When the main thread subsequently runs clean_sockets() and calls free(),
it could deadlock trying to acquire the same lock.
[ ... ]
> @@ -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: High]
This isn't a bug introduced by this patch, but are single-thread tests being
instantly aborted and bypassing their testing logic?
For single-interface scenarios (ifobj2 == NULL), __testapp_validate_traffic()
spawns t0 and immediately executes pthread_kill(t0, SIGUSR1). The worker
thread is terminated instantly before it can run its test logic (such as
waiting for poll() to time out in testapp_poll_rxq_tmout).
Since test->fail defaults to false, does this cause the test to return a false
positive success, providing zero coverage?
[Severity: High]
This is also a pre-existing issue, but could worker threads call
pthread_barrier_wait() on an uninitialized barrier during single-thread tests?
In __testapp_validate_traffic(), barr is only initialized if (ifobj2).
However, single-thread tests (like testapp_poll_rxq_tmout) invoke
worker_testapp_validate_rx() via t0, which unconditionally calls
pthread_barrier_wait(&barr).
Is waiting on an uninitialized barrier undefined behavior that could cause
memory corruption or deadlocks?
[Severity: Medium]
Another pre-existing issue here: is there a use-after-free race on the
pthread_barrier_destroy() error path higher up in
__testapp_validate_traffic()?
If pthread_barrier_destroy(&barr) fails, the RX thread (t0) is signaled via
pthread_kill() but not joined before clean_sockets() and clean_umem() are
invoked:
if (pthread_barrier_destroy(&barr)) {
pthread_kill(t0, SIGUSR1);
clean_sockets(test, ifobj1);
clean_umem(test, ifobj1, NULL);
return TEST_FAILURE;
}
Could the worker thread still be running or executing its signal handler
while its resources are torn down?
[Severity: Medium]
This is also a pre-existing issue, but does the framework call
pthread_create() for t0 and t1 without checking the return value in
__testapp_validate_traffic()?
If thread creation fails (e.g., due to EAGAIN), the pthread_t variable is
left uninitialized. The code subsequently passes this uninitialized ID to
pthread_kill() and pthread_join().
Could this invoke undefined behavior?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260603060327.298389-1-tushar.vyavahare@intel.com?part=4
^ permalink raw reply [flat|nested] 11+ messages in thread