12de03b45SFlorian Westphal#!/bin/bash
22de03b45SFlorian Westphal# SPDX-License-Identifier: GPL-2.0
32de03b45SFlorian Westphal#
42de03b45SFlorian Westphal# This tests basic flowtable functionality.
5dd08734dSFabian Frederick# Creates following default topology:
62de03b45SFlorian Westphal#
72de03b45SFlorian Westphal# Originator (MTU 9000) <-Router1-> MTU 1500 <-Router2-> Responder (MTU 2000)
82de03b45SFlorian Westphal# Router1 is the one doing flow offloading, Router2 has no special
92de03b45SFlorian Westphal# purpose other than having a link that is smaller than either Originator
102de03b45SFlorian Westphal# and responder, i.e. TCPMSS announced values are too large and will still
112de03b45SFlorian Westphal# result in fragmentation and/or PMTU discovery.
12dd08734dSFabian Frederick#
13dd08734dSFabian Frederick# You can check with different Orgininator/Link/Responder MTU eg:
14da2f849eSFabian Frederick# nft_flowtable.sh -o8000 -l1500 -r2000
15dd08734dSFabian Frederick#
16dd08734dSFabian Frederick
17b71b7bfeSFlorian Westphalsfx=$(mktemp -u "XXXXXXXX")
18b71b7bfeSFlorian Westphalns1="ns1-$sfx"
19b71b7bfeSFlorian Westphalns2="ns2-$sfx"
20b71b7bfeSFlorian Westphalnsr1="nsr1-$sfx"
21b71b7bfeSFlorian Westphalnsr2="nsr2-$sfx"
222de03b45SFlorian Westphal
232de03b45SFlorian Westphal# Kselftest framework requirement - SKIP code is 4.
242de03b45SFlorian Westphalksft_skip=4
252de03b45SFlorian Westphalret=0
262de03b45SFlorian Westphal
27c8550b90SFlorian Westphalnsin=""
282de03b45SFlorian Westphalns1out=""
292de03b45SFlorian Westphalns2out=""
302de03b45SFlorian Westphal
312de03b45SFlorian Westphallog_netns=$(sysctl -n net.netfilter.nf_log_all_netns)
322de03b45SFlorian Westphal
336d006a4eSFabian Frederickchecktool (){
342f4bba4eSFabian Frederick	if ! $1 > /dev/null 2>&1; then
356d006a4eSFabian Frederick		echo "SKIP: Could not $2"
362de03b45SFlorian Westphal		exit $ksft_skip
372de03b45SFlorian Westphal	fi
386d006a4eSFabian Frederick}
392de03b45SFlorian Westphal
406d006a4eSFabian Frederickchecktool "nft --version" "run test without nft tool"
416d006a4eSFabian Frederickchecktool "ip -Version" "run test without ip tool"
426d006a4eSFabian Frederickchecktool "which nc" "run test without nc (netcat)"
43b71b7bfeSFlorian Westphalchecktool "ip netns add $nsr1" "create net namespace $nsr1"
442de03b45SFlorian Westphal
45b71b7bfeSFlorian Westphalip netns add $ns1
46b71b7bfeSFlorian Westphalip netns add $ns2
47b71b7bfeSFlorian Westphalip netns add $nsr2
482de03b45SFlorian Westphal
492de03b45SFlorian Westphalcleanup() {
50b71b7bfeSFlorian Westphal	ip netns del $ns1
51b71b7bfeSFlorian Westphal	ip netns del $ns2
52b71b7bfeSFlorian Westphal	ip netns del $nsr1
53b71b7bfeSFlorian Westphal	ip netns del $nsr2
542de03b45SFlorian Westphal
55c8550b90SFlorian Westphal	rm -f "$nsin" "$ns1out" "$ns2out"
562de03b45SFlorian Westphal
572de03b45SFlorian Westphal	[ $log_netns -eq 0 ] && sysctl -q net.netfilter.nf_log_all_netns=$log_netns
582de03b45SFlorian Westphal}
592de03b45SFlorian Westphal
602de03b45SFlorian Westphaltrap cleanup EXIT
612de03b45SFlorian Westphal
622de03b45SFlorian Westphalsysctl -q net.netfilter.nf_log_all_netns=1
632de03b45SFlorian Westphal
64b71b7bfeSFlorian Westphalip link add veth0 netns $nsr1 type veth peer name eth0 netns $ns1
65b71b7bfeSFlorian Westphalip link add veth1 netns $nsr1 type veth peer name veth0 netns $nsr2
662de03b45SFlorian Westphal
67b71b7bfeSFlorian Westphalip link add veth1 netns $nsr2 type veth peer name eth0 netns $ns2
682de03b45SFlorian Westphal
692de03b45SFlorian Westphalfor dev in lo veth0 veth1; do
70b71b7bfeSFlorian Westphal    ip -net $nsr1 link set $dev up
71b71b7bfeSFlorian Westphal    ip -net $nsr2 link set $dev up
722de03b45SFlorian Westphaldone
732de03b45SFlorian Westphal
74b71b7bfeSFlorian Westphalip -net $nsr1 addr add 10.0.1.1/24 dev veth0
75b71b7bfeSFlorian Westphalip -net $nsr1 addr add dead:1::1/64 dev veth0
762de03b45SFlorian Westphal
77b71b7bfeSFlorian Westphalip -net $nsr2 addr add 10.0.2.1/24 dev veth1
78b71b7bfeSFlorian Westphalip -net $nsr2 addr add dead:2::1/64 dev veth1
792de03b45SFlorian Westphal
802de03b45SFlorian Westphal# set different MTUs so we need to push packets coming from ns1 (large MTU)
812de03b45SFlorian Westphal# to ns2 (smaller MTU) to stack either to perform fragmentation (ip_no_pmtu_disc=1),
822de03b45SFlorian Westphal# or to do PTMU discovery (send ICMP error back to originator).
832de03b45SFlorian Westphal# ns2 is going via nsr2 with a smaller mtu, so that TCPMSS announced by both peers
842de03b45SFlorian Westphal# is NOT the lowest link mtu.
852de03b45SFlorian Westphal
86dd08734dSFabian Frederickomtu=9000
87dd08734dSFabian Fredericklmtu=1500
88dd08734dSFabian Frederickrmtu=2000
892de03b45SFlorian Westphal
9067afbda6SFabian Frederickusage(){
9167afbda6SFabian Frederick	echo "nft_flowtable.sh [OPTIONS]"
9267afbda6SFabian Frederick	echo
9367afbda6SFabian Frederick	echo "MTU options"
9467afbda6SFabian Frederick	echo "   -o originator"
9567afbda6SFabian Frederick	echo "   -l link"
9667afbda6SFabian Frederick	echo "   -r responder"
9767afbda6SFabian Frederick	exit 1
9867afbda6SFabian Frederick}
9967afbda6SFabian Frederick
100dd08734dSFabian Frederickwhile getopts "o:l:r:" o
101dd08734dSFabian Frederickdo
102dd08734dSFabian Frederick	case $o in
103dd08734dSFabian Frederick		o) omtu=$OPTARG;;
104dd08734dSFabian Frederick		l) lmtu=$OPTARG;;
105dd08734dSFabian Frederick		r) rmtu=$OPTARG;;
10667afbda6SFabian Frederick		*) usage;;
107dd08734dSFabian Frederick	esac
108dd08734dSFabian Frederickdone
109dd08734dSFabian Frederick
110b71b7bfeSFlorian Westphalif ! ip -net $nsr1 link set veth0 mtu $omtu; then
111a7bf670eSFabian Frederick	exit 1
112a7bf670eSFabian Frederickfi
113a7bf670eSFabian Frederick
114b71b7bfeSFlorian Westphalip -net $ns1 link set eth0 mtu $omtu
115dd08734dSFabian Frederick
116b71b7bfeSFlorian Westphalif ! ip -net $nsr2 link set veth1 mtu $rmtu; then
117a7bf670eSFabian Frederick	exit 1
118a7bf670eSFabian Frederickfi
119a7bf670eSFabian Frederick
120b71b7bfeSFlorian Westphalip -net $ns2 link set eth0 mtu $rmtu
1212de03b45SFlorian Westphal
1222de03b45SFlorian Westphal# transfer-net between nsr1 and nsr2.
1232de03b45SFlorian Westphal# these addresses are not used for connections.
124b71b7bfeSFlorian Westphalip -net $nsr1 addr add 192.168.10.1/24 dev veth1
125b71b7bfeSFlorian Westphalip -net $nsr1 addr add fee1:2::1/64 dev veth1
1262de03b45SFlorian Westphal
127b71b7bfeSFlorian Westphalip -net $nsr2 addr add 192.168.10.2/24 dev veth0
128b71b7bfeSFlorian Westphalip -net $nsr2 addr add fee1:2::2/64 dev veth0
1292de03b45SFlorian Westphal
130b71b7bfeSFlorian Westphalfor i in 0 1; do
131b71b7bfeSFlorian Westphal  ip netns exec $nsr1 sysctl net.ipv4.conf.veth$i.forwarding=1 > /dev/null
132b71b7bfeSFlorian Westphal  ip netns exec $nsr2 sysctl net.ipv4.conf.veth$i.forwarding=1 > /dev/null
133b71b7bfeSFlorian Westphaldone
1342de03b45SFlorian Westphal
135b71b7bfeSFlorian Westphalfor ns in $ns1 $ns2;do
136b71b7bfeSFlorian Westphal  ip -net $ns link set lo up
137b71b7bfeSFlorian Westphal  ip -net $ns link set eth0 up
138b71b7bfeSFlorian Westphal
139b71b7bfeSFlorian Westphal  if ! ip netns exec $ns sysctl net.ipv4.tcp_no_metrics_save=1 > /dev/null; then
140a7bf670eSFabian Frederick	echo "ERROR: Check Originator/Responder values (problem during address addition)"
141a7bf670eSFabian Frederick	exit 1
142a7bf670eSFabian Frederick  fi
1432de03b45SFlorian Westphal  # don't set ip DF bit for first two tests
144b71b7bfeSFlorian Westphal  ip netns exec $ns sysctl net.ipv4.ip_no_pmtu_disc=1 > /dev/null
1452de03b45SFlorian Westphaldone
1462de03b45SFlorian Westphal
147b71b7bfeSFlorian Westphalip -net $ns1 addr add 10.0.1.99/24 dev eth0
148b71b7bfeSFlorian Westphalip -net $ns2 addr add 10.0.2.99/24 dev eth0
149b71b7bfeSFlorian Westphalip -net $ns1 route add default via 10.0.1.1
150b71b7bfeSFlorian Westphalip -net $ns2 route add default via 10.0.2.1
151b71b7bfeSFlorian Westphalip -net $ns1 addr add dead:1::99/64 dev eth0
152b71b7bfeSFlorian Westphalip -net $ns2 addr add dead:2::99/64 dev eth0
153b71b7bfeSFlorian Westphalip -net $ns1 route add default via dead:1::1
154b71b7bfeSFlorian Westphalip -net $ns2 route add default via dead:2::1
1552de03b45SFlorian Westphal
156b71b7bfeSFlorian Westphalip -net $nsr1 route add default via 192.168.10.2
157b71b7bfeSFlorian Westphalip -net $nsr2 route add default via 192.168.10.1
158b71b7bfeSFlorian Westphal
159b71b7bfeSFlorian Westphalip netns exec $nsr1 nft -f - <<EOF
1602de03b45SFlorian Westphaltable inet filter {
1612de03b45SFlorian Westphal  flowtable f1 {
1622de03b45SFlorian Westphal     hook ingress priority 0
1632de03b45SFlorian Westphal     devices = { veth0, veth1 }
1642de03b45SFlorian Westphal   }
1652de03b45SFlorian Westphal
166c8550b90SFlorian Westphal   counter routed_orig { }
167c8550b90SFlorian Westphal   counter routed_repl { }
168c8550b90SFlorian Westphal
1692de03b45SFlorian Westphal   chain forward {
1702de03b45SFlorian Westphal      type filter hook forward priority 0; policy drop;
1712de03b45SFlorian Westphal
1722de03b45SFlorian Westphal      # flow offloaded? Tag ct with mark 1, so we can detect when it fails.
173c8550b90SFlorian Westphal      meta oif "veth1" tcp dport 12345 ct mark set 1 flow add @f1 counter name routed_orig accept
1742de03b45SFlorian Westphal
175c8550b90SFlorian Westphal      # count packets supposedly offloaded as per direction.
176c8550b90SFlorian Westphal      ct mark 1 counter name ct direction map { original : routed_orig, reply : routed_repl } accept
1772de03b45SFlorian Westphal
1782de03b45SFlorian Westphal      ct state established,related accept
1792de03b45SFlorian Westphal
1802de03b45SFlorian Westphal      meta nfproto ipv4 meta l4proto icmp accept
1812de03b45SFlorian Westphal      meta nfproto ipv6 meta l4proto icmpv6 accept
1822de03b45SFlorian Westphal   }
1832de03b45SFlorian Westphal}
1842de03b45SFlorian WestphalEOF
1852de03b45SFlorian Westphal
1862de03b45SFlorian Westphalif [ $? -ne 0 ]; then
1872de03b45SFlorian Westphal	echo "SKIP: Could not load nft ruleset"
1882de03b45SFlorian Westphal	exit $ksft_skip
1892de03b45SFlorian Westphalfi
1902de03b45SFlorian Westphal
191*3acf8f6cSFlorian Westphalip netns exec $ns2 nft -f - <<EOF
192*3acf8f6cSFlorian Westphaltable inet filter {
193*3acf8f6cSFlorian Westphal   counter ip4dscp0 { }
194*3acf8f6cSFlorian Westphal   counter ip4dscp3 { }
195*3acf8f6cSFlorian Westphal
196*3acf8f6cSFlorian Westphal   chain input {
197*3acf8f6cSFlorian Westphal      type filter hook input priority 0; policy accept;
198*3acf8f6cSFlorian Westphal      meta l4proto tcp goto {
199*3acf8f6cSFlorian Westphal	      ip dscp cs3 counter name ip4dscp3 accept
200*3acf8f6cSFlorian Westphal	      ip dscp 0 counter name ip4dscp0 accept
201*3acf8f6cSFlorian Westphal      }
202*3acf8f6cSFlorian Westphal   }
203*3acf8f6cSFlorian Westphal}
204*3acf8f6cSFlorian WestphalEOF
205*3acf8f6cSFlorian Westphal
206*3acf8f6cSFlorian Westphalif [ $? -ne 0 ]; then
207*3acf8f6cSFlorian Westphal	echo "SKIP: Could not load nft ruleset"
208*3acf8f6cSFlorian Westphal	exit $ksft_skip
209*3acf8f6cSFlorian Westphalfi
210*3acf8f6cSFlorian Westphal
2112de03b45SFlorian Westphal# test basic connectivity
212b71b7bfeSFlorian Westphalif ! ip netns exec $ns1 ping -c 1 -q 10.0.2.99 > /dev/null; then
213b71b7bfeSFlorian Westphal  echo "ERROR: $ns1 cannot reach ns2" 1>&2
2142de03b45SFlorian Westphal  exit 1
2152de03b45SFlorian Westphalfi
2162de03b45SFlorian Westphal
217b71b7bfeSFlorian Westphalif ! ip netns exec $ns2 ping -c 1 -q 10.0.1.99 > /dev/null; then
218b71b7bfeSFlorian Westphal  echo "ERROR: $ns2 cannot reach $ns1" 1>&2
2192de03b45SFlorian Westphal  exit 1
2202de03b45SFlorian Westphalfi
2212de03b45SFlorian Westphal
2222de03b45SFlorian Westphalif [ $ret -eq 0 ];then
223b71b7bfeSFlorian Westphal	echo "PASS: netns routing/connectivity: $ns1 can reach $ns2"
2242de03b45SFlorian Westphalfi
2252de03b45SFlorian Westphal
226c8550b90SFlorian Westphalnsin=$(mktemp)
2272de03b45SFlorian Westphalns1out=$(mktemp)
2282de03b45SFlorian Westphalns2out=$(mktemp)
2292de03b45SFlorian Westphal
2302de03b45SFlorian Westphalmake_file()
2312de03b45SFlorian Westphal{
2322de03b45SFlorian Westphal	name=$1
2332de03b45SFlorian Westphal
234c8550b90SFlorian Westphal	SIZE=$((RANDOM % (1024 * 128)))
235c8550b90SFlorian Westphal	SIZE=$((SIZE + (1024 * 8)))
2362de03b45SFlorian Westphal	TSIZE=$((SIZE * 1024))
2372de03b45SFlorian Westphal
2382de03b45SFlorian Westphal	dd if=/dev/urandom of="$name" bs=1024 count=$SIZE 2> /dev/null
2392de03b45SFlorian Westphal
2402de03b45SFlorian Westphal	SIZE=$((RANDOM % 1024))
2412de03b45SFlorian Westphal	SIZE=$((SIZE + 128))
2422de03b45SFlorian Westphal	TSIZE=$((TSIZE + SIZE))
2432de03b45SFlorian Westphal	dd if=/dev/urandom conf=notrunc of="$name" bs=1 count=$SIZE 2> /dev/null
2442de03b45SFlorian Westphal}
2452de03b45SFlorian Westphal
246c8550b90SFlorian Westphalcheck_counters()
247c8550b90SFlorian Westphal{
248c8550b90SFlorian Westphal	local what=$1
249c8550b90SFlorian Westphal	local ok=1
250c8550b90SFlorian Westphal
251c8550b90SFlorian Westphal	local orig=$(ip netns exec $nsr1 nft reset counter inet filter routed_orig | grep packets)
252c8550b90SFlorian Westphal	local repl=$(ip netns exec $nsr1 nft reset counter inet filter routed_repl | grep packets)
253c8550b90SFlorian Westphal
254c8550b90SFlorian Westphal	local orig_cnt=${orig#*bytes}
255c8550b90SFlorian Westphal	local repl_cnt=${repl#*bytes}
256c8550b90SFlorian Westphal
257c8550b90SFlorian Westphal	local fs=$(du -sb $nsin)
258c8550b90SFlorian Westphal	local max_orig=${fs%%/*}
259c8550b90SFlorian Westphal	local max_repl=$((max_orig/4))
260c8550b90SFlorian Westphal
261c8550b90SFlorian Westphal	if [ $orig_cnt -gt $max_orig ];then
262c8550b90SFlorian Westphal		echo "FAIL: $what: original counter $orig_cnt exceeds expected value $max_orig" 1>&2
263c8550b90SFlorian Westphal		ret=1
264c8550b90SFlorian Westphal		ok=0
265c8550b90SFlorian Westphal	fi
266c8550b90SFlorian Westphal
267c8550b90SFlorian Westphal	if [ $repl_cnt -gt $max_repl ];then
268c8550b90SFlorian Westphal		echo "FAIL: $what: reply counter $repl_cnt exceeds expected value $max_repl" 1>&2
269c8550b90SFlorian Westphal		ret=1
270c8550b90SFlorian Westphal		ok=0
271c8550b90SFlorian Westphal	fi
272c8550b90SFlorian Westphal
273c8550b90SFlorian Westphal	if [ $ok -eq 1 ]; then
274c8550b90SFlorian Westphal		echo "PASS: $what"
275c8550b90SFlorian Westphal	fi
276c8550b90SFlorian Westphal}
277c8550b90SFlorian Westphal
278*3acf8f6cSFlorian Westphalcheck_dscp()
279*3acf8f6cSFlorian Westphal{
280*3acf8f6cSFlorian Westphal	local what=$1
281*3acf8f6cSFlorian Westphal	local ok=1
282*3acf8f6cSFlorian Westphal
283*3acf8f6cSFlorian Westphal	local counter=$(ip netns exec $ns2 nft reset counter inet filter ip4dscp3 | grep packets)
284*3acf8f6cSFlorian Westphal
285*3acf8f6cSFlorian Westphal	local pc4=${counter%*bytes*}
286*3acf8f6cSFlorian Westphal	local pc4=${pc4#*packets}
287*3acf8f6cSFlorian Westphal
288*3acf8f6cSFlorian Westphal	local counter=$(ip netns exec $ns2 nft reset counter inet filter ip4dscp0 | grep packets)
289*3acf8f6cSFlorian Westphal	local pc4z=${counter%*bytes*}
290*3acf8f6cSFlorian Westphal	local pc4z=${pc4z#*packets}
291*3acf8f6cSFlorian Westphal
292*3acf8f6cSFlorian Westphal	case "$what" in
293*3acf8f6cSFlorian Westphal	"dscp_none")
294*3acf8f6cSFlorian Westphal		if [ $pc4 -gt 0 ] || [ $pc4z -eq 0 ]; then
295*3acf8f6cSFlorian Westphal			echo "FAIL: dscp counters do not match, expected dscp3 == 0, dscp0 > 0, but got $pc4,$pc4z" 1>&2
296*3acf8f6cSFlorian Westphal			ret=1
297*3acf8f6cSFlorian Westphal			ok=0
298*3acf8f6cSFlorian Westphal		fi
299*3acf8f6cSFlorian Westphal		;;
300*3acf8f6cSFlorian Westphal	"dscp_fwd")
301*3acf8f6cSFlorian Westphal		if [ $pc4 -eq 0 ] || [ $pc4z -eq 0 ]; then
302*3acf8f6cSFlorian Westphal			echo "FAIL: dscp counters do not match, expected dscp3 and dscp0 > 0 but got $pc4,$pc4z" 1>&2
303*3acf8f6cSFlorian Westphal			ret=1
304*3acf8f6cSFlorian Westphal			ok=0
305*3acf8f6cSFlorian Westphal		fi
306*3acf8f6cSFlorian Westphal		;;
307*3acf8f6cSFlorian Westphal	"dscp_ingress")
308*3acf8f6cSFlorian Westphal		if [ $pc4 -eq 0 ] || [ $pc4z -gt 0 ]; then
309*3acf8f6cSFlorian Westphal			echo "FAIL: dscp counters do not match, expected dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2
310*3acf8f6cSFlorian Westphal			ret=1
311*3acf8f6cSFlorian Westphal			ok=0
312*3acf8f6cSFlorian Westphal		fi
313*3acf8f6cSFlorian Westphal		;;
314*3acf8f6cSFlorian Westphal	"dscp_egress")
315*3acf8f6cSFlorian Westphal		if [ $pc4 -eq 0 ] || [ $pc4z -gt 0 ]; then
316*3acf8f6cSFlorian Westphal			echo "FAIL: dscp counters do not match, expected dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2
317*3acf8f6cSFlorian Westphal			ret=1
318*3acf8f6cSFlorian Westphal			ok=0
319*3acf8f6cSFlorian Westphal		fi
320*3acf8f6cSFlorian Westphal		;;
321*3acf8f6cSFlorian Westphal	*)
322*3acf8f6cSFlorian Westphal		echo "FAIL: Unknown DSCP check" 1>&2
323*3acf8f6cSFlorian Westphal		ret=1
324*3acf8f6cSFlorian Westphal		ok=0
325*3acf8f6cSFlorian Westphal	esac
326*3acf8f6cSFlorian Westphal
327*3acf8f6cSFlorian Westphal	if [ $ok -eq 1 ] ;then
328*3acf8f6cSFlorian Westphal		echo "PASS: $what: dscp packet counters match"
329*3acf8f6cSFlorian Westphal	fi
330*3acf8f6cSFlorian Westphal}
331*3acf8f6cSFlorian Westphal
3322de03b45SFlorian Westphalcheck_transfer()
3332de03b45SFlorian Westphal{
3342de03b45SFlorian Westphal	in=$1
3352de03b45SFlorian Westphal	out=$2
3362de03b45SFlorian Westphal	what=$3
3372de03b45SFlorian Westphal
3382f4bba4eSFabian Frederick	if ! cmp "$in" "$out" > /dev/null 2>&1; then
3392de03b45SFlorian Westphal		echo "FAIL: file mismatch for $what" 1>&2
3402de03b45SFlorian Westphal		ls -l "$in"
3412de03b45SFlorian Westphal		ls -l "$out"
3422de03b45SFlorian Westphal		return 1
3432de03b45SFlorian Westphal	fi
3442de03b45SFlorian Westphal
3452de03b45SFlorian Westphal	return 0
3462de03b45SFlorian Westphal}
3472de03b45SFlorian Westphal
348d05d5db8SFlorian Westphaltest_tcp_forwarding_ip()
3492de03b45SFlorian Westphal{
3502de03b45SFlorian Westphal	local nsa=$1
3512de03b45SFlorian Westphal	local nsb=$2
352d05d5db8SFlorian Westphal	local dstip=$3
353d05d5db8SFlorian Westphal	local dstport=$4
3542de03b45SFlorian Westphal	local lret=0
3552de03b45SFlorian Westphal
356c8550b90SFlorian Westphal	ip netns exec $nsb nc -w 5 -l -p 12345 < "$nsin" > "$ns2out" &
3572de03b45SFlorian Westphal	lpid=$!
3582de03b45SFlorian Westphal
3592de03b45SFlorian Westphal	sleep 1
360c8550b90SFlorian Westphal	ip netns exec $nsa nc -w 4 "$dstip" "$dstport" < "$nsin" > "$ns1out" &
3612de03b45SFlorian Westphal	cpid=$!
3622de03b45SFlorian Westphal
36390ab5122SBoris Sukholitko	sleep 1
36490ab5122SBoris Sukholitko
36590ab5122SBoris Sukholitko	prev="$(ls -l $ns1out $ns2out)"
36690ab5122SBoris Sukholitko	sleep 1
36790ab5122SBoris Sukholitko
36890ab5122SBoris Sukholitko	while [[ "$prev" != "$(ls -l $ns1out $ns2out)" ]]; do
36990ab5122SBoris Sukholitko		sleep 1;
37090ab5122SBoris Sukholitko		prev="$(ls -l $ns1out $ns2out)"
37190ab5122SBoris Sukholitko	done
3722de03b45SFlorian Westphal
3730a11073eSBoris Sukholitko	if test -d /proc/"$lpid"/; then
3742de03b45SFlorian Westphal		kill $lpid
375d8bb9abeSFabian Frederick	fi
376d8bb9abeSFabian Frederick
3770a11073eSBoris Sukholitko	if test -d /proc/"$cpid"/; then
3782de03b45SFlorian Westphal		kill $cpid
379d8bb9abeSFabian Frederick	fi
380d8bb9abeSFabian Frederick
3811114803cSBoris Sukholitko	wait $lpid
3821114803cSBoris Sukholitko	wait $cpid
3832de03b45SFlorian Westphal
384c8550b90SFlorian Westphal	if ! check_transfer "$nsin" "$ns2out" "ns1 -> ns2"; then
3852de03b45SFlorian Westphal		lret=1
3862de03b45SFlorian Westphal	fi
3872de03b45SFlorian Westphal
388c8550b90SFlorian Westphal	if ! check_transfer "$nsin" "$ns1out" "ns1 <- ns2"; then
3892de03b45SFlorian Westphal		lret=1
3902de03b45SFlorian Westphal	fi
3912de03b45SFlorian Westphal
3922de03b45SFlorian Westphal	return $lret
3932de03b45SFlorian Westphal}
3942de03b45SFlorian Westphal
395d05d5db8SFlorian Westphaltest_tcp_forwarding()
396d05d5db8SFlorian Westphal{
397d05d5db8SFlorian Westphal	test_tcp_forwarding_ip "$1" "$2" 10.0.2.99 12345
398d05d5db8SFlorian Westphal
399d05d5db8SFlorian Westphal	return $?
400d05d5db8SFlorian Westphal}
401d05d5db8SFlorian Westphal
402*3acf8f6cSFlorian Westphaltest_tcp_forwarding_set_dscp()
403*3acf8f6cSFlorian Westphal{
404*3acf8f6cSFlorian Westphal	check_dscp "dscp_none"
405*3acf8f6cSFlorian Westphal
406*3acf8f6cSFlorian Westphalip netns exec $nsr1 nft -f - <<EOF
407*3acf8f6cSFlorian Westphaltable netdev dscpmangle {
408*3acf8f6cSFlorian Westphal   chain setdscp0 {
409*3acf8f6cSFlorian Westphal      type filter hook ingress device "veth0" priority 0; policy accept
410*3acf8f6cSFlorian Westphal	ip dscp set cs3
411*3acf8f6cSFlorian Westphal  }
412*3acf8f6cSFlorian Westphal}
413*3acf8f6cSFlorian WestphalEOF
414*3acf8f6cSFlorian Westphalif [ $? -eq 0 ]; then
415*3acf8f6cSFlorian Westphal	test_tcp_forwarding_ip "$1" "$2"  10.0.2.99 12345
416*3acf8f6cSFlorian Westphal	check_dscp "dscp_ingress"
417*3acf8f6cSFlorian Westphal
418*3acf8f6cSFlorian Westphal	ip netns exec $nsr1 nft delete table netdev dscpmangle
419*3acf8f6cSFlorian Westphalelse
420*3acf8f6cSFlorian Westphal	echo "SKIP: Could not load netdev:ingress for veth0"
421*3acf8f6cSFlorian Westphalfi
422*3acf8f6cSFlorian Westphal
423*3acf8f6cSFlorian Westphalip netns exec $nsr1 nft -f - <<EOF
424*3acf8f6cSFlorian Westphaltable netdev dscpmangle {
425*3acf8f6cSFlorian Westphal   chain setdscp0 {
426*3acf8f6cSFlorian Westphal      type filter hook egress device "veth1" priority 0; policy accept
427*3acf8f6cSFlorian Westphal      ip dscp set cs3
428*3acf8f6cSFlorian Westphal  }
429*3acf8f6cSFlorian Westphal}
430*3acf8f6cSFlorian WestphalEOF
431*3acf8f6cSFlorian Westphalif [ $? -eq 0 ]; then
432*3acf8f6cSFlorian Westphal	test_tcp_forwarding_ip "$1" "$2"  10.0.2.99 12345
433*3acf8f6cSFlorian Westphal	check_dscp "dscp_egress"
434*3acf8f6cSFlorian Westphal
435*3acf8f6cSFlorian Westphal	ip netns exec $nsr1 nft flush table netdev dscpmangle
436*3acf8f6cSFlorian Westphalelse
437*3acf8f6cSFlorian Westphal	echo "SKIP: Could not load netdev:egress for veth1"
438*3acf8f6cSFlorian Westphalfi
439*3acf8f6cSFlorian Westphal
440*3acf8f6cSFlorian Westphal	# partial.  If flowtable really works, then both dscp-is-0 and dscp-is-cs3
441*3acf8f6cSFlorian Westphal	# counters should have seen packets (before and after ft offload kicks in).
442*3acf8f6cSFlorian Westphal	ip netns exec $nsr1 nft -a insert rule inet filter forward ip dscp set cs3
443*3acf8f6cSFlorian Westphal	test_tcp_forwarding_ip "$1" "$2"  10.0.2.99 12345
444*3acf8f6cSFlorian Westphal	check_dscp "dscp_fwd"
445*3acf8f6cSFlorian Westphal}
446*3acf8f6cSFlorian Westphal
447d05d5db8SFlorian Westphaltest_tcp_forwarding_nat()
448d05d5db8SFlorian Westphal{
449d05d5db8SFlorian Westphal	local lret
450c8550b90SFlorian Westphal	local pmtu
451d05d5db8SFlorian Westphal
452d05d5db8SFlorian Westphal	test_tcp_forwarding_ip "$1" "$2" 10.0.2.99 12345
453d05d5db8SFlorian Westphal	lret=$?
454d05d5db8SFlorian Westphal
455c8550b90SFlorian Westphal	pmtu=$3
456c8550b90SFlorian Westphal	what=$4
457c8550b90SFlorian Westphal
458d05d5db8SFlorian Westphal	if [ $lret -eq 0 ] ; then
459c8550b90SFlorian Westphal		if [ $pmtu -eq 1 ] ;then
460c8550b90SFlorian Westphal			check_counters "flow offload for ns1/ns2 with masquerade and pmtu discovery $what"
461c8550b90SFlorian Westphal		else
462c8550b90SFlorian Westphal			echo "PASS: flow offload for ns1/ns2 with masquerade $what"
463c8550b90SFlorian Westphal		fi
464c8550b90SFlorian Westphal
465d05d5db8SFlorian Westphal		test_tcp_forwarding_ip "$1" "$2" 10.6.6.6 1666
466d05d5db8SFlorian Westphal		lret=$?
467c8550b90SFlorian Westphal		if [ $pmtu -eq 1 ] ;then
468c8550b90SFlorian Westphal			check_counters "flow offload for ns1/ns2 with dnat and pmtu discovery $what"
469c8550b90SFlorian Westphal		elif [ $lret -eq 0 ] ; then
470c8550b90SFlorian Westphal			echo "PASS: flow offload for ns1/ns2 with dnat $what"
471c8550b90SFlorian Westphal		fi
472d05d5db8SFlorian Westphal	fi
473d05d5db8SFlorian Westphal
474d05d5db8SFlorian Westphal	return $lret
475d05d5db8SFlorian Westphal}
476d05d5db8SFlorian Westphal
477c8550b90SFlorian Westphalmake_file "$nsin"
4782de03b45SFlorian Westphal
4792de03b45SFlorian Westphal# First test:
4802de03b45SFlorian Westphal# No PMTU discovery, nsr1 is expected to fragment packets from ns1 to ns2 as needed.
481c8550b90SFlorian Westphal# Due to MTU mismatch in both directions, all packets (except small packets like pure
482c8550b90SFlorian Westphal# acks) have to be handled by normal forwarding path.  Therefore, packet counters
483c8550b90SFlorian Westphal# are not checked.
484b71b7bfeSFlorian Westphalif test_tcp_forwarding $ns1 $ns2; then
4852de03b45SFlorian Westphal	echo "PASS: flow offloaded for ns1/ns2"
4862de03b45SFlorian Westphalelse
4872de03b45SFlorian Westphal	echo "FAIL: flow offload for ns1/ns2:" 1>&2
488b71b7bfeSFlorian Westphal	ip netns exec $nsr1 nft list ruleset
4892de03b45SFlorian Westphal	ret=1
4902de03b45SFlorian Westphalfi
4912de03b45SFlorian Westphal
4922de03b45SFlorian Westphal# delete default route, i.e. ns2 won't be able to reach ns1 and
4932de03b45SFlorian Westphal# will depend on ns1 being masqueraded in nsr1.
4942de03b45SFlorian Westphal# expect ns1 has nsr1 address.
495b71b7bfeSFlorian Westphalip -net $ns2 route del default via 10.0.2.1
496b71b7bfeSFlorian Westphalip -net $ns2 route del default via dead:2::1
497b71b7bfeSFlorian Westphalip -net $ns2 route add 192.168.10.1 via 10.0.2.1
4982de03b45SFlorian Westphal
4992de03b45SFlorian Westphal# Second test:
500c8550b90SFlorian Westphal# Same, but with NAT enabled.  Same as in first test: we expect normal forward path
501c8550b90SFlorian Westphal# to handle most packets.
502b71b7bfeSFlorian Westphalip netns exec $nsr1 nft -f - <<EOF
5032de03b45SFlorian Westphaltable ip nat {
504d05d5db8SFlorian Westphal   chain prerouting {
505d05d5db8SFlorian Westphal      type nat hook prerouting priority 0; policy accept;
506d05d5db8SFlorian Westphal      meta iif "veth0" ip daddr 10.6.6.6 tcp dport 1666 counter dnat ip to 10.0.2.99:12345
507d05d5db8SFlorian Westphal   }
508d05d5db8SFlorian Westphal
5092de03b45SFlorian Westphal   chain postrouting {
5102de03b45SFlorian Westphal      type nat hook postrouting priority 0; policy accept;
511d05d5db8SFlorian Westphal      meta oifname "veth1" counter masquerade
5122de03b45SFlorian Westphal   }
5132de03b45SFlorian Westphal}
5142de03b45SFlorian WestphalEOF
5152de03b45SFlorian Westphal
516*3acf8f6cSFlorian Westphalif ! test_tcp_forwarding_set_dscp $ns1 $ns2 0 ""; then
517*3acf8f6cSFlorian Westphal	echo "FAIL: flow offload for ns1/ns2 with dscp update" 1>&2
518*3acf8f6cSFlorian Westphal	exit 0
519*3acf8f6cSFlorian Westphalfi
520*3acf8f6cSFlorian Westphal
521c8550b90SFlorian Westphalif ! test_tcp_forwarding_nat $ns1 $ns2 0 ""; then
5222de03b45SFlorian Westphal	echo "FAIL: flow offload for ns1/ns2 with NAT" 1>&2
523b71b7bfeSFlorian Westphal	ip netns exec $nsr1 nft list ruleset
5242de03b45SFlorian Westphal	ret=1
5252de03b45SFlorian Westphalfi
5262de03b45SFlorian Westphal
5272de03b45SFlorian Westphal# Third test:
528c8550b90SFlorian Westphal# Same as second test, but with PMTU discovery enabled. This
529c8550b90SFlorian Westphal# means that we expect the fastpath to handle packets as soon
530c8550b90SFlorian Westphal# as the endpoints adjust the packet size.
531b71b7bfeSFlorian Westphalip netns exec $ns1 sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null
532b71b7bfeSFlorian Westphalip netns exec $ns2 sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null
5332de03b45SFlorian Westphal
534c8550b90SFlorian Westphal# reset counters.
535c8550b90SFlorian Westphal# With pmtu in-place we'll also check that nft counters
536c8550b90SFlorian Westphal# are lower than file size and packets were forwarded via flowtable layer.
537c8550b90SFlorian Westphal# For earlier tests (large mtus), packets cannot be handled via flowtable
538c8550b90SFlorian Westphal# (except pure acks and other small packets).
539c8550b90SFlorian Westphalip netns exec $nsr1 nft reset counters table inet filter >/dev/null
540c8550b90SFlorian Westphal
541c8550b90SFlorian Westphalif ! test_tcp_forwarding_nat $ns1 $ns2 1 ""; then
5422de03b45SFlorian Westphal	echo "FAIL: flow offload for ns1/ns2 with NAT and pmtu discovery" 1>&2
543b71b7bfeSFlorian Westphal	ip netns exec $nsr1 nft list ruleset
5442de03b45SFlorian Westphalfi
5452de03b45SFlorian Westphal
54679d4071eSPablo Neira Ayuso# Another test:
54779d4071eSPablo Neira Ayuso# Add bridge interface br0 to Router1, with NAT enabled.
548b71b7bfeSFlorian Westphalip -net $nsr1 link add name br0 type bridge
549b71b7bfeSFlorian Westphalip -net $nsr1 addr flush dev veth0
550b71b7bfeSFlorian Westphalip -net $nsr1 link set up dev veth0
551b71b7bfeSFlorian Westphalip -net $nsr1 link set veth0 master br0
552b71b7bfeSFlorian Westphalip -net $nsr1 addr add 10.0.1.1/24 dev br0
553b71b7bfeSFlorian Westphalip -net $nsr1 addr add dead:1::1/64 dev br0
554b71b7bfeSFlorian Westphalip -net $nsr1 link set up dev br0
55579d4071eSPablo Neira Ayuso
556b71b7bfeSFlorian Westphalip netns exec $nsr1 sysctl net.ipv4.conf.br0.forwarding=1 > /dev/null
55779d4071eSPablo Neira Ayuso
55879d4071eSPablo Neira Ayuso# br0 with NAT enabled.
559b71b7bfeSFlorian Westphalip netns exec $nsr1 nft -f - <<EOF
56079d4071eSPablo Neira Ayusoflush table ip nat
56179d4071eSPablo Neira Ayusotable ip nat {
56279d4071eSPablo Neira Ayuso   chain prerouting {
56379d4071eSPablo Neira Ayuso      type nat hook prerouting priority 0; policy accept;
56479d4071eSPablo Neira Ayuso      meta iif "br0" ip daddr 10.6.6.6 tcp dport 1666 counter dnat ip to 10.0.2.99:12345
56579d4071eSPablo Neira Ayuso   }
56679d4071eSPablo Neira Ayuso
56779d4071eSPablo Neira Ayuso   chain postrouting {
56879d4071eSPablo Neira Ayuso      type nat hook postrouting priority 0; policy accept;
56979d4071eSPablo Neira Ayuso      meta oifname "veth1" counter masquerade
57079d4071eSPablo Neira Ayuso   }
57179d4071eSPablo Neira Ayuso}
57279d4071eSPablo Neira AyusoEOF
57379d4071eSPablo Neira Ayuso
574c8550b90SFlorian Westphalif ! test_tcp_forwarding_nat $ns1 $ns2 1 "on bridge"; then
57579d4071eSPablo Neira Ayuso	echo "FAIL: flow offload for ns1/ns2 with bridge NAT" 1>&2
576b71b7bfeSFlorian Westphal	ip netns exec $nsr1 nft list ruleset
57779d4071eSPablo Neira Ayuso	ret=1
57879d4071eSPablo Neira Ayusofi
57979d4071eSPablo Neira Ayuso
580c8550b90SFlorian Westphal
58179d4071eSPablo Neira Ayuso# Another test:
58279d4071eSPablo Neira Ayuso# Add bridge interface br0 to Router1, with NAT and VLAN.
583b71b7bfeSFlorian Westphalip -net $nsr1 link set veth0 nomaster
584b71b7bfeSFlorian Westphalip -net $nsr1 link set down dev veth0
585b71b7bfeSFlorian Westphalip -net $nsr1 link add link veth0 name veth0.10 type vlan id 10
586b71b7bfeSFlorian Westphalip -net $nsr1 link set up dev veth0
587b71b7bfeSFlorian Westphalip -net $nsr1 link set up dev veth0.10
588b71b7bfeSFlorian Westphalip -net $nsr1 link set veth0.10 master br0
58979d4071eSPablo Neira Ayuso
590b71b7bfeSFlorian Westphalip -net $ns1 addr flush dev eth0
591b71b7bfeSFlorian Westphalip -net $ns1 link add link eth0 name eth0.10 type vlan id 10
592b71b7bfeSFlorian Westphalip -net $ns1 link set eth0 up
593b71b7bfeSFlorian Westphalip -net $ns1 link set eth0.10 up
594b71b7bfeSFlorian Westphalip -net $ns1 addr add 10.0.1.99/24 dev eth0.10
595b71b7bfeSFlorian Westphalip -net $ns1 route add default via 10.0.1.1
596b71b7bfeSFlorian Westphalip -net $ns1 addr add dead:1::99/64 dev eth0.10
59779d4071eSPablo Neira Ayuso
598c8550b90SFlorian Westphalif ! test_tcp_forwarding_nat $ns1 $ns2 1 "bridge and VLAN"; then
59979d4071eSPablo Neira Ayuso	echo "FAIL: flow offload for ns1/ns2 with bridge NAT and VLAN" 1>&2
600b71b7bfeSFlorian Westphal	ip netns exec $nsr1 nft list ruleset
60179d4071eSPablo Neira Ayuso	ret=1
60279d4071eSPablo Neira Ayusofi
60379d4071eSPablo Neira Ayuso
60479d4071eSPablo Neira Ayuso# restore test topology (remove bridge and VLAN)
605b71b7bfeSFlorian Westphalip -net $nsr1 link set veth0 nomaster
606b71b7bfeSFlorian Westphalip -net $nsr1 link set veth0 down
607b71b7bfeSFlorian Westphalip -net $nsr1 link set veth0.10 down
608b71b7bfeSFlorian Westphalip -net $nsr1 link delete veth0.10 type vlan
609b71b7bfeSFlorian Westphalip -net $nsr1 link delete br0 type bridge
610b71b7bfeSFlorian Westphalip -net $ns1 addr flush dev eth0.10
611b71b7bfeSFlorian Westphalip -net $ns1 link set eth0.10 down
612b71b7bfeSFlorian Westphalip -net $ns1 link set eth0 down
613b71b7bfeSFlorian Westphalip -net $ns1 link delete eth0.10 type vlan
61479d4071eSPablo Neira Ayuso
61579d4071eSPablo Neira Ayuso# restore address in ns1 and nsr1
616b71b7bfeSFlorian Westphalip -net $ns1 link set eth0 up
617b71b7bfeSFlorian Westphalip -net $ns1 addr add 10.0.1.99/24 dev eth0
618b71b7bfeSFlorian Westphalip -net $ns1 route add default via 10.0.1.1
619b71b7bfeSFlorian Westphalip -net $ns1 addr add dead:1::99/64 dev eth0
620b71b7bfeSFlorian Westphalip -net $ns1 route add default via dead:1::1
621b71b7bfeSFlorian Westphalip -net $nsr1 addr add 10.0.1.1/24 dev veth0
622b71b7bfeSFlorian Westphalip -net $nsr1 addr add dead:1::1/64 dev veth0
623b71b7bfeSFlorian Westphalip -net $nsr1 link set up dev veth0
62479d4071eSPablo Neira Ayuso
6250749d670SBoris SukholitkoKEY_SHA="0x"$(ps -af | sha1sum | cut -d " " -f 1)
6260749d670SBoris SukholitkoKEY_AES="0x"$(ps -af | md5sum | cut -d " " -f 1)
6270ca1bbb7SFlorian WestphalSPI1=$RANDOM
6280ca1bbb7SFlorian WestphalSPI2=$RANDOM
6290ca1bbb7SFlorian Westphal
6300ca1bbb7SFlorian Westphalif [ $SPI1 -eq $SPI2 ]; then
6310ca1bbb7SFlorian Westphal	SPI2=$((SPI2+1))
6320ca1bbb7SFlorian Westphalfi
6330ca1bbb7SFlorian Westphal
6340ca1bbb7SFlorian Westphaldo_esp() {
6350ca1bbb7SFlorian Westphal    local ns=$1
6360ca1bbb7SFlorian Westphal    local me=$2
6370ca1bbb7SFlorian Westphal    local remote=$3
6380ca1bbb7SFlorian Westphal    local lnet=$4
6390ca1bbb7SFlorian Westphal    local rnet=$5
6400ca1bbb7SFlorian Westphal    local spi_out=$6
6410ca1bbb7SFlorian Westphal    local spi_in=$7
6420ca1bbb7SFlorian Westphal
6430ca1bbb7SFlorian Westphal    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
6440ca1bbb7SFlorian Westphal    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
6450ca1bbb7SFlorian Westphal
6460ca1bbb7SFlorian Westphal    # to encrypt packets as they go out (includes forwarded packets that need encapsulation)
6470ca1bbb7SFlorian Westphal    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
6480ca1bbb7SFlorian Westphal    # to fwd decrypted packets after esp processing:
6490ca1bbb7SFlorian Westphal    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
6500ca1bbb7SFlorian Westphal
6510ca1bbb7SFlorian Westphal}
6520ca1bbb7SFlorian Westphal
653b71b7bfeSFlorian Westphaldo_esp $nsr1 192.168.10.1 192.168.10.2 10.0.1.0/24 10.0.2.0/24 $SPI1 $SPI2
6540ca1bbb7SFlorian Westphal
655b71b7bfeSFlorian Westphaldo_esp $nsr2 192.168.10.2 192.168.10.1 10.0.2.0/24 10.0.1.0/24 $SPI2 $SPI1
6560ca1bbb7SFlorian Westphal
657b71b7bfeSFlorian Westphalip netns exec $nsr1 nft delete table ip nat
6580ca1bbb7SFlorian Westphal
6590ca1bbb7SFlorian Westphal# restore default routes
660b71b7bfeSFlorian Westphalip -net $ns2 route del 192.168.10.1 via 10.0.2.1
661b71b7bfeSFlorian Westphalip -net $ns2 route add default via 10.0.2.1
662b71b7bfeSFlorian Westphalip -net $ns2 route add default via dead:2::1
6630ca1bbb7SFlorian Westphal
664b71b7bfeSFlorian Westphalif test_tcp_forwarding $ns1 $ns2; then
665c8550b90SFlorian Westphal	check_counters "ipsec tunnel mode for ns1/ns2"
6660ca1bbb7SFlorian Westphalelse
6670ca1bbb7SFlorian Westphal	echo "FAIL: ipsec tunnel mode for ns1/ns2"
668b71b7bfeSFlorian Westphal	ip netns exec $nsr1 nft list ruleset 1>&2
669b71b7bfeSFlorian Westphal	ip netns exec $nsr1 cat /proc/net/xfrm_stat 1>&2
6700ca1bbb7SFlorian Westphalfi
6710ca1bbb7SFlorian Westphal
6722de03b45SFlorian Westphalexit $ret
673