4 # 1. can process packets from all hooks
5 # 2. support running nfqueue from more than one base chain
7 # Kselftest framework requirement - SKIP code is 4.
11 sfx=$(mktemp -u "XXXXXXXX")
14 nsrouter="nsrouter-$sfx"
21 ip netns del ${nsrouter}
24 rm -f "$TMPFILE2" "$TMPFILE3"
27 nft --version > /dev/null 2>&1
29 echo "SKIP: Could not run test without nft tool"
33 ip -Version > /dev/null 2>&1
35 echo "SKIP: Could not run test without ip tool"
39 ip netns add ${nsrouter}
41 echo "SKIP: Could not create net namespace"
54 ip link add veth0 netns ${nsrouter} type veth peer name eth0 netns ${ns1} > /dev/null 2>&1
56 echo "SKIP: No virtual ethernet pair device support in kernel"
59 ip link add veth1 netns ${nsrouter} type veth peer name eth0 netns ${ns2}
61 ip -net ${nsrouter} link set lo up
62 ip -net ${nsrouter} link set veth0 up
63 ip -net ${nsrouter} addr add 10.0.1.1/24 dev veth0
64 ip -net ${nsrouter} addr add dead:1::1/64 dev veth0
66 ip -net ${nsrouter} link set veth1 up
67 ip -net ${nsrouter} addr add 10.0.2.1/24 dev veth1
68 ip -net ${nsrouter} addr add dead:2::1/64 dev veth1
70 ip -net ${ns1} link set lo up
71 ip -net ${ns1} link set eth0 up
73 ip -net ${ns2} link set lo up
74 ip -net ${ns2} link set eth0 up
76 ip -net ${ns1} addr add 10.0.1.99/24 dev eth0
77 ip -net ${ns1} addr add dead:1::99/64 dev eth0
78 ip -net ${ns1} route add default via 10.0.1.1
79 ip -net ${ns1} route add default via dead:1::1
81 ip -net ${ns2} addr add 10.0.2.99/24 dev eth0
82 ip -net ${ns2} addr add dead:2::99/64 dev eth0
83 ip -net ${ns2} route add default via 10.0.2.1
84 ip -net ${ns2} route add default via dead:2::1
90 ip netns exec ${nsrouter} nft -f /dev/stdin <<EOF
93 ip protocol icmp queue bypass
94 icmpv6 type { "echo-request", "echo-reply" } queue num 1 bypass
97 type filter hook prerouting priority $prio; policy accept;
101 type filter hook input priority $prio; policy accept;
105 type filter hook forward priority $prio; policy accept;
106 tcp dport 12345 queue num 2
110 type filter hook output priority $prio; policy accept;
111 tcp dport 12345 queue num 3
115 type filter hook postrouting priority $prio; policy accept;
122 load_counter_ruleset() {
125 ip netns exec ${nsrouter} nft -f /dev/stdin <<EOF
126 table inet countrules {
128 type filter hook prerouting priority $prio; policy accept;
132 type filter hook input priority $prio; policy accept;
136 type filter hook forward priority $prio; policy accept;
140 type filter hook output priority $prio; policy accept;
144 type filter hook postrouting priority $prio; policy accept;
152 ip netns exec ${ns1} ping -c 1 -q 10.0.2.99 > /dev/null
157 ip netns exec ${ns1} ping -c 1 -q dead:2::99 > /dev/null
166 ip netns exec ${ns1} ping -c 1 -q 10.0.2.1 > /dev/null
171 ip netns exec ${ns1} ping -c 1 -q dead:2::1 > /dev/null
179 test_queue_blackhole() {
182 ip netns exec ${nsrouter} nft -f /dev/stdin <<EOF
183 table $proto blackh {
185 type filter hook forward priority 0; policy accept;
190 if [ $proto = "ip" ] ;then
191 ip netns exec ${ns1} ping -W 2 -c 1 -q 10.0.2.99 > /dev/null
193 elif [ $proto = "ip6" ]; then
194 ip netns exec ${ns1} ping -W 2 -c 1 -q dead:2::99 > /dev/null
200 # queue without bypass keyword should drop traffic if no listener exists.
201 if [ $lret -eq 0 ];then
202 echo "FAIL: $proto expected failure, got $lret" 1>&2
206 ip netns exec ${nsrouter} nft delete table $proto blackh
207 if [ $? -ne 0 ] ;then
208 echo "FAIL: $proto: Could not delete blackh table"
212 echo "PASS: $proto: statement with no listener results in packet drop"
220 # spawn nf-queue listeners
221 ip netns exec ${nsrouter} ./nf-queue -c -q 0 -t $timeout > "$TMPFILE0" &
222 ip netns exec ${nsrouter} ./nf-queue -c -q 1 -t $timeout > "$TMPFILE1" &
226 if [ $ret -ne 0 ];then
227 echo "FAIL: netns routing/connectivity with active listener on queue $queue: $ret" 1>&2
233 if [ $ret -ne 0 ];then
234 echo "FAIL: netns router unreachable listener on queue $queue: $ret" 1>&2
241 for file in $TMPFILE0 $TMPFILE1; do
242 last=$(tail -n1 "$file")
243 if [ x"$last" != x"$expected packets total" ]; then
244 echo "FAIL: Expected $expected packets total, but got $last" 1>&2
247 ip netns exec ${nsrouter} nft list ruleset
252 echo "PASS: Expected and received $last"
257 ip netns exec ${nsrouter} ./nf-queue -q 2 -t $timeout &
260 tmpfile=$(mktemp) || exit 1
261 dd conv=sparse status=none if=/dev/zero bs=1M count=200 of=$tmpfile
262 ip netns exec ${ns2} nc -w 5 -l -p 12345 <"$tmpfile" >/dev/null &
266 ip netns exec ${ns1} nc -w 5 10.0.2.99 12345 <"$tmpfile" >/dev/null &
272 [ $? -eq 0 ] && echo "PASS: tcp and nfqueue in forward chain"
277 tmpfile=$(mktemp) || exit 1
279 dd conv=sparse status=none if=/dev/zero bs=1M count=200 of=$tmpfile
280 ip netns exec ${nsrouter} nc -w 5 -l -p 12345 <"$tmpfile" >/dev/null &
283 ip netns exec ${nsrouter} ./nf-queue -q 3 -t $timeout &
287 ip netns exec ${nsrouter} nc -w 5 127.0.0.1 12345 <"$tmpfile" > /dev/null
291 [ $? -eq 0 ] && echo "PASS: tcp via loopback"
295 test_tcp_localhost_requeue()
297 ip netns exec ${nsrouter} nft -f /dev/stdin <<EOF
301 type filter hook output priority 0; policy accept;
302 tcp dport 12345 limit rate 1/second burst 1 packets counter queue num 0
305 type filter hook postrouting priority 0; policy accept;
306 tcp dport 12345 limit rate 1/second burst 1 packets counter queue num 0
310 tmpfile=$(mktemp) || exit 1
311 dd conv=sparse status=none if=/dev/zero bs=1M count=200 of=$tmpfile
312 ip netns exec ${nsrouter} nc -w 5 -l -p 12345 <"$tmpfile" >/dev/null &
315 ip netns exec ${nsrouter} ./nf-queue -c -q 1 -t $timeout > "$TMPFILE2" &
317 # nfqueue 1 will be called via output hook. But this time,
318 # re-queue the packet to nfqueue program on queue 2.
319 ip netns exec ${nsrouter} ./nf-queue -G -d 150 -c -q 0 -Q 1 -t $timeout > "$TMPFILE3" &
322 ip netns exec ${nsrouter} nc -w 5 127.0.0.1 12345 <"$tmpfile" > /dev/null
327 if ! diff -u "$TMPFILE2" "$TMPFILE3" ; then
328 echo "FAIL: lost packets during requeue?!" 1>&2
332 echo "PASS: tcp via loopback and re-queueing"
335 ip netns exec ${nsrouter} sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
336 ip netns exec ${nsrouter} sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
337 ip netns exec ${nsrouter} sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
339 load_ruleset "filter" 0
345 if [ $ret -eq 0 ];then
346 # queue bypass works (rules were skipped, no listener)
347 echo "PASS: ${ns1} can reach ${ns2}"
349 echo "FAIL: ${ns1} cannot reach ${ns2}: $ret" 1>&2
353 test_queue_blackhole ip
354 test_queue_blackhole ip6
356 # dummy ruleset to add base chains between the
357 # queueing rules. We don't want the second reinject
358 # to re-execute the old hooks.
359 load_counter_ruleset 10
361 # we are hooking all: prerouting/input/forward/output/postrouting.
362 # we ping ${ns2} from ${ns1} via ${nsrouter} using ipv4 and ipv6, so:
363 # 1x icmp prerouting,forward,postrouting -> 3 queue events (6 incl. reply).
364 # 1x icmp prerouting,input,output postrouting -> 4 queue events incl. reply.
365 # so we expect that userspace program receives 10 packets.
368 # same. We queue to a second program as well.
369 load_ruleset "filter2" 20
374 test_tcp_localhost_requeue