1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# This test is for checking GRE GSO.
5
6ret=0
7# Kselftest framework requirement - SKIP code is 4.
8ksft_skip=4
9
10# all tests in this script. Can be overridden with -t option
11TESTS="gre_gso"
12
13VERBOSE=0
14PAUSE_ON_FAIL=no
15PAUSE=no
16IP="ip -netns ns1"
17NS_EXEC="ip netns exec ns1"
18TMPFILE=`mktemp`
19PID=
20
21log_test()
22{
23	local rc=$1
24	local expected=$2
25	local msg="$3"
26
27	if [ ${rc} -eq ${expected} ]; then
28		printf "    TEST: %-60s  [ OK ]\n" "${msg}"
29		nsuccess=$((nsuccess+1))
30	else
31		ret=1
32		nfail=$((nfail+1))
33		printf "    TEST: %-60s  [FAIL]\n" "${msg}"
34		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
35		echo
36			echo "hit enter to continue, 'q' to quit"
37			read a
38			[ "$a" = "q" ] && exit 1
39		fi
40	fi
41
42	if [ "${PAUSE}" = "yes" ]; then
43		echo
44		echo "hit enter to continue, 'q' to quit"
45		read a
46		[ "$a" = "q" ] && exit 1
47	fi
48}
49
50setup()
51{
52	set -e
53	ip netns add ns1
54	ip netns set ns1 auto
55	$IP link set dev lo up
56
57	ip link add veth0 type veth peer name veth1
58	ip link set veth0 up
59	ip link set veth1 netns ns1
60	$IP link set veth1 name veth0
61	$IP link set veth0 up
62
63	dd if=/dev/urandom of=$TMPFILE bs=1024 count=2048 &>/dev/null
64	set +e
65}
66
67cleanup()
68{
69	rm -rf $TMPFILE
70	[ -n "$PID" ] && kill $PID
71	ip link del dev gre1 &> /dev/null
72	ip link del dev veth0 &> /dev/null
73	ip netns del ns1
74}
75
76get_linklocal()
77{
78	local dev=$1
79	local ns=$2
80	local addr
81
82	[ -n "$ns" ] && ns="-netns $ns"
83
84	addr=$(ip -6 -br $ns addr show dev ${dev} | \
85	awk '{
86		for (i = 3; i <= NF; ++i) {
87			if ($i ~ /^fe80/)
88				print $i
89		}
90	}'
91	)
92	addr=${addr/\/*}
93
94	[ -z "$addr" ] && return 1
95
96	echo $addr
97
98	return 0
99}
100
101gre_create_tun()
102{
103	local a1=$1
104	local a2=$2
105	local mode
106
107	[[ $a1 =~ ^[0-9.]*$ ]] && mode=gre || mode=ip6gre
108
109	ip tunnel add gre1 mode $mode local $a1 remote $a2 dev veth0
110	ip link set gre1 up
111	$IP tunnel add gre1 mode $mode local $a2 remote $a1 dev veth0
112	$IP link set gre1 up
113}
114
115gre_gst_test_checks()
116{
117	local name=$1
118	local addr=$2
119	local proto=$3
120
121	$NS_EXEC nc $proto -kl $port >/dev/null &
122	PID=$!
123	while ! $NS_EXEC ss -ltn | grep -q $port; do ((i++)); sleep 0.01; done
124
125	cat $TMPFILE | timeout 1 nc $proto -N $addr $port
126	log_test $? 0 "$name - copy file w/ TSO"
127
128	ethtool -K veth0 tso off
129
130	cat $TMPFILE | timeout 1 nc $proto -N $addr $port
131	log_test $? 0 "$name - copy file w/ GSO"
132
133	ethtool -K veth0 tso on
134
135	kill $PID
136	PID=
137}
138
139gre6_gso_test()
140{
141	local port=7777
142
143	setup
144
145	a1=$(get_linklocal veth0)
146	a2=$(get_linklocal veth0 ns1)
147
148	gre_create_tun $a1 $a2
149
150	ip  addr add 172.16.2.1/24 dev gre1
151	$IP addr add 172.16.2.2/24 dev gre1
152
153	ip  -6 addr add 2001:db8:1::1/64 dev gre1 nodad
154	$IP -6 addr add 2001:db8:1::2/64 dev gre1 nodad
155
156	sleep 2
157
158	gre_gst_test_checks GREv6/v4 172.16.2.2
159	gre_gst_test_checks GREv6/v6 2001:db8:1::2 -6
160
161	cleanup
162}
163
164gre_gso_test()
165{
166	gre6_gso_test
167}
168
169################################################################################
170# usage
171
172usage()
173{
174	cat <<EOF
175usage: ${0##*/} OPTS
176
177        -t <test>   Test(s) to run (default: all)
178                    (options: $TESTS)
179        -p          Pause on fail
180        -P          Pause after each test before cleanup
181        -v          verbose mode (show commands and output)
182EOF
183}
184
185################################################################################
186# main
187
188while getopts :t:pPhv o
189do
190	case $o in
191		t) TESTS=$OPTARG;;
192		p) PAUSE_ON_FAIL=yes;;
193		P) PAUSE=yes;;
194		v) VERBOSE=$(($VERBOSE + 1));;
195		h) usage; exit 0;;
196		*) usage; exit 1;;
197	esac
198done
199
200PEER_CMD="ip netns exec ${PEER_NS}"
201
202# make sure we don't pause twice
203[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
204
205if [ "$(id -u)" -ne 0 ];then
206	echo "SKIP: Need root privileges"
207	exit $ksft_skip;
208fi
209
210if [ ! -x "$(command -v ip)" ]; then
211	echo "SKIP: Could not run test without ip tool"
212	exit $ksft_skip
213fi
214
215if [ ! -x "$(command -v nc)" ]; then
216	echo "SKIP: Could not run test without nc tool"
217	exit $ksft_skip
218fi
219
220# start clean
221cleanup &> /dev/null
222
223for t in $TESTS
224do
225	case $t in
226	gre_gso)		gre_gso_test;;
227
228	help) echo "Test names: $TESTS"; exit 0;;
229	esac
230done
231
232if [ "$TESTS" != "none" ]; then
233	printf "\nTests passed: %3d\n" ${nsuccess}
234	printf "Tests failed: %3d\n"   ${nfail}
235fi
236
237exit $ret
238