xref: /linux/tools/testing/selftests/net/big_tcp_tunnels.sh (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1#!/usr/bin/env bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Testing for IPv4 and IPv6 BIG TCP over VXLAN and GENEVE tunnels.
5
6SERVER_NS=$(mktemp -u server-XXXXXXXX)
7SERVER_IP4="192.168.1.1"
8SERVER_IP6="2001:db8::1:1"
9SERVER_IP4_TUN="192.168.2.1"
10SERVER_IP6_TUN="2001:db8::2:1"
11
12CLIENT_NS=$(mktemp -u client-XXXXXXXX)
13CLIENT_IP4="192.168.1.2"
14CLIENT_IP6="2001:db8::1:2"
15CLIENT_IP4_TUN="192.168.2.2"
16CLIENT_IP6_TUN="2001:db8::2:2"
17
18: "${PACKETS_THRESHOLD:=1000}"
19
20# Kselftest framework requirement - SKIP code is 4.
21ksft_skip=4
22
23setup() {
24	ip netns add "$SERVER_NS"
25	ip netns add "$CLIENT_NS"
26	ip -netns "$SERVER_NS" link add link1 type veth peer name link0 netns "$CLIENT_NS"
27
28	ip -netns "$CLIENT_NS" link set link0 up
29	ip -netns "$CLIENT_NS" addr replace "$CLIENT_IP4/24" dev link0
30	ip -netns "$CLIENT_NS" addr replace "$CLIENT_IP6/112" dev link0 nodad
31	ip -netns "$CLIENT_NS" link set link0 \
32		gso_max_size 196608 gso_ipv4_max_size 196608 \
33		gro_max_size 196608 gro_ipv4_max_size 196608
34	ip -netns "$SERVER_NS" link set link1 up
35	ip -netns "$SERVER_NS" addr replace "$SERVER_IP4/24" dev link1
36	ip -netns "$SERVER_NS" addr replace "$SERVER_IP6/112" dev link1 nodad
37	ip -netns "$SERVER_NS" link set link1 \
38		gso_max_size 196608 gso_ipv4_max_size 196608 \
39		gro_max_size 196608 gro_ipv4_max_size 196608
40
41	ip netns exec "$SERVER_NS" netserver >/dev/null
42}
43
44setup_tunnel() {
45	if [ "$2" = 4 ]; then
46		SERVER_IP="$SERVER_IP4"
47		CLIENT_IP="$CLIENT_IP4"
48		echo "Setting up ${1^^} over IPv4, veth tx csum offload $3"
49	else
50		SERVER_IP="$SERVER_IP6"
51		CLIENT_IP="$CLIENT_IP6"
52		echo "Setting up ${1^^} over IPv6, veth tx csum offload $3"
53	fi
54
55	if [ "$1" = vxlan ]; then
56		ip -netns "$CLIENT_NS" link add tun0 type vxlan \
57			id 5001 remote "$SERVER_IP" local "$CLIENT_IP" dev link0 dstport 4789
58	else
59		ip -netns "$CLIENT_NS" link add tun0 type geneve \
60			id 5001 remote "$SERVER_IP"
61	fi
62	ip -netns "$CLIENT_NS" link set tun0 up
63	ip -netns "$CLIENT_NS" addr replace "$CLIENT_IP4_TUN/24" dev tun0
64	ip -netns "$CLIENT_NS" addr replace "$CLIENT_IP6_TUN/112" dev tun0 nodad
65	ip -netns "$CLIENT_NS" link set tun0 \
66		gso_max_size 196608 gso_ipv4_max_size 196608 \
67		gro_max_size 196608 gro_ipv4_max_size 196608
68	if [ "$1" = vxlan ]; then
69		ip -netns "$SERVER_NS" link add tun1 type vxlan \
70			id 5001 remote "$CLIENT_IP" local "$SERVER_IP" dev link1 dstport 4789
71	else
72		ip -netns "$SERVER_NS" link add tun1 type geneve \
73			id 5001 remote "$CLIENT_IP"
74	fi
75	ip -netns "$SERVER_NS" link set tun1 up
76	ip -netns "$SERVER_NS" addr replace "$SERVER_IP4_TUN/24" dev tun1
77	ip -netns "$SERVER_NS" addr replace "$SERVER_IP6_TUN/112" dev tun1 nodad
78	ip -netns "$SERVER_NS" link set tun1 \
79		gso_max_size 196608 gso_ipv4_max_size 196608 \
80		gro_max_size 196608 gro_ipv4_max_size 196608
81
82	ip netns exec "$CLIENT_NS" ethtool -K link0 tx-checksumming "$3" > /dev/null
83	ip netns exec "$SERVER_NS" ethtool -K link1 tx-checksumming "$3" > /dev/null
84}
85
86cleanup_tunnel() {
87	ip -netns "$CLIENT_NS" link del tun0
88	ip -netns "$SERVER_NS" link del tun1
89}
90
91cleanup() {
92	ip netns pids "$SERVER_NS" | xargs -r kill
93	ip netns pids "$CLIENT_NS" | xargs -r kill
94	ip netns del "$SERVER_NS"
95	ip netns del "$CLIENT_NS"
96	rm -rf "$WORKDIR"
97}
98
99do_test() {
100	# When tx csum offload is off, software GSO is performed before passing the
101	# packet to veth. Check BIG TCP packets inside the VXLAN tunnel to verify
102	# the software checksum path: if the checksum code is broken, these packets
103	# will be dropped.
104	if [ "$3" = on ]; then
105		CAPTURE_IFACE='link'
106		if [ "$1" = 4 ]; then
107			IPTABLES=iptables
108		else
109			IPTABLES=ip6tables
110		fi
111	else
112		CAPTURE_IFACE='tun'
113		if [ "$2" = 4 ]; then
114			IPTABLES=iptables
115		else
116			IPTABLES=ip6tables
117		fi
118	fi
119	if [ "$2" = 4 ]; then
120		IPTABLES_SACK=iptables
121	else
122		IPTABLES_SACK=ip6tables
123	fi
124
125	ip netns exec "$SERVER_NS" "$IPTABLES" -w -t raw -I PREROUTING -i "${CAPTURE_IFACE}1" -m length ! --length 0:65535 -m comment --comment "bigtcp"
126	ip netns exec "$CLIENT_NS" "$IPTABLES" -w -t raw -I OUTPUT -o "${CAPTURE_IFACE}0" -m length ! --length 0:65535 -m comment --comment "bigtcp"
127	ip netns exec "$SERVER_NS" "$IPTABLES_SACK" -w -t raw -I OUTPUT -o "tun1" -p tcp -m tcp --tcp-flags ACK ACK --tcp-option 5 -m comment --comment "sack"
128
129	if [ "$2" = 4 ]; then
130		SERVER_IP="$SERVER_IP4_TUN"
131		echo "Running IPv4 traffic in the tunnel"
132	else
133		SERVER_IP="$SERVER_IP6_TUN"
134		echo "Running IPv6 traffic in the tunnel"
135	fi
136
137	ip netns exec "$CLIENT_NS" netperf -t TCP_STREAM -l 5 -H "$SERVER_IP" -- \
138		-m 80000 > /dev/null
139
140	PACKETS_SERVER=$(ip netns exec "$SERVER_NS" "$IPTABLES-save" -c -t raw | sed -rn '/ --comment bigtcp/{s/^\[([0-9]+):.*/\1/p;q}')
141	PACKETS_CLIENT=$(ip netns exec "$CLIENT_NS" "$IPTABLES-save" -c -t raw | sed -rn '/ --comment bigtcp/{s/^\[([0-9]+):.*/\1/p;q}')
142	PACKETS_SACK=$(ip netns exec "$SERVER_NS" "$IPTABLES_SACK-save" -c -t raw | sed -rn '/ --comment sack/{s/^\[([0-9]+):.*/\1/p;q}')
143	ip netns exec "$SERVER_NS" "$IPTABLES" -w -t raw -D PREROUTING -i "${CAPTURE_IFACE}1" -m length ! --length 0:65535 -m comment --comment "bigtcp"
144	ip netns exec "$CLIENT_NS" "$IPTABLES" -w -t raw -D OUTPUT -o "${CAPTURE_IFACE}0" -m length ! --length 0:65535 -m comment --comment "bigtcp"
145	ip netns exec "$SERVER_NS" "$IPTABLES_SACK" -w -t raw -D OUTPUT -o "tun1" -p tcp -m tcp --tcp-flags ACK ACK --tcp-option 5 -m comment --comment "sack"
146
147	echo "Captured BIG TCP RX packets: $PACKETS_SERVER"
148	echo "Captured BIG TCP TX packets: $PACKETS_CLIENT"
149	echo "Captured TCP SACK packets: $PACKETS_SACK"
150	[ "$PACKETS_SERVER" -gt "$PACKETS_THRESHOLD" ] || return 1
151	[ "$PACKETS_CLIENT" -gt "$PACKETS_THRESHOLD" ] || return 1
152	[ "$PACKETS_SACK" -lt "$(( PACKETS_CLIENT / 2 ))" ] || return 1
153}
154
155if ! netperf -V &> /dev/null; then
156	echo "SKIP: Could not run test without netperf tool"
157	exit "$ksft_skip"
158fi
159
160if ! iptables --version &> /dev/null; then
161	echo "SKIP: Could not run test without iptables tool"
162	exit "$ksft_skip"
163fi
164
165if ! ethtool --version &> /dev/null; then
166	echo "SKIP: Could not run test without ethtool tool"
167	exit "$ksft_skip"
168fi
169
170if ! ip link help 2>&1 | grep gso_ipv4_max_size &> /dev/null; then
171	echo "SKIP: Could not run test without gso/gro_ipv4_max_size supported in ip-link"
172	exit "$ksft_skip"
173fi
174
175WORKDIR=$(mktemp -d)
176trap cleanup EXIT
177setup
178for tunnel in vxlan geneve; do
179	for tun_family in 4 6; do
180		for traffic_family in 4 6; do
181			for csum_offload in on off; do
182				setup_tunnel "$tunnel" "$tun_family" "$csum_offload" || exit "$?"
183				do_test "$tun_family" "$traffic_family" "$csum_offload" || exit "$?"
184				cleanup_tunnel
185			done
186		done
187	done
188done
189