{"id":2220998,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2220998/?format=json","web_url":"http://patchwork.ozlabs.org/project/netfilter-devel/patch/20260408163512.30537-8-fw@strlen.de/","project":{"id":26,"url":"http://patchwork.ozlabs.org/api/1.1/projects/26/?format=json","name":"Netfilter Development","link_name":"netfilter-devel","list_id":"netfilter-devel.vger.kernel.org","list_email":"netfilter-devel@vger.kernel.org","web_url":null,"scm_url":null,"webscm_url":null},"msgid":"<20260408163512.30537-8-fw@strlen.de>","date":"2026-04-08T16:35:12","name":"[net,7/7] selftests: nft_queue.sh: add a parallel stress test","commit_ref":null,"pull_url":null,"state":"accepted","archived":true,"hash":"34736c12839cc36f0e854977843a763c699d4ea0","submitter":{"id":1025,"url":"http://patchwork.ozlabs.org/api/1.1/people/1025/?format=json","name":"Florian Westphal","email":"fw@strlen.de"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/netfilter-devel/patch/20260408163512.30537-8-fw@strlen.de/mbox/","series":[{"id":499159,"url":"http://patchwork.ozlabs.org/api/1.1/series/499159/?format=json","web_url":"http://patchwork.ozlabs.org/project/netfilter-devel/list/?series=499159","date":"2026-04-08T16:35:05","name":"[net,1/7] ipvs: fix NULL deref in ip_vs_add_service error path","version":1,"mbox":"http://patchwork.ozlabs.org/series/499159/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2220998/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2220998/checks/","tags":{},"headers":{"Return-Path":"\n <netfilter-devel+bounces-11745-incoming=patchwork.ozlabs.org@vger.kernel.org>","X-Original-To":["incoming@patchwork.ozlabs.org","netfilter-devel@vger.kernel.org"],"Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=172.234.253.10; helo=sea.lore.kernel.org;\n envelope-from=netfilter-devel+bounces-11745-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=91.216.245.30","smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=strlen.de","smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=Chamillionaire.breakpoint.cc"],"Received":["from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4frTL53x2kz1xv0\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 09 Apr 2026 02:39:25 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id 24A40307D8F9\n\tfor <incoming@patchwork.ozlabs.org>; Wed,  8 Apr 2026 16:35:50 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 160493D1CC5;\n\tWed,  8 Apr 2026 16:35:49 +0000 (UTC)","from Chamillionaire.breakpoint.cc (Chamillionaire.breakpoint.cc\n [91.216.245.30])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 6B8793B27CA;\n\tWed,  8 Apr 2026 16:35:47 +0000 (UTC)","by Chamillionaire.breakpoint.cc (Postfix, from userid 1003)\n\tid B5D7460560; Wed, 08 Apr 2026 18:35:45 +0200 (CEST)"],"ARC-Seal":"i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1775666148; cv=none;\n b=LVTskgK0kVhbc13mY4Mw0xDdX9WZyJbxwZK74msq+Jh5NU8uifh2qYC7/YEtN9U71uG+P8BnTbzL0Pv3zx17A88wdgu/ZU4c45OZY0Tk6vpAvQWgRx1k9CDth0b0SXFYp6gaIG0es9hDyxDKYvEE9tny+uDp43FjMzZtlgY5bo0=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1775666148; c=relaxed/simple;\n\tbh=+/rOeXhg1Ya6DR1P4O5XVmtQB/QwnQxKxP2BrEMvFko=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=ERePwnZqvn3UY2kEKT3t7WkEFu9oC7QBaT+SvLm0totqSwWPpr80DqxvDQPGGy+gUZU4mxt4U2dymrTuDTQ/5ftc0sxOAUu1Hm+xSHVJYaFb9Mi61eeUNvtp71jgnuKf9sfR19DA1nDXktdAfSN+ASJOtM+9hOdydHbIjneSKHg=","ARC-Authentication-Results":"i=1; smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=strlen.de;\n spf=pass smtp.mailfrom=Chamillionaire.breakpoint.cc;\n arc=none smtp.client-ip=91.216.245.30","From":"Florian Westphal <fw@strlen.de>","To":"<netdev@vger.kernel.org>","Cc":"Paolo Abeni <pabeni@redhat.com>,\n\t\"David S. Miller\" <davem@davemloft.net>,\n\tEric Dumazet <edumazet@google.com>,\n\tJakub Kicinski <kuba@kernel.org>,\n\t<netfilter-devel@vger.kernel.org>,\n\tpablo@netfilter.org","Subject":"[PATCH net 7/7] selftests: nft_queue.sh: add a parallel stress test","Date":"Wed,  8 Apr 2026 18:35:12 +0200","Message-ID":"<20260408163512.30537-8-fw@strlen.de>","X-Mailer":"git-send-email 2.52.0","In-Reply-To":"<20260408163512.30537-1-fw@strlen.de>","References":"<20260408163512.30537-1-fw@strlen.de>","Precedence":"bulk","X-Mailing-List":"netfilter-devel@vger.kernel.org","List-Id":"<netfilter-devel.vger.kernel.org>","List-Subscribe":"<mailto:netfilter-devel+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:netfilter-devel+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit"},"content":"From: Fernando Fernandez Mancera <fmancera@suse.de>\n\nIntroduce a new stress test to check for race conditions in the\nnfnetlink_queue subsystem, where an entry is freed while another CPU is\nconcurrently walking the global rhashtable.\n\nTo trigger this, `nf_queue.c` is extended with two new flags:\n  * -O (out-of-order): Buffers packet IDs and flushes them in reverse.\n  * -b (bogus verdicts): Floods the kernel with non-existent packet IDs.\n\nThe bogus verdict loop forces the kernel's lookup function to perform\nfull rhashtable bucket traversals (-ENOENT). Combined with reverse-order\nflushing and heavy parallel UDP/ping flooding across 8 queues, this puts\nthe nfnetlink_queue code under pressure.\n\nJoint work with Florian Westphal.\n\nSigned-off-by: Fernando Fernandez Mancera <fmancera@suse.de>\nSigned-off-by: Florian Westphal <fw@strlen.de>\n---\n .../selftests/net/netfilter/nf_queue.c        | 50 +++++++++--\n .../selftests/net/netfilter/nft_queue.sh      | 83 ++++++++++++++++---\n 2 files changed, 115 insertions(+), 18 deletions(-)","diff":"diff --git a/tools/testing/selftests/net/netfilter/nf_queue.c b/tools/testing/selftests/net/netfilter/nf_queue.c\nindex 116c0ca0eabb..8bbec37f5356 100644\n--- a/tools/testing/selftests/net/netfilter/nf_queue.c\n+++ b/tools/testing/selftests/net/netfilter/nf_queue.c\n@@ -19,6 +19,8 @@ struct options {\n \tbool count_packets;\n \tbool gso_enabled;\n \tbool failopen;\n+\tbool out_of_order;\n+\tbool bogus_verdict;\n \tint verbose;\n \tunsigned int queue_num;\n \tunsigned int timeout;\n@@ -31,7 +33,7 @@ static struct options opts;\n \n static void help(const char *p)\n {\n-\tprintf(\"Usage: %s [-c|-v [-vv] ] [-o] [-t timeout] [-q queue_num] [-Qdst_queue ] [ -d ms_delay ] [-G]\\n\", p);\n+\tprintf(\"Usage: %s [-c|-v [-vv] ] [-o] [-O] [-b] [-t timeout] [-q queue_num] [-Qdst_queue ] [ -d ms_delay ] [-G]\\n\", p);\n }\n \n static int parse_attr_cb(const struct nlattr *attr, void *data)\n@@ -275,7 +277,9 @@ static int mainloop(void)\n \tunsigned int buflen = 64 * 1024 + MNL_SOCKET_BUFFER_SIZE;\n \tstruct mnl_socket *nl;\n \tstruct nlmsghdr *nlh;\n+\tuint32_t ooo_ids[16];\n \tunsigned int portid;\n+\tint ooo_count = 0;\n \tchar *buf;\n \tint ret;\n \n@@ -308,6 +312,9 @@ static int mainloop(void)\n \n \t\tret = mnl_cb_run(buf, ret, 0, portid, queue_cb, NULL);\n \t\tif (ret < 0) {\n+\t\t\t/* bogus verdict mode will generate ENOENT error messages */\n+\t\t\tif (opts.bogus_verdict && errno == ENOENT)\n+\t\t\t\tcontinue;\n \t\t\tperror(\"mnl_cb_run\");\n \t\t\texit(EXIT_FAILURE);\n \t\t}\n@@ -316,10 +323,35 @@ static int mainloop(void)\n \t\tif (opts.delay_ms)\n \t\t\tsleep_ms(opts.delay_ms);\n \n-\t\tnlh = nfq_build_verdict(buf, id, opts.queue_num, opts.verdict);\n-\t\tif (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {\n-\t\t\tperror(\"mnl_socket_sendto\");\n-\t\t\texit(EXIT_FAILURE);\n+\t\tif (opts.bogus_verdict) {\n+\t\t\tfor (int i = 0; i < 50; i++) {\n+\t\t\t\tnlh = nfq_build_verdict(buf, id + 0x7FFFFFFF + i,\n+\t\t\t\t\t\t\topts.queue_num, opts.verdict);\n+\t\t\t\tmnl_socket_sendto(nl, nlh, nlh->nlmsg_len);\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (opts.out_of_order) {\n+\t\t\tooo_ids[ooo_count] = id;\n+\t\t\tif (ooo_count >= 15) {\n+\t\t\t\tfor (ooo_count; ooo_count >= 0; ooo_count--) {\n+\t\t\t\t\tnlh = nfq_build_verdict(buf, ooo_ids[ooo_count],\n+\t\t\t\t\t\t\t\topts.queue_num, opts.verdict);\n+\t\t\t\t\tif (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {\n+\t\t\t\t\t\tperror(\"mnl_socket_sendto\");\n+\t\t\t\t\t\texit(EXIT_FAILURE);\n+\t\t\t\t\t}\n+\t\t\t\t}\n+\t\t\t\tooo_count = 0;\n+\t\t\t} else {\n+\t\t\t\tooo_count++;\n+\t\t\t}\n+\t\t} else {\n+\t\t\tnlh = nfq_build_verdict(buf, id, opts.queue_num, opts.verdict);\n+\t\t\tif (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {\n+\t\t\t\tperror(\"mnl_socket_sendto\");\n+\t\t\t\texit(EXIT_FAILURE);\n+\t\t\t}\n \t\t}\n \t}\n \n@@ -332,7 +364,7 @@ static void parse_opts(int argc, char **argv)\n {\n \tint c;\n \n-\twhile ((c = getopt(argc, argv, \"chvot:q:Q:d:G\")) != -1) {\n+\twhile ((c = getopt(argc, argv, \"chvoObt:q:Q:d:G\")) != -1) {\n \t\tswitch (c) {\n \t\tcase 'c':\n \t\t\topts.count_packets = true;\n@@ -375,6 +407,12 @@ static void parse_opts(int argc, char **argv)\n \t\tcase 'v':\n \t\t\topts.verbose++;\n \t\t\tbreak;\n+\t\tcase 'O':\n+\t\t\topts.out_of_order = true;\n+\t\t\tbreak;\n+\t\tcase 'b':\n+\t\t\topts.bogus_verdict = true;\n+\t\t\tbreak;\n \t\t}\n \t}\n \ndiff --git a/tools/testing/selftests/net/netfilter/nft_queue.sh b/tools/testing/selftests/net/netfilter/nft_queue.sh\nindex ea766bdc5d04..d80390848e85 100755\n--- a/tools/testing/selftests/net/netfilter/nft_queue.sh\n+++ b/tools/testing/selftests/net/netfilter/nft_queue.sh\n@@ -11,6 +11,7 @@ ret=0\n timeout=5\n \n SCTP_TEST_TIMEOUT=60\n+STRESS_TEST_TIMEOUT=30\n \n cleanup()\n {\n@@ -719,6 +720,74 @@ EOF\n \tfi\n }\n \n+check_tainted()\n+{\n+\tlocal msg=\"$1\"\n+\n+\tif [ \"$tainted_then\" -ne 0 ];then\n+\t\treturn\n+\tfi\n+\n+\tread tainted_now < /proc/sys/kernel/tainted\n+\tif [ \"$tainted_now\" -eq 0 ];then\n+\t\techo \"PASS: $msg\"\n+\telse\n+\t\techo \"TAINT: $msg\"\n+\t\tdmesg\n+\t\tret=1\n+\tfi\n+}\n+\n+test_queue_stress()\n+{\n+\tread tainted_then < /proc/sys/kernel/tainted\n+\tlocal i\n+\n+        ip netns exec \"$nsrouter\" nft -f /dev/stdin <<EOF\n+flush ruleset\n+table inet t {\n+\tchain forward {\n+\t\ttype filter hook forward priority 0; policy accept;\n+\n+\t\tqueue flags bypass to numgen random mod 8\n+\t}\n+}\n+EOF\n+\ttimeout \"$STRESS_TEST_TIMEOUT\" ip netns exec \"$ns2\" \\\n+\t\tsocat -u UDP-LISTEN:12345,fork,pf=ipv4 STDOUT > /dev/null &\n+\n+\ttimeout \"$STRESS_TEST_TIMEOUT\" ip netns exec \"$ns3\" \\\n+\t\tsocat -u UDP-LISTEN:12345,fork,pf=ipv4 STDOUT > /dev/null &\n+\n+\tfor i in $(seq 0 7); do\n+\t\tip netns exec \"$nsrouter\" timeout \"$STRESS_TEST_TIMEOUT\" \\\n+\t\t\t./nf_queue -q $i -t 2 -O -b > /dev/null &\n+\tdone\n+\n+\tip netns exec \"$ns1\" timeout \"$STRESS_TEST_TIMEOUT\" \\\n+\t\tping -q -f 10.0.2.99 > /dev/null 2>&1 &\n+\tip netns exec \"$ns1\" timeout \"$STRESS_TEST_TIMEOUT\" \\\n+\t\tping -q -f 10.0.3.99 > /dev/null 2>&1 &\n+\tip netns exec \"$ns1\" timeout \"$STRESS_TEST_TIMEOUT\" \\\n+\t\tping -q -f \"dead:2::99\" > /dev/null 2>&1 &\n+\tip netns exec \"$ns1\" timeout \"$STRESS_TEST_TIMEOUT\" \\\n+\t\tping -q -f \"dead:3::99\" > /dev/null 2>&1 &\n+\n+\tbusywait \"$BUSYWAIT_TIMEOUT\" udp_listener_ready \"$ns2\" 12345\n+\tbusywait \"$BUSYWAIT_TIMEOUT\" udp_listener_ready \"$ns3\" 12345\n+\n+\tfor i in $(seq 1 4);do\n+\t\tip netns exec \"$ns1\" timeout \"$STRESS_TEST_TIMEOUT\" \\\n+\t\t\tsocat -u STDIN UDP-DATAGRAM:10.0.2.99:12345 < /dev/zero > /dev/null &\n+\t\tip netns exec \"$ns1\" timeout \"$STRESS_TEST_TIMEOUT\" \\\n+\t\t\tsocat -u STDIN UDP-DATAGRAM:10.0.3.99:12345 < /dev/zero > /dev/null &\n+\tdone\n+\n+\twait\n+\n+\tcheck_tainted \"concurrent queueing\"\n+}\n+\n test_queue_removal()\n {\n \tread tainted_then < /proc/sys/kernel/tainted\n@@ -742,18 +811,7 @@ EOF\n \n \tip netns exec \"$ns1\" nft flush ruleset\n \n-\tif [ \"$tainted_then\" -ne 0 ];then\n-\t\treturn\n-\tfi\n-\n-\tread tainted_now < /proc/sys/kernel/tainted\n-\tif [ \"$tainted_now\" -eq 0 ];then\n-\t\techo \"PASS: queue program exiting while packets queued\"\n-\telse\n-\t\techo \"TAINT: queue program exiting while packets queued\"\n-\t\tdmesg\n-\t\tret=1\n-\tfi\n+\tcheck_tainted \"queue program exiting while packets queued\"\n }\n \n ip netns exec \"$nsrouter\" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null\n@@ -799,6 +857,7 @@ test_sctp_forward\n test_sctp_output\n test_udp_nat_race\n test_udp_gro_ct\n+test_queue_stress\n \n # should be last, adds vrf device in ns1 and changes routes\n test_icmp_vrf\n","prefixes":["net","7/7"]}