xref: /OK3568_Linux_fs/kernel/tools/testing/selftests/net/fib_nexthop_multiprefix.sh (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/bin/bash
2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0
3*4882a593Smuzhiyun#
4*4882a593Smuzhiyun# Validate cached routes in fib{6}_nh that is used by multiple prefixes.
5*4882a593Smuzhiyun# Validate a different # exception is generated in h0 for each remote host.
6*4882a593Smuzhiyun#
7*4882a593Smuzhiyun#               h1
8*4882a593Smuzhiyun#            /
9*4882a593Smuzhiyun#    h0 - r1 -  h2
10*4882a593Smuzhiyun#            \
11*4882a593Smuzhiyun#               h3
12*4882a593Smuzhiyun#
13*4882a593Smuzhiyun# routing in h0 to hN is done with nexthop objects.
14*4882a593Smuzhiyun
15*4882a593SmuzhiyunPAUSE_ON_FAIL=no
16*4882a593SmuzhiyunVERBOSE=0
17*4882a593Smuzhiyun
18*4882a593Smuzhiyunwhich ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun################################################################################
21*4882a593Smuzhiyun# helpers
22*4882a593Smuzhiyun
23*4882a593Smuzhiyunlog_test()
24*4882a593Smuzhiyun{
25*4882a593Smuzhiyun	local rc=$1
26*4882a593Smuzhiyun	local expected=$2
27*4882a593Smuzhiyun	local msg="$3"
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun	if [ ${rc} -eq ${expected} ]; then
30*4882a593Smuzhiyun		printf "TEST: %-60s  [ OK ]\n" "${msg}"
31*4882a593Smuzhiyun		nsuccess=$((nsuccess+1))
32*4882a593Smuzhiyun	else
33*4882a593Smuzhiyun		ret=1
34*4882a593Smuzhiyun		nfail=$((nfail+1))
35*4882a593Smuzhiyun		printf "TEST: %-60s  [FAIL]\n" "${msg}"
36*4882a593Smuzhiyun		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
37*4882a593Smuzhiyun			echo
38*4882a593Smuzhiyun			echo "hit enter to continue, 'q' to quit"
39*4882a593Smuzhiyun			read a
40*4882a593Smuzhiyun			[ "$a" = "q" ] && exit 1
41*4882a593Smuzhiyun		fi
42*4882a593Smuzhiyun	fi
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun	[ "$VERBOSE" = "1" ] && echo
45*4882a593Smuzhiyun}
46*4882a593Smuzhiyun
47*4882a593Smuzhiyunrun_cmd()
48*4882a593Smuzhiyun{
49*4882a593Smuzhiyun	local cmd="$*"
50*4882a593Smuzhiyun	local out
51*4882a593Smuzhiyun	local rc
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun	if [ "$VERBOSE" = "1" ]; then
54*4882a593Smuzhiyun		echo "COMMAND: $cmd"
55*4882a593Smuzhiyun	fi
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun	out=$(eval $cmd 2>&1)
58*4882a593Smuzhiyun	rc=$?
59*4882a593Smuzhiyun	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
60*4882a593Smuzhiyun		echo "$out"
61*4882a593Smuzhiyun	fi
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun	[ "$VERBOSE" = "1" ] && echo
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun	return $rc
66*4882a593Smuzhiyun}
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun################################################################################
69*4882a593Smuzhiyun# config
70*4882a593Smuzhiyun
71*4882a593Smuzhiyuncreate_ns()
72*4882a593Smuzhiyun{
73*4882a593Smuzhiyun	local ns=${1}
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun	ip netns del ${ns} 2>/dev/null
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun	ip netns add ${ns}
78*4882a593Smuzhiyun	ip -netns ${ns} addr add 127.0.0.1/8 dev lo
79*4882a593Smuzhiyun	ip -netns ${ns} link set lo up
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun	ip netns exec ${ns} sysctl -q -w net.ipv6.conf.all.keep_addr_on_down=1
82*4882a593Smuzhiyun	case ${ns} in
83*4882a593Smuzhiyun	h*)
84*4882a593Smuzhiyun		ip netns exec $ns sysctl -q -w net.ipv6.conf.all.forwarding=0
85*4882a593Smuzhiyun		;;
86*4882a593Smuzhiyun	r*)
87*4882a593Smuzhiyun		ip netns exec $ns sysctl -q -w net.ipv4.ip_forward=1
88*4882a593Smuzhiyun		ip netns exec $ns sysctl -q -w net.ipv6.conf.all.forwarding=1
89*4882a593Smuzhiyun		;;
90*4882a593Smuzhiyun	esac
91*4882a593Smuzhiyun}
92*4882a593Smuzhiyun
93*4882a593Smuzhiyunsetup()
94*4882a593Smuzhiyun{
95*4882a593Smuzhiyun	local ns
96*4882a593Smuzhiyun	local i
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun	#set -e
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun	for ns in h0 r1 h1 h2 h3
101*4882a593Smuzhiyun	do
102*4882a593Smuzhiyun		create_ns ${ns}
103*4882a593Smuzhiyun	done
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun	#
106*4882a593Smuzhiyun	# create interconnects
107*4882a593Smuzhiyun	#
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun	for i in 0 1 2 3
110*4882a593Smuzhiyun	do
111*4882a593Smuzhiyun		ip -netns h${i} li add eth0 type veth peer name r1h${i}
112*4882a593Smuzhiyun		ip -netns h${i} li set eth0 up
113*4882a593Smuzhiyun		ip -netns h${i} li set r1h${i} netns r1 name eth${i} up
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun		ip -netns h${i}    addr add dev eth0 172.16.10${i}.1/24
116*4882a593Smuzhiyun		ip -netns h${i} -6 addr add dev eth0 2001:db8:10${i}::1/64
117*4882a593Smuzhiyun		ip -netns r1    addr add dev eth${i} 172.16.10${i}.254/24
118*4882a593Smuzhiyun		ip -netns r1 -6 addr add dev eth${i} 2001:db8:10${i}::64/64
119*4882a593Smuzhiyun	done
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun	ip -netns h0 nexthop add id 4 via 172.16.100.254 dev eth0
122*4882a593Smuzhiyun	ip -netns h0 nexthop add id 6 via 2001:db8:100::64 dev eth0
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun	# routing from h0 to h1-h3 and back
125*4882a593Smuzhiyun	for i in 1 2 3
126*4882a593Smuzhiyun	do
127*4882a593Smuzhiyun		ip -netns h0    ro add 172.16.10${i}.0/24 nhid 4
128*4882a593Smuzhiyun		ip -netns h${i} ro add 172.16.100.0/24 via 172.16.10${i}.254
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun		ip -netns h0    -6 ro add 2001:db8:10${i}::/64 nhid 6
131*4882a593Smuzhiyun		ip -netns h${i} -6 ro add 2001:db8:100::/64 via 2001:db8:10${i}::64
132*4882a593Smuzhiyun	done
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun	if [ "$VERBOSE" = "1" ]; then
135*4882a593Smuzhiyun		echo
136*4882a593Smuzhiyun		echo "host 1 config"
137*4882a593Smuzhiyun		ip -netns h0 li sh
138*4882a593Smuzhiyun		ip -netns h0 ro sh
139*4882a593Smuzhiyun		ip -netns h0 -6 ro sh
140*4882a593Smuzhiyun	fi
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun	#set +e
143*4882a593Smuzhiyun}
144*4882a593Smuzhiyun
145*4882a593Smuzhiyuncleanup()
146*4882a593Smuzhiyun{
147*4882a593Smuzhiyun	for n in h0 r1 h1 h2 h3
148*4882a593Smuzhiyun	do
149*4882a593Smuzhiyun		ip netns del ${n} 2>/dev/null
150*4882a593Smuzhiyun	done
151*4882a593Smuzhiyun}
152*4882a593Smuzhiyun
153*4882a593Smuzhiyunchange_mtu()
154*4882a593Smuzhiyun{
155*4882a593Smuzhiyun	local hostid=$1
156*4882a593Smuzhiyun	local mtu=$2
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun	run_cmd ip -netns h${hostid} li set eth0 mtu ${mtu}
159*4882a593Smuzhiyun	run_cmd ip -netns r1 li set eth${hostid} mtu ${mtu}
160*4882a593Smuzhiyun}
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun################################################################################
163*4882a593Smuzhiyun# validate exceptions
164*4882a593Smuzhiyun
165*4882a593Smuzhiyunvalidate_v4_exception()
166*4882a593Smuzhiyun{
167*4882a593Smuzhiyun	local i=$1
168*4882a593Smuzhiyun	local mtu=$2
169*4882a593Smuzhiyun	local ping_sz=$3
170*4882a593Smuzhiyun	local dst="172.16.10${i}.1"
171*4882a593Smuzhiyun	local h0=172.16.100.1
172*4882a593Smuzhiyun	local r1=172.16.100.254
173*4882a593Smuzhiyun	local rc
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun	if [ ${ping_sz} != "0" ]; then
176*4882a593Smuzhiyun		run_cmd ip netns exec h0 ping -s ${ping_sz} -c5 -w5 ${dst}
177*4882a593Smuzhiyun	fi
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun	if [ "$VERBOSE" = "1" ]; then
180*4882a593Smuzhiyun		echo "Route get"
181*4882a593Smuzhiyun		ip -netns h0 ro get ${dst}
182*4882a593Smuzhiyun		echo "Searching for:"
183*4882a593Smuzhiyun		echo "    cache .* mtu ${mtu}"
184*4882a593Smuzhiyun		echo
185*4882a593Smuzhiyun	fi
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun	ip -netns h0 ro get ${dst} | \
188*4882a593Smuzhiyun	grep -q "cache .* mtu ${mtu}"
189*4882a593Smuzhiyun	rc=$?
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun	log_test $rc 0 "IPv4: host 0 to host ${i}, mtu ${mtu}"
192*4882a593Smuzhiyun}
193*4882a593Smuzhiyun
194*4882a593Smuzhiyunvalidate_v6_exception()
195*4882a593Smuzhiyun{
196*4882a593Smuzhiyun	local i=$1
197*4882a593Smuzhiyun	local mtu=$2
198*4882a593Smuzhiyun	local ping_sz=$3
199*4882a593Smuzhiyun	local dst="2001:db8:10${i}::1"
200*4882a593Smuzhiyun	local h0=2001:db8:100::1
201*4882a593Smuzhiyun	local r1=2001:db8:100::64
202*4882a593Smuzhiyun	local rc
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun	if [ ${ping_sz} != "0" ]; then
205*4882a593Smuzhiyun		run_cmd ip netns exec h0 ${ping6} -s ${ping_sz} -c5 -w5 ${dst}
206*4882a593Smuzhiyun	fi
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun	if [ "$VERBOSE" = "1" ]; then
209*4882a593Smuzhiyun		echo "Route get"
210*4882a593Smuzhiyun		ip -netns h0 -6 ro get ${dst}
211*4882a593Smuzhiyun		echo "Searching for:"
212*4882a593Smuzhiyun		echo "    ${dst} from :: via ${r1} dev eth0 src ${h0} .* mtu ${mtu}"
213*4882a593Smuzhiyun		echo
214*4882a593Smuzhiyun	fi
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun	ip -netns h0 -6 ro get ${dst} | \
217*4882a593Smuzhiyun	grep -q "${dst} from :: via ${r1} dev eth0 src ${h0} .* mtu ${mtu}"
218*4882a593Smuzhiyun	rc=$?
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun	log_test $rc 0 "IPv6: host 0 to host ${i}, mtu ${mtu}"
221*4882a593Smuzhiyun}
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun################################################################################
224*4882a593Smuzhiyun# main
225*4882a593Smuzhiyun
226*4882a593Smuzhiyunwhile getopts :pv o
227*4882a593Smuzhiyundo
228*4882a593Smuzhiyun	case $o in
229*4882a593Smuzhiyun		p) PAUSE_ON_FAIL=yes;;
230*4882a593Smuzhiyun		v) VERBOSE=1;;
231*4882a593Smuzhiyun	esac
232*4882a593Smuzhiyundone
233*4882a593Smuzhiyun
234*4882a593Smuzhiyuncleanup
235*4882a593Smuzhiyunsetup
236*4882a593Smuzhiyunsleep 2
237*4882a593Smuzhiyun
238*4882a593Smuzhiyuncpus=$(cat  /sys/devices/system/cpu/online)
239*4882a593Smuzhiyuncpus="$(seq ${cpus/-/ })"
240*4882a593Smuzhiyunret=0
241*4882a593Smuzhiyunfor i in 1 2 3
242*4882a593Smuzhiyundo
243*4882a593Smuzhiyun	# generate a cached route per-cpu
244*4882a593Smuzhiyun	for c in ${cpus}; do
245*4882a593Smuzhiyun		run_cmd taskset -c ${c} ip netns exec h0 ping -c1 -w1 172.16.10${i}.1
246*4882a593Smuzhiyun		[ $? -ne 0 ] && printf "\nERROR: ping to h${i} failed\n" && ret=1
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun		run_cmd taskset -c ${c} ip netns exec h0 ${ping6} -c1 -w1 2001:db8:10${i}::1
249*4882a593Smuzhiyun		[ $? -ne 0 ] && printf "\nERROR: ping6 to h${i} failed\n" && ret=1
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun		[ $ret -ne 0 ] && break
252*4882a593Smuzhiyun	done
253*4882a593Smuzhiyun	[ $ret -ne 0 ] && break
254*4882a593Smuzhiyundone
255*4882a593Smuzhiyun
256*4882a593Smuzhiyunif [ $ret -eq 0 ]; then
257*4882a593Smuzhiyun	# generate different exceptions in h0 for h1, h2 and h3
258*4882a593Smuzhiyun	change_mtu 1 1300
259*4882a593Smuzhiyun	validate_v4_exception 1 1300 1350
260*4882a593Smuzhiyun	validate_v6_exception 1 1300 1350
261*4882a593Smuzhiyun	echo
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun	change_mtu 2 1350
264*4882a593Smuzhiyun	validate_v4_exception 2 1350 1400
265*4882a593Smuzhiyun	validate_v6_exception 2 1350 1400
266*4882a593Smuzhiyun	echo
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun	change_mtu 3 1400
269*4882a593Smuzhiyun	validate_v4_exception 3 1400 1450
270*4882a593Smuzhiyun	validate_v6_exception 3 1400 1450
271*4882a593Smuzhiyun	echo
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun	validate_v4_exception 1 1300 0
274*4882a593Smuzhiyun	validate_v6_exception 1 1300 0
275*4882a593Smuzhiyun	echo
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun	validate_v4_exception 2 1350 0
278*4882a593Smuzhiyun	validate_v6_exception 2 1350 0
279*4882a593Smuzhiyun	echo
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun	validate_v4_exception 3 1400 0
282*4882a593Smuzhiyun	validate_v6_exception 3 1400 0
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun	# targeted deletes to trigger cleanup paths in kernel
285*4882a593Smuzhiyun	ip -netns h0 ro del 172.16.102.0/24 nhid 4
286*4882a593Smuzhiyun	ip -netns h0 -6 ro del 2001:db8:102::/64 nhid 6
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun	ip -netns h0 nexthop del id 4
289*4882a593Smuzhiyun	ip -netns h0 nexthop del id 6
290*4882a593Smuzhiyunfi
291*4882a593Smuzhiyun
292*4882a593Smuzhiyuncleanup
293