| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/07 16:57 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"KMSANReasoning": "",
"NeedsKMSAN": false,
"Reasoning": "The patch only modifies BPF selftests (userspace test programs and test BPF programs) and does not make any functional changes to the core kernel, drivers, or architectures.",
"WorthFuzzing": false
} |
| 1/1 | 2026/08/07 16:57 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit df24cb11cc2617fe2a6f26249c4487e69933f4af\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Fri Aug 7 16:57:26 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/tools/testing/selftests/bpf/prog_tests/test_xsk.c b/tools/testing/selftests/bpf/prog_tests/test_xsk.c\nindex 477aedbb01bad..ccfd9e8436a7b 100644\n--- a/tools/testing/selftests/bpf/prog_tests/test_xsk.c\n+++ b/tools/testing/selftests/bpf/prog_tests/test_xsk.c\n@@ -101,6 +101,7 @@ int xsk_configure_umem(struct ifobject *ifobj, struct xsk_umem_info *umem, void\n \t\treturn ret;\n \n \tumem-\u003ebuffer = buffer;\n+\trefcount_set(\u0026umem-\u003eusers, 1);\n \tif (ifobj-\u003eshared_umem \u0026\u0026 ifobj-\u003erx_on) {\n \t\tumem-\u003ebase_addr = umem_size(umem);\n \t\tumem-\u003enext_buffer = umem_size(umem);\n@@ -154,6 +155,7 @@ int xsk_configure_socket(struct xsk_socket_info *xsk, struct xsk_umem_info *umem\n \tstruct xsk_socket_config cfg = {};\n \tstruct xsk_ring_cons *rxr;\n \tstruct xsk_ring_prod *txr;\n+\tint ret;\n \n \txsk-\u003eumem = umem;\n \tcfg.rx_size = xsk-\u003erxqsize;\n@@ -170,7 +172,21 @@ int xsk_configure_socket(struct xsk_socket_info *xsk, struct xsk_umem_info *umem\n \n \ttxr = ifobject-\u003etx_on ? \u0026xsk-\u003etx : NULL;\n \trxr = ifobject-\u003erx_on ? \u0026xsk-\u003erx : NULL;\n-\treturn xsk_socket__create(\u0026xsk-\u003exsk, ifobject-\u003eifindex, 0, umem-\u003eumem, rxr, txr, \u0026cfg);\n+\tret = xsk_socket__create(\u0026xsk-\u003exsk, ifobject-\u003eifindex, 0, umem-\u003eumem, rxr, txr, \u0026cfg);\n+\tif (ret) {\n+\t\tif (shared)\n+\t\t\t/* Shared socket failed before acquiring a UMEM reference. */\n+\t\t\txsk-\u003eumem = NULL;\n+\n+\t\t/* Keep failed socket state inert for later cleanup paths. */\n+\t\txsk-\u003exsk = NULL;\n+\t\treturn ret;\n+\t}\n+\n+\tif (shared)\n+\t\trefcount_inc(\u0026umem-\u003eusers);\n+\n+\treturn ret;\n }\n \n static int set_ring_size(struct ifobject *ifobj)\n@@ -203,6 +219,12 @@ int hw_ring_size_reset(struct ifobject *ifobj)\n static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx,\n \t\t\t struct ifobject *ifobj_rx)\n {\n+\t/*\n+\t * Keep the same default as xskxceiver startup: when TX and RX share the same netdev,\n+\t * shared UMEM is the baseline mode for this test harness. Individual tests can still\n+\t * override this as needed.\n+\t */\n+\tbool shared_default = ifobj_tx-\u003eifindex == ifobj_rx-\u003eifindex;\n \tu32 i, j;\n \n \tfor (i = 0; i \u003c MAX_INTERFACES; i++) {\n@@ -214,6 +236,7 @@ static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx,\n \t\tifobj-\u003euse_fill_ring = true;\n \t\tifobj-\u003erelease_rx = true;\n \t\tifobj-\u003evalidation_func = NULL;\n+\t\tifobj-\u003eshared_umem = shared_default;\n \t\tifobj-\u003euse_metadata = false;\n \n \t\tif (i == 0) {\n@@ -574,26 +597,122 @@ static int pkt_stream_receive_half(struct test_spec *test)\n \n static int pkt_stream_even_odd_sequence(struct test_spec *test)\n {\n+\tstruct pkt_stream *tx_streams[MAX_SOCKETS] = {};\n+\tstruct pkt_stream *rx_streams[MAX_SOCKETS] = {};\n \tstruct pkt_stream *pkt_stream;\n \tu32 i;\n \n \tfor (i = 0; i \u003c test-\u003enb_sockets; i++) {\n \t\tpkt_stream = test-\u003eifobj_tx-\u003exsk_arr[i].pkt_stream;\n-\t\tpkt_stream = __pkt_stream_generate(pkt_stream-\u003enb_pkts / 2,\n-\t\t\t\t\t\t pkt_stream-\u003epkts[0].len, i, 2);\n-\t\tif (!pkt_stream)\n-\t\t\treturn -ENOMEM;\n-\t\ttest-\u003eifobj_tx-\u003exsk_arr[i].pkt_stream = pkt_stream;\n+\t\ttx_streams[i] = __pkt_stream_generate(pkt_stream-\u003enb_pkts / 2,\n+\t\t\t\t\t\t pkt_stream-\u003epkts[0].len, i, 2);\n+\t\tif (!tx_streams[i])\n+\t\t\tgoto err;\n \n \t\tpkt_stream = test-\u003eifobj_rx-\u003exsk_arr[i].pkt_stream;\n-\t\tpkt_stream = __pkt_stream_generate(pkt_stream-\u003enb_pkts / 2,\n-\t\t\t\t\t\t pkt_stream-\u003epkts[0].len, i, 2);\n-\t\tif (!pkt_stream)\n-\t\t\treturn -ENOMEM;\n-\t\ttest-\u003eifobj_rx-\u003exsk_arr[i].pkt_stream = pkt_stream;\n+\t\trx_streams[i] = __pkt_stream_generate(pkt_stream-\u003enb_pkts / 2,\n+\t\t\t\t\t\t pkt_stream-\u003epkts[0].len, i, 2);\n+\t\tif (!rx_streams[i])\n+\t\t\tgoto err;\n+\t}\n+\n+\tfor (i = 0; i \u003c test-\u003enb_sockets; i++) {\n+\t\ttest-\u003eifobj_tx-\u003exsk_arr[i].pkt_stream = tx_streams[i];\n+\t\ttest-\u003eifobj_rx-\u003exsk_arr[i].pkt_stream = rx_streams[i];\n+\t}\n+\n+\treturn 0;\n+\n+err:\n+\tfor (i = 0; i \u003c test-\u003enb_sockets; i++) {\n+\t\tif (tx_streams[i])\n+\t\t\tpkt_stream_delete(tx_streams[i]);\n+\t\tif (rx_streams[i])\n+\t\t\tpkt_stream_delete(rx_streams[i]);\n+\t}\n+\n+\treturn -ENOMEM;\n+}\n+\n+static int pkt_stream_len_seq(struct test_spec *test, u32 short_len, u32 long_len)\n+{\n+\tstruct pkt_stream *tx_streams[MAX_SOCKETS] = {};\n+\tstruct pkt_stream *rx_streams[MAX_SOCKETS] = {};\n+\tstruct pkt_stream *pkt_stream;\n+\tu32 i;\n+\n+\tfor (i = 0; i \u003c test-\u003enb_sockets; i++) {\n+\t\tu32 pkt_len = i ? long_len : short_len;\n+\n+\t\tpkt_stream = test-\u003eifobj_tx-\u003exsk_arr[i].pkt_stream;\n+\t\ttx_streams[i] = __pkt_stream_generate(pkt_stream-\u003enb_pkts / 2, pkt_len, i, 2);\n+\t\tif (!tx_streams[i])\n+\t\t\tgoto err;\n+\n+\t\tpkt_stream = test-\u003eifobj_rx-\u003exsk_arr[i].pkt_stream;\n+\t\trx_streams[i] = __pkt_stream_generate(pkt_stream-\u003enb_pkts / 2, pkt_len, i, 2);\n+\t\tif (!rx_streams[i])\n+\t\t\tgoto err;\n+\t}\n+\n+\tfor (i = 0; i \u003c test-\u003enb_sockets; i++) {\n+\t\ttest-\u003eifobj_tx-\u003exsk_arr[i].pkt_stream = tx_streams[i];\n+\t\ttest-\u003eifobj_rx-\u003exsk_arr[i].pkt_stream = rx_streams[i];\n+\t}\n+\n+\treturn 0;\n+\n+err:\n+\tfor (i = 0; i \u003c test-\u003enb_sockets; i++) {\n+\t\tif (tx_streams[i])\n+\t\t\tpkt_stream_delete(tx_streams[i]);\n+\t\tif (rx_streams[i])\n+\t\t\tpkt_stream_delete(rx_streams[i]);\n+\t}\n+\n+\treturn -ENOMEM;\n+}\n+\n+static int pkt_stream_weighted_uneven_dist_sequence(struct test_spec *test, u32 total_pkts,\n+\t\t\t\t\t\t u32 pkt_len)\n+{\n+\tstruct pkt_stream *tx_streams[MAX_SOCKETS] = {};\n+\tstruct pkt_stream *rx_streams[MAX_SOCKETS] = {};\n+\tu32 i, pkts_sock0;\n+\n+\tif (test-\u003enb_sockets \u003c 2 || total_pkts \u003c 4)\n+\t\treturn -EINVAL;\n+\n+\tpkts_sock0 = total_pkts / 4;\n+\n+\tfor (i = 0; i \u003c test-\u003enb_sockets; i++) {\n+\t\tu32 nb_pkts = (i == 0) ? pkts_sock0 : (total_pkts - pkts_sock0);\n+\n+\t\ttx_streams[i] = __pkt_stream_generate(nb_pkts, pkt_len, i, 2);\n+\t\tif (!tx_streams[i])\n+\t\t\tgoto err;\n+\n+\t\trx_streams[i] = __pkt_stream_generate(nb_pkts, pkt_len, i, 2);\n+\t\tif (!rx_streams[i])\n+\t\t\tgoto err;\n+\t}\n+\n+\tfor (i = 0; i \u003c test-\u003enb_sockets; i++) {\n+\t\ttest-\u003eifobj_tx-\u003exsk_arr[i].pkt_stream = tx_streams[i];\n+\t\ttest-\u003eifobj_rx-\u003exsk_arr[i].pkt_stream = rx_streams[i];\n \t}\n \n \treturn 0;\n+\n+err:\n+\tfor (i = 0; i \u003c test-\u003enb_sockets; i++) {\n+\t\tif (tx_streams[i])\n+\t\t\tpkt_stream_delete(tx_streams[i]);\n+\t\tif (rx_streams[i])\n+\t\t\tpkt_stream_delete(rx_streams[i]);\n+\t}\n+\n+\treturn -ENOMEM;\n }\n \n static void release_even_odd_sequence(struct test_spec *test)\n@@ -1468,6 +1587,28 @@ static int validate_tx_invalid_descs(struct ifobject *ifobject)\n \treturn TEST_PASS;\n }\n \n+static void xsk_delete_socket_batch(struct ifobject *ifobject, u32 count)\n+{\n+\tu32 i;\n+\n+\tif (!ifobject)\n+\t\treturn;\n+\n+\tfor (i = count; i \u003e 0; i--)\n+\t\txsk_delete_socket(\u0026ifobject-\u003exsk_arr[i - 1]);\n+}\n+\n+static void xsk_configure_rollback(struct ifobject *ifobject, int last)\n+{\n+\tu32 count;\n+\n+\tif (!ifobject || last \u003c 0)\n+\t\treturn;\n+\n+\tcount = last + 1;\n+\txsk_delete_socket_batch(ifobject, count);\n+}\n+\n static int xsk_configure(struct test_spec *test, struct ifobject *ifobject,\n \t\t\t struct xsk_umem_info *umem, bool tx)\n {\n@@ -1484,14 +1625,18 @@ static int xsk_configure(struct test_spec *test, struct ifobject *ifobject,\n \t\t\t\tbreak;\n \n \t\t\t/* Retry if it fails as xsk_socket__create() is asynchronous */\n-\t\t\tif (ctr \u003e= SOCK_RECONF_CTR)\n+\t\t\tif (ctr \u003e= SOCK_RECONF_CTR) {\n+\t\t\t\txsk_configure_rollback(ifobject, i);\n \t\t\t\treturn ret;\n+\t\t\t}\n \t\t\tusleep(USLEEP_MAX);\n \t\t}\n \t\tif (ifobject-\u003ebusy_poll) {\n \t\t\tret = enable_busy_poll(\u0026ifobject-\u003exsk_arr[i]);\n-\t\t\tif (ret)\n+\t\t\tif (ret) {\n+\t\t\t\txsk_configure_rollback(ifobject, i);\n \t\t\t\treturn ret;\n+\t\t\t}\n \t\t}\n \t}\n \n@@ -1702,12 +1847,60 @@ void *worker_testapp_validate_rx(void *arg)\n \tpthread_exit(NULL);\n }\n \n-static void testapp_clean_xsk_umem(struct ifobject *ifobj)\n+void xsk_delete_socket(struct xsk_socket_info *xsk)\n {\n-\tstruct xsk_umem_info *umem = ifobj-\u003exsk-\u003eumem;\n+\tstruct xsk_umem_info *umem;\n \n-\txsk_umem__delete(umem-\u003eumem);\n-\tmunmap(umem-\u003ebuffer, umem-\u003emmap_size);\n+\t/*\n+\t * Callers must serialize teardown for a given xsk/umem pair.\n+\t * This helper does refcount-based lifetime management only.\n+\t */\n+\tif (!xsk)\n+\t\treturn;\n+\n+\tumem = xsk-\u003eumem;\n+\tif (!umem)\n+\t\treturn;\n+\n+\t/* Delete the socket handle when available, then drop UMEM reference. */\n+\tif (xsk-\u003exsk)\n+\t\txsk_socket__delete(xsk-\u003exsk);\n+\txsk-\u003exsk = NULL;\n+\n+\t/* Mark this socket as cleaned up to prevent double-decrement */\n+\txsk-\u003eumem = NULL;\n+\n+\t/*\n+\t * Teardown may walk the full xsk array, including slots that never completed setup but\n+\t * still carry a preinitialized umem pointer. After a partial-setup rollback, the last UMEM\n+\t * ref may already be dropped.\n+\t */\n+\tif (!refcount_read(\u0026umem-\u003eusers))\n+\t\treturn;\n+\n+\t/* Always decrement refcount for this socket's UMEM reference */\n+\tif (refcount_dec_and_test(\u0026umem-\u003eusers)) {\n+\t\tif (umem-\u003eumem) {\n+\t\t\tint err = xsk_umem__delete(umem-\u003eumem);\n+\n+\t\t\tif (err)\n+\t\t\t\tksft_print_msg(\"xsk_umem__delete failed: %d (umem still busy?)\\n\",\n+\t\t\t\t\t err);\n+\t\t}\n+\t\tif (umem-\u003ebuffer \u0026\u0026 umem-\u003emmap_size)\n+\t\t\tmunmap(umem-\u003ebuffer, umem-\u003emmap_size);\n+\t\tumem-\u003eumem = NULL;\n+\t\tumem-\u003ebuffer = NULL;\n+\t\tumem-\u003emmap_size = 0;\n+\t}\n+}\n+\n+static void xsk_delete_all_ifobj_sockets(struct test_spec *test, struct ifobject *ifobj)\n+{\n+\tif (!ifobj)\n+\t\treturn;\n+\n+\txsk_delete_socket_batch(ifobj, test-\u003enb_sockets);\n }\n \n static bool xdp_prog_changed_rx(struct test_spec *test)\n@@ -1769,27 +1962,6 @@ static int xsk_attach_xdp_progs(struct test_spec *test, struct ifobject *ifobj_r\n \treturn err;\n }\n \n-static void clean_sockets(struct test_spec *test, struct ifobject *ifobj)\n-{\n-\tu32 i;\n-\n-\tif (!ifobj || !test)\n-\t\treturn;\n-\n-\tfor (i = 0; i \u003c test-\u003enb_sockets; i++)\n-\t\txsk_socket__delete(ifobj-\u003exsk_arr[i].xsk);\n-}\n-\n-static void clean_umem(struct test_spec *test, struct ifobject *ifobj1, struct ifobject *ifobj2)\n-{\n-\tif (!ifobj1)\n-\t\treturn;\n-\n-\ttestapp_clean_xsk_umem(ifobj1);\n-\tif (ifobj2 \u0026\u0026 !ifobj2-\u003eshared_umem)\n-\t\ttestapp_clean_xsk_umem(ifobj2);\n-}\n-\n static int __testapp_validate_traffic(struct test_spec *test, struct ifobject *ifobj1,\n \t\t\t\t struct ifobject *ifobj2)\n {\n@@ -1841,8 +2013,7 @@ static int __testapp_validate_traffic(struct test_spec *test, struct ifobject *i\n \t\tif (pthread_barrier_destroy(\u0026barr)) {\n \t\t\ttest-\u003euse_barrier = false;\n \t\t\tpthread_join(t0, NULL);\n-\t\t\tclean_sockets(test, ifobj1);\n-\t\t\tclean_umem(test, ifobj1, NULL);\n+\t\t\txsk_delete_all_ifobj_sockets(test, ifobj1);\n \t\t\treturn TEST_FAILURE;\n \t\t}\n \t}\n@@ -1856,9 +2027,8 @@ static int __testapp_validate_traffic(struct test_spec *test, struct ifobject *i\n \tpthread_join(t0, NULL);\n \n \tif (test-\u003etotal_steps == test-\u003ecurrent_step || test-\u003efail) {\n-\t\tclean_sockets(test, ifobj1);\n-\t\tclean_sockets(test, ifobj2);\n-\t\tclean_umem(test, ifobj1, ifobj2);\n+\t\txsk_delete_all_ifobj_sockets(test, ifobj2);\n+\t\txsk_delete_all_ifobj_sockets(test, ifobj1);\n \t}\n \n \tif (test-\u003efail)\n@@ -1967,9 +2137,8 @@ int testapp_xdp_prog_cleanup(struct test_spec *test)\n \t\treturn TEST_FAILURE;\n \n \tif (swap_xsk_resources(test)) {\n-\t\tclean_sockets(test, test-\u003eifobj_rx);\n-\t\tclean_sockets(test, test-\u003eifobj_tx);\n-\t\tclean_umem(test, test-\u003eifobj_rx, test-\u003eifobj_tx);\n+\t\txsk_delete_all_ifobj_sockets(test, test-\u003eifobj_tx);\n+\t\txsk_delete_all_ifobj_sockets(test, test-\u003eifobj_rx);\n \t\treturn TEST_FAILURE;\n \t}\n \n@@ -2224,6 +2393,168 @@ int testapp_xdp_shared_umem(struct test_spec *test)\n \treturn ret;\n }\n \n+static int shared_umem_test_prepare(struct test_spec *test)\n+{\n+\tu32 i;\n+\n+\tif (test-\u003enb_sockets \u003e MAX_SOCKETS) {\n+\t\tksft_print_msg(\"ERROR: [%s] invalid socket count %u\\n\", __func__, test-\u003enb_sockets);\n+\t\treturn TEST_FAILURE;\n+\t}\n+\n+\tfor (i = 0; i \u003c test-\u003enb_sockets; i++) {\n+\t\tif (!test-\u003eifobj_rx-\u003exsk_arr[i].pkt_stream ||\n+\t\t !test-\u003eifobj_tx-\u003exsk_arr[i].pkt_stream) {\n+\t\t\tksft_print_msg(\"ERROR: [%s] missing stream for socket %u\\n\", __func__, i);\n+\t\t\treturn TEST_FAILURE;\n+\t\t}\n+\t}\n+\n+\treturn TEST_PASS;\n+}\n+\n+static int shared_umem_seq_even_odd(struct test_spec *test, const void *ctx)\n+{\n+\t(void)ctx;\n+\n+\treturn pkt_stream_even_odd_sequence(test) ? TEST_FAILURE : TEST_PASS;\n+}\n+\n+static int shared_umem_seq_len(struct test_spec *test, const void *ctx)\n+{\n+\tconst struct shared_umem_len_ctx *cfg = ctx;\n+\n+\treturn pkt_stream_len_seq(test, cfg-\u003eshort_len, cfg-\u003elong_len) ? TEST_FAILURE : TEST_PASS;\n+}\n+\n+static int shared_umem_seq_uneven_dist(struct test_spec *test, const void *ctx)\n+{\n+\tconst struct shared_umem_uneven_dist_ctx *cfg = ctx;\n+\n+\treturn pkt_stream_weighted_uneven_dist_sequence(test, cfg-\u003etotal_pkts,\n+\t\t\t\t\t\t cfg-\u003epkt_len) ? TEST_FAILURE : TEST_PASS;\n+}\n+\n+static int shared_umem_post_uneven_dist(struct test_spec *test, int ret, const void *ctx)\n+{\n+\tstruct pkt_stream *tx_stream_0, *tx_stream_1;\n+\tstruct pkt_stream *rx_stream_0, *rx_stream_1;\n+\n+\t(void)ctx;\n+\n+\ttx_stream_0 = test-\u003eifobj_tx-\u003exsk_arr[0].pkt_stream;\n+\ttx_stream_1 = test-\u003eifobj_tx-\u003exsk_arr[1].pkt_stream;\n+\trx_stream_0 = test-\u003eifobj_rx-\u003exsk_arr[0].pkt_stream;\n+\trx_stream_1 = test-\u003eifobj_rx-\u003exsk_arr[1].pkt_stream;\n+\n+\tif (tx_stream_1-\u003enb_valid_entries \u003c= tx_stream_0-\u003enb_valid_entries)\n+\t\treturn TEST_FAILURE;\n+\n+\tif (!ret \u0026\u0026 rx_stream_1-\u003enb_rx_pkts \u003c= rx_stream_0-\u003enb_rx_pkts) {\n+\t\tksft_print_msg(\"ERROR: socket1 rx_pkts (%u) not greater than socket0 (%u)\\n\",\n+\t\t\t rx_stream_1-\u003enb_rx_pkts, rx_stream_0-\u003enb_rx_pkts);\n+\t\tret = TEST_FAILURE;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int run_shared_umem_test(struct test_spec *test, struct bpf_program *xdp_prog_rx,\n+\t\t\t\tstruct bpf_program *xdp_prog_tx, struct bpf_map *xskmap_rx,\n+\t\t\t\tstruct bpf_map *xskmap_tx, u32 nb_sockets,\n+\t\t\t\tshared_umem_seq_fn seq_fn, shared_umem_post_fn post_fn,\n+\t\t\t\tconst void *ctx)\n+{\n+\tint ret;\n+\n+\ttest-\u003etotal_steps = 1;\n+\ttest-\u003enb_sockets = nb_sockets;\n+\n+\ttest_spec_set_xdp_prog(test, xdp_prog_rx, xdp_prog_tx, xskmap_rx, xskmap_tx);\n+\n+\tret = shared_umem_test_prepare(test);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = seq_fn(test, ctx);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = testapp_validate_traffic(test);\n+\tif (post_fn)\n+\t\tret = post_fn(test, ret, ctx);\n+\n+\trelease_even_odd_sequence(test);\n+\n+\treturn ret;\n+}\n+\n+int testapp_shared_umem_4_sockets(struct test_spec *test)\n+{\n+\tstruct xsk_xdp_progs *skel_rx = test-\u003eifobj_rx-\u003exdp_progs;\n+\tstruct xsk_xdp_progs *skel_tx = test-\u003eifobj_tx-\u003exdp_progs;\n+\n+\treturn run_shared_umem_test(test, skel_rx-\u003eprogs.xsk_xdp_shared_umem,\n+\t\t\t\t skel_tx-\u003eprogs.xsk_xdp_shared_umem, skel_rx-\u003emaps.xsk,\n+\t\t\t\t skel_tx-\u003emaps.xsk, 4, shared_umem_seq_even_odd, NULL, NULL);\n+}\n+\n+int testapp_shared_umem_length_based(struct test_spec *test)\n+{\n+\tstruct xsk_xdp_progs *skel_rx = test-\u003eifobj_rx-\u003exdp_progs;\n+\tstruct xsk_xdp_progs *skel_tx = test-\u003eifobj_tx-\u003exdp_progs;\n+\tconst struct shared_umem_len_ctx len_ctx = {\n+\t\t.short_len = MIN_PKT_SIZE,\n+\t\t.long_len = MIN_PKT_SIZE * 2,\n+\t};\n+\n+\treturn run_shared_umem_test(test, skel_rx-\u003eprogs.xsk_xdp_shared_umem_length_based,\n+\t\t\t\t skel_tx-\u003eprogs.xsk_xdp_shared_umem_length_based,\n+\t\t\t\t skel_rx-\u003emaps.xsk, skel_tx-\u003emaps.xsk, 2, shared_umem_seq_len,\n+\t\t\t\t NULL, \u0026len_ctx);\n+}\n+\n+int testapp_shared_umem_uneven_dist(struct test_spec *test)\n+{\n+\tstruct xsk_xdp_progs *skel_rx = test-\u003eifobj_rx-\u003exdp_progs;\n+\tstruct xsk_xdp_progs *skel_tx = test-\u003eifobj_tx-\u003exdp_progs;\n+\tconst struct shared_umem_uneven_dist_ctx uneven_dist_ctx = {\n+\t\t.total_pkts = DEFAULT_PKT_CNT * 4,\n+\t\t.pkt_len = MIN_PKT_SIZE,\n+\t};\n+\n+\treturn run_shared_umem_test(test, skel_rx-\u003eprogs.xsk_xdp_shared_umem,\n+\t\t\t\t skel_tx-\u003eprogs.xsk_xdp_shared_umem, skel_rx-\u003emaps.xsk,\n+\t\t\t\t skel_tx-\u003emaps.xsk, 2, shared_umem_seq_uneven_dist,\n+\t\t\t\t shared_umem_post_uneven_dist, \u0026uneven_dist_ctx);\n+}\n+\n+int testapp_shared_umem_unaligned(struct test_spec *test)\n+{\n+\tstruct xsk_xdp_progs *skel_rx = test-\u003eifobj_rx-\u003exdp_progs;\n+\tstruct xsk_xdp_progs *skel_tx = test-\u003eifobj_tx-\u003exdp_progs;\n+\tstruct xsk_umem_info *tx_umem = test-\u003eifobj_tx \u0026\u0026 test-\u003eifobj_tx-\u003exsk ?\n+\t\ttest-\u003eifobj_tx-\u003exsk-\u003eumem : NULL;\n+\tstruct xsk_umem_info *rx_umem = test-\u003eifobj_rx \u0026\u0026 test-\u003eifobj_rx-\u003exsk ?\n+\t\ttest-\u003eifobj_rx-\u003exsk-\u003eumem : NULL;\n+\tbool tx_unaligned = tx_umem ? tx_umem-\u003eunaligned_mode : false;\n+\tbool rx_unaligned = rx_umem ? rx_umem-\u003eunaligned_mode : false;\n+\tint ret;\n+\n+\ttest_spec_set_unaligned(test);\n+\n+\tret = run_shared_umem_test(test, skel_rx-\u003eprogs.xsk_xdp_shared_umem,\n+\t\t\t\t skel_tx-\u003eprogs.xsk_xdp_shared_umem, skel_rx-\u003emaps.xsk,\n+\t\t\t\t skel_tx-\u003emaps.xsk, 2, shared_umem_seq_even_odd, NULL, NULL);\n+\n+\tif (tx_umem)\n+\t\ttx_umem-\u003eunaligned_mode = tx_unaligned;\n+\tif (rx_umem)\n+\t\trx_umem-\u003eunaligned_mode = rx_unaligned;\n+\n+\treturn ret;\n+}\n+\n int testapp_poll_txq_tmout(struct test_spec *test)\n {\n \tbool shared_umem = test-\u003eifobj_tx-\u003eshared_umem;\n@@ -2498,9 +2829,8 @@ int testapp_hw_sw_max_ring_size(struct test_spec *test)\n \ttest-\u003eifobj_tx-\u003exsk-\u003ebatch_size = test-\u003eifobj_tx-\u003ering.tx_max_pending - 8;\n \ttest-\u003eifobj_rx-\u003exsk-\u003ebatch_size = test-\u003eifobj_tx-\u003ering.tx_max_pending - 8;\n \tif (pkt_stream_replace(test, max_descs, MIN_PKT_SIZE)) {\n-\t\tclean_sockets(test, test-\u003eifobj_tx);\n-\t\tclean_sockets(test, test-\u003eifobj_rx);\n-\t\tclean_umem(test, test-\u003eifobj_rx, test-\u003eifobj_tx);\n+\t\txsk_delete_all_ifobj_sockets(test, test-\u003eifobj_tx);\n+\t\txsk_delete_all_ifobj_sockets(test, test-\u003eifobj_rx);\n \t\treturn TEST_FAILURE;\n \t}\n \ndiff --git a/tools/testing/selftests/bpf/prog_tests/test_xsk.h b/tools/testing/selftests/bpf/prog_tests/test_xsk.h\nindex 03753ddc5dcda..ef9c422d7763e 100644\n--- a/tools/testing/selftests/bpf/prog_tests/test_xsk.h\n+++ b/tools/testing/selftests/bpf/prog_tests/test_xsk.h\n@@ -4,6 +4,7 @@\n \n #include \u003clinux/ethtool.h\u003e\n #include \u003clinux/if_xdp.h\u003e\n+#include \u003clinux/refcount.h\u003e\n \n #include \"../kselftest.h\"\n #include \"xsk.h\"\n@@ -79,6 +80,9 @@ struct test_spec;\n typedef int (*validation_func_t)(struct ifobject *ifobj);\n typedef void *(*thread_func_t)(void *arg);\n typedef int (*test_func_t)(struct test_spec *test);\n+typedef int (*shared_umem_seq_fn)(struct test_spec *test, const void *ctx);\n+typedef int (*shared_umem_post_fn)(struct test_spec *test, int ret,\n+\t\t\t\t\t const void *ctx);\n \n struct xsk_socket_info {\n \tstruct xsk_ring_cons rx;\n@@ -104,6 +108,7 @@ struct xsk_umem_info {\n \tstruct xsk_umem *umem;\n \tu64 next_buffer;\n \tu64 mmap_size;\n+\trefcount_t users;\n \tu32 num_frames;\n \tu32 frame_headroom;\n \tvoid *buffer;\n@@ -159,6 +164,7 @@ int init_iface(struct ifobject *ifobj, thread_func_t func_ptr);\n int xsk_configure_umem(struct ifobject *ifobj, struct xsk_umem_info *umem, void *buffer, u64 size);\n int xsk_configure_socket(struct xsk_socket_info *xsk, struct xsk_umem_info *umem,\n \t\t\t struct ifobject *ifobject, bool shared);\n+void xsk_delete_socket(struct xsk_socket_info *xsk);\n \n \n struct pkt {\n@@ -179,6 +185,16 @@ struct pkt_stream {\n \tbool verbatim;\n };\n \n+struct shared_umem_len_ctx {\n+\tu32 short_len;\n+\tu32 long_len;\n+};\n+\n+struct shared_umem_uneven_dist_ctx {\n+\tu32 total_pkts;\n+\tu32 pkt_len;\n+};\n+\n static inline bool pkt_continues(u32 options)\n {\n \treturn options \u0026 XDP_PKT_CONTD;\n@@ -268,6 +284,10 @@ int testapp_xdp_metadata(struct test_spec *test);\n int testapp_xdp_metadata_mb(struct test_spec *test);\n int testapp_xdp_prog_cleanup(struct test_spec *test);\n int testapp_xdp_shared_umem(struct test_spec *test);\n+int testapp_shared_umem_4_sockets(struct test_spec *test);\n+int testapp_shared_umem_length_based(struct test_spec *test);\n+int testapp_shared_umem_uneven_dist(struct test_spec *test);\n+int testapp_shared_umem_unaligned(struct test_spec *test);\n \n void *worker_testapp_validate_rx(void *arg);\n void *worker_testapp_validate_tx(void *arg);\n@@ -291,6 +311,10 @@ static const struct test_spec tests[] = {\n \t{.name = \"XDP_PROG_CLEANUP\", .test_func = testapp_xdp_prog_cleanup},\n \t{.name = \"XDP_DROP_HALF\", .test_func = testapp_xdp_drop},\n \t{.name = \"XDP_SHARED_UMEM\", .test_func = testapp_xdp_shared_umem},\n+\t{.name = \"SHARED_UMEM_4_SOCKETS\", .test_func = testapp_shared_umem_4_sockets},\n+\t{.name = \"SHARED_UMEM_LENGTH_BASED\", .test_func = testapp_shared_umem_length_based},\n+\t{.name = \"SHARED_UMEM_UNEVEN_DIST\", .test_func = testapp_shared_umem_uneven_dist},\n+\t{.name = \"SHARED_UMEM_UNALIGNED\", .test_func = testapp_shared_umem_unaligned},\n \t{.name = \"XDP_METADATA_COPY\", .test_func = testapp_xdp_metadata},\n \t{.name = \"XDP_METADATA_COPY_MULTI_BUFF\", .test_func = testapp_xdp_metadata_mb},\n \t{.name = \"ALIGNED_INV_DESC_MULTI_BUFF\", .test_func = testapp_aligned_inv_desc_mb},\ndiff --git a/tools/testing/selftests/bpf/progs/xsk_xdp_progs.c b/tools/testing/selftests/bpf/progs/xsk_xdp_progs.c\nindex 023d8befd4cab..543b61df3a2b1 100644\n--- a/tools/testing/selftests/bpf/progs/xsk_xdp_progs.c\n+++ b/tools/testing/selftests/bpf/progs/xsk_xdp_progs.c\n@@ -10,7 +10,7 @@\n \n struct {\n \t__uint(type, BPF_MAP_TYPE_XSKMAP);\n-\t__uint(max_entries, 2);\n+\t__uint(max_entries, MAX_SOCKETS);\n \t__uint(key_size, sizeof(int));\n \t__uint(value_size, sizeof(int));\n } xsk SEC(\".maps\");\n@@ -75,6 +75,23 @@ SEC(\"xdp\") int xsk_xdp_shared_umem(struct xdp_md *xdp)\n \treturn bpf_redirect_map(\u0026xsk, idx, XDP_DROP);\n }\n \n+SEC(\"xdp\") int xsk_xdp_shared_umem_length_based(struct xdp_md *xdp)\n+{\n+\tvoid *data = (void *)(long)xdp-\u003edata;\n+\tvoid *data_end = (void *)(long)xdp-\u003edata_end;\n+\t__u32 pkt_len = data_end - data;\n+\n+\t/* \n+\t * Route packets by total XDP-visible packet length (data_end - data):\n+\t * - Socket 0: packets \u003c= SHARED_UMEM_LEN_SPLIT bytes\n+\t * - Socket 1: packets \u003e SHARED_UMEM_LEN_SPLIT bytes\n+\t */\n+\tif (pkt_len \u003c= SHARED_UMEM_LEN_SPLIT)\n+\t\treturn bpf_redirect_map(\u0026xsk, 0, XDP_DROP);\n+\telse\n+\t\treturn bpf_redirect_map(\u0026xsk, 1, XDP_DROP);\n+}\n+\n SEC(\"xdp.frags\") int xsk_xdp_adjust_tail(struct xdp_md *xdp)\n {\n \t__u32 buff_len, curr_buff_len;\ndiff --git a/tools/testing/selftests/bpf/xsk_xdp_common.h b/tools/testing/selftests/bpf/xsk_xdp_common.h\nindex 45810ff552dae..bd9b5dcf8c8ee 100644\n--- a/tools/testing/selftests/bpf/xsk_xdp_common.h\n+++ b/tools/testing/selftests/bpf/xsk_xdp_common.h\n@@ -3,7 +3,8 @@\n #ifndef XSK_XDP_COMMON_H_\n #define XSK_XDP_COMMON_H_\n \n-#define MAX_SOCKETS 2\n+#define MAX_SOCKETS 4\n+#define SHARED_UMEM_LEN_SPLIT 64\n #define PKT_HDR_ALIGN (sizeof(struct ethhdr) + 2) /* Just to align the data in the packet */\n \n struct xdp_info {\ndiff --git a/tools/testing/selftests/bpf/xskxceiver.c b/tools/testing/selftests/bpf/xskxceiver.c\nindex 7dad8556a722e..ed7716b637567 100644\n--- a/tools/testing/selftests/bpf/xskxceiver.c\n+++ b/tools/testing/selftests/bpf/xskxceiver.c\n@@ -117,12 +117,13 @@ static void __exit_with_error(int error, const char *file, const char *func, int\n \n #define exit_with_error(error) __exit_with_error(error, __FILE__, __func__, __LINE__)\n \n-static bool ifobj_zc_avail(struct ifobject *ifobject)\n+static bool ifobj_zc_avail(struct ifobject *ifobj)\n {\n \tsize_t umem_sz = DEFAULT_UMEM_BUFFERS * XSK_UMEM__DEFAULT_FRAME_SIZE;\n \tint mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;\n-\tstruct xsk_socket_info *xsk;\n-\tstruct xsk_umem_info *umem;\n+\tstruct xsk_socket_info xsk = {};\n+\tstruct xsk_umem_info umem_info = {};\n+\tstruct xsk_umem_info *umem = \u0026umem_info;\n \tbool zc_avail = false;\n \tvoid *bufs;\n \tint ret;\n@@ -131,32 +132,22 @@ static bool ifobj_zc_avail(struct ifobject *ifobject)\n \tif (bufs == MAP_FAILED)\n \t\texit_with_error(errno);\n \n-\tumem = calloc(1, sizeof(struct xsk_umem_info));\n-\tif (!umem) {\n-\t\tmunmap(bufs, umem_sz);\n-\t\texit_with_error(ENOMEM);\n-\t}\n+\tumem-\u003emmap_size = umem_sz;\n \tumem-\u003eframe_size = XSK_UMEM__DEFAULT_FRAME_SIZE;\n-\tret = xsk_configure_umem(ifobject, umem, bufs, umem_sz);\n+\tret = xsk_configure_umem(ifobj, umem, bufs, umem_sz);\n \tif (ret)\n \t\texit_with_error(-ret);\n \n-\txsk = calloc(1, sizeof(struct xsk_socket_info));\n-\tif (!xsk)\n-\t\tgoto out;\n-\tifobject-\u003ebind_flags = XDP_USE_NEED_WAKEUP | XDP_ZEROCOPY;\n-\tifobject-\u003erx_on = true;\n-\txsk-\u003erxqsize = XSK_RING_CONS__DEFAULT_NUM_DESCS;\n-\tret = xsk_configure_socket(xsk, umem, ifobject, false);\n+\tifobj-\u003ebind_flags = XDP_USE_NEED_WAKEUP | XDP_ZEROCOPY;\n+\tifobj-\u003erx_on = true;\n+\txsk.rxqsize = XSK_RING_CONS__DEFAULT_NUM_DESCS;\n+\tret = xsk_configure_socket(\u0026xsk, umem, ifobj, false);\n \tif (!ret)\n \t\tzc_avail = true;\n \n-\txsk_socket__delete(xsk-\u003exsk);\n-\tfree(xsk);\n-out:\n-\tmunmap(umem-\u003ebuffer, umem_sz);\n-\txsk_umem__delete(umem-\u003eumem);\n-\tfree(umem);\n+\t/* Use the same refcount-based teardown path for both success and failure. */\n+\txsk_delete_socket(\u0026xsk);\n+\n \treturn zc_avail;\n }\n \n"
} |
| 2/1 | 2026/08/07 16:57 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch only modifies BPF selftests (userspace test programs and test BPF programs) and does not make any functional changes to the core kernel, drivers, or architectures.",
"WorthFuzzing": false
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). - Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU. - Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove) that are executed only during PCI hot-unplug or sysfs driver unbind operations. If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. Prefer non-static, non-inlined API entrypoint functions over internal static helper functions (which are inlined by the compiler and do not have distinct symbol addresses). 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit df24cb11cc2617fe2a6f26249c4487e69933f4af
Author: syz-cluster <triage@syzkaller.com>
Date: Fri Aug 7 16:57:26 2026 +0000
syz-cluster: applied patch under review
diff --git a/tools/testing/selftests/bpf/prog_tests/test_xsk.c b/tools/testing/selftests/bpf/prog_tests/test_xsk.c
index 477aedbb01bad..ccfd9e8436a7b 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_xsk.c
+++ b/tools/testing/selftests/bpf/prog_tests/test_xsk.c
@@ -101,6 +101,7 @@ int xsk_configure_umem(struct ifobject *ifobj, struct xsk_umem_info *umem, void
return ret;
umem->buffer = buffer;
+ refcount_set(&umem->users, 1);
if (ifobj->shared_umem && ifobj->rx_on) {
umem->base_addr = umem_size(umem);
umem->next_buffer = umem_size(umem);
@@ -154,6 +155,7 @@ int xsk_configure_socket(struct xsk_socket_info *xsk, struct xsk_umem_info *umem
struct xsk_socket_config cfg = {};
struct xsk_ring_cons *rxr;
struct xsk_ring_prod *txr;
+ int ret;
xsk->umem = umem;
cfg.rx_size = xsk->rxqsize;
@@ -170,7 +172,21 @@ int xsk_configure_socket(struct xsk_socket_info *xsk, struct xsk_umem_info *umem
txr = ifobject->tx_on ? &xsk->tx : NULL;
rxr = ifobject->rx_on ? &xsk->rx : NULL;
- return xsk_socket__create(&xsk->xsk, ifobject->ifindex, 0, umem->umem, rxr, txr, &cfg);
+ ret = xsk_socket__create(&xsk->xsk, ifobject->ifindex, 0, umem->umem, rxr, txr, &cfg);
+ if (ret) {
+ if (shared)
+ /* Shared socket failed before acquiring a UMEM reference. */
+ xsk->umem = NULL;
+
+ /* Keep failed socket state inert for later cleanup paths. */
+ xsk->xsk = NULL;
+ return ret;
+ }
+
+ if (shared)
+ refcount_inc(&umem->users);
+
+ return ret;
}
static int set_ring_size(struct ifobject *ifobj)
@@ -203,6 +219,12 @@ int hw_ring_size_reset(struct ifobject *ifobj)
static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx,
struct ifobject *ifobj_rx)
{
+ /*
+ * Keep the same default as xskxceiver startup: when TX and RX share the same netdev,
+ * shared UMEM is the baseline mode for this test harness. Individual tests can still
+ * override this as needed.
+ */
+ bool shared_default = ifobj_tx->ifindex == ifobj_rx->ifindex;
u32 i, j;
for (i = 0; i < MAX_INTERFACES; i++) {
@@ -214,6 +236,7 @@ static void __test_spec_init(struct test_spec *test, struct ifobject *ifobj_tx,
ifobj->use_fill_ring = true;
ifobj->release_rx = true;
ifobj->validation_func = NULL;
+ ifobj->shared_umem = shared_default;
ifobj->use_metadata = false;
if (i == 0) {
@@ -574,26 +597,122 @@ static int pkt_stream_receive_half(struct test_spec *test)
static int pkt_stream_even_odd_sequence(struct test_spec *test)
{
+ struct pkt_stream *tx_streams[MAX_SOCKETS] = {};
+ struct pkt_stream *rx_streams[MAX_SOCKETS] = {};
struct pkt_stream *pkt_stream;
u32 i;
for (i = 0; i < test->nb_sockets; i++) {
pkt_stream = test->ifobj_tx->xsk_arr[i].pkt_stream;
- pkt_stream = __pkt_stream_generate(pkt_stream->nb_pkts / 2,
- pkt_stream->pkts[0].len, i, 2);
- if (!pkt_stream)
- return -ENOMEM;
- test->ifobj_tx->xsk_arr[i].pkt_stream = pkt_stream;
+ tx_streams[i] = __pkt_stream_generate(pkt_stream->nb_pkts / 2,
+ pkt_stream->pkts[0].len, i, 2);
+ if (!tx_streams[i])
+ goto err;
pkt_stream = test->ifobj_rx->xsk_arr[i].pkt_stream;
- pkt_stream = __pkt_stream_generate(pkt_stream->nb_pkts / 2,
- pkt_stream->pkts[0].len, i, 2);
- if (!pkt_stream)
- return -ENOMEM;
- test->ifobj_rx->xsk_arr[i].pkt_stream = pkt_stream;
+ rx_streams[i] = __pkt_stream_generate(pkt_stream->nb_pkts / 2,
+ pkt_stream->pkts[0].len, i, 2);
+ if (!rx_streams[i])
+ goto err;
+ }
+
+ for (i = 0; i < test->nb_sockets; i++) {
+ test->ifobj_tx->xsk_arr[i].pkt_stream = tx_streams[i];
+ test->ifobj_rx->xsk_arr[i].pkt_stream = rx_streams[i];
+ }
+
+ return 0;
+
+err:
+ for (i = 0; i < test->nb_sockets; i++) {
+ if (tx_streams[i])
+ pkt_stream_delete(tx_streams[i]);
+ if (rx_streams[i])
+ pkt_stream_delete(rx_streams[i]);
+ }
+
+ return -ENOMEM;
+}
+
+static int pkt_stream_len_seq(struct test_spec *test, u32 short_len, u32 long_len)
+{
+ struct pkt_stream *tx_streams[MAX_SOCKETS] = {};
+ struct pkt_stream *rx_streams[MAX_SOCKETS] = {};
+ struct pkt_stream *pkt_stream;
+ u32 i;
+
+ for (i = 0; i < test->nb_sockets; i++) {
+ u32 pkt_len = i ? long_len : short_len;
+
+ pkt_stream = test->ifobj_tx->xsk_arr[i].pkt_stream;
+ tx_streams[i] = __pkt_stream_generate(pkt_stream->nb_pkts / 2, pkt_len, i, 2);
+ if (!tx_streams[i])
+ goto err;
+
+ pkt_stream = test->ifobj_rx->xsk_arr[i].pkt_stream;
+ rx_streams[i] = __pkt_stream_generate(pkt_stream->nb_pkts / 2, pkt_len, i, 2);
+ if (!rx_streams[i])
+ goto err;
+ }
+
+ for (i = 0; i < test->nb_sockets; i++) {
+ test->ifobj_tx->xsk_arr[i].pkt_stream = tx_streams[i];
+ test->ifobj_rx->xsk_arr[i].pkt_stream = rx_streams[i];
+ }
+
+ return 0;
+
+err:
+ for (i = 0; i < test->nb_sockets; i++) {
+ if (tx_streams[i])
+ pkt_stream_delete(tx_streams[i]);
+ if (rx_streams[i])
+ pkt_stream_delete(rx_streams[i]);
+ }
+
+ return -ENOMEM;
+}
+
+static int pkt_stream_weighted_uneven_dist_sequence(struct test_spec *test, u32 total_pkts,
+ u32 pkt_len)
+{
+ struct pkt_stream *tx_streams[MAX_SOCKETS] = {};
+ struct pkt_stream *rx_streams[MAX_SOCKETS] = {};
+ u32 i, pkts_sock0;
+
+ if (test->nb_sockets < 2 || total_pkts < 4)
+ return -EINVAL;
+
+ pkts_sock0 = total_pkts / 4;
+
+ for (i = 0; i < test->nb_sockets; i++) {
+ u32 nb_pkts = (i == 0) ? pkts_sock0 : (total_pkts - pkts_sock0);
+
+ tx_streams[i] = __pkt_stream_generate(nb_pkts, pkt_len, i, 2);
+ if (!tx_streams[i])
+ goto err;
+
+ rx_streams[i] = __pkt_stream_generate(nb_pkts, pkt_len, i, 2);
+ if (!rx_streams[i])
+ goto err;
+ }
+
+ for (i = 0; i < test->nb_sockets; i++) {
+ test->ifobj_tx->xsk_arr[i].pkt_stream = tx_streams[i];
+ test->ifobj_rx->xsk_arr[i].pkt_stream = rx_streams[i];
}
return 0;
+
+err:
+ for (i = 0; i < test->nb_sockets; i++) {
+ if (tx_streams[i])
+ pkt_stream_delete(tx_streams[i]);
+ if (rx_streams[i])
+ pkt_stream_delete(rx_streams[i]);
+ }
+
+ return -ENOMEM;
}
static void release_even_odd_sequence(struct test_spec *test)
@@ -1468,6 +1587,28 @@ static int validate_tx_invalid_descs(struct ifobject *ifobject)
return TEST_PASS;
}
+static void xsk_delete_socket_batch(struct ifobject *ifobject, u32 count)
+{
+ u32 i;
+
+ if (!ifobject)
+ return;
+
+ for (i = count; i > 0; i--)
+ xsk_delete_socket(&ifobject->xsk_arr[i - 1]);
+}
+
+static void xsk_configure_rollback(struct ifobject *ifobject, int last)
+{
+ u32 count;
+
+ if (!ifobject || last < 0)
+ return;
+
+ count = last + 1;
+ xsk_delete_socket_batch(ifobject, count);
+}
+
static int xsk_configure(struct test_spec *test, struct ifobject *ifobject,
struct xsk_umem_info *umem, bool tx)
{
@@ -1484,14 +1625,18 @@ static int xsk_configure(struct test_spec *test, struct ifobject *ifobject,
break;
/* Retry if it fails as xsk_socket__create() is asynchronous */
- if (ctr >= SOCK_RECONF_CTR)
+ if (ctr >= SOCK_RECONF_CTR) {
+ xsk_configure_rollback(ifobject, i);
return ret;
+ }
usleep(USLEEP_MAX);
}
if (ifobject->busy_poll) {
ret = enable_busy_poll(&ifobject->xsk_arr[i]);
- if (ret)
+ if (ret) {
+ xsk_configure_rollback(ifobject, i);
return ret;
+ }
}
}
@@ -1702,12 +1847,60 @@ void *worker_testapp_validate_rx(void *arg)
pthread_exit(NULL);
}
-static void testapp_clean_xsk_umem(struct ifobject *ifobj)
+void xsk_delete_socket(struct xsk_socket_info *xsk)
{
- struct xsk_umem_info *umem = ifobj->xsk->umem;
+ struct xsk_umem_info *umem;
- xsk_umem__delete(umem->umem);
- munmap(umem->buffer, umem->mmap_size);
+ /*
+ * Callers must serialize teardown for a given xsk/umem pair.
+ * This helper does refcount-based lifetime management only.
+ */
+ if (!xsk)
+ return;
+
+ umem = xsk->umem;
+ if (!umem)
+ return;
+
+ /* Delete the socket handle when available, then drop UMEM reference. */
+ if (xsk->xsk)
+ xsk_socket__delete(xsk->xsk);
+ xsk->xsk = NULL;
+
+ /* Mark this socket as cleaned up to prevent double-decrement */
+ xsk->umem = NULL;
+
+ /*
+ * Teardown may walk the full xsk array, including slots that never completed setup but
+ * still carry a preinitialized umem pointer. After a partial-setup rollback, the last UMEM
+ * ref may already be dropped.
+ */
+ if (!refcount_read(&umem->users))
+ return;
+
+ /* Always decrement refcount for this socket's UMEM reference */
+ if (refcount_dec_and_test(&umem->users)) {
+ if (umem->umem) {
+ int err = xsk_umem__delete(umem->umem);
+
+ if (err)
+ ksft_print_msg("xsk_umem__delete failed: %d (umem still busy?)\n",
+ err);
+ }
+ if (umem->buffer && umem->mmap_size)
+ munmap(umem->buffer, umem->mmap_size);
+ umem->umem = NULL;
+ umem->buffer = NULL;
+ umem->mmap_size = 0;
+ }
+}
+
+static void xsk_delete_all_ifobj_sockets(struct test_spec *test, struct ifobject *ifobj)
+{
+ if (!ifobj)
+ return;
+
+ xsk_delete_socket_batch(ifobj, test->nb_sockets);
}
static bool xdp_prog_changed_rx(struct test_spec *test)
@@ -1769,27 +1962,6 @@ static int xsk_attach_xdp_progs(struct test_spec *test, struct ifobject *ifobj_r
return err;
}
-static void clean_sockets(struct test_spec *test, struct ifobject *ifobj)
-{
- u32 i;
-
- if (!ifobj || !test)
- return;
-
- for (i = 0; i < test->nb_sockets; i++)
- xsk_socket__delete(ifobj->xsk_arr[i].xsk);
-}
-
-static void clean_umem(struct test_spec *test, struct ifobject *ifobj1, struct ifobject *ifobj2)
-{
- if (!ifobj1)
- return;
-
- testapp_clean_xsk_umem(ifobj1);
- if (ifobj2 && !ifobj2->shared_umem)
- testapp_clean_xsk_umem(ifobj2);
-}
-
static int __testapp_validate_traffic(struct test_spec *test, struct ifobject *ifobj1,
struct ifobject *ifobj2)
{
@@ -1841,8 +2013,7 @@ static int __testapp_validate_traffic(struct test_spec *test, struct ifobject *i
if (pthread_barrier_destroy(&barr)) {
test->use_barrier = false;
pthread_join(t0, NULL);
- clean_sockets(test, ifobj1);
- clean_umem(test, ifobj1, NULL);
+ xsk_delete_all_ifobj_sockets(test, ifobj1);
return TEST_FAILURE;
}
}
@@ -1856,9 +2027,8 @@ static int __testapp_validate_traffic(struct test_spec *test, struct ifobject *i
pthread_join(t0, NULL);
if (test->total_steps == test->current_step || test->fail) {
- clean_sockets(test, ifobj1);
- clean_sockets(test, ifobj2);
- clean_umem(test, ifobj1, ifobj2);
+ xsk_delete_all_ifobj_sockets(test, ifobj2);
+ xsk_delete_all_ifobj_sockets(test, ifobj1);
}
if (test->fail)
@@ -1967,9 +2137,8 @@ int testapp_xdp_prog_cleanup(struct test_spec *test)
return TEST_FAILURE;
if (swap_xsk_resources(test)) {
- clean_sockets(test, test->ifobj_rx);
- clean_sockets(test, test->ifobj_tx);
- clean_umem(test, test->ifobj_rx, test->ifobj_tx);
+ xsk_delete_all_ifobj_sockets(test, test->ifobj_tx);
+ xsk_delete_all_ifobj_sockets(test, test->ifobj_rx);
return TEST_FAILURE;
}
@@ -2224,6 +2393,168 @@ int testapp_xdp_shared_umem(struct test_spec *test)
return ret;
}
+static int shared_umem_test_prepare(struct test_spec *test)
+{
+ u32 i;
+
+ if (test->nb_sockets > MAX_SOCKETS) {
+ ksft_print_msg("ERROR: [%s] invalid socket count %u\n", __func__, test->nb_sockets);
+ return TEST_FAILURE;
+ }
+
+ for (i = 0; i < test->nb_sockets; i++) {
+ if (!test->ifobj_rx->xsk_arr[i].pkt_stream ||
+ !test->ifobj_tx->xsk_arr[i].pkt_stream) {
+ ksft_print_msg("ERROR: [%s] missing stream for socket %u\n", __func__, i);
+ return TEST_FAILURE;
+ }
+ }
+
+ return TEST_PASS;
+}
+
+static int shared_umem_seq_even_odd(struct test_spec *test, const void *ctx)
+{
+ (void)ctx;
+
+ return pkt_stream_even_odd_sequence(test) ? TEST_FAILURE : TEST_PASS;
+}
+
+static int shared_umem_seq_len(struct test_spec *test, const void *ctx)
+{
+ const struct shared_umem_len_ctx *cfg = ctx;
+
+ return pkt_stream_len_seq(test, cfg->short_len, cfg->long_len) ? TEST_FAILURE : TEST_PASS;
+}
+
+static int shared_umem_seq_uneven_dist(struct test_spec *test, const void *ctx)
+{
+ const struct shared_umem_uneven_dist_ctx *cfg = ctx;
+
+ return pkt_stream_weighted_uneven_dist_sequence(test, cfg->total_pkts,
+ cfg->pkt_len) ? TEST_FAILURE : TEST_PASS;
+}
+
+static int shared_umem_post_uneven_dist(struct test_spec *test, int ret, const void *ctx)
+{
+ struct pkt_stream *tx_stream_0, *tx_stream_1;
+ struct pkt_stream *rx_stream_0, *rx_stream_1;
+
+ (void)ctx;
+
+ tx_stream_0 = test->ifobj_tx->xsk_arr[0].pkt_stream;
+ tx_stream_1 = test->ifobj_tx->xsk_arr[1].pkt_stream;
+ rx_stream_0 = test->ifobj_rx->xsk_arr[0].pkt_stream;
+ rx_stream_1 = test->ifobj_rx->xsk_arr[1].pkt_stream;
+
+ if (tx_stream_1->nb_valid_entries <= tx_stream_0->nb_valid_entries)
+ return TEST_FAILURE;
+
+ if (!ret && rx_stream_1->nb_rx_pkts <= rx_stream_0->nb_rx_pkts) {
+ ksft_print_msg("ERROR: socket1 rx_pkts (%u) not greater than socket0 (%u)\n",
+ rx_stream_1->nb_rx_pkts, rx_stream_0->nb_rx_pkts);
+ ret = TEST_FAILURE;
+ }
+
+ return ret;
+}
+
+static int run_shared_umem_test(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, u32 nb_sockets,
+ shared_umem_seq_fn seq_fn, shared_umem_post_fn post_fn,
+ const void *ctx)
+{
+ int ret;
+
+ test->total_steps = 1;
+ test->nb_sockets = nb_sockets;
+
+ test_spec_set_xdp_prog(test, xdp_prog_rx, xdp_prog_tx, xskmap_rx, xskmap_tx);
+
+ ret = shared_umem_test_prepare(test);
+ if (ret)
+ return ret;
+
+ ret = seq_fn(test, ctx);
+ if (ret)
+ return ret;
+
+ ret = testapp_validate_traffic(test);
+ if (post_fn)
+ ret = post_fn(test, ret, ctx);
+
+ release_even_odd_sequence(test);
+
+ return ret;
+}
+
+int testapp_shared_umem_4_sockets(struct test_spec *test)
+{
+ struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs;
+ struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs;
+
+ return run_shared_umem_test(test, skel_rx->progs.xsk_xdp_shared_umem,
+ skel_tx->progs.xsk_xdp_shared_umem, skel_rx->maps.xsk,
+ skel_tx->maps.xsk, 4, shared_umem_seq_even_odd, NULL, NULL);
+}
+
+int testapp_shared_umem_length_based(struct test_spec *test)
+{
+ struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs;
+ struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs;
+ const struct shared_umem_len_ctx len_ctx = {
+ .short_len = MIN_PKT_SIZE,
+ .long_len = MIN_PKT_SIZE * 2,
+ };
+
+ return run_shared_umem_test(test, skel_rx->progs.xsk_xdp_shared_umem_length_based,
+ skel_tx->progs.xsk_xdp_shared_umem_length_based,
+ skel_rx->maps.xsk, skel_tx->maps.xsk, 2, shared_umem_seq_len,
+ NULL, &len_ctx);
+}
+
+int testapp_shared_umem_uneven_dist(struct test_spec *test)
+{
+ struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs;
+ struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs;
+ const struct shared_umem_uneven_dist_ctx uneven_dist_ctx = {
+ .total_pkts = DEFAULT_PKT_CNT * 4,
+ .pkt_len = MIN_PKT_SIZE,
+ };
+
+ return run_shared_umem_test(test, skel_rx->progs.xsk_xdp_shared_umem,
+ skel_tx->progs.xsk_xdp_shared_umem, skel_rx->maps.xsk,
+ skel_tx->maps.xsk, 2, shared_umem_seq_uneven_dist,
+ shared_umem_post_uneven_dist, &uneven_dist_ctx);
+}
+
+int testapp_shared_umem_unaligned(struct test_spec *test)
+{
+ struct xsk_xdp_progs *skel_rx = test->ifobj_rx->xdp_progs;
+ struct xsk_xdp_progs *skel_tx = test->ifobj_tx->xdp_progs;
+ struct xsk_umem_info *tx_umem = test->ifobj_tx && test->ifobj_tx->xsk ?
+ test->ifobj_tx->xsk->umem : NULL;
+ struct xsk_umem_info *rx_umem = test->ifobj_rx && test->ifobj_rx->xsk ?
+ test->ifobj_rx->xsk->umem : NULL;
+ bool tx_unaligned = tx_umem ? tx_umem->unaligned_mode : false;
+ bool rx_unaligned = rx_umem ? rx_umem->unaligned_mode : false;
+ int ret;
+
+ test_spec_set_unaligned(test);
+
+ ret = run_shared_umem_test(test, skel_rx->progs.xsk_xdp_shared_umem,
+ skel_tx->progs.xsk_xdp_shared_umem, skel_rx->maps.xsk,
+ skel_tx->maps.xsk, 2, shared_umem_seq_even_odd, NULL, NULL);
+
+ if (tx_umem)
+ tx_umem->unaligned_mode = tx_unaligned;
+ if (rx_umem)
+ rx_umem->unaligned_mode = rx_unaligned;
+
+ return ret;
+}
+
int testapp_poll_txq_tmout(struct test_spec *test)
{
bool shared_umem = test->ifobj_tx->shared_umem;
@@ -2498,9 +2829,8 @@ int testapp_hw_sw_max_ring_size(struct test_spec *test)
test->ifobj_tx->xsk->batch_size = test->ifobj_tx->ring.tx_max_pending - 8;
test->ifobj_rx->xsk->batch_size = test->ifobj_tx->ring.tx_max_pending - 8;
if (pkt_stream_replace(test, max_descs, MIN_PKT_SIZE)) {
- clean_sockets(test, test->ifobj_tx);
- clean_sockets(test, test->ifobj_rx);
- clean_umem(test, test->ifobj_rx, test->ifobj_tx);
+ xsk_delete_all_ifobj_sockets(test, test->ifobj_tx);
+ xsk_delete_all_ifobj_sockets(test, test->ifobj_rx);
return TEST_FAILURE;
}
diff --git a/tools/testing/selftests/bpf/prog_tests/test_xsk.h b/tools/testing/selftests/bpf/prog_tests/test_xsk.h
index 03753ddc5dcda..ef9c422d7763e 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_xsk.h
+++ b/tools/testing/selftests/bpf/prog_tests/test_xsk.h
@@ -4,6 +4,7 @@
#include <linux/ethtool.h>
#include <linux/if_xdp.h>
+#include <linux/refcount.h>
#include "../kselftest.h"
#include "xsk.h"
@@ -79,6 +80,9 @@ struct test_spec;
typedef int (*validation_func_t)(struct ifobject *ifobj);
typedef void *(*thread_func_t)(void *arg);
typedef int (*test_func_t)(struct test_spec *test);
+typedef int (*shared_umem_seq_fn)(struct test_spec *test, const void *ctx);
+typedef int (*shared_umem_post_fn)(struct test_spec *test, int ret,
+ const void *ctx);
struct xsk_socket_info {
struct xsk_ring_cons rx;
@@ -104,6 +108,7 @@ struct xsk_umem_info {
struct xsk_umem *umem;
u64 next_buffer;
u64 mmap_size;
+ refcount_t users;
u32 num_frames;
u32 frame_headroom;
void *buffer;
@@ -159,6 +164,7 @@ int init_iface(struct ifobject *ifobj, thread_func_t func_ptr);
int xsk_configure_umem(struct ifobject *ifobj, struct xsk_umem_info *umem, void *buffer, u64 size);
int xsk_configure_socket(struct xsk_socket_info *xsk, struct xsk_umem_info *umem,
struct ifobject *ifobject, bool shared);
+void xsk_delete_socket(struct xsk_socket_info *xsk);
struct pkt {
@@ -179,6 +185,16 @@ struct pkt_stream {
bool verbatim;
};
+struct shared_umem_len_ctx {
+ u32 short_len;
+ u32 long_len;
+};
+
+struct shared_umem_uneven_dist_ctx {
+ u32 total_pkts;
+ u32 pkt_len;
+};
+
static inline bool pkt_continues(u32 options)
{
return options & XDP_PKT_CONTD;
@@ -268,6 +284,10 @@ int testapp_xdp_metadata(struct test_spec *test);
int testapp_xdp_metadata_mb(struct test_spec *test);
int testapp_xdp_prog_cleanup(struct test_spec *test);
int testapp_xdp_shared_umem(struct test_spec *test);
+int testapp_shared_umem_4_sockets(struct test_spec *test);
+int testapp_shared_umem_length_based(struct test_spec *test);
+int testapp_shared_umem_uneven_dist(struct test_spec *test);
+int testapp_shared_umem_unaligned(struct test_spec *test);
void *worker_testapp_validate_rx(void *arg);
void *worker_testapp_validate_tx(void *arg);
@@ -291,6 +311,10 @@ static const struct test_spec tests[] = {
{.name = "XDP_PROG_CLEANUP", .test_func = testapp_xdp_prog_cleanup},
{.name = "XDP_DROP_HALF", .test_func = testapp_xdp_drop},
{.name = "XDP_SHARED_UMEM", .test_func = testapp_xdp_shared_umem},
+ {.name = "SHARED_UMEM_4_SOCKETS", .test_func = testapp_shared_umem_4_sockets},
+ {.name = "SHARED_UMEM_LENGTH_BASED", .test_func = testapp_shared_umem_length_based},
+ {.name = "SHARED_UMEM_UNEVEN_DIST", .test_func = testapp_shared_umem_uneven_dist},
+ {.name = "SHARED_UMEM_UNALIGNED", .test_func = testapp_shared_umem_unaligned},
{.name = "XDP_METADATA_COPY", .test_func = testapp_xdp_metadata},
{.name = "XDP_METADATA_COPY_MULTI_BUFF", .test_func = testapp_xdp_metadata_mb},
{.name = "ALIGNED_INV_DESC_MULTI_BUFF", .test_func = testapp_aligned_inv_desc_mb},
diff --git a/tools/testing/selftests/bpf/progs/xsk_xdp_progs.c b/tools/testing/selftests/bpf/progs/xsk_xdp_progs.c
index 023d8befd4cab..543b61df3a2b1 100644
--- a/tools/testing/selftests/bpf/progs/xsk_xdp_progs.c
+++ b/tools/testing/selftests/bpf/progs/xsk_xdp_progs.c
@@ -10,7 +10,7 @@
struct {
__uint(type, BPF_MAP_TYPE_XSKMAP);
- __uint(max_entries, 2);
+ __uint(max_entries, MAX_SOCKETS);
__uint(key_size, sizeof(int));
__uint(value_size, sizeof(int));
} xsk SEC(".maps");
@@ -75,6 +75,23 @@ SEC("xdp") int xsk_xdp_shared_umem(struct xdp_md *xdp)
return bpf_redirect_map(&xsk, idx, XDP_DROP);
}
+SEC("xdp") int xsk_xdp_shared_umem_length_based(struct xdp_md *xdp)
+{
+ void *data = (void *)(long)xdp->data;
+ void *data_end = (void *)(long)xdp->data_end;
+ __u32 pkt_len = data_end - data;
+
+ /*
+ * Route packets by total XDP-visible packet length (data_end - data):
+ * - Socket 0: packets <= SHARED_UMEM_LEN_SPLIT bytes
+ * - Socket 1: packets > SHARED_UMEM_LEN_SPLIT bytes
+ */
+ if (pkt_len <= SHARED_UMEM_LEN_SPLIT)
+ return bpf_redirect_map(&xsk, 0, XDP_DROP);
+ else
+ return bpf_redirect_map(&xsk, 1, XDP_DROP);
+}
+
SEC("xdp.frags") int xsk_xdp_adjust_tail(struct xdp_md *xdp)
{
__u32 buff_len, curr_buff_len;
diff --git a/tools/testing/selftests/bpf/xsk_xdp_common.h b/tools/testing/selftests/bpf/xsk_xdp_common.h
index 45810ff552dae..bd9b5dcf8c8ee 100644
--- a/tools/testing/selftests/bpf/xsk_xdp_common.h
+++ b/tools/testing/selftests/bpf/xsk_xdp_common.h
@@ -3,7 +3,8 @@
#ifndef XSK_XDP_COMMON_H_
#define XSK_XDP_COMMON_H_
-#define MAX_SOCKETS 2
+#define MAX_SOCKETS 4
+#define SHARED_UMEM_LEN_SPLIT 64
#define PKT_HDR_ALIGN (sizeof(struct ethhdr) + 2) /* Just to align the data in the packet */
struct xdp_info {
diff --git a/tools/testing/selftests/bpf/xskxceiver.c b/tools/testing/selftests/bpf/xskxceiver.c
index 7dad8556a722e..ed7716b637567 100644
--- a/tools/testing/selftests/bpf/xskxceiver.c
+++ b/tools/testing/selftests/bpf/xskxceiver.c
@@ -117,12 +117,13 @@ static void __exit_with_error(int error, const char *file, const char *func, int
#define exit_with_error(error) __exit_with_error(error, __FILE__, __func__, __LINE__)
-static bool ifobj_zc_avail(struct ifobject *ifobject)
+static bool ifobj_zc_avail(struct ifobject *ifobj)
{
size_t umem_sz = DEFAULT_UMEM_BUFFERS * XSK_UMEM__DEFAULT_FRAME_SIZE;
int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
- struct xsk_socket_info *xsk;
- struct xsk_umem_info *umem;
+ struct xsk_socket_info xsk = {};
+ struct xsk_umem_info umem_info = {};
+ struct xsk_umem_info *umem = &umem_info;
bool zc_avail = false;
void *bufs;
int ret;
@@ -131,32 +132,22 @@ static bool ifobj_zc_avail(struct ifobject *ifobject)
if (bufs == MAP_FAILED)
exit_with_error(errno);
- umem = calloc(1, sizeof(struct xsk_umem_info));
- if (!umem) {
- munmap(bufs, umem_sz);
- exit_with_error(ENOMEM);
- }
+ umem->mmap_size = umem_sz;
umem->frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE;
- ret = xsk_configure_umem(ifobject, umem, bufs, umem_sz);
+ ret = xsk_configure_umem(ifobj, umem, bufs, umem_sz);
if (ret)
exit_with_error(-ret);
- xsk = calloc(1, sizeof(struct xsk_socket_info));
- if (!xsk)
- goto out;
- ifobject->bind_flags = XDP_USE_NEED_WAKEUP | XDP_ZEROCOPY;
- ifobject->rx_on = true;
- xsk->rxqsize = XSK_RING_CONS__DEFAULT_NUM_DESCS;
- ret = xsk_configure_socket(xsk, umem, ifobject, false);
+ ifobj->bind_flags = XDP_USE_NEED_WAKEUP | XDP_ZEROCOPY;
+ ifobj->rx_on = true;
+ xsk.rxqsize = XSK_RING_CONS__DEFAULT_NUM_DESCS;
+ ret = xsk_configure_socket(&xsk, umem, ifobj, false);
if (!ret)
zc_avail = true;
- xsk_socket__delete(xsk->xsk);
- free(xsk);
-out:
- munmap(umem->buffer, umem_sz);
- xsk_umem__delete(umem->umem);
- free(umem);
+ /* Use the same refcount-based teardown path for both success and failure. */
+ xsk_delete_socket(&xsk);
+
return zc_avail;
}
|
| 3/2 | 2026/08/07 16:57 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12241 output: 68 thoughts: 787 Thoughts: **WorthFuzzing Assessment** Okay, let's break this down. I've got a patch that's touched a bunch of files, all under `tools/testing/selftests/bpf/`. My first instinct is to check if these changes warrant fuzzing. The instructions are pretty clear: return `WorthFuzzing=false` if the patch *only* contains modifications to tests, documentation, comments, decorative logging, non-functional numeric changes, unreachable code paths, or vendor-specific drivers requiring specific hardware. Right, so, first things first: let me isolate where the changes are. `tools/testing/selftests/bpf/prog_tests/test_xsk.c`, `tools/testing/selftests/bpf/prog_tests/test_xsk.h`, `tools/testing/selftests/bpf/progs/xsk_xdp_progs.c`, `tools/testing/selftests/bpf/xsk_xdp_common.h`, and `tools/testing/selftests/bpf/xskxceiver.c`. Bingo! All test code. Now the important question: are these selftests touching core kernel logic, drivers, or architectures? The answer is no, this is all test infrastructure, userspace programs, and BPF programs used for testing. These files don't change any of the kernel's functional behavior, but are test programs for BPF. The guidelines are explicit. If core kernel logic, drivers, or architectures were touched, I'd need to confirm executability and then return `WorthFuzzing=true`. However, since it is only a change to selftests, I don't see any changes to the kernel. So, let me reconfirm: the files modified are limited to BPF selftests, within `tools/testing/selftests/bpf/`. This means the patch *only* impacts the test suite, and doesn't introduce any functional alterations to the kernel itself. Therefore, my assessment is: `WorthFuzzing=false`. The rationale is straightforward: This patch focuses solely on modifying and improving BPF selftests, not core kernel functionality, and does not warrant fuzzing the kernel. |
| 4/2 | 2026/08/07 16:57 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch only modifies BPF selftests (userspace test programs and test BPF programs) and does not make any functional changes to the core kernel, drivers, or architectures.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch only modifies BPF selftests (userspace test programs and test BPF programs) and does not make any functional changes to the core kernel, drivers, or architectures.",
"WorthFuzzing": false
} |
| 5/1 | 2026/08/07 16:57 | action | If |
0mArgs:{
"WorthFuzzing": false
}Results: null |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|