From: Julius Bairaktaris <julius@bairaktaris.de>
To: pablo@netfilter.org, netfilter-devel@vger.kernel.org
Cc: kadlec@netfilter.org, fw@strlen.de, coreteam@netfilter.org,
netdev@vger.kernel.org, geldot@protonmail.com
Subject: [PATCH nf-next 4/4] selftests: netfilter: cover a TCP flow whose reply is never seen
Date: Thu, 10 Sep 2026 11:00:52 +0200 [thread overview]
Message-ID: <20260910090052.2034970-5-julius@bairaktaris.de> (raw)
In-Reply-To: <20260910090052.2034970-1-julius@bairaktaris.de>
Add an arm to nft_flowtable.sh in which ns2 answers over a direct link,
so that nsr1 sees the original direction only. The forward hook counter
then has to stay far below the size of the transferred file, which only
happens if the flowtable takes the connection over.
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
Assisted-by: Claude:claude-opus-5
---
.../selftests/net/netfilter/nft_flowtable.sh | 73 +++++++++++++++++++
1 file changed, 73 insertions(+)
diff --git a/tools/testing/selftests/net/netfilter/nft_flowtable.sh b/tools/testing/selftests/net/netfilter/nft_flowtable.sh
index 449c518bd947..516a544266f1 100755
--- a/tools/testing/selftests/net/netfilter/nft_flowtable.sh
+++ b/tools/testing/selftests/net/netfilter/nft_flowtable.sh
@@ -516,6 +516,79 @@ else
ret=1
fi
+# Asymmetric path test:
+# ns2 answers over a direct link, so nsr1 sees the original direction only.
+# Such a connection never becomes assured, but the flowtable is expected to
+# take over the direction that nsr1 does see.
+check_orig_offloaded()
+{
+ local what=$1
+
+ local orig
+ orig=$(ip netns exec "$nsr1" nft reset counter inet filter routed_orig | grep packets)
+ local orig_cnt=${orig#*bytes}
+
+ local fs
+ fs=$(du -sb "$nsin")
+ local max_orig=$(( ${fs%%/*} / 2 ))
+
+ # the flowtable takes over after the first few packets, so the forward
+ # hook must see a small fraction of the transferred file.
+ if [ "$orig_cnt" -gt "$max_orig" ];then
+ echo "FAIL: $what: original counter $orig_cnt exceeds expected value $max_orig" 1>&2
+ ret=1
+ return 1
+ fi
+
+ echo "PASS: $what"
+}
+
+test_asymmetric_path()
+{
+ ip link add name eth1 netns "$ns1" type veth peer name eth1 netns "$ns2"
+ ip -net "$ns1" addr add 10.0.9.99/24 dev eth1
+ ip -net "$ns2" addr add 10.0.9.98/24 dev eth1
+ ip -net "$ns1" addr add dead:9::99/64 dev eth1 nodad
+ ip -net "$ns2" addr add dead:9::98/64 dev eth1 nodad
+ ip -net "$ns1" link set eth1 up
+ ip -net "$ns2" link set eth1 up
+
+ # ns1 keeps sending through nsr1, ns2 answers on the direct link.
+ ip -net "$ns2" route add 10.0.1.99 via 10.0.9.99 dev eth1
+ ip -6 -net "$ns2" route add dead:1::99 via dead:9::99 dev eth1
+
+ ip netns exec "$ns1" sysctl -q net.ipv4.ip_no_pmtu_disc=0
+ ip netns exec "$ns2" sysctl -q net.ipv4.ip_no_pmtu_disc=0
+
+ ip netns exec "$nsr1" nft reset counters table inet filter >/dev/null
+
+ if test_tcp_forwarding "$ns1" "$ns2" 1 4 10.0.2.99 12345; then
+ check_orig_offloaded "flow offloaded for ns1/ns2 without reply"
+ else
+ echo "FAIL: flow offload for ns1/ns2 without reply" 1>&2
+ ip netns exec "$nsr1" nft list ruleset 1>&2
+ ret=1
+ fi
+
+ ip netns exec "$nsr1" nft reset counters table inet filter >/dev/null
+
+ if test_tcp_forwarding "$ns1" "$ns2" 1 6 "[dead:2::99]" 12345; then
+ check_orig_offloaded "IPv6 flow offloaded for ns1/ns2 without reply"
+ else
+ echo "FAIL: IPv6 flow offload for ns1/ns2 without reply" 1>&2
+ ip netns exec "$nsr1" nft list ruleset 1>&2
+ ret=1
+ fi
+
+ ip netns exec "$ns1" sysctl -q net.ipv4.ip_no_pmtu_disc=1
+ ip netns exec "$ns2" sysctl -q net.ipv4.ip_no_pmtu_disc=1
+
+ ip -net "$ns1" link del eth1
+ ip netns exec "$nsr1" nft reset counters table inet filter >/dev/null
+}
+
+test_asymmetric_path
+
# delete default route, i.e. ns2 won't be able to reach ns1 and
# will depend on ns1 being masqueraded in nsr1.
# expect ns1 has nsr1 address.
--
2.53.0
next prev parent reply other threads:[~2026-09-10 9:01 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-10 9:00 [PATCH nf-next 0/4] netfilter: offload a TCP flow whose reply is never seen Julius Bairaktaris
2026-09-10 9:00 ` [PATCH nf-next 1/4] netfilter: conntrack: pick up a TCP flow whose SYN was never answered Julius Bairaktaris
2026-09-10 9:00 ` [PATCH nf-next 2/4] netfilter: flowtable: promote a flow offloaded in one direction only Julius Bairaktaris
2026-09-10 9:00 ` [PATCH nf-next 3/4] netfilter: nft_flow_offload: offload a TCP flow that has no reply Julius Bairaktaris
2026-09-10 9:00 ` Julius Bairaktaris [this message]
2026-09-11 11:41 ` [PATCH nf-next 0/4] netfilter: offload a TCP flow whose reply is never seen Pablo Neira Ayuso
2026-09-11 12:10 ` Julius Bairaktaris
2026-09-11 14:09 ` Pablo Neira Ayuso
2026-09-11 14:16 ` Pablo Neira Ayuso
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260910090052.2034970-5-julius@bairaktaris.de \
--to=julius@bairaktaris.de \
--cc=coreteam@netfilter.org \
--cc=fw@strlen.de \
--cc=geldot@protonmail.com \
--cc=kadlec@netfilter.org \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=pablo@netfilter.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox