File Index
Files and directories
Sign in
FILE

nft_flowtable.sh

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/net/netfilter/nft_flowtable.sh BASH
  1#!/bin/bash
  2# SPDX-License-Identifier: GPL-2.0
  3#
  4# This tests basic flowtable functionality.
  5# Creates following default topology:
  6#
  7# Originator (MTU 9000) <-Router1-> MTU 1500 <-Router2-> Responder (MTU 2000)
  8# Router1 is the one doing flow offloading, Router2 has no special
  9# purpose other than having a link that is smaller than either Originator
 10# and responder, i.e. TCPMSS announced values are too large and will still
 11# result in fragmentation and/or PMTU discovery.
 12#
 13# You can check with different Orgininator/Link/Responder MTU eg:
 14# nft_flowtable.sh -o8000 -l1500 -r2000
 15#
 16
 17source lib.sh
 18
 19ret=0
 20SOCAT_TIMEOUT=60
 21
 22nsin=""
 23nsin_small=""
 24ns1out=""
 25ns2out=""
 26
 27log_netns=$(sysctl -n net.netfilter.nf_log_all_netns)
 28
 29checktool "nft --version" "run test without nft tool"
 30checktool "socat -h" "run test without socat"
 31
 32setup_ns ns1 ns2 nsr1 nsr2
 33
 34cleanup() {
 35	ip netns pids "$ns1" | xargs kill 2>/dev/null
 36	ip netns pids "$ns2" | xargs kill 2>/dev/null
 37
 38	cleanup_all_ns
 39
 40	rm -f "$nsin" "$nsin_small" "$ns1out" "$ns2out"
 41
 42	[ "$log_netns" -eq 0 ] && sysctl -q net.netfilter.nf_log_all_netns="$log_netns"
 43}
 44
 45trap cleanup EXIT
 46
 47sysctl -q net.netfilter.nf_log_all_netns=1
 48
 49ip link add veth0 netns "$nsr1" type veth peer name eth0 netns "$ns1"
 50ip link add veth1 netns "$nsr1" type veth peer name veth0 netns "$nsr2"
 51
 52ip link add veth1 netns "$nsr2" type veth peer name eth0 netns "$ns2"
 53
 54for dev in veth0 veth1; do
 55    ip -net "$nsr1" link set "$dev" up
 56    ip -net "$nsr2" link set "$dev" up
 57done
 58
 59ip -net "$nsr1" addr add 10.0.1.1/24 dev veth0
 60ip -net "$nsr1" addr add dead:1::1/64 dev veth0 nodad
 61
 62ip -net "$nsr2" addr add 10.0.2.1/24 dev veth1
 63ip -net "$nsr2" addr add dead:2::1/64 dev veth1 nodad
 64
 65# set different MTUs so we need to push packets coming from ns1 (large MTU)
 66# to ns2 (smaller MTU) to stack either to perform fragmentation (ip_no_pmtu_disc=1),
 67# or to do PTMU discovery (send ICMP error back to originator).
 68# ns2 is going via nsr2 with a smaller mtu, so that TCPMSS announced by both peers
 69# is NOT the lowest link mtu.
 70
 71omtu=9000
 72lmtu=1500
 73rmtu=2000
 74
 75filesize=$((2 * 1024 * 1024))
 76filesize_small=$((filesize / 16))
 77
 78usage(){
 79	echo "nft_flowtable.sh [OPTIONS]"
 80	echo
 81	echo "MTU options"
 82	echo "   -o originator"
 83	echo "   -l link"
 84	echo "   -r responder"
 85	exit 1
 86}
 87
 88while getopts "o:l:r:s:" o
 89do
 90	case $o in
 91		o) omtu=$OPTARG;;
 92		l) lmtu=$OPTARG;;
 93		r) rmtu=$OPTARG;;
 94		s)
 95			filesize=$OPTARG
 96			filesize_small=$((OPTARG / 16))
 97		;;
 98		*) usage;;
 99	esac
100done
101
102if ! ip -net "$nsr1" link set veth0 mtu "$omtu"; then
103	exit 1
104fi
105
106ip -net "$ns1" link set eth0 mtu "$omtu"
107
108if ! ip -net "$nsr2" link set veth1 mtu "$rmtu"; then
109	exit 1
110fi
111
112if ! ip -net "$nsr1" link set veth1 mtu "$lmtu"; then
113	exit 1
114fi
115
116if ! ip -net "$nsr2" link set veth0 mtu "$lmtu"; then
117	exit 1
118fi
119
120ip -net "$ns2" link set eth0 mtu "$rmtu"
121
122# transfer-net between nsr1 and nsr2.
123# these addresses are not used for connections.
124ip -net "$nsr1" addr add 192.168.10.1/24 dev veth1
125ip -net "$nsr1" addr add fee1:2::1/64 dev veth1 nodad
126
127ip -net "$nsr2" addr add 192.168.10.2/24 dev veth0
128ip -net "$nsr2" addr add fee1:2::2/64 dev veth0 nodad
129
130ip netns exec "$nsr1" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
131ip netns exec "$nsr2" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
132for i in 0 1; do
133  ip netns exec "$nsr1" sysctl net.ipv4.conf.veth$i.forwarding=1 > /dev/null
134  ip netns exec "$nsr2" sysctl net.ipv4.conf.veth$i.forwarding=1 > /dev/null
135done
136
137for ns in "$ns1" "$ns2";do
138  ip -net "$ns" link set eth0 up
139
140  if ! ip netns exec "$ns" sysctl net.ipv4.tcp_no_metrics_save=1 > /dev/null; then
141	echo "ERROR: Check Originator/Responder values (problem during address addition)"
142	exit 1
143  fi
144  # don't set ip DF bit for first two tests
145  ip netns exec "$ns" sysctl net.ipv4.ip_no_pmtu_disc=1 > /dev/null
146done
147
148ip -net "$ns1" addr add 10.0.1.99/24 dev eth0
149ip -net "$ns2" addr add 10.0.2.99/24 dev eth0
150ip -net "$ns1" route add default via 10.0.1.1
151ip -net "$ns2" route add default via 10.0.2.1
152ip -net "$ns1" addr add dead:1::99/64 dev eth0 nodad
153ip -net "$ns2" addr add dead:2::99/64 dev eth0 nodad
154ip -net "$ns1" route add default via dead:1::1
155ip -net "$ns2" route add default via dead:2::1
156
157ip -net "$nsr1" route add default via 192.168.10.2
158ip -6 -net "$nsr1" route add default via fee1:2::2
159ip -net "$nsr2" route add default via 192.168.10.1
160ip -6 -net "$nsr2" route add default via fee1:2::1
161
162ip netns exec "$nsr1" nft -f - <<EOF
163table inet filter {
164  flowtable f1 {
165     hook ingress priority 0
166     devices = { veth0, veth1 }
167   }
168
169   counter routed_orig { }
170   counter routed_repl { }
171
172   chain forward {
173      type filter hook forward priority 0; policy drop;
174
175      # flow offloaded? Tag ct with mark 1, so we can detect when it fails.
176      meta oif "veth1" tcp dport 12345 ct mark set 1 flow add @f1 counter name routed_orig accept
177
178      # count packets supposedly offloaded as per direction.
179      ct mark 1 counter name ct direction map { original : routed_orig, reply : routed_repl } accept
180
181      ct state established,related accept
182
183      meta nfproto ipv4 meta l4proto icmp accept
184      meta nfproto ipv6 meta l4proto icmpv6 accept
185   }
186}
187EOF
188
189if [ $? -ne 0 ]; then
190	echo "SKIP: Could not load nft ruleset"
191	exit $ksft_skip
192fi
193
194ip netns exec "$ns2" nft -f - <<EOF
195table inet filter {
196   counter ip4dscp0 { }
197   counter ip4dscp3 { }
198
199   chain input {
200      type filter hook input priority 0; policy accept;
201      meta l4proto tcp goto {
202	      ip dscp cs3 counter name ip4dscp3 accept
203	      ip dscp 0 counter name ip4dscp0 accept
204      }
205   }
206}
207EOF
208
209if [ $? -ne 0 ]; then
210	echo -n "SKIP: Could not load ruleset: "
211	nft --version
212	exit $ksft_skip
213fi
214
215# test basic connectivity
216if ! ip netns exec "$ns1" ping -c 1 -q 10.0.2.99 > /dev/null; then
217  echo "ERROR: $ns1 cannot reach ns2" 1>&2
218  exit 1
219fi
220
221if ! ip netns exec "$ns2" ping -c 1 -q 10.0.1.99 > /dev/null; then
222  echo "ERROR: $ns2 cannot reach $ns1" 1>&2
223  exit 1
224fi
225
226nsin=$(mktemp)
227nsin_small=$(mktemp)
228ns1out=$(mktemp)
229ns2out=$(mktemp)
230
231make_file()
232{
233	name="$1"
234	sz="$2"
235
236	head -c "$sz" < /dev/urandom > "$name"
237}
238
239check_counters()
240{
241	local what=$1
242	local ok=1
243
244	local orig repl
245	orig=$(ip netns exec "$nsr1" nft reset counter inet filter routed_orig | grep packets)
246	repl=$(ip netns exec "$nsr1" nft reset counter inet filter routed_repl | grep packets)
247
248	local orig_cnt=${orig#*bytes}
249	local repl_cnt=${repl#*bytes}
250
251	local fs
252	fs=$(du -sb "$nsin")
253	local max_orig=${fs%%/*}
254	local max_repl=$((max_orig))
255
256	# flowtable fastpath should bypass normal routing one, i.e. the counters in forward hook
257	# should always be lower than the size of the transmitted file (max_orig).
258	if [ "$orig_cnt" -gt "$max_orig" ];then
259		echo "FAIL: $what: original counter $orig_cnt exceeds expected value $max_orig, reply counter $repl_cnt" 1>&2
260		ret=1
261		ok=0
262	fi
263
264	if [ "$repl_cnt" -gt $max_repl ];then
265		echo "FAIL: $what: reply counter $repl_cnt exceeds expected value $max_repl, original counter $orig_cnt" 1>&2
266		ret=1
267		ok=0
268	fi
269
270	if [ $ok -eq 1 ]; then
271		echo "PASS: $what"
272	fi
273}
274
275check_dscp()
276{
277	local what=$1
278	local pmtud="$2"
279	local ok=1
280
281	local counter
282	counter=$(ip netns exec "$ns2" nft reset counter inet filter ip4dscp3 | grep packets)
283
284	local pc4=${counter%*bytes*}
285	local pc4=${pc4#*packets}
286
287	counter=$(ip netns exec "$ns2" nft reset counter inet filter ip4dscp0 | grep packets)
288	local pc4z=${counter%*bytes*}
289	local pc4z=${pc4z#*packets}
290
291	local failmsg="FAIL: pmtu $pmtu: $what counters do not match, expected"
292
293	case "$what" in
294	"dscp_none")
295		if [ "$pc4" -gt 0 ] || [ "$pc4z" -eq 0 ]; then
296			echo "$failmsg dscp3 == 0, dscp0 > 0, but got $pc4,$pc4z" 1>&2
297			ret=1
298			ok=0
299		fi
300		;;
301	"dscp_fwd")
302		if [ "$pc4" -eq 0 ] || [ "$pc4z" -eq 0 ]; then
303			echo "$failmsg dscp3 and dscp0 > 0 but got $pc4,$pc4z" 1>&2
304			ret=1
305			ok=0
306		fi
307		;;
308	"dscp_ingress")
309		if [ "$pc4" -eq 0 ] || [ "$pc4z" -gt 0 ]; then
310			echo "$failmsg dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2
311			ret=1
312			ok=0
313		fi
314		;;
315	"dscp_egress")
316		if [ "$pc4" -eq 0 ] || [ "$pc4z" -gt 0 ]; then
317			echo "$failmsg dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2
318			ret=1
319			ok=0
320		fi
321		;;
322	*)
323		echo "$failmsg: Unknown DSCP check" 1>&2
324		ret=1
325		ok=0
326	esac
327
328	if [ "$ok" -eq 1 ] ;then
329		echo "PASS: $what: dscp packet counters match"
330	fi
331}
332
333check_transfer()
334{
335	local in=$1
336	local out=$2
337	local what=$3
338
339	if ! cmp "$in" "$out" > /dev/null 2>&1; then
340		echo "FAIL: file mismatch for $what" 1>&2
341		ls -l "$in"
342		ls -l "$out"
343		return 1
344	fi
345
346	return 0
347}
348
349listener_ready()
350{
351	ss -N "$nsb" -lnt -o "sport = :12345" | grep -q 12345
352}
353
354test_tcp_forwarding_ip()
355{
356	local nsa=$1
357	local nsb=$2
358	local pmtu=$3
359	local proto=$4
360	local dstip=$5
361	local dstport=$6
362	local lret=0
363	local socatc
364	local socatl
365	local infile="$nsin"
366
367	if [ $pmtu -eq 0 ]; then
368		infile="$nsin_small"
369	fi
370
371	timeout "$SOCAT_TIMEOUT" ip netns exec "$nsb" socat -${proto} \
372            TCP"${proto}"-LISTEN:12345,reuseaddr STDIO < "$infile" > "$ns2out" &
373	lpid=$!
374
375	busywait 1000 listener_ready
376
377	timeout "$SOCAT_TIMEOUT" ip netns exec "$nsa" socat -${proto} \
378            TCP"${proto}":"$dstip":"$dstport" STDIO < "$infile" > "$ns1out"
379	socatc=$?
380
381	wait $lpid
382	socatl=$?
383
384	if [ $socatl -ne 0 ] || [ $socatc -ne 0 ];then
385		rc=1
386	fi
387
388	if ! check_transfer "$infile" "$ns2out" "ns1 -> ns2"; then
389		lret=1
390		ret=1
391	fi
392
393	if ! check_transfer "$infile" "$ns1out" "ns1 <- ns2"; then
394		lret=1
395		ret=1
396	fi
397
398	return $lret
399}
400
401test_tcp_forwarding()
402{
403	local pmtu="$3"
404	local proto="$4"
405	local dstip="$5"
406	local dstport="$6"
407
408	test_tcp_forwarding_ip "$1" "$2" "$pmtu" "$proto" "$dstip" "$dstport"
409
410	return $?
411}
412
413test_tcp_forwarding_set_dscp()
414{
415	local pmtu="$3"
416	local proto="$4"
417	local dstip="$5"
418	local dstport="$6"
419
420ip netns exec "$nsr1" nft -f - <<EOF
421table netdev dscpmangle {
422   chain setdscp0 {
423      type filter hook ingress device "veth0" priority 0; policy accept
424	ip dscp set cs3
425  }
426}
427EOF
428if [ $? -eq 0 ]; then
429	test_tcp_forwarding_ip "$1" "$2" "$pmtu" "$proto" "$dstip" "$dstport"
430	check_dscp "dscp_ingress" "$pmtu"
431
432	ip netns exec "$nsr1" nft delete table netdev dscpmangle
433else
434	echo "SKIP: Could not load netdev:ingress for veth0"
435fi
436
437ip netns exec "$nsr1" nft -f - <<EOF
438table netdev dscpmangle {
439   chain setdscp0 {
440      type filter hook egress device "veth1" priority 0; policy accept
441      ip dscp set cs3
442  }
443}
444EOF
445if [ $? -eq 0 ]; then
446	test_tcp_forwarding_ip "$1" "$2" "$pmtu" "$proto" "$dstip" "$dstport"
447	check_dscp "dscp_egress" "$pmtu"
448
449	ip netns exec "$nsr1" nft delete table netdev dscpmangle
450else
451	echo "SKIP: Could not load netdev:egress for veth1"
452fi
453
454	# partial.  If flowtable really works, then both dscp-is-0 and dscp-is-cs3
455	# counters should have seen packets (before and after ft offload kicks in).
456	ip netns exec "$nsr1" nft -a insert rule inet filter forward ip dscp set cs3
457	test_tcp_forwarding_ip "$1" "$2" "$pmtu" "$proto" "$dstip" "$dstport"
458	check_dscp "dscp_fwd" "$pmtu"
459}
460
461test_tcp_forwarding_nat()
462{
463	local nsa="$1"
464	local nsb="$2"
465	local pmtu="$3"
466	local what="$4"
467	local lret
468
469	[ "$pmtu" -eq 0 ] && what="$what (pmtu disabled)"
470
471	test_tcp_forwarding_ip "$nsa" "$nsb" "$pmtu" 4 10.0.2.99 12345
472	lret=$?
473
474	if [ "$lret" -eq 0 ] ; then
475		if [ "$pmtu" -eq 1 ] ;then
476			check_counters "flow offload for ns1/ns2 with masquerade $what"
477		else
478			echo "PASS: flow offload for ns1/ns2 with masquerade $what"
479		fi
480
481		test_tcp_forwarding_ip "$1" "$2" "$pmtu" 4 10.6.6.6 1666
482		lret=$?
483		if [ "$pmtu" -eq 1 ] ;then
484			check_counters "flow offload for ns1/ns2 with dnat $what"
485		elif [ "$lret" -eq 0 ] ; then
486			echo "PASS: flow offload for ns1/ns2 with dnat $what"
487		fi
488	else
489		echo "FAIL: flow offload for ns1/ns2 with dnat $what"
490	fi
491
492	return $lret
493}
494
495make_file "$nsin" "$filesize"
496make_file "$nsin_small" "$filesize_small"
497
498# First test:
499# No PMTU discovery, nsr1 is expected to fragment packets from ns1 to ns2 as needed.
500# Due to MTU mismatch in both directions, all packets (except small packets like pure
501# acks) have to be handled by normal forwarding path.  Therefore, packet counters
502# are not checked.
503if test_tcp_forwarding "$ns1" "$ns2" 0 4 10.0.2.99 12345; then
504	echo "PASS: flow offloaded for ns1/ns2"
505else
506	echo "FAIL: flow offload for ns1/ns2:" 1>&2
507	ip netns exec "$nsr1" nft list ruleset
508	ret=1
509fi
510
511if test_tcp_forwarding "$ns1" "$ns2" 0 6 "[dead:2::99]" 12345; then
512	echo "PASS: IPv6 flow offloaded for ns1/ns2"
513else
514	echo "FAIL: IPv6 flow offload for ns1/ns2:" 1>&2
515	ip netns exec "$nsr1" nft list ruleset
516	ret=1
517fi
518
519# delete default route, i.e. ns2 won't be able to reach ns1 and
520# will depend on ns1 being masqueraded in nsr1.
521# expect ns1 has nsr1 address.
522ip -net "$ns2" route del default via 10.0.2.1
523ip -net "$ns2" route del default via dead:2::1
524ip -net "$ns2" route add 192.168.10.1 via 10.0.2.1
525
526# Second test:
527# Same, but with NAT enabled.  Same as in first test: we expect normal forward path
528# to handle most packets.
529ip netns exec "$nsr1" nft -f - <<EOF
530table ip nat {
531   chain prerouting {
532      type nat hook prerouting priority 0; policy accept;
533      meta iif "veth0" ip daddr 10.6.6.6 tcp dport 1666 counter dnat ip to 10.0.2.99:12345
534   }
535
536   chain postrouting {
537      type nat hook postrouting priority 0; policy accept;
538      meta oifname "veth1" counter masquerade
539   }
540}
541EOF
542
543check_dscp "dscp_none" "0"
544if ! test_tcp_forwarding_set_dscp "$ns1" "$ns2" 0 4 10.0.2.99 12345; then
545	echo "FAIL: flow offload for ns1/ns2 with dscp update and no pmtu discovery" 1>&2
546	exit 0
547fi
548
549if ! test_tcp_forwarding_nat "$ns1" "$ns2" 0 ""; then
550	echo "FAIL: flow offload for ns1/ns2 with NAT" 1>&2
551	ip netns exec "$nsr1" nft list ruleset
552	ret=1
553fi
554
555# Third test:
556# Same as second test, but with PMTU discovery enabled. This
557# means that we expect the fastpath to handle packets as soon
558# as the endpoints adjust the packet size.
559ip netns exec "$ns1" sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null
560ip netns exec "$ns2" sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null
561
562# reset counters.
563# With pmtu in-place we'll also check that nft counters
564# are lower than file size and packets were forwarded via flowtable layer.
565# For earlier tests (large mtus), packets cannot be handled via flowtable
566# (except pure acks and other small packets).
567ip netns exec "$nsr1" nft reset counters table inet filter >/dev/null
568ip netns exec "$ns2"  nft reset counters table inet filter >/dev/null
569
570if ! test_tcp_forwarding_set_dscp "$ns1" "$ns2" 1 4 10.0.2.99 12345; then
571	echo "FAIL: flow offload for ns1/ns2 with dscp update and pmtu discovery" 1>&2
572	exit 0
573fi
574
575ip netns exec "$nsr1" nft reset counters table inet filter >/dev/null
576
577if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 ""; then
578	echo "FAIL: flow offload for ns1/ns2 with NAT and pmtu discovery" 1>&2
579	ip netns exec "$nsr1" nft list ruleset
580fi
581
582# IPIP tunnel test:
583# Add IPIP tunnel interfaces and check flowtable acceleration.
584test_ipip() {
585if ! ip -net "$nsr1" link add name tun0 type ipip \
586     local 192.168.10.1 remote 192.168.10.2 >/dev/null;then
587	echo "SKIP: could not add ipip tunnel"
588	[ "$ret" -eq 0 ] && ret=$ksft_skip
589	return
590fi
591ip -net "$nsr1" link set tun0 up
592ip -net "$nsr1" addr add 192.168.100.1/24 dev tun0
593ip netns exec "$nsr1" sysctl net.ipv4.conf.tun0.forwarding=1 > /dev/null
594
595ip -net "$nsr2" link add name tun0 type ipip local 192.168.10.2 remote 192.168.10.1
596ip -net "$nsr2" link set tun0 up
597ip -net "$nsr2" addr add 192.168.100.2/24 dev tun0
598ip netns exec "$nsr2" sysctl net.ipv4.conf.tun0.forwarding=1 > /dev/null
599
600ip -net "$nsr1" route change default via 192.168.100.2
601ip -net "$nsr2" route change default via 192.168.100.1
602ip -net "$ns2" route add default via 10.0.2.1
603
604ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif tun0 accept'
605ip netns exec "$nsr1" nft -a insert rule inet filter forward \
606	'meta oif "veth0" tcp sport 12345 ct mark set 1 flow add @f1 counter name routed_repl accept'
607
608if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 "IPIP tunnel"; then
609	echo "FAIL: flow offload for ns1/ns2 with IPIP tunnel" 1>&2
610	ip netns exec "$nsr1" nft list ruleset
611	ret=1
612fi
613
614# Create vlan tagged devices for IPIP traffic.
615ip -net "$nsr1" link add link veth1 name veth1.10 type vlan id 10
616ip -net "$nsr1" link set veth1.10 up
617ip -net "$nsr1" addr add 192.168.20.1/24 dev veth1.10
618ip netns exec "$nsr1" sysctl net.ipv4.conf.veth1/10.forwarding=1 > /dev/null
619ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif veth1.10 accept'
620ip -net "$nsr1" link add name tun1 type ipip local 192.168.20.1 remote 192.168.20.2
621ip -net "$nsr1" link set tun1 up
622ip -net "$nsr1" addr add 192.168.200.1/24 dev tun1
623ip -net "$nsr1" route change default via 192.168.200.2
624ip netns exec "$nsr1" sysctl net.ipv4.conf.tun1.forwarding=1 > /dev/null
625ip netns exec "$nsr1" nft -a insert rule inet filter forward 'meta oif tun1 accept'
626
627ip -net "$nsr2" link add link veth0 name veth0.10 type vlan id 10
628ip -net "$nsr2" link set veth0.10 up
629ip -net "$nsr2" addr add 192.168.20.2/24 dev veth0.10
630ip netns exec "$nsr2" sysctl net.ipv4.conf.veth0/10.forwarding=1 > /dev/null
631ip -net "$nsr2" link add name tun1 type ipip local 192.168.20.2 remote 192.168.20.1
632ip -net "$nsr2" link set tun1 up
633ip -net "$nsr2" addr add 192.168.200.2/24 dev tun1
634ip -net "$nsr2" route change default via 192.168.200.1
635ip netns exec "$nsr2" sysctl net.ipv4.conf.tun1.forwarding=1 > /dev/null
636
637if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 "IPIP tunnel over vlan"; then
638	echo "FAIL: flow offload for ns1/ns2 with IPIP tunnel over vlan" 1>&2
639	ip netns exec "$nsr1" nft list ruleset
640	ret=1
641fi
642
643# Restore the previous configuration
644ip -net "$nsr1" route change default via 192.168.10.2
645ip -net "$nsr2" route change default via 192.168.10.1
646ip -net "$ns2" route del default via 10.0.2.1
647}
648
649# Another test:
650# Add bridge interface br0 to Router1, with NAT enabled.
651test_bridge() {
652if ! ip -net "$nsr1" link add name br0 type bridge 2>/dev/null;then
653	echo "SKIP: could not add bridge br0"
654	[ "$ret" -eq 0 ] && ret=$ksft_skip
655	return
656fi
657ip -net "$nsr1" addr flush dev veth0
658ip -net "$nsr1" link set up dev veth0
659ip -net "$nsr1" link set veth0 master br0
660ip -net "$nsr1" addr add 10.0.1.1/24 dev br0
661ip -net "$nsr1" addr add dead:1::1/64 dev br0 nodad
662ip -net "$nsr1" link set up dev br0
663
664ip netns exec "$nsr1" sysctl net.ipv4.conf.br0.forwarding=1 > /dev/null
665
666# br0 with NAT enabled.
667ip netns exec "$nsr1" nft -f - <<EOF
668flush table ip nat
669table ip nat {
670   chain prerouting {
671      type nat hook prerouting priority 0; policy accept;
672      meta iif "br0" ip daddr 10.6.6.6 tcp dport 1666 counter dnat ip to 10.0.2.99:12345
673   }
674
675   chain postrouting {
676      type nat hook postrouting priority 0; policy accept;
677      meta oifname "veth1" counter masquerade
678   }
679}
680EOF
681
682if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 "on bridge"; then
683	echo "FAIL: flow offload for ns1/ns2 with bridge NAT" 1>&2
684	ip netns exec "$nsr1" nft list ruleset
685	ret=1
686fi
687
688
689# Another test:
690# Add bridge interface br0 to Router1, with NAT and VLAN.
691ip -net "$nsr1" link set veth0 nomaster
692ip -net "$nsr1" link set down dev veth0
693ip -net "$nsr1" link add link veth0 name veth0.10 type vlan id 10
694ip -net "$nsr1" link set up dev veth0
695ip -net "$nsr1" link set up dev veth0.10
696ip -net "$nsr1" link set veth0.10 master br0
697
698ip -net "$ns1" addr flush dev eth0
699ip -net "$ns1" link add link eth0 name eth0.10 type vlan id 10
700ip -net "$ns1" link set eth0 up
701ip -net "$ns1" link set eth0.10 up
702ip -net "$ns1" addr add 10.0.1.99/24 dev eth0.10
703ip -net "$ns1" route add default via 10.0.1.1
704ip -net "$ns1" addr add dead:1::99/64 dev eth0.10 nodad
705
706if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 "bridge and VLAN"; then
707	echo "FAIL: flow offload for ns1/ns2 with bridge NAT and VLAN" 1>&2
708	ip netns exec "$nsr1" nft list ruleset
709	ret=1
710fi
711
712# restore test topology (remove bridge and VLAN)
713ip -net "$nsr1" link set veth0 nomaster
714ip -net "$nsr1" link set veth0 down
715ip -net "$nsr1" link set veth0.10 down
716ip -net "$nsr1" link delete veth0.10 type vlan
717ip -net "$nsr1" link delete br0 type bridge
718ip -net "$ns1" addr flush dev eth0.10
719ip -net "$ns1" link set eth0.10 down
720ip -net "$ns1" link set eth0 down
721ip -net "$ns1" link delete eth0.10 type vlan
722
723# restore address in ns1 and nsr1
724ip -net "$ns1" link set eth0 up
725ip -net "$ns1" addr add 10.0.1.99/24 dev eth0
726ip -net "$ns1" route add default via 10.0.1.1
727ip -net "$ns1" addr add dead:1::99/64 dev eth0 nodad
728ip -net "$ns1" route add default via dead:1::1
729ip -net "$nsr1" addr add 10.0.1.1/24 dev veth0
730ip -net "$nsr1" addr add dead:1::1/64 dev veth0 nodad
731ip -net "$nsr1" link set up dev veth0
732}
733
734test_ipip
735
736test_bridge
737
738KEY_SHA="0x"$(ps -af | sha1sum | cut -d " " -f 1)
739KEY_AES="0x"$(ps -af | md5sum | cut -d " " -f 1)
740SPI1=$RANDOM
741SPI2=$RANDOM
742
743if [ $SPI1 -eq $SPI2 ]; then
744	SPI2=$((SPI2+1))
745fi
746
747do_esp() {
748    local ns=$1
749    local me=$2
750    local remote=$3
751    local lnet=$4
752    local rnet=$5
753    local spi_out=$6
754    local spi_in=$7
755
756    ip -net "$ns" xfrm state add src "$remote" dst "$me" proto esp spi "$spi_in"  enc aes "$KEY_AES"  auth sha1 "$KEY_SHA" mode tunnel sel src "$rnet" dst "$lnet"
757    ip -net "$ns" xfrm state add src "$me"  dst "$remote" proto esp spi "$spi_out" enc aes "$KEY_AES" auth sha1 "$KEY_SHA" mode tunnel sel src "$lnet" dst "$rnet"
758
759    # to encrypt packets as they go out (includes forwarded packets that need encapsulation)
760    ip -net "$ns" xfrm policy add src "$lnet" dst "$rnet" dir out tmpl src "$me" dst "$remote" proto esp mode tunnel priority 1 action allow
761    # to fwd decrypted packets after esp processing:
762    ip -net "$ns" xfrm policy add src "$rnet" dst "$lnet" dir fwd tmpl src "$remote" dst "$me" proto esp mode tunnel priority 1 action allow
763}
764
765do_esp "$nsr1" 192.168.10.1 192.168.10.2 10.0.1.0/24 10.0.2.0/24 "$SPI1" "$SPI2"
766
767do_esp "$nsr2" 192.168.10.2 192.168.10.1 10.0.2.0/24 10.0.1.0/24 "$SPI2" "$SPI1"
768
769ip netns exec "$nsr1" nft delete table ip nat
770
771# restore default routes
772ip -net "$ns2" route del 192.168.10.1 via 10.0.2.1
773ip -net "$ns2" route add default via 10.0.2.1
774ip -net "$ns2" route add default via dead:2::1
775
776if test_tcp_forwarding "$ns1" "$ns2" 1 4 10.0.2.99 12345; then
777	check_counters "ipsec tunnel mode for ns1/ns2"
778else
779	echo "FAIL: ipsec tunnel mode for ns1/ns2"
780	ip netns exec "$nsr1" nft list ruleset 1>&2
781	ip netns exec "$nsr1" cat /proc/net/xfrm_stat 1>&2
782fi
783
784if test_tcp_forwarding "$ns1" "$ns2" 1 6 "[dead:2::99]" 12345; then
785	check_counters "IPv6 ipsec tunnel mode for ns1/ns2"
786else
787	echo "FAIL: IPv6 ipsec tunnel mode for ns1/ns2"
788	ip netns exec "$nsr1" nft list ruleset 1>&2
789	ip netns exec "$nsr1" cat /proc/net/xfrm_stat 1>&2
790fi
791
792if [ "$1" = "" ]; then
793	low=1280
794	mtu=$((65536 - low))
795	o=$(((RANDOM%mtu) + low))
796	l=$(((RANDOM%mtu) + low))
797	r=$(((RANDOM%mtu) + low))
798
799	MINSIZE=$((2 *  1000 * 1000))
800	MAXSIZE=$((64 * 1000 * 1000))
801
802	filesize=$(((RANDOM * RANDOM) % MAXSIZE))
803	if [ "$filesize" -lt "$MINSIZE" ]; then
804		filesize=$((filesize+MINSIZE))
805	fi
806
807	echo "re-run with random mtus and file size: -o $o -l $l -r $r -s $filesize"
808	$0 -o "$o" -l "$l" -r "$r" -s "$filesize" || ret=1
809fi
810
811exit $ret
~/ Read-only file preview.