xref: /OK3568_Linux_fs/kernel/tools/testing/selftests/net/traceroute.sh (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/bin/bash
2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0
3*4882a593Smuzhiyun#
4*4882a593Smuzhiyun# Run traceroute/traceroute6 tests
5*4882a593Smuzhiyun#
6*4882a593Smuzhiyun
7*4882a593SmuzhiyunVERBOSE=0
8*4882a593SmuzhiyunPAUSE_ON_FAIL=no
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun################################################################################
11*4882a593Smuzhiyun#
12*4882a593Smuzhiyunlog_test()
13*4882a593Smuzhiyun{
14*4882a593Smuzhiyun	local rc=$1
15*4882a593Smuzhiyun	local expected=$2
16*4882a593Smuzhiyun	local msg="$3"
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun	if [ ${rc} -eq ${expected} ]; then
19*4882a593Smuzhiyun		printf "TEST: %-60s  [ OK ]\n" "${msg}"
20*4882a593Smuzhiyun		nsuccess=$((nsuccess+1))
21*4882a593Smuzhiyun	else
22*4882a593Smuzhiyun		ret=1
23*4882a593Smuzhiyun		nfail=$((nfail+1))
24*4882a593Smuzhiyun		printf "TEST: %-60s  [FAIL]\n" "${msg}"
25*4882a593Smuzhiyun		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
26*4882a593Smuzhiyun			echo
27*4882a593Smuzhiyun			echo "hit enter to continue, 'q' to quit"
28*4882a593Smuzhiyun			read a
29*4882a593Smuzhiyun			[ "$a" = "q" ] && exit 1
30*4882a593Smuzhiyun		fi
31*4882a593Smuzhiyun	fi
32*4882a593Smuzhiyun}
33*4882a593Smuzhiyun
34*4882a593Smuzhiyunrun_cmd()
35*4882a593Smuzhiyun{
36*4882a593Smuzhiyun	local ns
37*4882a593Smuzhiyun	local cmd
38*4882a593Smuzhiyun	local out
39*4882a593Smuzhiyun	local rc
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun	ns="$1"
42*4882a593Smuzhiyun	shift
43*4882a593Smuzhiyun	cmd="$*"
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun	if [ "$VERBOSE" = "1" ]; then
46*4882a593Smuzhiyun		printf "    COMMAND: $cmd\n"
47*4882a593Smuzhiyun	fi
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun	out=$(eval ip netns exec ${ns} ${cmd} 2>&1)
50*4882a593Smuzhiyun	rc=$?
51*4882a593Smuzhiyun	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
52*4882a593Smuzhiyun		echo "    $out"
53*4882a593Smuzhiyun	fi
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun	[ "$VERBOSE" = "1" ] && echo
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun	return $rc
58*4882a593Smuzhiyun}
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun################################################################################
61*4882a593Smuzhiyun# create namespaces and interconnects
62*4882a593Smuzhiyun
63*4882a593Smuzhiyuncreate_ns()
64*4882a593Smuzhiyun{
65*4882a593Smuzhiyun	local ns=$1
66*4882a593Smuzhiyun	local addr=$2
67*4882a593Smuzhiyun	local addr6=$3
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun	[ -z "${addr}" ] && addr="-"
70*4882a593Smuzhiyun	[ -z "${addr6}" ] && addr6="-"
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun	ip netns add ${ns}
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun	ip netns exec ${ns} ip link set lo up
75*4882a593Smuzhiyun	if [ "${addr}" != "-" ]; then
76*4882a593Smuzhiyun		ip netns exec ${ns} ip addr add dev lo ${addr}
77*4882a593Smuzhiyun	fi
78*4882a593Smuzhiyun	if [ "${addr6}" != "-" ]; then
79*4882a593Smuzhiyun		ip netns exec ${ns} ip -6 addr add dev lo ${addr6}
80*4882a593Smuzhiyun	fi
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun	ip netns exec ${ns} ip ro add unreachable default metric 8192
83*4882a593Smuzhiyun	ip netns exec ${ns} ip -6 ro add unreachable default metric 8192
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun	ip netns exec ${ns} sysctl -qw net.ipv4.ip_forward=1
86*4882a593Smuzhiyun	ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1
87*4882a593Smuzhiyun	ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.forwarding=1
88*4882a593Smuzhiyun	ip netns exec ${ns} sysctl -qw net.ipv6.conf.default.forwarding=1
89*4882a593Smuzhiyun	ip netns exec ${ns} sysctl -qw net.ipv6.conf.default.accept_dad=0
90*4882a593Smuzhiyun}
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun# create veth pair to connect namespaces and apply addresses.
93*4882a593Smuzhiyunconnect_ns()
94*4882a593Smuzhiyun{
95*4882a593Smuzhiyun	local ns1=$1
96*4882a593Smuzhiyun	local ns1_dev=$2
97*4882a593Smuzhiyun	local ns1_addr=$3
98*4882a593Smuzhiyun	local ns1_addr6=$4
99*4882a593Smuzhiyun	local ns2=$5
100*4882a593Smuzhiyun	local ns2_dev=$6
101*4882a593Smuzhiyun	local ns2_addr=$7
102*4882a593Smuzhiyun	local ns2_addr6=$8
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun	ip netns exec ${ns1} ip li add ${ns1_dev} type veth peer name tmp
105*4882a593Smuzhiyun	ip netns exec ${ns1} ip li set ${ns1_dev} up
106*4882a593Smuzhiyun	ip netns exec ${ns1} ip li set tmp netns ${ns2} name ${ns2_dev}
107*4882a593Smuzhiyun	ip netns exec ${ns2} ip li set ${ns2_dev} up
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun	if [ "${ns1_addr}" != "-" ]; then
110*4882a593Smuzhiyun		ip netns exec ${ns1} ip addr add dev ${ns1_dev} ${ns1_addr}
111*4882a593Smuzhiyun	fi
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun	if [ "${ns2_addr}" != "-" ]; then
114*4882a593Smuzhiyun		ip netns exec ${ns2} ip addr add dev ${ns2_dev} ${ns2_addr}
115*4882a593Smuzhiyun	fi
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun	if [ "${ns1_addr6}" != "-" ]; then
118*4882a593Smuzhiyun		ip netns exec ${ns1} ip addr add dev ${ns1_dev} ${ns1_addr6}
119*4882a593Smuzhiyun	fi
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun	if [ "${ns2_addr6}" != "-" ]; then
122*4882a593Smuzhiyun		ip netns exec ${ns2} ip addr add dev ${ns2_dev} ${ns2_addr6}
123*4882a593Smuzhiyun	fi
124*4882a593Smuzhiyun}
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun################################################################################
127*4882a593Smuzhiyun# traceroute6 test
128*4882a593Smuzhiyun#
129*4882a593Smuzhiyun# Verify that in this scenario
130*4882a593Smuzhiyun#
131*4882a593Smuzhiyun#        ------------------------ N2
132*4882a593Smuzhiyun#         |                    |
133*4882a593Smuzhiyun#       ------              ------  N3  ----
134*4882a593Smuzhiyun#       | R1 |              | R2 |------|H2|
135*4882a593Smuzhiyun#       ------              ------      ----
136*4882a593Smuzhiyun#         |                    |
137*4882a593Smuzhiyun#        ------------------------ N1
138*4882a593Smuzhiyun#                  |
139*4882a593Smuzhiyun#                 ----
140*4882a593Smuzhiyun#                 |H1|
141*4882a593Smuzhiyun#                 ----
142*4882a593Smuzhiyun#
143*4882a593Smuzhiyun# where H1's default route goes through R1 and R1's default route goes
144*4882a593Smuzhiyun# through R2 over N2, traceroute6 from H1 to H2 reports R2's address
145*4882a593Smuzhiyun# on N2 and not N1.
146*4882a593Smuzhiyun#
147*4882a593Smuzhiyun# Addresses are assigned as follows:
148*4882a593Smuzhiyun#
149*4882a593Smuzhiyun# N1: 2000:101::/64
150*4882a593Smuzhiyun# N2: 2000:102::/64
151*4882a593Smuzhiyun# N3: 2000:103::/64
152*4882a593Smuzhiyun#
153*4882a593Smuzhiyun# R1's host part of address: 1
154*4882a593Smuzhiyun# R2's host part of address: 2
155*4882a593Smuzhiyun# H1's host part of address: 3
156*4882a593Smuzhiyun# H2's host part of address: 4
157*4882a593Smuzhiyun#
158*4882a593Smuzhiyun# For example:
159*4882a593Smuzhiyun# the IPv6 address of R1's interface on N2 is 2000:102::1/64
160*4882a593Smuzhiyun
161*4882a593Smuzhiyuncleanup_traceroute6()
162*4882a593Smuzhiyun{
163*4882a593Smuzhiyun	local ns
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun	for ns in host-1 host-2 router-1 router-2
166*4882a593Smuzhiyun	do
167*4882a593Smuzhiyun		ip netns del ${ns} 2>/dev/null
168*4882a593Smuzhiyun	done
169*4882a593Smuzhiyun}
170*4882a593Smuzhiyun
171*4882a593Smuzhiyunsetup_traceroute6()
172*4882a593Smuzhiyun{
173*4882a593Smuzhiyun	brdev=br0
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun	# start clean
176*4882a593Smuzhiyun	cleanup_traceroute6
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun	set -e
179*4882a593Smuzhiyun	create_ns host-1
180*4882a593Smuzhiyun	create_ns host-2
181*4882a593Smuzhiyun	create_ns router-1
182*4882a593Smuzhiyun	create_ns router-2
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun	# Setup N3
185*4882a593Smuzhiyun	connect_ns router-2 eth3 - 2000:103::2/64 host-2 eth3 - 2000:103::4/64
186*4882a593Smuzhiyun	ip netns exec host-2 ip route add default via 2000:103::2
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun	# Setup N2
189*4882a593Smuzhiyun	connect_ns router-1 eth2 - 2000:102::1/64 router-2 eth2 - 2000:102::2/64
190*4882a593Smuzhiyun	ip netns exec router-1 ip route add default via 2000:102::2
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun	# Setup N1. host-1 and router-2 connect to a bridge in router-1.
193*4882a593Smuzhiyun	ip netns exec router-1 ip link add name ${brdev} type bridge
194*4882a593Smuzhiyun	ip netns exec router-1 ip link set ${brdev} up
195*4882a593Smuzhiyun	ip netns exec router-1 ip addr add 2000:101::1/64 dev ${brdev}
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun	connect_ns host-1 eth0 - 2000:101::3/64 router-1 eth0 - -
198*4882a593Smuzhiyun	ip netns exec router-1 ip link set dev eth0 master ${brdev}
199*4882a593Smuzhiyun	ip netns exec host-1 ip route add default via 2000:101::1
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun	connect_ns router-2 eth1 - 2000:101::2/64 router-1 eth1 - -
202*4882a593Smuzhiyun	ip netns exec router-1 ip link set dev eth1 master ${brdev}
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun	# Prime the network
205*4882a593Smuzhiyun	ip netns exec host-1 ping6 -c5 2000:103::4 >/dev/null 2>&1
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun	set +e
208*4882a593Smuzhiyun}
209*4882a593Smuzhiyun
210*4882a593Smuzhiyunrun_traceroute6()
211*4882a593Smuzhiyun{
212*4882a593Smuzhiyun	if [ ! -x "$(command -v traceroute6)" ]; then
213*4882a593Smuzhiyun		echo "SKIP: Could not run IPV6 test without traceroute6"
214*4882a593Smuzhiyun		return
215*4882a593Smuzhiyun	fi
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun	setup_traceroute6
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun	# traceroute6 host-2 from host-1 (expects 2000:102::2)
220*4882a593Smuzhiyun	run_cmd host-1 "traceroute6 2000:103::4 | grep -q 2000:102::2"
221*4882a593Smuzhiyun	log_test $? 0 "IPV6 traceroute"
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun	cleanup_traceroute6
224*4882a593Smuzhiyun}
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun################################################################################
227*4882a593Smuzhiyun# traceroute test
228*4882a593Smuzhiyun#
229*4882a593Smuzhiyun# Verify that traceroute from H1 to H2 shows 1.0.1.1 in this scenario
230*4882a593Smuzhiyun#
231*4882a593Smuzhiyun#                    1.0.3.1/24
232*4882a593Smuzhiyun# ---- 1.0.1.3/24    1.0.1.1/24 ---- 1.0.2.1/24    1.0.2.4/24 ----
233*4882a593Smuzhiyun# |H1|--------------------------|R1|--------------------------|H2|
234*4882a593Smuzhiyun# ----            N1            ----            N2            ----
235*4882a593Smuzhiyun#
236*4882a593Smuzhiyun# where net.ipv4.icmp_errors_use_inbound_ifaddr is set on R1 and
237*4882a593Smuzhiyun# 1.0.3.1/24 and 1.0.1.1/24 are respectively R1's primary and secondary
238*4882a593Smuzhiyun# address on N1.
239*4882a593Smuzhiyun#
240*4882a593Smuzhiyun
241*4882a593Smuzhiyuncleanup_traceroute()
242*4882a593Smuzhiyun{
243*4882a593Smuzhiyun	local ns
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun	for ns in host-1 host-2 router
246*4882a593Smuzhiyun	do
247*4882a593Smuzhiyun		ip netns del ${ns} 2>/dev/null
248*4882a593Smuzhiyun	done
249*4882a593Smuzhiyun}
250*4882a593Smuzhiyun
251*4882a593Smuzhiyunsetup_traceroute()
252*4882a593Smuzhiyun{
253*4882a593Smuzhiyun	# start clean
254*4882a593Smuzhiyun	cleanup_traceroute
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun	set -e
257*4882a593Smuzhiyun	create_ns host-1
258*4882a593Smuzhiyun	create_ns host-2
259*4882a593Smuzhiyun	create_ns router
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun	connect_ns host-1 eth0 1.0.1.3/24 - \
262*4882a593Smuzhiyun	           router eth1 1.0.3.1/24 -
263*4882a593Smuzhiyun	ip netns exec host-1 ip route add default via 1.0.1.1
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun	ip netns exec router ip addr add 1.0.1.1/24 dev eth1
266*4882a593Smuzhiyun	ip netns exec router sysctl -qw \
267*4882a593Smuzhiyun				net.ipv4.icmp_errors_use_inbound_ifaddr=1
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun	connect_ns host-2 eth0 1.0.2.4/24 - \
270*4882a593Smuzhiyun	           router eth2 1.0.2.1/24 -
271*4882a593Smuzhiyun	ip netns exec host-2 ip route add default via 1.0.2.1
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun	# Prime the network
274*4882a593Smuzhiyun	ip netns exec host-1 ping -c5 1.0.2.4 >/dev/null 2>&1
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun	set +e
277*4882a593Smuzhiyun}
278*4882a593Smuzhiyun
279*4882a593Smuzhiyunrun_traceroute()
280*4882a593Smuzhiyun{
281*4882a593Smuzhiyun	if [ ! -x "$(command -v traceroute)" ]; then
282*4882a593Smuzhiyun		echo "SKIP: Could not run IPV4 test without traceroute"
283*4882a593Smuzhiyun		return
284*4882a593Smuzhiyun	fi
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun	setup_traceroute
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun	# traceroute host-2 from host-1 (expects 1.0.1.1). Takes a while.
289*4882a593Smuzhiyun	run_cmd host-1 "traceroute 1.0.2.4 | grep -q 1.0.1.1"
290*4882a593Smuzhiyun	log_test $? 0 "IPV4 traceroute"
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun	cleanup_traceroute
293*4882a593Smuzhiyun}
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun################################################################################
296*4882a593Smuzhiyun# Run tests
297*4882a593Smuzhiyun
298*4882a593Smuzhiyunrun_tests()
299*4882a593Smuzhiyun{
300*4882a593Smuzhiyun	run_traceroute6
301*4882a593Smuzhiyun	run_traceroute
302*4882a593Smuzhiyun}
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun################################################################################
305*4882a593Smuzhiyun# main
306*4882a593Smuzhiyun
307*4882a593Smuzhiyundeclare -i nfail=0
308*4882a593Smuzhiyundeclare -i nsuccess=0
309*4882a593Smuzhiyun
310*4882a593Smuzhiyunwhile getopts :pv o
311*4882a593Smuzhiyundo
312*4882a593Smuzhiyun	case $o in
313*4882a593Smuzhiyun		p) PAUSE_ON_FAIL=yes;;
314*4882a593Smuzhiyun		v) VERBOSE=$(($VERBOSE + 1));;
315*4882a593Smuzhiyun		*) exit 1;;
316*4882a593Smuzhiyun	esac
317*4882a593Smuzhiyundone
318*4882a593Smuzhiyun
319*4882a593Smuzhiyunrun_tests
320*4882a593Smuzhiyun
321*4882a593Smuzhiyunprintf "\nTests passed: %3d\n" ${nsuccess}
322*4882a593Smuzhiyunprintf "Tests failed: %3d\n"   ${nfail}
323