3 # This test is for basic NAT functionality: snat, dnat, redirect, masquerade.
6 # Kselftest framework requirement - SKIP code is 4.
10 nft --version > /dev/null 2>&1
12 echo "SKIP: Could not run test without nft tool"
16 ip -Version > /dev/null 2>&1
18 echo "SKIP: Could not run test without ip tool"
26 ip link add veth0 netns ns0 type veth peer name eth0 netns ns1 > /dev/null 2>&1
28 echo "SKIP: No virtual ethernet pair device support in kernel"
31 ip link add veth1 netns ns0 type veth peer name eth0 netns ns2
33 ip -net ns0 link set lo up
34 ip -net ns0 link set veth0 up
35 ip -net ns0 addr add 10.0.1.1/24 dev veth0
36 ip -net ns0 addr add dead:1::1/64 dev veth0
38 ip -net ns0 link set veth1 up
39 ip -net ns0 addr add 10.0.2.1/24 dev veth1
40 ip -net ns0 addr add dead:2::1/64 dev veth1
43 ip -net ns$i link set lo up
44 ip -net ns$i link set eth0 up
45 ip -net ns$i addr add 10.0.$i.99/24 dev eth0
46 ip -net ns$i route add default via 10.0.$i.1
47 ip -net ns$i addr add dead:$i::99/64 dev eth0
48 ip -net ns$i route add default via dead:$i::1
57 echo "ERROR: $counter counter in $ns has unexpected value (expected $expect)" 1>&2
58 ip netns exec $ns nft list counter inet filter $counter 1>&2
66 cnt=$(ip netns exec $ns nft list counter inet filter ns0in | grep -q "packets 1 bytes 84")
68 bad_counter $ns ns0in "packets 1 bytes 84"
71 cnt=$(ip netns exec $ns nft list counter inet filter ns0out | grep -q "packets 1 bytes 84")
73 bad_counter $ns ns0out "packets 1 bytes 84"
77 expect="packets 1 bytes 104"
78 cnt=$(ip netns exec $ns nft list counter inet filter ns0in6 | grep -q "$expect")
80 bad_counter $ns ns0in6 "$expect"
83 cnt=$(ip netns exec $ns nft list counter inet filter ns0out6 | grep -q "$expect")
85 bad_counter $ns ns0out6 "$expect"
97 cnt=$(ip netns exec ns0 nft list counter inet filter ns0in | grep -q "packets 0 bytes 0")
99 bad_counter ns0 ns0in "packets 0 bytes 0"
103 cnt=$(ip netns exec ns0 nft list counter inet filter ns0in6 | grep -q "packets 0 bytes 0")
104 if [ $? -ne 0 ]; then
105 bad_counter ns0 ns0in6 "packets 0 bytes 0"
109 cnt=$(ip netns exec ns0 nft list counter inet filter ns0out | grep -q "packets 0 bytes 0")
110 if [ $? -ne 0 ]; then
111 bad_counter ns0 ns0out "packets 0 bytes 0"
114 cnt=$(ip netns exec ns0 nft list counter inet filter ns0out6 | grep -q "packets 0 bytes 0")
115 if [ $? -ne 0 ]; then
116 bad_counter ns0 ns0out6 "packets 0 bytes 0"
120 for dir in "in" "out" ; do
121 expect="packets 1 bytes 84"
122 cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir} | grep -q "$expect")
123 if [ $? -ne 0 ]; then
124 bad_counter ns0 $ns$dir "$expect"
128 expect="packets 1 bytes 104"
129 cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir}6 | grep -q "$expect")
130 if [ $? -ne 0 ]; then
131 bad_counter ns0 $ns$dir6 "$expect"
142 ip netns exec ns$i nft reset counters inet > /dev/null
149 ip netns exec ns0 nft -f - <<EOF
152 type nat hook output priority 0; policy accept;
153 ip6 daddr dead:1::99 dnat to dead:2::99
157 if [ $? -ne 0 ]; then
158 echo "SKIP: Could not add add ip6 dnat hook"
162 # ping netns1, expect rewrite to netns2
163 ip netns exec ns0 ping -q -c 1 dead:1::99 > /dev/null
164 if [ $? -ne 0 ]; then
166 echo "ERROR: ping6 failed"
170 expect="packets 0 bytes 0"
171 for dir in "in6" "out6" ; do
172 cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
173 if [ $? -ne 0 ]; then
174 bad_counter ns0 ns1$dir "$expect"
179 expect="packets 1 bytes 104"
180 for dir in "in6" "out6" ; do
181 cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
182 if [ $? -ne 0 ]; then
183 bad_counter ns0 ns2$dir "$expect"
188 # expect 0 count in ns1
189 expect="packets 0 bytes 0"
190 for dir in "in6" "out6" ; do
191 cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
192 if [ $? -ne 0 ]; then
193 bad_counter ns1 ns0$dir "$expect"
198 # expect 1 packet in ns2
199 expect="packets 1 bytes 104"
200 for dir in "in6" "out6" ; do
201 cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
202 if [ $? -ne 0 ]; then
203 bad_counter ns2 ns0$dir "$expect"
208 test $lret -eq 0 && echo "PASS: ipv6 ping to ns1 was NATted to ns2"
209 ip netns exec ns0 nft flush chain ip6 nat output
217 ip netns exec ns0 nft -f - <<EOF
220 type nat hook output priority 0; policy accept;
221 ip daddr 10.0.1.99 dnat to 10.0.2.99
225 # ping netns1, expect rewrite to netns2
226 ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
227 if [ $? -ne 0 ]; then
229 echo "ERROR: ping failed"
233 expect="packets 0 bytes 0"
234 for dir in "in" "out" ; do
235 cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
236 if [ $? -ne 0 ]; then
237 bad_counter ns0 ns1$dir "$expect"
242 expect="packets 1 bytes 84"
243 for dir in "in" "out" ; do
244 cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
245 if [ $? -ne 0 ]; then
246 bad_counter ns0 ns2$dir "$expect"
251 # expect 0 count in ns1
252 expect="packets 0 bytes 0"
253 for dir in "in" "out" ; do
254 cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
255 if [ $? -ne 0 ]; then
256 bad_counter ns1 ns0$dir "$expect"
261 # expect 1 packet in ns2
262 expect="packets 1 bytes 84"
263 for dir in "in" "out" ; do
264 cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
265 if [ $? -ne 0 ]; then
266 bad_counter ns2 ns0$dir "$expect"
271 test $lret -eq 0 && echo "PASS: ping to ns1 was NATted to ns2"
273 ip netns exec ns0 nft flush chain ip nat output
276 ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
277 if [ $? -ne 0 ]; then
279 echo "ERROR: ping failed"
283 expect="packets 1 bytes 84"
284 for dir in "in" "out" ; do
285 cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
286 if [ $? -ne 0 ]; then
287 bad_counter ns1 ns1$dir "$expect"
291 expect="packets 0 bytes 0"
292 for dir in "in" "out" ; do
293 cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
294 if [ $? -ne 0 ]; then
295 bad_counter ns0 ns2$dir "$expect"
300 # expect 1 count in ns1
301 expect="packets 1 bytes 84"
302 for dir in "in" "out" ; do
303 cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
304 if [ $? -ne 0 ]; then
305 bad_counter ns0 ns0$dir "$expect"
310 # expect 0 packet in ns2
311 expect="packets 0 bytes 0"
312 for dir in "in" "out" ; do
313 cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
314 if [ $? -ne 0 ]; then
315 bad_counter ns2 ns2$dir "$expect"
320 test $lret -eq 0 && echo "PASS: ping to ns1 OK after nat output chain flush"
330 ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
332 ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
333 if [ $? -ne 0 ] ; then
334 echo "ERROR: cannot ping ns1 from ns2 via ipv6"
339 expect="packets 1 bytes 104"
340 for dir in "in6" "out6" ; do
341 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
342 if [ $? -ne 0 ]; then
343 bad_counter ns1 ns2$dir "$expect"
347 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
348 if [ $? -ne 0 ]; then
349 bad_counter ns2 ns1$dir "$expect"
356 # add masquerading rule
357 ip netns exec ns0 nft -f - <<EOF
360 type nat hook postrouting priority 0; policy accept;
361 meta oif veth0 masquerade
365 ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
366 if [ $? -ne 0 ] ; then
367 echo "ERROR: cannot ping ns1 from ns2 with active ipv6 masquerading"
371 # ns1 should have seen packets from ns0, due to masquerade
372 expect="packets 1 bytes 104"
373 for dir in "in6" "out6" ; do
375 cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
376 if [ $? -ne 0 ]; then
377 bad_counter ns1 ns0$dir "$expect"
381 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
382 if [ $? -ne 0 ]; then
383 bad_counter ns2 ns1$dir "$expect"
388 # ns1 should not have seen packets from ns2, due to masquerade
389 expect="packets 0 bytes 0"
390 for dir in "in6" "out6" ; do
391 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
392 if [ $? -ne 0 ]; then
393 bad_counter ns1 ns0$dir "$expect"
397 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
398 if [ $? -ne 0 ]; then
399 bad_counter ns2 ns1$dir "$expect"
404 ip netns exec ns0 nft flush chain ip6 nat postrouting
405 if [ $? -ne 0 ]; then
406 echo "ERROR: Could not flush ip6 nat postrouting" 1>&2
410 test $lret -eq 0 && echo "PASS: IPv6 masquerade for ns2"
419 ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
420 ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
422 ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
423 if [ $? -ne 0 ] ; then
424 echo "ERROR: canot ping ns1 from ns2"
428 expect="packets 1 bytes 84"
429 for dir in "in" "out" ; do
430 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
431 if [ $? -ne 0 ]; then
432 bad_counter ns1 ns2$dir "$expect"
436 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
437 if [ $? -ne 0 ]; then
438 bad_counter ns2 ns1$dir "$expect"
445 # add masquerading rule
446 ip netns exec ns0 nft -f - <<EOF
449 type nat hook postrouting priority 0; policy accept;
450 meta oif veth0 masquerade
454 ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
455 if [ $? -ne 0 ] ; then
456 echo "ERROR: cannot ping ns1 from ns2 with active ip masquerading"
460 # ns1 should have seen packets from ns0, due to masquerade
461 expect="packets 1 bytes 84"
462 for dir in "in" "out" ; do
463 cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
464 if [ $? -ne 0 ]; then
465 bad_counter ns1 ns0$dir "$expect"
469 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
470 if [ $? -ne 0 ]; then
471 bad_counter ns2 ns1$dir "$expect"
476 # ns1 should not have seen packets from ns2, due to masquerade
477 expect="packets 0 bytes 0"
478 for dir in "in" "out" ; do
479 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
480 if [ $? -ne 0 ]; then
481 bad_counter ns1 ns0$dir "$expect"
485 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
486 if [ $? -ne 0 ]; then
487 bad_counter ns2 ns1$dir "$expect"
492 ip netns exec ns0 nft flush chain ip nat postrouting
493 if [ $? -ne 0 ]; then
494 echo "ERROR: Could not flush nat postrouting" 1>&2
498 test $lret -eq 0 && echo "PASS: IP masquerade for ns2"
507 ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
509 ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
510 if [ $? -ne 0 ] ; then
511 echo "ERROR: cannnot ping ns1 from ns2 via ipv6"
515 expect="packets 1 bytes 104"
516 for dir in "in6" "out6" ; do
517 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
518 if [ $? -ne 0 ]; then
519 bad_counter ns1 ns2$dir "$expect"
523 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
524 if [ $? -ne 0 ]; then
525 bad_counter ns2 ns1$dir "$expect"
533 ip netns exec ns0 nft -f - <<EOF
536 type nat hook prerouting priority 0; policy accept;
537 meta iif veth1 meta l4proto icmpv6 ip6 saddr dead:2::99 ip6 daddr dead:1::99 redirect
541 ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
542 if [ $? -ne 0 ] ; then
543 echo "ERROR: cannot ping ns1 from ns2 with active ip6 redirect"
547 # ns1 should have seen no packets from ns2, due to redirection
548 expect="packets 0 bytes 0"
549 for dir in "in6" "out6" ; do
550 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
551 if [ $? -ne 0 ]; then
552 bad_counter ns1 ns0$dir "$expect"
557 # ns0 should have seen packets from ns2, due to masquerade
558 expect="packets 1 bytes 104"
559 for dir in "in6" "out6" ; do
560 cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
561 if [ $? -ne 0 ]; then
562 bad_counter ns1 ns0$dir "$expect"
567 ip netns exec ns0 nft delete table ip6 nat
568 if [ $? -ne 0 ]; then
569 echo "ERROR: Could not delete ip6 nat table" 1>&2
573 test $lret -eq 0 && echo "PASS: IPv6 redirection for ns2"
582 ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
583 ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
585 ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
586 if [ $? -ne 0 ] ; then
587 echo "ERROR: cannot ping ns1 from ns2"
591 expect="packets 1 bytes 84"
592 for dir in "in" "out" ; do
593 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
594 if [ $? -ne 0 ]; then
595 bad_counter ns1 ns2$dir "$expect"
599 cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
600 if [ $? -ne 0 ]; then
601 bad_counter ns2 ns1$dir "$expect"
609 ip netns exec ns0 nft -f - <<EOF
612 type nat hook prerouting priority 0; policy accept;
613 meta iif veth1 ip protocol icmp ip saddr 10.0.2.99 ip daddr 10.0.1.99 redirect
617 ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
618 if [ $? -ne 0 ] ; then
619 echo "ERROR: cannot ping ns1 from ns2 with active ip redirect"
623 # ns1 should have seen no packets from ns2, due to redirection
624 expect="packets 0 bytes 0"
625 for dir in "in" "out" ; do
627 cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
628 if [ $? -ne 0 ]; then
629 bad_counter ns1 ns0$dir "$expect"
634 # ns0 should have seen packets from ns2, due to masquerade
635 expect="packets 1 bytes 84"
636 for dir in "in" "out" ; do
637 cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
638 if [ $? -ne 0 ]; then
639 bad_counter ns1 ns0$dir "$expect"
644 ip netns exec ns0 nft delete table ip nat
645 if [ $? -ne 0 ]; then
646 echo "ERROR: Could not delete nat table" 1>&2
650 test $lret -eq 0 && echo "PASS: IP redirection for ns2"
656 # ip netns exec ns0 ping -c 1 -q 10.0.$i.99
658 ip netns exec ns$i nft -f - <<EOF
677 type ipv4_addr : counter
678 elements = { 10.0.1.1 : "ns0in",
681 10.0.2.99 : "ns2in" }
685 type ipv6_addr : counter
686 elements = { dead:1::1 : "ns0in6",
687 dead:2::1 : "ns0in6",
688 dead:1::99 : "ns1in6",
689 dead:2::99 : "ns2in6" }
693 type ipv4_addr : counter
694 elements = { 10.0.1.1 : "ns0out",
697 10.0.2.99: "ns2out" }
701 type ipv6_addr : counter
702 elements = { dead:1::1 : "ns0out6",
703 dead:2::1 : "ns0out6",
704 dead:1::99 : "ns1out6",
705 dead:2::99 : "ns2out6" }
709 type filter hook input priority 0; policy accept;
710 counter name ip saddr map @nsincounter
711 icmpv6 type { "echo-request", "echo-reply" } counter name ip6 saddr map @nsincounter6
714 type filter hook output priority 0; policy accept;
715 counter name ip daddr map @nsoutcounter
716 icmpv6 type { "echo-request", "echo-reply" } counter name ip6 daddr map @nsoutcounter6
723 # test basic connectivity
725 ip netns exec ns0 ping -c 1 -q 10.0.$i.99 > /dev/null
727 echo "ERROR: Could not reach other namespace(s)" 1>&2
731 ip netns exec ns0 ping -c 1 -q dead:$i::99 > /dev/null
733 echo "ERROR: Could not reach other namespace(s) via ipv6" 1>&2
737 if [ $? -ne 0 ]; then
741 check_ns0_counters ns$i
742 if [ $? -ne 0 ]; then
748 if [ $ret -eq 0 ];then
749 echo "PASS: netns routing/connectivity: ns0 can reach ns1 and ns2"
764 for i in 0 1 2; do ip netns del ns$i;done