xref: /openbmc/linux/tools/testing/selftests/net/fib-onlink-tests.sh (revision 93707cbabcc8baf2b2b5f4a99c1f08ee83eb7abd)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# IPv4 and IPv6 onlink tests
5
6PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
7
8# Network interfaces
9# - odd in current namespace; even in peer ns
10declare -A NETIFS
11# default VRF
12NETIFS[p1]=veth1
13NETIFS[p2]=veth2
14NETIFS[p3]=veth3
15NETIFS[p4]=veth4
16# VRF
17NETIFS[p5]=veth5
18NETIFS[p6]=veth6
19NETIFS[p7]=veth7
20NETIFS[p8]=veth8
21
22# /24 network
23declare -A V4ADDRS
24V4ADDRS[p1]=169.254.1.1
25V4ADDRS[p2]=169.254.1.2
26V4ADDRS[p3]=169.254.3.1
27V4ADDRS[p4]=169.254.3.2
28V4ADDRS[p5]=169.254.5.1
29V4ADDRS[p6]=169.254.5.2
30V4ADDRS[p7]=169.254.7.1
31V4ADDRS[p8]=169.254.7.2
32
33# /64 network
34declare -A V6ADDRS
35V6ADDRS[p1]=2001:db8:101::1
36V6ADDRS[p2]=2001:db8:101::2
37V6ADDRS[p3]=2001:db8:301::1
38V6ADDRS[p4]=2001:db8:301::2
39V6ADDRS[p5]=2001:db8:501::1
40V6ADDRS[p6]=2001:db8:501::2
41V6ADDRS[p7]=2001:db8:701::1
42V6ADDRS[p8]=2001:db8:701::2
43
44# Test networks:
45# [1] = default table
46# [2] = VRF
47#
48# /32 host routes
49declare -A TEST_NET4
50TEST_NET4[1]=169.254.101
51TEST_NET4[2]=169.254.102
52# /128 host routes
53declare -A TEST_NET6
54TEST_NET6[1]=2001:db8:101
55TEST_NET6[2]=2001:db8:102
56
57# connected gateway
58CONGW[1]=169.254.1.254
59CONGW[2]=169.254.5.254
60
61# recursive gateway
62RECGW4[1]=169.254.11.254
63RECGW4[2]=169.254.12.254
64RECGW6[1]=2001:db8:11::64
65RECGW6[2]=2001:db8:12::64
66
67# for v4 mapped to v6
68declare -A TEST_NET4IN6IN6
69TEST_NET4IN6[1]=10.1.1.254
70TEST_NET4IN6[2]=10.2.1.254
71
72# mcast address
73MCAST6=ff02::1
74
75
76PEER_NS=bart
77PEER_CMD="ip netns exec ${PEER_NS}"
78VRF=lisa
79VRF_TABLE=1101
80PBR_TABLE=101
81
82################################################################################
83# utilities
84
85log_test()
86{
87	local rc=$1
88	local expected=$2
89	local msg="$3"
90
91	if [ ${rc} -eq ${expected} ]; then
92		nsuccess=$((nsuccess+1))
93		printf "\n    TEST: %-50s  [ OK ]\n" "${msg}"
94	else
95		nfail=$((nfail+1))
96		printf "\n    TEST: %-50s  [FAIL]\n" "${msg}"
97		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
98			echo
99			echo "hit enter to continue, 'q' to quit"
100			read a
101			[ "$a" = "q" ] && exit 1
102		fi
103	fi
104}
105
106log_section()
107{
108	echo
109	echo "######################################################################"
110	echo "TEST SECTION: $*"
111	echo "######################################################################"
112}
113
114log_subsection()
115{
116	echo
117	echo "#########################################"
118	echo "TEST SUBSECTION: $*"
119}
120
121run_cmd()
122{
123	echo
124	echo "COMMAND: $*"
125	eval $*
126}
127
128get_linklocal()
129{
130	local dev=$1
131	local pfx
132	local addr
133
134	addr=$(${pfx} ip -6 -br addr show dev ${dev} | \
135	awk '{
136		for (i = 3; i <= NF; ++i) {
137			if ($i ~ /^fe80/)
138				print $i
139		}
140	}'
141	)
142	addr=${addr/\/*}
143
144	[ -z "$addr" ] && return 1
145
146	echo $addr
147
148	return 0
149}
150
151################################################################################
152#
153
154setup()
155{
156	echo
157	echo "########################################"
158	echo "Configuring interfaces"
159
160	set -e
161
162	# create namespace
163	ip netns add ${PEER_NS}
164	ip -netns ${PEER_NS} li set lo up
165
166	# add vrf table
167	ip li add ${VRF} type vrf table ${VRF_TABLE}
168	ip li set ${VRF} up
169	ip ro add table ${VRF_TABLE} unreachable default
170	ip -6 ro add table ${VRF_TABLE} unreachable default
171
172	# create test interfaces
173	ip li add ${NETIFS[p1]} type veth peer name ${NETIFS[p2]}
174	ip li add ${NETIFS[p3]} type veth peer name ${NETIFS[p4]}
175	ip li add ${NETIFS[p5]} type veth peer name ${NETIFS[p6]}
176	ip li add ${NETIFS[p7]} type veth peer name ${NETIFS[p8]}
177
178	# enslave vrf interfaces
179	for n in 5 7; do
180		ip li set ${NETIFS[p${n}]} vrf ${VRF}
181	done
182
183	# add addresses
184	for n in 1 3 5 7; do
185		ip li set ${NETIFS[p${n}]} up
186		ip addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
187		ip addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]}
188	done
189
190	# move peer interfaces to namespace and add addresses
191	for n in 2 4 6 8; do
192		ip li set ${NETIFS[p${n}]} netns ${PEER_NS} up
193		ip -netns ${PEER_NS} addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
194		ip -netns ${PEER_NS} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]}
195	done
196
197	set +e
198
199	# let DAD complete - assume default of 1 probe
200	sleep 1
201}
202
203cleanup()
204{
205	# make sure we start from a clean slate
206	ip netns del ${PEER_NS} 2>/dev/null
207	for n in 1 3 5 7; do
208		ip link del ${NETIFS[p${n}]} 2>/dev/null
209	done
210	ip link del ${VRF} 2>/dev/null
211	ip ro flush table ${VRF_TABLE}
212	ip -6 ro flush table ${VRF_TABLE}
213}
214
215################################################################################
216# IPv4 tests
217#
218
219run_ip()
220{
221	local table="$1"
222	local prefix="$2"
223	local gw="$3"
224	local dev="$4"
225	local exp_rc="$5"
226	local desc="$6"
227
228	# dev arg may be empty
229	[ -n "${dev}" ] && dev="dev ${dev}"
230
231	run_cmd ip ro add table "${table}" "${prefix}"/32 via "${gw}" "${dev}" onlink
232	log_test $? ${exp_rc} "${desc}"
233}
234
235valid_onlink_ipv4()
236{
237	# - unicast connected, unicast recursive
238	#
239	log_subsection "default VRF - main table"
240
241	run_ip 254 ${TEST_NET4[1]}.1 ${CONGW[1]} ${NETIFS[p1]} 0 "unicast connected"
242	run_ip 254 ${TEST_NET4[1]}.2 ${RECGW4[1]} ${NETIFS[p1]} 0 "unicast recursive"
243
244	log_subsection "VRF ${VRF}"
245
246	run_ip ${VRF_TABLE} ${TEST_NET4[2]}.1 ${CONGW[2]} ${NETIFS[p5]} 0 "unicast connected"
247	run_ip ${VRF_TABLE} ${TEST_NET4[2]}.2 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"
248
249	log_subsection "VRF device, PBR table"
250
251	run_ip ${PBR_TABLE} ${TEST_NET4[2]}.3 ${CONGW[2]} ${NETIFS[p5]} 0 "unicast connected"
252	run_ip ${PBR_TABLE} ${TEST_NET4[2]}.4 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"
253}
254
255invalid_onlink_ipv4()
256{
257	run_ip 254 ${TEST_NET4[1]}.11 ${V4ADDRS[p1]} ${NETIFS[p1]} 2 \
258		"Invalid gw - local unicast address"
259
260	run_ip ${VRF_TABLE} ${TEST_NET4[2]}.11 ${V4ADDRS[p5]} ${NETIFS[p5]} 2 \
261		"Invalid gw - local unicast address, VRF"
262
263	run_ip 254 ${TEST_NET4[1]}.101 ${V4ADDRS[p1]} "" 2 "No nexthop device given"
264
265	run_ip 254 ${TEST_NET4[1]}.102 ${V4ADDRS[p3]} ${NETIFS[p1]} 2 \
266		"Gateway resolves to wrong nexthop device"
267
268	run_ip ${VRF_TABLE} ${TEST_NET4[2]}.103 ${V4ADDRS[p7]} ${NETIFS[p5]} 2 \
269		"Gateway resolves to wrong nexthop device - VRF"
270}
271
272################################################################################
273# IPv6 tests
274#
275
276run_ip6()
277{
278	local table="$1"
279	local prefix="$2"
280	local gw="$3"
281	local dev="$4"
282	local exp_rc="$5"
283	local desc="$6"
284
285	# dev arg may be empty
286	[ -n "${dev}" ] && dev="dev ${dev}"
287
288	run_cmd ip -6 ro add table "${table}" "${prefix}"/128 via "${gw}" "${dev}" onlink
289	log_test $? ${exp_rc} "${desc}"
290}
291
292valid_onlink_ipv6()
293{
294	# - unicast connected, unicast recursive, v4-mapped
295	#
296	log_subsection "default VRF - main table"
297
298	run_ip6 254 ${TEST_NET6[1]}::1 ${V6ADDRS[p1]/::*}::64 ${NETIFS[p1]} 0 "unicast connected"
299	run_ip6 254 ${TEST_NET6[1]}::2 ${RECGW6[1]} ${NETIFS[p1]} 0 "unicast recursive"
300	run_ip6 254 ${TEST_NET6[1]}::3 ::ffff:${TEST_NET4IN6[1]} ${NETIFS[p1]} 0 "v4-mapped"
301
302	log_subsection "VRF ${VRF}"
303
304	run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::1 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"
305	run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::2 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"
306	run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::3 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"
307
308	log_subsection "VRF device, PBR table"
309
310	run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::4 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"
311	run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::5 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"
312	run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::6 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"
313}
314
315invalid_onlink_ipv6()
316{
317	local lladdr
318
319	lladdr=$(get_linklocal ${NETIFS[p1]}) || return 1
320
321	run_ip6 254 ${TEST_NET6[1]}::11 ${V6ADDRS[p1]} ${NETIFS[p1]} 2 \
322		"Invalid gw - local unicast address"
323	run_ip6 254 ${TEST_NET6[1]}::12 ${lladdr} ${NETIFS[p1]} 2 \
324		"Invalid gw - local linklocal address"
325	run_ip6 254 ${TEST_NET6[1]}::12 ${MCAST6} ${NETIFS[p1]} 2 \
326		"Invalid gw - multicast address"
327
328	lladdr=$(get_linklocal ${NETIFS[p5]}) || return 1
329	run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::11 ${V6ADDRS[p5]} ${NETIFS[p5]} 2 \
330		"Invalid gw - local unicast address, VRF"
331	run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${lladdr} ${NETIFS[p5]} 2 \
332		"Invalid gw - local linklocal address, VRF"
333	run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${MCAST6} ${NETIFS[p5]} 2 \
334		"Invalid gw - multicast address, VRF"
335
336	run_ip6 254 ${TEST_NET6[1]}::101 ${V6ADDRS[p1]} "" 2 \
337		"No nexthop device given"
338
339	# default VRF validation is done against LOCAL table
340	# run_ip6 254 ${TEST_NET6[1]}::102 ${V6ADDRS[p3]/::[0-9]/::64} ${NETIFS[p1]} 2 \
341	#	"Gateway resolves to wrong nexthop device"
342
343	run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::103 ${V6ADDRS[p7]/::[0-9]/::64} ${NETIFS[p5]} 2 \
344		"Gateway resolves to wrong nexthop device - VRF"
345}
346
347run_onlink_tests()
348{
349	log_section "IPv4 onlink"
350	log_subsection "Valid onlink commands"
351	valid_onlink_ipv4
352	log_subsection "Invalid onlink commands"
353	invalid_onlink_ipv4
354
355	log_section "IPv6 onlink"
356	log_subsection "Valid onlink commands"
357	valid_onlink_ipv6
358	invalid_onlink_ipv6
359}
360
361################################################################################
362# main
363
364nsuccess=0
365nfail=0
366
367cleanup
368setup
369run_onlink_tests
370cleanup
371
372if [ "$TESTS" != "none" ]; then
373	printf "\nTests passed: %3d\n" ${nsuccess}
374	printf "Tests failed: %3d\n"   ${nfail}
375fi
376