3 # Test connection tracking zone and NAT source port reallocation support.
6 # Kselftest framework requirement - SKIP code is 4.
9 # Don't increase too much, 2000 clients should work
10 # just fine but script can then take several minutes with
20 # NAT Gateway --veth0--> Server
25 # clientX----vethX---'
27 # All clients share identical IP address.
28 # NAT Gateway uses policy routing and conntrack zones to isolate client
29 # namespaces. Each client connects to Server, each with colliding tuples:
30 # clientsaddr:10000 -> serveraddr:dport
31 # NAT Gateway is supposed to do port reallocation for each of the
34 sfx=$(mktemp -u "XXXXXXXX")
40 v4gc1=$(sysctl -n net.ipv4.neigh.default.gc_thresh1 2>/dev/null)
41 v4gc2=$(sysctl -n net.ipv4.neigh.default.gc_thresh2 2>/dev/null)
42 v4gc3=$(sysctl -n net.ipv4.neigh.default.gc_thresh3 2>/dev/null)
43 v6gc1=$(sysctl -n net.ipv6.neigh.default.gc_thresh1 2>/dev/null)
44 v6gc2=$(sysctl -n net.ipv6.neigh.default.gc_thresh2 2>/dev/null)
45 v6gc3=$(sysctl -n net.ipv6.neigh.default.gc_thresh3 2>/dev/null)
51 for i in $(seq 1 $maxclients); do
52 ip netns del ns-cl$i-$sfx 2>/dev/null
55 sysctl -q net.ipv4.neigh.default.gc_thresh1=$v4gc1 2>/dev/null
56 sysctl -q net.ipv4.neigh.default.gc_thresh2=$v4gc2 2>/dev/null
57 sysctl -q net.ipv4.neigh.default.gc_thresh3=$v4gc3 2>/dev/null
58 sysctl -q net.ipv6.neigh.default.gc_thresh1=$v6gc1 2>/dev/null
59 sysctl -q net.ipv6.neigh.default.gc_thresh2=$v6gc2 2>/dev/null
60 sysctl -q net.ipv6.neigh.default.gc_thresh3=$v6gc3 2>/dev/null
63 nft --version > /dev/null 2>&1
65 echo "SKIP: Could not run test without nft tool"
69 ip -Version > /dev/null 2>&1
71 echo "SKIP: Could not run test without ip tool"
75 conntrack -V > /dev/null 2>&1
77 echo "SKIP: Could not run test without conntrack tool"
81 iperf3 -v >/dev/null 2>&1
88 echo "SKIP: Could not create net namespace $gw"
91 ip -net "$gw" link set lo up
97 echo "SKIP: Could not create server netns $srv"
101 ip link add veth0 netns "$gw" type veth peer name eth0 netns "$srv"
102 ip -net "$gw" link set veth0 up
103 ip -net "$srv" link set lo up
104 ip -net "$srv" link set eth0 up
106 sysctl -q net.ipv6.neigh.default.gc_thresh1=512 2>/dev/null
107 sysctl -q net.ipv6.neigh.default.gc_thresh2=1024 2>/dev/null
108 sysctl -q net.ipv6.neigh.default.gc_thresh3=4096 2>/dev/null
109 sysctl -q net.ipv4.neigh.default.gc_thresh1=512 2>/dev/null
110 sysctl -q net.ipv4.neigh.default.gc_thresh2=1024 2>/dev/null
111 sysctl -q net.ipv4.neigh.default.gc_thresh3=4096 2>/dev/null
113 for i in $(seq 1 $maxclients);do
118 echo "SKIP: Could not create client netns $cl"
121 ip link add veth$i netns "$gw" type veth peer name eth0 netns "$cl" > /dev/null 2>&1
123 echo "SKIP: No virtual ethernet pair device support in kernel"
128 for i in $(seq 1 $maxclients);do
130 echo netns exec "$cl" ip link set lo up
131 echo netns exec "$cl" ip link set eth0 up
132 echo netns exec "$cl" sysctl -q net.ipv4.tcp_syn_retries=2
133 echo netns exec "$gw" ip link set veth$i up
134 echo netns exec "$gw" sysctl -q net.ipv4.conf.veth$i.arp_ignore=2
135 echo netns exec "$gw" sysctl -q net.ipv4.conf.veth$i.rp_filter=0
137 # clients have same IP addresses.
138 echo netns exec "$cl" ip addr add 10.1.0.3/24 dev eth0
139 echo netns exec "$cl" ip addr add dead:1::3/64 dev eth0
140 echo netns exec "$cl" ip route add default via 10.1.0.2 dev eth0
141 echo netns exec "$cl" ip route add default via dead:1::2 dev eth0
143 # NB: same addresses on client-facing interfaces.
144 echo netns exec "$gw" ip addr add 10.1.0.2/24 dev veth$i
145 echo netns exec "$gw" ip addr add dead:1::2/64 dev veth$i
148 echo netns exec "$gw" ip route add 10.1.0.0/24 dev veth$i table $((1000+i))
149 echo netns exec "$gw" ip route add dead:1::0/64 dev veth$i table $((1000+i))
150 echo netns exec "$gw" ip route add 10.3.0.0/24 dev veth0 table $((1000+i))
151 echo netns exec "$gw" ip route add dead:3::0/64 dev veth0 table $((1000+i))
152 echo netns exec "$gw" ip rule add fwmark $i lookup $((1000+i))
153 done | ip -batch /dev/stdin
155 ip -net "$gw" addr add 10.3.0.1/24 dev veth0
156 ip -net "$gw" addr add dead:3::1/64 dev veth0
158 ip -net "$srv" addr add 10.3.0.99/24 dev eth0
159 ip -net "$srv" addr add dead:3::99/64 dev eth0
161 ip netns exec $gw nft -f /dev/stdin<<EOF
168 typeof iifname : ct zone
173 type ipv4_addr . ifname . ipv4_addr
177 type ipv4_addr . inet_service . ifname . ipv4_addr . inet_service
182 type ipv6_addr . inet_service . ifname . ipv6_addr . inet_service
186 type filter hook prerouting priority -64000; policy accept;
187 ct original zone set meta iifname map @iiftozone
188 meta mark set meta iifname map @iiftomark
190 tcp flags & (syn|ack) == ack add @inflows { ip saddr . tcp sport . meta iifname . ip daddr . tcp dport counter }
191 add @inflows6 { ip6 saddr . tcp sport . meta iifname . ip6 daddr . tcp dport counter }
192 ip protocol icmp add @inicmp { ip saddr . meta iifname . ip daddr counter }
195 chain nat_postrouting {
196 type nat hook postrouting priority 0; policy accept;
197 ct mark set meta mark meta oifname veth0 masquerade
200 chain mangle_prerouting {
201 type filter hook prerouting priority -100; policy accept;
202 ct direction reply meta mark set ct mark
207 ( echo add element inet raw iiftomark \{
208 for i in $(seq 1 $((maxclients-1))); do
209 echo \"veth$i\" : $i,
211 echo \"veth$maxclients\" : $maxclients \}
212 echo add element inet raw iiftozone \{
213 for i in $(seq 1 $((maxclients-1))); do
214 echo \"veth$i\" : $i,
216 echo \"veth$maxclients\" : $maxclients \}
217 ) | ip netns exec $gw nft -f /dev/stdin
219 ip netns exec "$gw" sysctl -q net.ipv4.conf.all.forwarding=1 > /dev/null
220 ip netns exec "$gw" sysctl -q net.ipv6.conf.all.forwarding=1 > /dev/null
221 ip netns exec "$gw" sysctl -q net.ipv4.conf.all.rp_filter=0 >/dev/null
223 # useful for debugging: allows to use 'ping' from clients to gateway.
224 ip netns exec "$gw" sysctl -q net.ipv4.fwmark_reflect=1 > /dev/null
225 ip netns exec "$gw" sysctl -q net.ipv6.fwmark_reflect=1 > /dev/null
227 for i in $(seq 1 $maxclients); do
229 ip netns exec $cl ping -i 0.5 -q -c 3 10.3.0.99 > /dev/null 2>&1 &
230 if [ $? -ne 0 ]; then
231 echo FAIL: Ping failure from $cl 1>&2
239 for i in $(seq 1 $maxclients); do
240 ip netns exec $gw nft get element inet raw inicmp "{ 10.1.0.3 . \"veth$i\" . 10.3.0.99 }" | grep -q "{ 10.1.0.3 . \"veth$i\" . 10.3.0.99 counter packets 3 bytes 252 }"
243 echo "FAIL: counter icmp mismatch for veth$i" 1>&2
244 ip netns exec $gw nft get element inet raw inicmp "{ 10.1.0.3 . \"veth$i\" . 10.3.0.99 }" 1>&2
249 ip netns exec $gw nft get element inet raw inicmp "{ 10.3.0.99 . \"veth0\" . 10.3.0.1 }" | grep -q "{ 10.3.0.99 . \"veth0\" . 10.3.0.1 counter packets $((3 * $maxclients)) bytes $((252 * $maxclients)) }"
252 echo "FAIL: counter icmp mismatch for veth0: { 10.3.0.99 . \"veth0\" . 10.3.0.1 counter packets $((3 * $maxclients)) bytes $((252 * $maxclients)) }"
253 ip netns exec $gw nft get element inet raw inicmp "{ 10.3.99 . \"veth0\" . 10.3.0.1 }" 1>&2
256 if [ $ret -eq 0 ]; then
257 echo "PASS: ping test from all $maxclients namespaces"
260 if [ $have_iperf -eq 0 ];then
261 echo "SKIP: iperf3 not installed"
262 if [ $ret -ne 0 ];then
268 ip netns exec $srv iperf3 -s > /dev/null 2>&1 &
272 for i in $(seq 1 $maxclients); do
273 if [ $ret -ne 0 ]; then
277 ip netns exec $cl iperf3 -c 10.3.0.99 --cport 10000 -n 1 > /dev/null
278 if [ $? -ne 0 ]; then
279 echo FAIL: Failure to connect for $cl 1>&2
280 ip netns exec $gw conntrack -S 1>&2
284 if [ $ret -eq 0 ];then
285 echo "PASS: iperf3 connections for all $maxclients net namespaces"
291 for i in $(seq 1 $maxclients); do
292 ip netns exec $gw nft get element inet raw inflows "{ 10.1.0.3 . 10000 . \"veth$i\" . 10.3.0.99 . 5201 }" > /dev/null
295 echo "FAIL: can't find expected tcp entry for veth$i" 1>&2
299 if [ $ret -eq 0 ];then
300 echo "PASS: Found client connection for all $maxclients net namespaces"
303 ip netns exec $gw nft get element inet raw inflows "{ 10.3.0.99 . 5201 . \"veth0\" . 10.3.0.1 . 10000 }" > /dev/null
306 echo "FAIL: cannot find return entry on veth0" 1>&2