xref: /linux/tools/testing/selftests/net/udpgro.sh (revision aa0743a229366e8c1963f1b72a1c974a9d15f08f)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Run a series of udpgro functional tests.
5
6source net_helper.sh
7
8readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)"
9
10# set global exit status, but never reset nonzero one.
11check_err()
12{
13	if [ $ret -eq 0 ]; then
14		ret=$1
15	fi
16}
17
18cleanup() {
19	local -r jobs="$(jobs -p)"
20	local -r ns="$(ip netns list|grep $PEER_NS)"
21
22	[ -n "${jobs}" ] && kill -1 ${jobs} 2>/dev/null
23	[ -n "$ns" ] && ip netns del $ns 2>/dev/null
24}
25trap cleanup EXIT
26
27cfg_veth() {
28	ip netns add "${PEER_NS}"
29	ip -netns "${PEER_NS}" link set lo up
30	ip link add type veth
31	ip link set dev veth0 up
32	ip addr add dev veth0 192.168.1.2/24
33	ip addr add dev veth0 2001:db8::2/64 nodad
34
35	ip link set dev veth1 netns "${PEER_NS}"
36	ip -netns "${PEER_NS}" addr add dev veth1 192.168.1.1/24
37	ip -netns "${PEER_NS}" addr add dev veth1 2001:db8::1/64 nodad
38	ip -netns "${PEER_NS}" link set dev veth1 up
39	ip netns exec "${PEER_NS}" ethtool -K veth1 gro on
40}
41
42run_one() {
43	# use 'rx' as separator between sender args and receiver args
44	local -r all="$@"
45	local -r tx_args=${all%rx*}
46	local -r rx_args=${all#*rx}
47	local ret=0
48
49	cfg_veth
50
51	ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} &
52	local PID1=$!
53
54	wait_local_port_listen ${PEER_NS} 8000 udp
55	./udpgso_bench_tx ${tx_args}
56	check_err $?
57	wait ${PID1}
58	check_err $?
59	[ "$ret" -eq 0 ] && echo "ok" || echo "failed"
60	return $ret
61}
62
63run_test() {
64	local -r args=$@
65
66	printf " %-40s" "$1"
67	./in_netns.sh $0 __subprocess $2 rx -G -r $3
68}
69
70run_one_nat() {
71	# use 'rx' as separator between sender args and receiver args
72	local addr1 addr2 pid family="" ipt_cmd=ip6tables
73	local -r all="$@"
74	local -r tx_args=${all%rx*}
75	local -r rx_args=${all#*rx}
76	local ret=0
77
78	if [[ ${tx_args} = *-4* ]]; then
79		ipt_cmd=iptables
80		family=-4
81		addr1=192.168.1.1
82		addr2=192.168.1.3/24
83	else
84		addr1=2001:db8::1
85		addr2="2001:db8::3/64 nodad"
86	fi
87
88	cfg_veth
89	ip -netns "${PEER_NS}" addr add dev veth1 ${addr2}
90
91	# fool the GRO engine changing the destination address ...
92	ip netns exec "${PEER_NS}" $ipt_cmd -t nat -I PREROUTING -d ${addr1} -j DNAT --to-destination ${addr2%/*}
93
94	# ... so that GRO will match the UDP_GRO enabled socket, but packets
95	# will land on the 'plain' one
96	ip netns exec "${PEER_NS}" ./udpgso_bench_rx -G ${family} -b ${addr1} -n 0 &
97	local PID1=$!
98	ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${family} -b ${addr2%/*} ${rx_args} &
99	local PID2=$!
100
101	wait_local_port_listen "${PEER_NS}" 8000 udp
102	./udpgso_bench_tx ${tx_args}
103	check_err $?
104	kill -INT ${PID1}
105	wait ${PID2}
106	check_err $?
107	[ "$ret" -eq 0 ] && echo "ok" || echo "failed"
108	return $ret
109}
110
111run_one_2sock() {
112	# use 'rx' as separator between sender args and receiver args
113	local -r all="$@"
114	local -r tx_args=${all%rx*}
115	local -r rx_args=${all#*rx}
116	local ret=0
117
118	cfg_veth
119
120	ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} -p 12345 &
121	local PID1=$!
122	ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 2000 -R 10 ${rx_args} &
123	local PID2=$!
124
125	wait_local_port_listen "${PEER_NS}" 12345 udp
126	./udpgso_bench_tx ${tx_args} -p 12345
127	check_err $?
128	wait_local_port_listen "${PEER_NS}" 8000 udp
129	./udpgso_bench_tx ${tx_args}
130	check_err $?
131	wait ${PID1}
132	check_err $?
133	wait ${PID2}
134	check_err $?
135	[ "$ret" -eq 0 ] && echo "ok" || echo "failed"
136	return $ret
137}
138
139run_nat_test() {
140	local -r args=$@
141
142	printf " %-40s" "$1"
143	./in_netns.sh $0 __subprocess_nat $2 rx -r $3
144}
145
146run_2sock_test() {
147	local -r args=$@
148
149	printf " %-40s" "$1"
150	./in_netns.sh $0 __subprocess_2sock $2 rx -G -r $3
151}
152
153run_all() {
154	local -r core_args="-l 4"
155	local -r ipv4_args="${core_args} -4 -D 192.168.1.1"
156	local -r ipv6_args="${core_args} -6 -D 2001:db8::1"
157	ret=0
158
159	echo "ipv4"
160	run_test "no GRO" "${ipv4_args} -M 10 -s 1400" "-4 -n 10 -l 1400"
161	check_err $?
162
163	# explicitly check we are not receiving UDP_SEGMENT cmsg (-S -1)
164	# when GRO does not take place
165	run_test "no GRO chk cmsg" "${ipv4_args} -M 10 -s 1400" "-4 -n 10 -l 1400 -S -1"
166	check_err $?
167
168	# the GSO packets are aggregated because:
169	# * veth schedule napi after each xmit
170	# * segmentation happens in BH context, veth napi poll is delayed after
171	#   the transmission of the last segment
172	run_test "GRO" "${ipv4_args} -M 1 -s 14720 -S 0 " "-4 -n 1 -l 14720"
173	check_err $?
174	run_test "GRO chk cmsg" "${ipv4_args} -M 1 -s 14720 -S 0 " "-4 -n 1 -l 14720 -S 1472"
175	check_err $?
176	run_test "GRO with custom segment size" "${ipv4_args} -M 1 -s 14720 -S 500 " "-4 -n 1 -l 14720"
177	check_err $?
178	run_test "GRO with custom segment size cmsg" "${ipv4_args} -M 1 -s 14720 -S 500 " "-4 -n 1 -l 14720 -S 500"
179	check_err $?
180
181	run_nat_test "bad GRO lookup" "${ipv4_args} -M 1 -s 14720 -S 0" "-n 10 -l 1472"
182	check_err $?
183	run_2sock_test "multiple GRO socks" "${ipv4_args} -M 1 -s 14720 -S 0 " "-4 -n 1 -l 14720 -S 1472"
184	check_err $?
185
186	echo "ipv6"
187	run_test "no GRO" "${ipv6_args} -M 10 -s 1400" "-n 10 -l 1400"
188	check_err $?
189	run_test "no GRO chk cmsg" "${ipv6_args} -M 10 -s 1400" "-n 10 -l 1400 -S -1"
190	check_err $?
191	run_test "GRO" "${ipv6_args} -M 1 -s 14520 -S 0" "-n 1 -l 14520"
192	check_err $?
193	run_test "GRO chk cmsg" "${ipv6_args} -M 1 -s 14520 -S 0" "-n 1 -l 14520 -S 1452"
194	check_err $?
195	run_test "GRO with custom segment size" "${ipv6_args} -M 1 -s 14520 -S 500" "-n 1 -l 14520"
196	check_err $?
197	run_test "GRO with custom segment size cmsg" "${ipv6_args} -M 1 -s 14520 -S 500" "-n 1 -l 14520 -S 500"
198	check_err $?
199
200	run_nat_test "bad GRO lookup" "${ipv6_args} -M 1 -s 14520 -S 0" "-n 10 -l 1452"
201	check_err $?
202	run_2sock_test "multiple GRO socks" "${ipv6_args} -M 1 -s 14520 -S 0 " "-n 1 -l 14520 -S 1452"
203	check_err $?
204	return $ret
205}
206
207if [[ $# -eq 0 ]]; then
208	run_all
209elif [[ $1 == "__subprocess" ]]; then
210	shift
211	run_one $@
212elif [[ $1 == "__subprocess_nat" ]]; then
213	shift
214	run_one_nat $@
215elif [[ $1 == "__subprocess_2sock" ]]; then
216	shift
217	run_one_2sock $@
218fi
219
220exit $?
221