summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/net/veth.sh
blob: 430895d1a2b63e2748fc6a4f776051f79d13cdde (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0

readonly STATS="$(mktemp -p /tmp ns-XXXXXX)"
readonly BASE=`basename $STATS`
readonly SRC=2
readonly DST=1
readonly DST_NAT=100
readonly NS_SRC=$BASE$SRC
readonly NS_DST=$BASE$DST

# "baremetal" network used for raw UDP traffic
readonly BM_NET_V4=192.168.1.
readonly BM_NET_V6=2001:db8::

readonly CPUS=`nproc`
ret=0

cleanup() {
	local ns
	local jobs
	readonly jobs="$(jobs -p)"
	[ -n "${jobs}" ] && kill -1 ${jobs} 2>/dev/null
	rm -f $STATS

	for ns in $NS_SRC $NS_DST; do
		ip netns del $ns 2>/dev/null
	done
}

trap cleanup EXIT

create_ns() {
	local ns

	for ns in $NS_SRC $NS_DST; do
		ip netns add $ns
		ip -n $ns link set dev lo up
	done

	ip link add name veth$SRC type veth peer name veth$DST

	for ns in $SRC $DST; do
		ip link set dev veth$ns netns $BASE$ns up
		ip -n $BASE$ns addr add dev veth$ns $BM_NET_V4$ns/24
		ip -n $BASE$ns addr add dev veth$ns $BM_NET_V6$ns/64 nodad
	done
	echo "#kernel" > $BASE
	chmod go-rw $BASE
}

__chk_flag() {
	local msg="$1"
	local target=$2
	local expected=$3
	local flagname=$4

	local flag=`ip netns exec $BASE$target ethtool -k veth$target |\
		    grep $flagname | awk '{print $2}'`

	printf "%-60s" "$msg"
	if [ "$flag" = "$expected" ]; then
		echo " ok "
	else
		echo " fail - expected $expected found $flag"
		ret=1
	fi
}

chk_gro_flag() {
	__chk_flag "$1" $2 $3 generic-receive-offload
}

chk_tso_flag() {
	__chk_flag "$1" $2 $3 tcp-segmentation-offload
}

chk_channels() {
	local msg="$1"
	local target=$2
	local rx=$3
	local tx=$4

	local dev=veth$target

	local cur_rx=`ip netns exec $BASE$target ethtool -l $dev |\
		grep RX: | tail -n 1 | awk '{print $2}' `
		local cur_tx=`ip netns exec $BASE$target ethtool -l $dev |\
		grep TX: | tail -n 1 | awk '{print $2}'`
	local cur_combined=`ip netns exec $BASE$target ethtool -l $dev |\
		grep Combined: | tail -n 1 | awk '{print $2}'`

	printf "%-60s" "$msg"
	if [ "$cur_rx" = "$rx" -a "$cur_tx" = "$tx" -a "$cur_combined" = "n/a" ]; then
		echo " ok "
	else
		echo " fail rx:$rx:$cur_rx tx:$tx:$cur_tx combined:n/a:$cur_combined"
	fi
}

chk_gro() {
	local msg="$1"
	local expected=$2

	ip netns exec $BASE$SRC ping -qc 1 $BM_NET_V4$DST >/dev/null
	NSTAT_HISTORY=$STATS ip netns exec $NS_DST nstat -n

	printf "%-60s" "$msg"
	ip netns exec $BASE$DST ./udpgso_bench_rx -C 1000 -R 10 &
	local spid=$!
	sleep 0.1

	ip netns exec $NS_SRC ./udpgso_bench_tx -4 -s 13000 -S 1300 -M 1 -D $BM_NET_V4$DST
	local retc=$?
	wait $spid
	local rets=$?
	if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ]; then
		echo " fail client exit code $retc, server $rets"
		ret=1
		return
	fi

	local pkts=`NSTAT_HISTORY=$STATS ip netns exec $NS_DST nstat IpInReceives | \
		    awk '{print $2}' | tail -n 1`
	if [ "$pkts" = "$expected" ]; then
		echo " ok "
	else
		echo " fail - got $pkts packets, expected $expected "
		ret=1
	fi
}

__change_channels()
{
	local cur_cpu
	local end=$1
	local cur
	local i

	while true; do
		printf -v cur '%(%s)T'
		[ $cur -le $end ] || break

		for i in `seq 1 $CPUS`; do
			ip netns exec $NS_SRC ethtool -L veth$SRC rx $i tx $i
			ip netns exec $NS_DST ethtool -L veth$DST rx $i tx $i
		done

		for i in `seq 1 $((CPUS - 1))`; do
			cur_cpu=$((CPUS - $i))
			ip netns exec $NS_SRC ethtool -L veth$SRC rx $cur_cpu tx $cur_cpu
			ip netns exec $NS_DST ethtool -L veth$DST rx $cur_cpu tx $cur_cpu
		done
	done
}

__send_data() {
	local end=$1

	while true; do
		printf -v cur '%(%s)T'
		[ $cur -le $end ] || break

		ip netns exec $NS_SRC ./udpgso_bench_tx -4 -s 1000 -M 300 -D $BM_NET_V4$DST
	done
}

do_stress() {
	local end
	printf -v end '%(%s)T'
	end=$((end + $STRESS))

	ip netns exec $NS_SRC ethtool -L veth$SRC rx 3 tx 3
	ip netns exec $NS_DST ethtool -L veth$DST rx 3 tx 3

	ip netns exec $NS_DST ./udpgso_bench_rx &
	local rx_pid=$!

	echo "Running stress test for $STRESS seconds..."
	__change_channels $end &
	local ch_pid=$!
	__send_data $end &
	local data_pid_1=$!
	__send_data $end &
	local data_pid_2=$!
	__send_data $end &
	local data_pid_3=$!
	__send_data $end &
	local data_pid_4=$!

	wait $ch_pid $data_pid_1 $data_pid_2 $data_pid_3 $data_pid_4
	kill -9 $rx_pid
	echo "done"

	# restore previous setting
	ip netns exec $NS_SRC ethtool -L veth$SRC rx 2 tx 2
	ip netns exec $NS_DST ethtool -L veth$DST rx 2 tx 1
}

usage() {
	echo "Usage: $0 [-h] [-s <seconds>]"
	echo -e "\t-h: show this help"
	echo -e "\t-s: run optional stress tests for the given amount of seconds"
}

STRESS=0
while getopts "hs:" option; do
	case "$option" in
	"h")
		usage $0
		exit 0
		;;
	"s")
		STRESS=$OPTARG
		;;
	esac
done

if [ ! -f ../bpf/xdp_dummy.o ]; then
	echo "Missing xdp_dummy helper. Build bpf selftest first"
	exit 1
fi

[ $CPUS -lt 2 ] && echo "Only one CPU available, some tests will be skipped"
[ $STRESS -gt 0 -a $CPUS -lt 3 ] && echo " stress test will be skipped, too"

create_ns
chk_gro_flag "default - gro flag" $SRC off
chk_gro_flag "        - peer gro flag" $DST off
chk_tso_flag "        - tso flag" $SRC on
chk_tso_flag "        - peer tso flag" $DST on
chk_gro "        - aggregation" 1
ip netns exec $NS_SRC ethtool -K veth$SRC tx-udp-segmentation off
chk_gro "        - aggregation with TSO off" 10
cleanup

create_ns
ip netns exec $NS_DST ethtool -K veth$DST gro on
chk_gro_flag "with gro on - gro flag" $DST on
chk_gro_flag "        - peer gro flag" $SRC off
chk_tso_flag "        - tso flag" $SRC on
chk_tso_flag "        - peer tso flag" $DST on
ip netns exec $NS_SRC ethtool -K veth$SRC tx-udp-segmentation off
ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on
chk_gro "        - aggregation with TSO off" 1
cleanup

create_ns
chk_channels "default channels" $DST 1 1

ip -n $NS_DST link set dev veth$DST down
ip netns exec $NS_DST ethtool -K veth$DST gro on
chk_gro_flag "with gro enabled on link down - gro flag" $DST on
chk_gro_flag "        - peer gro flag" $SRC off
chk_tso_flag "        - tso flag" $SRC on
chk_tso_flag "        - peer tso flag" $DST on
ip -n $NS_DST link set dev veth$DST up
ip netns exec $NS_SRC ethtool -K veth$SRC tx-udp-segmentation off
ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on
chk_gro "        - aggregation with TSO off" 1
cleanup

create_ns

CUR_TX=1
CUR_RX=1
if [ $CPUS -gt 1 ]; then
	ip netns exec $NS_DST ethtool -L veth$DST tx 2
	chk_channels "setting tx channels" $DST 1 2
	CUR_TX=2
fi

if [ $CPUS -gt 2 ]; then
	ip netns exec $NS_DST ethtool -L veth$DST rx 3 tx 3
	chk_channels "setting both rx and tx channels" $DST 3 3
	CUR_RX=3
	CUR_TX=3
fi

ip netns exec $NS_DST ethtool -L veth$DST combined 2 2>/dev/null
chk_channels "bad setting: combined channels" $DST $CUR_RX $CUR_TX

ip netns exec $NS_DST ethtool -L veth$DST tx $((CPUS + 1)) 2>/dev/null
chk_channels "setting invalid channels nr" $DST $CUR_RX $CUR_TX

if [ $CPUS -gt 1 ]; then
	# this also tests queues nr reduction
	ip netns exec $NS_DST ethtool -L veth$DST rx 1 tx 2 2>/dev/null
	ip netns exec $NS_SRC ethtool -L veth$SRC rx 1 tx 2 2>/dev/null
	printf "%-60s" "bad setting: XDP with RX nr less than TX"
	ip -n $NS_DST link set dev veth$DST xdp object ../bpf/xdp_dummy.o \
		section xdp 2>/dev/null &&\
		echo "fail - set operation successful ?!?" || echo " ok "

	# the following tests will run with multiple channels active
	ip netns exec $NS_SRC ethtool -L veth$SRC rx 2
	ip netns exec $NS_DST ethtool -L veth$DST rx 2
	ip -n $NS_DST link set dev veth$DST xdp object ../bpf/xdp_dummy.o \
		section xdp 2>/dev/null
	printf "%-60s" "bad setting: reducing RX nr below peer TX with XDP set"
	ip netns exec $NS_DST ethtool -L veth$DST rx 1 2>/dev/null &&\
		echo "fail - set operation successful ?!?" || echo " ok "
	CUR_RX=2
	CUR_TX=2
fi

if [ $CPUS -gt 2 ]; then
	printf "%-60s" "bad setting: increasing peer TX nr above RX with XDP set"
	ip netns exec $NS_SRC ethtool -L veth$SRC tx 3 2>/dev/null &&\
		echo "fail - set operation successful ?!?" || echo " ok "
	chk_channels "setting invalid channels nr" $DST 2 2
fi

ip -n $NS_DST link set dev veth$DST xdp object ../bpf/xdp_dummy.o section xdp 2>/dev/null
chk_gro_flag "with xdp attached - gro flag" $DST on
chk_gro_flag "        - peer gro flag" $SRC off
chk_tso_flag "        - tso flag" $SRC off
chk_tso_flag "        - peer tso flag" $DST on
ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on
chk_gro "        - aggregation" 1


ip -n $NS_DST link set dev veth$DST down
ip -n $NS_SRC link set dev veth$SRC down
chk_gro_flag "        - after dev off, flag" $DST on
chk_gro_flag "        - peer flag" $SRC off

ip netns exec $NS_DST ethtool -K veth$DST gro on
ip -n $NS_DST link set dev veth$DST xdp off
chk_gro_flag "        - after gro on xdp off, gro flag" $DST on
chk_gro_flag "        - peer gro flag" $SRC off
chk_tso_flag "        - tso flag" $SRC on
chk_tso_flag "        - peer tso flag" $DST on

if [ $CPUS -gt 1 ]; then
	ip netns exec $NS_DST ethtool -L veth$DST tx 1
	chk_channels "decreasing tx channels with device down" $DST 2 1
fi

ip -n $NS_DST link set dev veth$DST up
ip -n $NS_SRC link set dev veth$SRC up
chk_gro "        - aggregation" 1

if [ $CPUS -gt 1 ]; then
	[ $STRESS -gt 0 -a $CPUS -gt 2 ] && do_stress

	ip -n $NS_DST link set dev veth$DST down
	ip -n $NS_SRC link set dev veth$SRC down
	ip netns exec $NS_DST ethtool -L veth$DST tx 2
	chk_channels "increasing tx channels with device down" $DST 2 2
	ip -n $NS_DST link set dev veth$DST up
	ip -n $NS_SRC link set dev veth$SRC up
fi

ip netns exec $NS_DST ethtool -K veth$DST gro off
ip netns exec $NS_SRC ethtool -K veth$SRC tx-udp-segmentation off
chk_gro "aggregation again with default and TSO off" 10

exit $ret