All of lore.kernel.org
 help / color / mirror / Atom feed
From: Florian Westphal <fw@strlen.de>
To: <netfilter-devel@vger.kernel.org>
Cc: Florian Westphal <fw@strlen.de>
Subject: [PATCH nft] tests: shell: add packetpath test for nft ct expectation support
Date: Mon,  3 Aug 2026 18:43:45 +0200	[thread overview]
Message-ID: <20260803164351.5377-1-fw@strlen.de> (raw)

This will fail on kernels that lack
6fb421bd07f1 ("netfilter: nft_ct: expectation timeouts are passed in milliseconds").

On kernels that lack NAT support the test will indicate SKIP.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 tests/shell/testcases/packetpath/ct_expect    | 261 ++++++++++++++++++
 .../packetpath/dumps/ct_expect.nodump         |   0
 2 files changed, 261 insertions(+)
 create mode 100755 tests/shell/testcases/packetpath/ct_expect
 create mode 100644 tests/shell/testcases/packetpath/dumps/ct_expect.nodump

diff --git a/tests/shell/testcases/packetpath/ct_expect b/tests/shell/testcases/packetpath/ct_expect
new file mode 100755
index 000000000000..d9824ca3cdaf
--- /dev/null
+++ b/tests/shell/testcases/packetpath/ct_expect
@@ -0,0 +1,261 @@
+#!/bin/bash
+
+# NFT_TEST_REQUIRES(NFT_TEST_HAVE_socat)
+
+. $NFT_TEST_LIBRARY_FILE
+
+set -x
+
+rc=1
+
+cleanup()
+{
+	for i in $R $C $S;do
+		kill $(ip netns pid $i) 2>/dev/null
+		ip netns del $i
+	done
+
+	exit $rc
+}
+trap cleanup EXIT
+
+dump_expect_table() {
+	ip netns exec "$R" conntrack --family ipv6 -L expect
+	ip netns exec "$R" conntrack --family ipv4 -L expect
+}
+
+assert_failout()
+{
+	ip netns exec $R $NFT list ruleset
+	ip netns exec $R conntrack -L
+	dump_expect_table
+}
+
+do_connect() {
+	local ns="$1"
+	local addr="$2"
+	local port="$3"
+
+	ip netns exec "$ns" socat -u STDIN TCP-CONNECT:$addr:$port,connect-timeout=1 < /dev/null
+}
+
+connect_fail() {
+	local ns="$1"
+	local addr="$2"
+	local port="$3"
+	local msg="$4"
+
+	do_connect "$ns" "$addr" "$port"
+	assert_fail "connect from $ns to $addr:$port $msg"
+}
+
+connect_ok() {
+	local ns="$1"
+	local addr="$2"
+	local port="$3"
+	local msg="$4"
+
+	do_connect "$ns" "$addr" "$port"
+	assert_pass "connect from $ns to $addr:$port $msg"
+}
+
+test_expect() {
+	local ip_cr="$1"
+	local ip_sr="$2"
+	local msg="$3"
+
+	echo check port is closed from outside.
+	connect_fail "$S" "$ip_cr" 1234
+
+	echo "Test: expectation via ruleset$msg"
+
+	echo control port should be open.
+	connect_ok "$C" "$ip_sr" 2222 "$msg"
+
+	dump_expect_table
+
+	echo expected port. Should now pass.
+	connect_ok "$S" "$ip_cr" 1234 "$msg"
+
+	echo one expectation max, expect fail.
+	connect_fail "$S" "$ip_cr" 1234 "$msg"
+}
+
+test_timeout() {
+	echo "Test: expectation auto-timeout"
+	# control port - this should be open.
+	connect_ok "$C" "$ip4_sr" 2222
+	connect_ok "$C" "[$ip6_sr]" 2222
+
+	dump_expect_table
+
+	# timeout. We 'bundle' ipv4 and ipv6 test here.
+	sleep 6
+
+	dump_expect_table
+
+	echo "expect failures"
+	connect_fail "$S" "$ip4_cr" 1234
+	connect_fail "$S" "[$ip6_cr]" 1234
+}
+
+rnd=$(mktemp -u XXXXXXXX)
+R="ns-router-$rnd"
+C="ns-client-$rnd"
+S="ns-server-$rnd"
+
+ip6_sr=dead:d8:ff:22::1
+ip6_cr=dead:d8:ff:21::2
+ip6_rs=dead:d8:ff:22::fffe
+ip6_rc=dead:d8:ff:21::fffe
+
+ip4_sr=10.1.22.1
+ip4_cr=10.1.21.2
+ip4_rs=10.1.22.99
+ip4_rc=10.1.21.99
+
+set -e
+ip netns add $R
+ip netns add $S
+ip netns add $C
+ip -net $S link set lo up
+ip -net $R link set lo up
+ip -net $C link set lo up
+ip netns exec $R sysctl -wq net.ipv4.ip_forward=1
+ip netns exec $R sysctl -wq net.ipv6.conf.all.forwarding=1
+
+ip link add s_r netns $S type veth peer name r_s netns $R
+ip link add c_r netns $C type veth peer name r_c netns $R
+ip -net $S link set s_r up
+ip -net $R link set r_s up
+ip -net $R link set r_c up
+ip -net $C link set c_r up
+
+ip -net $S addr add ${ip6_sr}/64 dev s_r nodad
+ip -net $C addr add ${ip6_cr}/64 dev c_r nodad
+ip -net $R addr add ${ip6_rs}/64 dev r_s nodad
+ip -net $R addr add ${ip6_rc}/64 dev r_c nodad
+ip -net $C route add ${ip6_rs}/64 via ${ip6_rc} dev c_r
+ip -net $S route add ${ip6_rc}/64 via ${ip6_rs} dev s_r
+assert_pass "topo initialization"
+
+ip -net $S addr add ${ip4_sr}/24 dev s_r
+ip -net $C addr add ${ip4_cr}/24 dev c_r
+ip -net $R addr add ${ip4_rs}/24 dev r_s
+ip -net $R addr add ${ip4_rc}/24 dev r_c
+
+ip -net $C route add 10.1.22.0/24 via ${ip4_rc} dev c_r
+ip -net $S route add 10.1.21.0/24 via ${ip4_rs} dev s_r
+
+ip netns exec "$C" ping -q -c 1 "$ip4_sr"
+ip netns exec "$C" ping -q -c 1 "$ip6_sr"
+
+timeout 20 ip netns exec "$S" socat TCP6-LISTEN:2222,ipv6only=1,fork,reuseaddr PIPE &
+timeout 20 ip netns exec "$S" socat TCP4-LISTEN:2222,fork,reuseaddr PIPE &
+timeout 20 ip netns exec "$C" socat TCP6-LISTEN:1234,ipv6only=1,fork,reuseaddr PIPE &
+timeout 20 ip netns exec "$C" socat TCP4-LISTEN:1234,fork,reuseaddr PIPE &
+wait_local_port_listen $S 2222 tcp
+wait_local_port_listen $C 1234 tcp
+
+ip netns exec $R $NFT -f - <<-EOF
+flush ruleset
+table inet t {
+	ct expectation ctexpect4 {
+		protocol tcp
+		dport 1234
+		timeout 5s
+		size 1
+		l3proto ip
+	}
+
+	ct expectation ctexpect6 {
+		protocol tcp
+		dport 1234
+		timeout 5s
+		size 1
+		l3proto ip6
+	}
+
+	chain c {
+		type filter hook forward priority filter; policy drop;
+		ct state established accept
+		meta l4proto tcp ct state related counter accept
+		meta iifname r_c ct state new jump {
+			tcp dport 2222 counter ct expectation set meta nfproto map { ipv4 : ctexpect4, ipv6 : ctexpect6 } counter accept
+			counter accept
+		}
+		meta l4proto tcp counter reject with tcp reset
+		meta l4proto { icmp, icmpv6 } accept
+	}
+}
+EOF
+
+ip netns exec "$C" ping -q -c 1 "$ip4_sr"
+ip netns exec "$C" ping -q -c 1 "$ip6_sr"
+
+set +e
+echo check port is closed from outside.
+connect_fail "$S" "$ip4_cr" 1234
+connect_fail "$S" "[$ip6_cr]" 1234
+
+test_expect "$ip4_cr" "$ip4_sr"	""
+test_expect "[$ip6_cr]" "[$ip6_sr]" ""
+
+ip netns exec $R conntrack -F
+test_timeout
+
+set -e
+ip netns exec $R $NFT -f - <<-EOF
+flush ruleset
+table inet t {
+	ct expectation ctexpect4 {
+		protocol tcp
+		dport 1234
+		timeout 5s
+		size 1
+		l3proto ip
+	}
+
+	ct expectation ctexpect6 {
+		protocol tcp
+		dport 1234
+		timeout 5s
+		size 1
+		l3proto ip6
+	}
+	chain c {
+		type filter hook forward priority filter; policy drop;
+		ct state established accept
+		meta l4proto tcp ct state related counter accept
+		meta iifname r_c ct state new accept
+		meta l4proto tcp counter reject with tcp reset
+		meta l4proto { icmp, icmpv6 } accept
+	}
+
+	chain masq {
+		type nat hook postrouting priority srcnat; policy accept;
+		meta oifname "r_s" counter masquerade
+	}
+
+	chain e {
+		type filter hook postrouting priority 50000 ; policy accept;
+		meta iifname r_c ct state new jump {
+			tcp dport 2222 counter ct expectation set meta nfproto map { ipv4 : ctexpect4, ipv6 : ctexpect6 } counter accept
+			counter accept
+		}
+	}
+}
+EOF
+
+ip netns exec $R conntrack -F
+echo "Test: conntrack expectation with masquerade"
+set +e
+
+# Skip here, this is a kernel bug / missing feature we can't
+# test for.
+rc=77
+test_expect "$ip4_rs" "$ip4_sr" " with masquerade"
+test_expect "[$ip6_rs]" "[$ip6_sr]" " with masquerade"
+
+ip netns exec "$R" conntrack -L
+rc=0
diff --git a/tests/shell/testcases/packetpath/dumps/ct_expect.nodump b/tests/shell/testcases/packetpath/dumps/ct_expect.nodump
new file mode 100644
index 000000000000..e69de29bb2d1
-- 
2.54.0


                 reply	other threads:[~2026-08-03 16:44 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20260803164351.5377-1-fw@strlen.de \
    --to=fw@strlen.de \
    --cc=netfilter-devel@vger.kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.