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