xref: /OK3568_Linux_fs/kernel/tools/testing/selftests/net/fib-onlink-tests.sh (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/bin/bash
2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun# IPv4 and IPv6 onlink tests
5*4882a593Smuzhiyun
6*4882a593SmuzhiyunPAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no}
7*4882a593SmuzhiyunVERBOSE=0
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun# Network interfaces
10*4882a593Smuzhiyun# - odd in current namespace; even in peer ns
11*4882a593Smuzhiyundeclare -A NETIFS
12*4882a593Smuzhiyun# default VRF
13*4882a593SmuzhiyunNETIFS[p1]=veth1
14*4882a593SmuzhiyunNETIFS[p2]=veth2
15*4882a593SmuzhiyunNETIFS[p3]=veth3
16*4882a593SmuzhiyunNETIFS[p4]=veth4
17*4882a593Smuzhiyun# VRF
18*4882a593SmuzhiyunNETIFS[p5]=veth5
19*4882a593SmuzhiyunNETIFS[p6]=veth6
20*4882a593SmuzhiyunNETIFS[p7]=veth7
21*4882a593SmuzhiyunNETIFS[p8]=veth8
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun# /24 network
24*4882a593Smuzhiyundeclare -A V4ADDRS
25*4882a593SmuzhiyunV4ADDRS[p1]=169.254.1.1
26*4882a593SmuzhiyunV4ADDRS[p2]=169.254.1.2
27*4882a593SmuzhiyunV4ADDRS[p3]=169.254.3.1
28*4882a593SmuzhiyunV4ADDRS[p4]=169.254.3.2
29*4882a593SmuzhiyunV4ADDRS[p5]=169.254.5.1
30*4882a593SmuzhiyunV4ADDRS[p6]=169.254.5.2
31*4882a593SmuzhiyunV4ADDRS[p7]=169.254.7.1
32*4882a593SmuzhiyunV4ADDRS[p8]=169.254.7.2
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun# /64 network
35*4882a593Smuzhiyundeclare -A V6ADDRS
36*4882a593SmuzhiyunV6ADDRS[p1]=2001:db8:101::1
37*4882a593SmuzhiyunV6ADDRS[p2]=2001:db8:101::2
38*4882a593SmuzhiyunV6ADDRS[p3]=2001:db8:301::1
39*4882a593SmuzhiyunV6ADDRS[p4]=2001:db8:301::2
40*4882a593SmuzhiyunV6ADDRS[p5]=2001:db8:501::1
41*4882a593SmuzhiyunV6ADDRS[p6]=2001:db8:501::2
42*4882a593SmuzhiyunV6ADDRS[p7]=2001:db8:701::1
43*4882a593SmuzhiyunV6ADDRS[p8]=2001:db8:701::2
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun# Test networks:
46*4882a593Smuzhiyun# [1] = default table
47*4882a593Smuzhiyun# [2] = VRF
48*4882a593Smuzhiyun#
49*4882a593Smuzhiyun# /32 host routes
50*4882a593Smuzhiyundeclare -A TEST_NET4
51*4882a593SmuzhiyunTEST_NET4[1]=169.254.101
52*4882a593SmuzhiyunTEST_NET4[2]=169.254.102
53*4882a593Smuzhiyun# /128 host routes
54*4882a593Smuzhiyundeclare -A TEST_NET6
55*4882a593SmuzhiyunTEST_NET6[1]=2001:db8:101
56*4882a593SmuzhiyunTEST_NET6[2]=2001:db8:102
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun# connected gateway
59*4882a593SmuzhiyunCONGW[1]=169.254.1.254
60*4882a593SmuzhiyunCONGW[2]=169.254.3.254
61*4882a593SmuzhiyunCONGW[3]=169.254.5.254
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun# recursive gateway
64*4882a593SmuzhiyunRECGW4[1]=169.254.11.254
65*4882a593SmuzhiyunRECGW4[2]=169.254.12.254
66*4882a593SmuzhiyunRECGW6[1]=2001:db8:11::64
67*4882a593SmuzhiyunRECGW6[2]=2001:db8:12::64
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun# for v4 mapped to v6
70*4882a593Smuzhiyundeclare -A TEST_NET4IN6IN6
71*4882a593SmuzhiyunTEST_NET4IN6[1]=10.1.1.254
72*4882a593SmuzhiyunTEST_NET4IN6[2]=10.2.1.254
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun# mcast address
75*4882a593SmuzhiyunMCAST6=ff02::1
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun
78*4882a593SmuzhiyunPEER_NS=bart
79*4882a593SmuzhiyunPEER_CMD="ip netns exec ${PEER_NS}"
80*4882a593SmuzhiyunVRF=lisa
81*4882a593SmuzhiyunVRF_TABLE=1101
82*4882a593SmuzhiyunPBR_TABLE=101
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun################################################################################
85*4882a593Smuzhiyun# utilities
86*4882a593Smuzhiyun
87*4882a593Smuzhiyunlog_test()
88*4882a593Smuzhiyun{
89*4882a593Smuzhiyun	local rc=$1
90*4882a593Smuzhiyun	local expected=$2
91*4882a593Smuzhiyun	local msg="$3"
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun	if [ ${rc} -eq ${expected} ]; then
94*4882a593Smuzhiyun		nsuccess=$((nsuccess+1))
95*4882a593Smuzhiyun		printf "    TEST: %-50s  [ OK ]\n" "${msg}"
96*4882a593Smuzhiyun	else
97*4882a593Smuzhiyun		nfail=$((nfail+1))
98*4882a593Smuzhiyun		printf "    TEST: %-50s  [FAIL]\n" "${msg}"
99*4882a593Smuzhiyun		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
100*4882a593Smuzhiyun			echo
101*4882a593Smuzhiyun			echo "hit enter to continue, 'q' to quit"
102*4882a593Smuzhiyun			read a
103*4882a593Smuzhiyun			[ "$a" = "q" ] && exit 1
104*4882a593Smuzhiyun		fi
105*4882a593Smuzhiyun	fi
106*4882a593Smuzhiyun}
107*4882a593Smuzhiyun
108*4882a593Smuzhiyunlog_section()
109*4882a593Smuzhiyun{
110*4882a593Smuzhiyun	echo
111*4882a593Smuzhiyun	echo "######################################################################"
112*4882a593Smuzhiyun	echo "TEST SECTION: $*"
113*4882a593Smuzhiyun	echo "######################################################################"
114*4882a593Smuzhiyun}
115*4882a593Smuzhiyun
116*4882a593Smuzhiyunlog_subsection()
117*4882a593Smuzhiyun{
118*4882a593Smuzhiyun	echo
119*4882a593Smuzhiyun	echo "#########################################"
120*4882a593Smuzhiyun	echo "TEST SUBSECTION: $*"
121*4882a593Smuzhiyun}
122*4882a593Smuzhiyun
123*4882a593Smuzhiyunrun_cmd()
124*4882a593Smuzhiyun{
125*4882a593Smuzhiyun	local cmd="$*"
126*4882a593Smuzhiyun	local out
127*4882a593Smuzhiyun	local rc
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun	if [ "$VERBOSE" = "1" ]; then
130*4882a593Smuzhiyun		printf "    COMMAND: $cmd\n"
131*4882a593Smuzhiyun	fi
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun	out=$(eval $cmd 2>&1)
134*4882a593Smuzhiyun	rc=$?
135*4882a593Smuzhiyun	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
136*4882a593Smuzhiyun		echo "    $out"
137*4882a593Smuzhiyun	fi
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun	[ "$VERBOSE" = "1" ] && echo
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun	return $rc
142*4882a593Smuzhiyun}
143*4882a593Smuzhiyun
144*4882a593Smuzhiyunget_linklocal()
145*4882a593Smuzhiyun{
146*4882a593Smuzhiyun	local dev=$1
147*4882a593Smuzhiyun	local pfx
148*4882a593Smuzhiyun	local addr
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun	addr=$(${pfx} ip -6 -br addr show dev ${dev} | \
151*4882a593Smuzhiyun	awk '{
152*4882a593Smuzhiyun		for (i = 3; i <= NF; ++i) {
153*4882a593Smuzhiyun			if ($i ~ /^fe80/)
154*4882a593Smuzhiyun				print $i
155*4882a593Smuzhiyun		}
156*4882a593Smuzhiyun	}'
157*4882a593Smuzhiyun	)
158*4882a593Smuzhiyun	addr=${addr/\/*}
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun	[ -z "$addr" ] && return 1
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun	echo $addr
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun	return 0
165*4882a593Smuzhiyun}
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun################################################################################
168*4882a593Smuzhiyun#
169*4882a593Smuzhiyun
170*4882a593Smuzhiyunsetup()
171*4882a593Smuzhiyun{
172*4882a593Smuzhiyun	echo
173*4882a593Smuzhiyun	echo "########################################"
174*4882a593Smuzhiyun	echo "Configuring interfaces"
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun	set -e
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun	# create namespace
179*4882a593Smuzhiyun	ip netns add ${PEER_NS}
180*4882a593Smuzhiyun	ip -netns ${PEER_NS} li set lo up
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun	# add vrf table
183*4882a593Smuzhiyun	ip li add ${VRF} type vrf table ${VRF_TABLE}
184*4882a593Smuzhiyun	ip li set ${VRF} up
185*4882a593Smuzhiyun	ip ro add table ${VRF_TABLE} unreachable default metric 8192
186*4882a593Smuzhiyun	ip -6 ro add table ${VRF_TABLE} unreachable default metric 8192
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun	# create test interfaces
189*4882a593Smuzhiyun	ip li add ${NETIFS[p1]} type veth peer name ${NETIFS[p2]}
190*4882a593Smuzhiyun	ip li add ${NETIFS[p3]} type veth peer name ${NETIFS[p4]}
191*4882a593Smuzhiyun	ip li add ${NETIFS[p5]} type veth peer name ${NETIFS[p6]}
192*4882a593Smuzhiyun	ip li add ${NETIFS[p7]} type veth peer name ${NETIFS[p8]}
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun	# enslave vrf interfaces
195*4882a593Smuzhiyun	for n in 5 7; do
196*4882a593Smuzhiyun		ip li set ${NETIFS[p${n}]} vrf ${VRF}
197*4882a593Smuzhiyun	done
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun	# add addresses
200*4882a593Smuzhiyun	for n in 1 3 5 7; do
201*4882a593Smuzhiyun		ip li set ${NETIFS[p${n}]} up
202*4882a593Smuzhiyun		ip addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
203*4882a593Smuzhiyun		ip addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
204*4882a593Smuzhiyun	done
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun	# move peer interfaces to namespace and add addresses
207*4882a593Smuzhiyun	for n in 2 4 6 8; do
208*4882a593Smuzhiyun		ip li set ${NETIFS[p${n}]} netns ${PEER_NS} up
209*4882a593Smuzhiyun		ip -netns ${PEER_NS} addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
210*4882a593Smuzhiyun		ip -netns ${PEER_NS} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
211*4882a593Smuzhiyun	done
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun	ip -6 ro add default via ${V6ADDRS[p3]/::[0-9]/::64}
214*4882a593Smuzhiyun	ip -6 ro add table ${VRF_TABLE} default via ${V6ADDRS[p7]/::[0-9]/::64}
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun	set +e
217*4882a593Smuzhiyun}
218*4882a593Smuzhiyun
219*4882a593Smuzhiyuncleanup()
220*4882a593Smuzhiyun{
221*4882a593Smuzhiyun	# make sure we start from a clean slate
222*4882a593Smuzhiyun	ip netns del ${PEER_NS} 2>/dev/null
223*4882a593Smuzhiyun	for n in 1 3 5 7; do
224*4882a593Smuzhiyun		ip link del ${NETIFS[p${n}]} 2>/dev/null
225*4882a593Smuzhiyun	done
226*4882a593Smuzhiyun	ip link del ${VRF} 2>/dev/null
227*4882a593Smuzhiyun	ip ro flush table ${VRF_TABLE}
228*4882a593Smuzhiyun	ip -6 ro flush table ${VRF_TABLE}
229*4882a593Smuzhiyun}
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun################################################################################
232*4882a593Smuzhiyun# IPv4 tests
233*4882a593Smuzhiyun#
234*4882a593Smuzhiyun
235*4882a593Smuzhiyunrun_ip()
236*4882a593Smuzhiyun{
237*4882a593Smuzhiyun	local table="$1"
238*4882a593Smuzhiyun	local prefix="$2"
239*4882a593Smuzhiyun	local gw="$3"
240*4882a593Smuzhiyun	local dev="$4"
241*4882a593Smuzhiyun	local exp_rc="$5"
242*4882a593Smuzhiyun	local desc="$6"
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun	# dev arg may be empty
245*4882a593Smuzhiyun	[ -n "${dev}" ] && dev="dev ${dev}"
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun	run_cmd ip ro add table "${table}" "${prefix}"/32 via "${gw}" "${dev}" onlink
248*4882a593Smuzhiyun	log_test $? ${exp_rc} "${desc}"
249*4882a593Smuzhiyun}
250*4882a593Smuzhiyun
251*4882a593Smuzhiyunrun_ip_mpath()
252*4882a593Smuzhiyun{
253*4882a593Smuzhiyun	local table="$1"
254*4882a593Smuzhiyun	local prefix="$2"
255*4882a593Smuzhiyun	local nh1="$3"
256*4882a593Smuzhiyun	local nh2="$4"
257*4882a593Smuzhiyun	local exp_rc="$5"
258*4882a593Smuzhiyun	local desc="$6"
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun	# dev arg may be empty
261*4882a593Smuzhiyun	[ -n "${dev}" ] && dev="dev ${dev}"
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun	run_cmd ip ro add table "${table}" "${prefix}"/32 \
264*4882a593Smuzhiyun		nexthop via ${nh1} nexthop via ${nh2}
265*4882a593Smuzhiyun	log_test $? ${exp_rc} "${desc}"
266*4882a593Smuzhiyun}
267*4882a593Smuzhiyun
268*4882a593Smuzhiyunvalid_onlink_ipv4()
269*4882a593Smuzhiyun{
270*4882a593Smuzhiyun	# - unicast connected, unicast recursive
271*4882a593Smuzhiyun	#
272*4882a593Smuzhiyun	log_subsection "default VRF - main table"
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun	run_ip 254 ${TEST_NET4[1]}.1 ${CONGW[1]} ${NETIFS[p1]} 0 "unicast connected"
275*4882a593Smuzhiyun	run_ip 254 ${TEST_NET4[1]}.2 ${RECGW4[1]} ${NETIFS[p1]} 0 "unicast recursive"
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun	log_subsection "VRF ${VRF}"
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun	run_ip ${VRF_TABLE} ${TEST_NET4[2]}.1 ${CONGW[3]} ${NETIFS[p5]} 0 "unicast connected"
280*4882a593Smuzhiyun	run_ip ${VRF_TABLE} ${TEST_NET4[2]}.2 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun	log_subsection "VRF device, PBR table"
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun	run_ip ${PBR_TABLE} ${TEST_NET4[2]}.3 ${CONGW[3]} ${NETIFS[p5]} 0 "unicast connected"
285*4882a593Smuzhiyun	run_ip ${PBR_TABLE} ${TEST_NET4[2]}.4 ${RECGW4[2]} ${NETIFS[p5]} 0 "unicast recursive"
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun	# multipath version
288*4882a593Smuzhiyun	#
289*4882a593Smuzhiyun	log_subsection "default VRF - main table - multipath"
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun	run_ip_mpath 254 ${TEST_NET4[1]}.5 \
292*4882a593Smuzhiyun		"${CONGW[1]} dev ${NETIFS[p1]} onlink" \
293*4882a593Smuzhiyun		"${CONGW[2]} dev ${NETIFS[p3]} onlink" \
294*4882a593Smuzhiyun		0 "unicast connected - multipath"
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun	run_ip_mpath 254 ${TEST_NET4[1]}.6 \
297*4882a593Smuzhiyun		"${RECGW4[1]} dev ${NETIFS[p1]} onlink" \
298*4882a593Smuzhiyun		"${RECGW4[2]} dev ${NETIFS[p3]} onlink" \
299*4882a593Smuzhiyun		0 "unicast recursive - multipath"
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun	run_ip_mpath 254 ${TEST_NET4[1]}.7 \
302*4882a593Smuzhiyun		"${CONGW[1]} dev ${NETIFS[p1]}"        \
303*4882a593Smuzhiyun		"${CONGW[2]} dev ${NETIFS[p3]} onlink" \
304*4882a593Smuzhiyun		0 "unicast connected - multipath onlink first only"
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun	run_ip_mpath 254 ${TEST_NET4[1]}.8 \
307*4882a593Smuzhiyun		"${CONGW[1]} dev ${NETIFS[p1]} onlink" \
308*4882a593Smuzhiyun		"${CONGW[2]} dev ${NETIFS[p3]}"        \
309*4882a593Smuzhiyun		0 "unicast connected - multipath onlink second only"
310*4882a593Smuzhiyun}
311*4882a593Smuzhiyun
312*4882a593Smuzhiyuninvalid_onlink_ipv4()
313*4882a593Smuzhiyun{
314*4882a593Smuzhiyun	run_ip 254 ${TEST_NET4[1]}.11 ${V4ADDRS[p1]} ${NETIFS[p1]} 2 \
315*4882a593Smuzhiyun		"Invalid gw - local unicast address"
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun	run_ip ${VRF_TABLE} ${TEST_NET4[2]}.11 ${V4ADDRS[p5]} ${NETIFS[p5]} 2 \
318*4882a593Smuzhiyun		"Invalid gw - local unicast address, VRF"
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun	run_ip 254 ${TEST_NET4[1]}.101 ${V4ADDRS[p1]} "" 2 "No nexthop device given"
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun	run_ip 254 ${TEST_NET4[1]}.102 ${V4ADDRS[p3]} ${NETIFS[p1]} 2 \
323*4882a593Smuzhiyun		"Gateway resolves to wrong nexthop device"
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun	run_ip ${VRF_TABLE} ${TEST_NET4[2]}.103 ${V4ADDRS[p7]} ${NETIFS[p5]} 2 \
326*4882a593Smuzhiyun		"Gateway resolves to wrong nexthop device - VRF"
327*4882a593Smuzhiyun}
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun################################################################################
330*4882a593Smuzhiyun# IPv6 tests
331*4882a593Smuzhiyun#
332*4882a593Smuzhiyun
333*4882a593Smuzhiyunrun_ip6()
334*4882a593Smuzhiyun{
335*4882a593Smuzhiyun	local table="$1"
336*4882a593Smuzhiyun	local prefix="$2"
337*4882a593Smuzhiyun	local gw="$3"
338*4882a593Smuzhiyun	local dev="$4"
339*4882a593Smuzhiyun	local exp_rc="$5"
340*4882a593Smuzhiyun	local desc="$6"
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun	# dev arg may be empty
343*4882a593Smuzhiyun	[ -n "${dev}" ] && dev="dev ${dev}"
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun	run_cmd ip -6 ro add table "${table}" "${prefix}"/128 via "${gw}" "${dev}" onlink
346*4882a593Smuzhiyun	log_test $? ${exp_rc} "${desc}"
347*4882a593Smuzhiyun}
348*4882a593Smuzhiyun
349*4882a593Smuzhiyunrun_ip6_mpath()
350*4882a593Smuzhiyun{
351*4882a593Smuzhiyun	local table="$1"
352*4882a593Smuzhiyun	local prefix="$2"
353*4882a593Smuzhiyun	local opts="$3"
354*4882a593Smuzhiyun	local nh1="$4"
355*4882a593Smuzhiyun	local nh2="$5"
356*4882a593Smuzhiyun	local exp_rc="$6"
357*4882a593Smuzhiyun	local desc="$7"
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun	run_cmd ip -6 ro add table "${table}" "${prefix}"/128 "${opts}" \
360*4882a593Smuzhiyun		nexthop via ${nh1} nexthop via ${nh2}
361*4882a593Smuzhiyun	log_test $? ${exp_rc} "${desc}"
362*4882a593Smuzhiyun}
363*4882a593Smuzhiyun
364*4882a593Smuzhiyunvalid_onlink_ipv6()
365*4882a593Smuzhiyun{
366*4882a593Smuzhiyun	# - unicast connected, unicast recursive, v4-mapped
367*4882a593Smuzhiyun	#
368*4882a593Smuzhiyun	log_subsection "default VRF - main table"
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun	run_ip6 254 ${TEST_NET6[1]}::1 ${V6ADDRS[p1]/::*}::64 ${NETIFS[p1]} 0 "unicast connected"
371*4882a593Smuzhiyun	run_ip6 254 ${TEST_NET6[1]}::2 ${RECGW6[1]} ${NETIFS[p1]} 0 "unicast recursive"
372*4882a593Smuzhiyun	run_ip6 254 ${TEST_NET6[1]}::3 ::ffff:${TEST_NET4IN6[1]} ${NETIFS[p1]} 0 "v4-mapped"
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun	log_subsection "VRF ${VRF}"
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun	run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::1 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"
377*4882a593Smuzhiyun	run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::2 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"
378*4882a593Smuzhiyun	run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::3 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun	log_subsection "VRF device, PBR table"
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun	run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::4 ${V6ADDRS[p5]/::*}::64 ${NETIFS[p5]} 0 "unicast connected"
383*4882a593Smuzhiyun	run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::5 ${RECGW6[2]} ${NETIFS[p5]} 0 "unicast recursive"
384*4882a593Smuzhiyun	run_ip6 ${PBR_TABLE} ${TEST_NET6[2]}::6 ::ffff:${TEST_NET4IN6[2]} ${NETIFS[p5]} 0 "v4-mapped"
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun	# multipath version
387*4882a593Smuzhiyun	#
388*4882a593Smuzhiyun	log_subsection "default VRF - main table - multipath"
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun	run_ip6_mpath 254 ${TEST_NET6[1]}::4 "onlink" \
391*4882a593Smuzhiyun		"${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]}" \
392*4882a593Smuzhiyun		"${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]}" \
393*4882a593Smuzhiyun		0 "unicast connected - multipath onlink"
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun	run_ip6_mpath 254 ${TEST_NET6[1]}::5 "onlink" \
396*4882a593Smuzhiyun		"${RECGW6[1]} dev ${NETIFS[p1]}" \
397*4882a593Smuzhiyun		"${RECGW6[2]} dev ${NETIFS[p3]}" \
398*4882a593Smuzhiyun		0 "unicast recursive - multipath onlink"
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun	run_ip6_mpath 254 ${TEST_NET6[1]}::6 "onlink" \
401*4882a593Smuzhiyun		"::ffff:${TEST_NET4IN6[1]} dev ${NETIFS[p1]}" \
402*4882a593Smuzhiyun		"::ffff:${TEST_NET4IN6[2]} dev ${NETIFS[p3]}" \
403*4882a593Smuzhiyun		0 "v4-mapped - multipath onlink"
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun	run_ip6_mpath 254 ${TEST_NET6[1]}::7 "" \
406*4882a593Smuzhiyun		"${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]} onlink" \
407*4882a593Smuzhiyun		"${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]} onlink" \
408*4882a593Smuzhiyun		0 "unicast connected - multipath onlink both nexthops"
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun	run_ip6_mpath 254 ${TEST_NET6[1]}::8 "" \
411*4882a593Smuzhiyun		"${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]} onlink" \
412*4882a593Smuzhiyun		"${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]}" \
413*4882a593Smuzhiyun		0 "unicast connected - multipath onlink first only"
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun	run_ip6_mpath 254 ${TEST_NET6[1]}::9 "" \
416*4882a593Smuzhiyun		"${V6ADDRS[p1]/::*}::64 dev ${NETIFS[p1]}"        \
417*4882a593Smuzhiyun		"${V6ADDRS[p3]/::*}::64 dev ${NETIFS[p3]} onlink" \
418*4882a593Smuzhiyun		0 "unicast connected - multipath onlink second only"
419*4882a593Smuzhiyun}
420*4882a593Smuzhiyun
421*4882a593Smuzhiyuninvalid_onlink_ipv6()
422*4882a593Smuzhiyun{
423*4882a593Smuzhiyun	local lladdr
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun	lladdr=$(get_linklocal ${NETIFS[p1]}) || return 1
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun	run_ip6 254 ${TEST_NET6[1]}::11 ${V6ADDRS[p1]} ${NETIFS[p1]} 2 \
428*4882a593Smuzhiyun		"Invalid gw - local unicast address"
429*4882a593Smuzhiyun	run_ip6 254 ${TEST_NET6[1]}::12 ${lladdr} ${NETIFS[p1]} 2 \
430*4882a593Smuzhiyun		"Invalid gw - local linklocal address"
431*4882a593Smuzhiyun	run_ip6 254 ${TEST_NET6[1]}::12 ${MCAST6} ${NETIFS[p1]} 2 \
432*4882a593Smuzhiyun		"Invalid gw - multicast address"
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun	lladdr=$(get_linklocal ${NETIFS[p5]}) || return 1
435*4882a593Smuzhiyun	run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::11 ${V6ADDRS[p5]} ${NETIFS[p5]} 2 \
436*4882a593Smuzhiyun		"Invalid gw - local unicast address, VRF"
437*4882a593Smuzhiyun	run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${lladdr} ${NETIFS[p5]} 2 \
438*4882a593Smuzhiyun		"Invalid gw - local linklocal address, VRF"
439*4882a593Smuzhiyun	run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::12 ${MCAST6} ${NETIFS[p5]} 2 \
440*4882a593Smuzhiyun		"Invalid gw - multicast address, VRF"
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun	run_ip6 254 ${TEST_NET6[1]}::101 ${V6ADDRS[p1]} "" 2 \
443*4882a593Smuzhiyun		"No nexthop device given"
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun	# default VRF validation is done against LOCAL table
446*4882a593Smuzhiyun	# run_ip6 254 ${TEST_NET6[1]}::102 ${V6ADDRS[p3]/::[0-9]/::64} ${NETIFS[p1]} 2 \
447*4882a593Smuzhiyun	#	"Gateway resolves to wrong nexthop device"
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun	run_ip6 ${VRF_TABLE} ${TEST_NET6[2]}::103 ${V6ADDRS[p7]/::[0-9]/::64} ${NETIFS[p5]} 2 \
450*4882a593Smuzhiyun		"Gateway resolves to wrong nexthop device - VRF"
451*4882a593Smuzhiyun}
452*4882a593Smuzhiyun
453*4882a593Smuzhiyunrun_onlink_tests()
454*4882a593Smuzhiyun{
455*4882a593Smuzhiyun	log_section "IPv4 onlink"
456*4882a593Smuzhiyun	log_subsection "Valid onlink commands"
457*4882a593Smuzhiyun	valid_onlink_ipv4
458*4882a593Smuzhiyun	log_subsection "Invalid onlink commands"
459*4882a593Smuzhiyun	invalid_onlink_ipv4
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun	log_section "IPv6 onlink"
462*4882a593Smuzhiyun	log_subsection "Valid onlink commands"
463*4882a593Smuzhiyun	valid_onlink_ipv6
464*4882a593Smuzhiyun	log_subsection "Invalid onlink commands"
465*4882a593Smuzhiyun	invalid_onlink_ipv6
466*4882a593Smuzhiyun}
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun################################################################################
469*4882a593Smuzhiyun# usage
470*4882a593Smuzhiyun
471*4882a593Smuzhiyunusage()
472*4882a593Smuzhiyun{
473*4882a593Smuzhiyun	cat <<EOF
474*4882a593Smuzhiyunusage: ${0##*/} OPTS
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun        -p          Pause on fail
477*4882a593Smuzhiyun        -v          verbose mode (show commands and output)
478*4882a593SmuzhiyunEOF
479*4882a593Smuzhiyun}
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun################################################################################
482*4882a593Smuzhiyun# main
483*4882a593Smuzhiyun
484*4882a593Smuzhiyunnsuccess=0
485*4882a593Smuzhiyunnfail=0
486*4882a593Smuzhiyun
487*4882a593Smuzhiyunwhile getopts :t:pPhv o
488*4882a593Smuzhiyundo
489*4882a593Smuzhiyun	case $o in
490*4882a593Smuzhiyun		p) PAUSE_ON_FAIL=yes;;
491*4882a593Smuzhiyun		v) VERBOSE=$(($VERBOSE + 1));;
492*4882a593Smuzhiyun		h) usage; exit 0;;
493*4882a593Smuzhiyun		*) usage; exit 1;;
494*4882a593Smuzhiyun	esac
495*4882a593Smuzhiyundone
496*4882a593Smuzhiyun
497*4882a593Smuzhiyuncleanup
498*4882a593Smuzhiyunsetup
499*4882a593Smuzhiyunrun_onlink_tests
500*4882a593Smuzhiyuncleanup
501*4882a593Smuzhiyun
502*4882a593Smuzhiyunif [ "$TESTS" != "none" ]; then
503*4882a593Smuzhiyun	printf "\nTests passed: %3d\n" ${nsuccess}
504*4882a593Smuzhiyun	printf "Tests failed: %3d\n"   ${nfail}
505*4882a593Smuzhiyunfi
506