| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/13 07:28 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"KMSANReasoning": "",
"NeedsKMSAN": false,
"Reasoning": "The patch only modifies BPF selftests in tools/testing/selftests/bpf/. It does not make any functional changes to the kernel code itself.",
"WorthFuzzing": false
} |
| 1/1 | 2026/08/13 07:28 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 99b0355ee99cd1a54064ed7002fb30da3424e405\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Thu Aug 13 07:28:02 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 4549358cc8c21..ae6a091b64852 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,26 @@ 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\t/*\n+\t\t * For shared sockets refcount_inc hasn't run yet, so clear umem to mark this slot\n+\t\t * as having no reference. For the owner (non-shared) the reference was taken by\n+\t\t * xsk_configure_umem; leave umem set so the caller's rollback path can release it\n+\t\t * via umem_ref.\n+\t\t */\n+\t\tif (shared)\n+\t\t\txsk-\u003eumem = NULL;\n+\t\txsk-\u003exsk = NULL;\n+\t\treturn ret;\n+\t}\n+\n+\tif (shared) {\n+\t\trefcount_inc(\u0026umem-\u003eusers);\n+\t\txsk-\u003eumem_ref = true;\n+\t}\n+\n+\treturn ret;\n }\n \n static int set_ring_size(struct ifobject *ifobj)\n@@ -203,6 +224,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 +241,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 +602,121 @@ 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\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\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\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, 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\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, 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_uneven_dist_seq(struct test_spec *test, u32 total_pkts, 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@@ -1467,6 +1590,17 @@ 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 int xsk_configure(struct test_spec *test, struct ifobject *ifobject,\n \t\t\t struct xsk_umem_info *umem, bool tx)\n {\n@@ -1599,6 +1733,8 @@ static int thread_common_ops(struct test_spec *test, struct ifobject *ifobject)\n \tret = xsk_configure_umem(ifobject, umem, bufs, umem_sz);\n \tif (ret)\n \t\treturn ret;\n+\t/* Mark before xsk_configure so rollback can release the UMEM if it fails. */\n+\tifobject-\u003exsk-\u003eumem_ref = true;\n \n \tret = xsk_configure(test, ifobject, umem, false);\n \tif (ret)\n@@ -1669,12 +1805,15 @@ void *worker_testapp_validate_rx(void *arg)\n \t\t\t\t strerror(-err));\n \t}\n \n+\t/* Publish setup failure before releasing the main thread from the barrier. */\n+\tif (err)\n+\t\ttest-\u003efail = true;\n+\n \tif (test-\u003euse_barrier)\n \t\tpthread_barrier_wait(\u0026barr);\n \n \t/* We leave only now in case of error to avoid getting stuck in the barrier */\n \tif (err) {\n-\t\ttest-\u003efail = true;\n \t\tpthread_exit(NULL);\n \t}\n \n@@ -1701,12 +1840,61 @@ 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+\tif (!xsk)\n+\t\treturn;\n \n-\txsk_umem__delete(umem-\u003eumem);\n-\tmunmap(umem-\u003ebuffer, umem-\u003emmap_size);\n+\tumem = xsk-\u003eumem;\n+\tif (!umem)\n+\t\treturn;\n+\n+\tif (xsk-\u003exsk)\n+\t\txsk_socket__delete(xsk-\u003exsk);\n+\txsk-\u003exsk = NULL;\n+\n+\t/* Skip slots that never acquired a UMEM reference (pre-initialized but unconfigured). */\n+\tif (!xsk-\u003eumem_ref) {\n+\t\txsk-\u003eumem = NULL;\n+\t\treturn;\n+\t}\n+\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\t\t/* Keep ownership explicit so a later cleanup pass can retry\n+\t\t\t\t * delete.\n+\t\t\t\t */\n+\t\t\t\trefcount_set(\u0026umem-\u003eusers, 1);\n+\t\t\t\txsk-\u003eumem_ref = true;\n+\t\t\t\txsk-\u003eumem = umem;\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t\tumem-\u003eumem = NULL;\n+\t\t}\n+\t\tif (umem-\u003ebuffer \u0026\u0026 umem-\u003emmap_size) {\n+\t\t\tmunmap(umem-\u003ebuffer, umem-\u003emmap_size);\n+\t\t\tumem-\u003ebuffer = NULL;\n+\t\t\tumem-\u003emmap_size = 0;\n+\t\t}\n+\t}\n+\n+\txsk-\u003eumem_ref = false;\n+\txsk-\u003eumem = NULL;\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@@ -1768,27 +1956,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@@ -1840,13 +2007,12 @@ 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 \n-\tif (ifobj2) {\n+\tif (ifobj2 \u0026\u0026 !test-\u003efail) {\n \t\t/*Spawn TX thread */\n \t\tpthread_create(\u0026t1, NULL, ifobj2-\u003efunc_ptr, test);\n \t\tpthread_join(t1, NULL);\n@@ -1855,9 +2021,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@@ -1966,9 +2131,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@@ -2226,6 +2390,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_uneven_dist_seq(test, cfg-\u003etotal_pkts,\n+\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@@ -2506,9 +2832,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..93dcf66b4e625 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@@ -93,6 +97,7 @@ struct xsk_socket_info {\n \tu8 dst_mac[ETH_ALEN];\n \tu8 src_mac[ETH_ALEN];\n \tbool check_consumer;\n+\tbool umem_ref; /* true if this slot holds a counted UMEM reference */\n };\n \n int kick_rx(struct xsk_socket_info *xsk);\n@@ -104,6 +109,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,7 +165,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-\n+void xsk_delete_socket(struct xsk_socket_info *xsk);\n \n struct pkt {\n \tint offset;\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..8bab2bcf52ab2 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,19 @@ 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/* Route packets by total XDP-visible packet length. */\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..a86eaf141e931 100644\n--- a/tools/testing/selftests/bpf/xskxceiver.c\n+++ b/tools/testing/selftests/bpf/xskxceiver.c\n@@ -117,12 +117,12 @@ 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 = {};\n \tbool zc_avail = false;\n \tvoid *bufs;\n \tint ret;\n@@ -131,32 +131,24 @@ 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-\u003eframe_size = XSK_UMEM__DEFAULT_FRAME_SIZE;\n-\tret = xsk_configure_umem(ifobject, umem, bufs, umem_sz);\n+\tumem.mmap_size = umem_sz;\n+\tumem.frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE;\n+\tret = xsk_configure_umem(ifobj, \u0026umem, 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+\txsk.umem_ref = true;\n+\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, \u0026umem, 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/13 07:28 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch only modifies BPF selftests in tools/testing/selftests/bpf/. It does not make any functional changes to the kernel code itself.",
"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 99b0355ee99cd1a54064ed7002fb30da3424e405
Author: syz-cluster <triage@syzkaller.com>
Date: Thu Aug 13 07:28:02 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 4549358cc8c21..ae6a091b64852 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,26 @@ 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) {
+ /*
+ * For shared sockets refcount_inc hasn't run yet, so clear umem to mark this slot
+ * as having no reference. For the owner (non-shared) the reference was taken by
+ * xsk_configure_umem; leave umem set so the caller's rollback path can release it
+ * via umem_ref.
+ */
+ if (shared)
+ xsk->umem = NULL;
+ xsk->xsk = NULL;
+ return ret;
+ }
+
+ if (shared) {
+ refcount_inc(&umem->users);
+ xsk->umem_ref = true;
+ }
+
+ return ret;
}
static int set_ring_size(struct ifobject *ifobj)
@@ -203,6 +224,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 +241,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 +602,121 @@ 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;
+ 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;
+ 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;
- 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_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_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_uneven_dist_seq(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)
@@ -1467,6 +1590,17 @@ 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 int xsk_configure(struct test_spec *test, struct ifobject *ifobject,
struct xsk_umem_info *umem, bool tx)
{
@@ -1599,6 +1733,8 @@ static int thread_common_ops(struct test_spec *test, struct ifobject *ifobject)
ret = xsk_configure_umem(ifobject, umem, bufs, umem_sz);
if (ret)
return ret;
+ /* Mark before xsk_configure so rollback can release the UMEM if it fails. */
+ ifobject->xsk->umem_ref = true;
ret = xsk_configure(test, ifobject, umem, false);
if (ret)
@@ -1669,12 +1805,15 @@ void *worker_testapp_validate_rx(void *arg)
strerror(-err));
}
+ /* Publish setup failure before releasing the main thread from the barrier. */
+ if (err)
+ test->fail = true;
+
if (test->use_barrier)
pthread_barrier_wait(&barr);
/* We leave only now in case of error to avoid getting stuck in the barrier */
if (err) {
- test->fail = true;
pthread_exit(NULL);
}
@@ -1701,12 +1840,61 @@ 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;
+
+ if (!xsk)
+ return;
- xsk_umem__delete(umem->umem);
- munmap(umem->buffer, umem->mmap_size);
+ umem = xsk->umem;
+ if (!umem)
+ return;
+
+ if (xsk->xsk)
+ xsk_socket__delete(xsk->xsk);
+ xsk->xsk = NULL;
+
+ /* Skip slots that never acquired a UMEM reference (pre-initialized but unconfigured). */
+ if (!xsk->umem_ref) {
+ xsk->umem = NULL;
+ return;
+ }
+
+ 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);
+ /* Keep ownership explicit so a later cleanup pass can retry
+ * delete.
+ */
+ refcount_set(&umem->users, 1);
+ xsk->umem_ref = true;
+ xsk->umem = umem;
+ return;
+ }
+ umem->umem = NULL;
+ }
+ if (umem->buffer && umem->mmap_size) {
+ munmap(umem->buffer, umem->mmap_size);
+ umem->buffer = NULL;
+ umem->mmap_size = 0;
+ }
+ }
+
+ xsk->umem_ref = false;
+ xsk->umem = NULL;
+}
+
+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)
@@ -1768,27 +1956,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)
{
@@ -1840,13 +2007,12 @@ 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;
}
}
- if (ifobj2) {
+ if (ifobj2 && !test->fail) {
/*Spawn TX thread */
pthread_create(&t1, NULL, ifobj2->func_ptr, test);
pthread_join(t1, NULL);
@@ -1855,9 +2021,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)
@@ -1966,9 +2131,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;
}
@@ -2226,6 +2390,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_uneven_dist_seq(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;
@@ -2506,9 +2832,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..93dcf66b4e625 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;
@@ -93,6 +97,7 @@ struct xsk_socket_info {
u8 dst_mac[ETH_ALEN];
u8 src_mac[ETH_ALEN];
bool check_consumer;
+ bool umem_ref; /* true if this slot holds a counted UMEM reference */
};
int kick_rx(struct xsk_socket_info *xsk);
@@ -104,6 +109,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,7 +165,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 {
int offset;
@@ -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..8bab2bcf52ab2 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,19 @@ 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. */
+ 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..a86eaf141e931 100644
--- a/tools/testing/selftests/bpf/xskxceiver.c
+++ b/tools/testing/selftests/bpf/xskxceiver.c
@@ -117,12 +117,12 @@ 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 = {};
bool zc_avail = false;
void *bufs;
int ret;
@@ -131,32 +131,24 @@ 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->frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE;
- ret = xsk_configure_umem(ifobject, umem, bufs, umem_sz);
+ umem.mmap_size = umem_sz;
+ umem.frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE;
+ 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);
+ xsk.umem_ref = true;
+
+ 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/13 07:28 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12420 output: 65 thoughts: 731 Thoughts: **WorthFuzzing=false: A Quick Decision** Okay, so I'm looking at a patch here, and it's touching files within `tools/testing/selftests/bpf/`. My initial reaction is that this is a straightforward case. These are *selftests*, right? They're not kernel code, they're userspace tests. The instructions are pretty clear: does the patch make functional changes to the kernel? This is the core question for fuzzing. My immediate thought is no, selftests are tests; so, they don't *directly* alter kernel functionality. But, I need to be absolutely sure, let me double check the files affected in this patch. Okay, it's just the selftest files: `test_xsk.c`, `test_xsk.h`, `xsk_xdp_progs.c`, `xsk_xdp_common.h`, and `xskxceiver.c`. Nope, still only selftests. Let me refresh myself on the "WorthFuzzing=false" conditions. Documentation, Kconfig, comments, purely decorative changes, unreachable code paths... nothing in this list explicitly mentions "selftests," but they're not *kernel* code. So, again, based on the prompt's instruction: "determine if it makes functional changes to the kernel that should be fuzzed", the answer is a definitive "no". Selftest changes are not kernel changes. Yep, I'm confident. I'm going to set `WorthFuzzing=false`. Done. |
| 4/2 | 2026/08/13 07:28 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch only modifies BPF selftests in tools/testing/selftests/bpf/. It does not make any functional changes to the kernel code itself.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch only modifies BPF selftests in tools/testing/selftests/bpf/. It does not make any functional changes to the kernel code itself.",
"WorthFuzzing": false
} |
| 5/1 | 2026/08/13 07:28 | 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) |
|---|