blob: 782db6ccef3237712453b2eef5aae81527e25144 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# This test is for checking IPv4 and IPv6 FIB behavior in response to
5# different events.
6
7ret=0
8# Kselftest framework requirement - SKIP code is 4.
9ksft_skip=4
10
11# all tests in this script. Can be overridden with -t option
12TESTS="unregister down carrier nexthop suppress ipv6_rt ipv4_rt ipv6_addr_metric ipv4_addr_metric ipv6_route_metrics ipv4_route_metrics ipv4_route_v6_gw rp_filter"
13
14VERBOSE=0
15PAUSE_ON_FAIL=no
16PAUSE=no
17IP="ip -netns ns1"
18NS_EXEC="ip netns exec ns1"
19
20which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
21
22log_test()
23{
24 local rc=$1
25 local expected=$2
26 local msg="$3"
27
28 if [ ${rc} -eq ${expected} ]; then
29 printf " TEST: %-60s [ OK ]\n" "${msg}"
30 nsuccess=$((nsuccess+1))
31 else
32 ret=1
33 nfail=$((nfail+1))
34 printf " TEST: %-60s [FAIL]\n" "${msg}"
35 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
36 echo
37 echo "hit enter to continue, 'q' to quit"
38 read a
39 [ "$a" = "q" ] && exit 1
40 fi
41 fi
42
43 if [ "${PAUSE}" = "yes" ]; then
44 echo
45 echo "hit enter to continue, 'q' to quit"
46 read a
47 [ "$a" = "q" ] && exit 1
48 fi
49}
50
51setup()
52{
53 set -e
54 ip netns add ns1
55 ip netns set ns1 auto
56 $IP link set dev lo up
57 ip netns exec ns1 sysctl -qw net.ipv4.ip_forward=1
58 ip netns exec ns1 sysctl -qw net.ipv6.conf.all.forwarding=1
59
60 $IP link add dummy0 type dummy
61 $IP link set dev dummy0 up
62 $IP address add 198.51.100.1/24 dev dummy0
63 $IP -6 address add 2001:db8:1::1/64 dev dummy0
64 set +e
65
66}
67
68cleanup()
69{
70 $IP link del dev dummy0 &> /dev/null
71 ip netns del ns1 &> /dev/null
72 ip netns del ns2 &> /dev/null
73}
74
75get_linklocal()
76{
77 local dev=$1
78 local addr
79
80 addr=$($IP -6 -br addr show dev ${dev} | \
81 awk '{
82 for (i = 3; i <= NF; ++i) {
83 if ($i ~ /^fe80/)
84 print $i
85 }
86 }'
87 )
88 addr=${addr/\/*}
89
90 [ -z "$addr" ] && return 1
91
92 echo $addr
93
94 return 0
95}
96
97fib_unreg_unicast_test()
98{
99 echo
100 echo "Single path route test"
101
102 setup
103
104 echo " Start point"
105 $IP route get fibmatch 198.51.100.2 &> /dev/null
106 log_test $? 0 "IPv4 fibmatch"
107 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
108 log_test $? 0 "IPv6 fibmatch"
109
110 set -e
111 $IP link del dev dummy0
112 set +e
113
114 echo " Nexthop device deleted"
115 $IP route get fibmatch 198.51.100.2 &> /dev/null
116 log_test $? 2 "IPv4 fibmatch - no route"
117 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
118 log_test $? 2 "IPv6 fibmatch - no route"
119
120 cleanup
121}
122
123fib_unreg_multipath_test()
124{
125
126 echo
127 echo "Multipath route test"
128
129 setup
130
131 set -e
132 $IP link add dummy1 type dummy
133 $IP link set dev dummy1 up
134 $IP address add 192.0.2.1/24 dev dummy1
135 $IP -6 address add 2001:db8:2::1/64 dev dummy1
136
137 $IP route add 203.0.113.0/24 \
138 nexthop via 198.51.100.2 dev dummy0 \
139 nexthop via 192.0.2.2 dev dummy1
140 $IP -6 route add 2001:db8:3::/64 \
141 nexthop via 2001:db8:1::2 dev dummy0 \
142 nexthop via 2001:db8:2::2 dev dummy1
143 set +e
144
145 echo " Start point"
146 $IP route get fibmatch 203.0.113.1 &> /dev/null
147 log_test $? 0 "IPv4 fibmatch"
148 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
149 log_test $? 0 "IPv6 fibmatch"
150
151 set -e
152 $IP link del dev dummy0
153 set +e
154
155 echo " One nexthop device deleted"
156 $IP route get fibmatch 203.0.113.1 &> /dev/null
157 log_test $? 2 "IPv4 - multipath route removed on delete"
158
159 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
160 # In IPv6 we do not flush the entire multipath route.
161 log_test $? 0 "IPv6 - multipath down to single path"
162
163 set -e
164 $IP link del dev dummy1
165 set +e
166
167 echo " Second nexthop device deleted"
168 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
169 log_test $? 2 "IPv6 - no route"
170
171 cleanup
172}
173
174fib_unreg_test()
175{
176 fib_unreg_unicast_test
177 fib_unreg_multipath_test
178}
179
180fib_down_unicast_test()
181{
182 echo
183 echo "Single path, admin down"
184
185 setup
186
187 echo " Start point"
188 $IP route get fibmatch 198.51.100.2 &> /dev/null
189 log_test $? 0 "IPv4 fibmatch"
190 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
191 log_test $? 0 "IPv6 fibmatch"
192
193 set -e
194 $IP link set dev dummy0 down
195 set +e
196
197 echo " Route deleted on down"
198 $IP route get fibmatch 198.51.100.2 &> /dev/null
199 log_test $? 2 "IPv4 fibmatch"
200 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
201 log_test $? 2 "IPv6 fibmatch"
202
203 cleanup
204}
205
206fib_down_multipath_test_do()
207{
208 local down_dev=$1
209 local up_dev=$2
210
211 $IP route get fibmatch 203.0.113.1 \
212 oif $down_dev &> /dev/null
213 log_test $? 2 "IPv4 fibmatch on down device"
214 $IP -6 route get fibmatch 2001:db8:3::1 \
215 oif $down_dev &> /dev/null
216 log_test $? 2 "IPv6 fibmatch on down device"
217
218 $IP route get fibmatch 203.0.113.1 \
219 oif $up_dev &> /dev/null
220 log_test $? 0 "IPv4 fibmatch on up device"
221 $IP -6 route get fibmatch 2001:db8:3::1 \
222 oif $up_dev &> /dev/null
223 log_test $? 0 "IPv6 fibmatch on up device"
224
225 $IP route get fibmatch 203.0.113.1 | \
226 grep $down_dev | grep -q "dead linkdown"
227 log_test $? 0 "IPv4 flags on down device"
228 $IP -6 route get fibmatch 2001:db8:3::1 | \
229 grep $down_dev | grep -q "dead linkdown"
230 log_test $? 0 "IPv6 flags on down device"
231
232 $IP route get fibmatch 203.0.113.1 | \
233 grep $up_dev | grep -q "dead linkdown"
234 log_test $? 1 "IPv4 flags on up device"
235 $IP -6 route get fibmatch 2001:db8:3::1 | \
236 grep $up_dev | grep -q "dead linkdown"
237 log_test $? 1 "IPv6 flags on up device"
238}
239
240fib_down_multipath_test()
241{
242 echo
243 echo "Admin down multipath"
244
245 setup
246
247 set -e
248 $IP link add dummy1 type dummy
249 $IP link set dev dummy1 up
250
251 $IP address add 192.0.2.1/24 dev dummy1
252 $IP -6 address add 2001:db8:2::1/64 dev dummy1
253
254 $IP route add 203.0.113.0/24 \
255 nexthop via 198.51.100.2 dev dummy0 \
256 nexthop via 192.0.2.2 dev dummy1
257 $IP -6 route add 2001:db8:3::/64 \
258 nexthop via 2001:db8:1::2 dev dummy0 \
259 nexthop via 2001:db8:2::2 dev dummy1
260 set +e
261
262 echo " Verify start point"
263 $IP route get fibmatch 203.0.113.1 &> /dev/null
264 log_test $? 0 "IPv4 fibmatch"
265
266 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
267 log_test $? 0 "IPv6 fibmatch"
268
269 set -e
270 $IP link set dev dummy0 down
271 set +e
272
273 echo " One device down, one up"
274 fib_down_multipath_test_do "dummy0" "dummy1"
275
276 set -e
277 $IP link set dev dummy0 up
278 $IP link set dev dummy1 down
279 set +e
280
281 echo " Other device down and up"
282 fib_down_multipath_test_do "dummy1" "dummy0"
283
284 set -e
285 $IP link set dev dummy0 down
286 set +e
287
288 echo " Both devices down"
289 $IP route get fibmatch 203.0.113.1 &> /dev/null
290 log_test $? 2 "IPv4 fibmatch"
291 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
292 log_test $? 2 "IPv6 fibmatch"
293
294 $IP link del dev dummy1
295 cleanup
296}
297
298fib_down_test()
299{
300 fib_down_unicast_test
301 fib_down_multipath_test
302}
303
304# Local routes should not be affected when carrier changes.
305fib_carrier_local_test()
306{
307 echo
308 echo "Local carrier tests - single path"
309
310 setup
311
312 set -e
313 $IP link set dev dummy0 carrier on
314 set +e
315
316 echo " Start point"
317 $IP route get fibmatch 198.51.100.1 &> /dev/null
318 log_test $? 0 "IPv4 fibmatch"
319 $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
320 log_test $? 0 "IPv6 fibmatch"
321
322 $IP route get fibmatch 198.51.100.1 | \
323 grep -q "linkdown"
324 log_test $? 1 "IPv4 - no linkdown flag"
325 $IP -6 route get fibmatch 2001:db8:1::1 | \
326 grep -q "linkdown"
327 log_test $? 1 "IPv6 - no linkdown flag"
328
329 set -e
330 $IP link set dev dummy0 carrier off
331 sleep 1
332 set +e
333
334 echo " Carrier off on nexthop"
335 $IP route get fibmatch 198.51.100.1 &> /dev/null
336 log_test $? 0 "IPv4 fibmatch"
337 $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
338 log_test $? 0 "IPv6 fibmatch"
339
340 $IP route get fibmatch 198.51.100.1 | \
341 grep -q "linkdown"
342 log_test $? 1 "IPv4 - linkdown flag set"
343 $IP -6 route get fibmatch 2001:db8:1::1 | \
344 grep -q "linkdown"
345 log_test $? 1 "IPv6 - linkdown flag set"
346
347 set -e
348 $IP address add 192.0.2.1/24 dev dummy0
349 $IP -6 address add 2001:db8:2::1/64 dev dummy0
350 set +e
351
352 echo " Route to local address with carrier down"
353 $IP route get fibmatch 192.0.2.1 &> /dev/null
354 log_test $? 0 "IPv4 fibmatch"
355 $IP -6 route get fibmatch 2001:db8:2::1 &> /dev/null
356 log_test $? 0 "IPv6 fibmatch"
357
358 $IP route get fibmatch 192.0.2.1 | \
359 grep -q "linkdown"
360 log_test $? 1 "IPv4 linkdown flag set"
361 $IP -6 route get fibmatch 2001:db8:2::1 | \
362 grep -q "linkdown"
363 log_test $? 1 "IPv6 linkdown flag set"
364
365 cleanup
366}
367
368fib_carrier_unicast_test()
369{
370 ret=0
371
372 echo
373 echo "Single path route carrier test"
374
375 setup
376
377 set -e
378 $IP link set dev dummy0 carrier on
379 set +e
380
381 echo " Start point"
382 $IP route get fibmatch 198.51.100.2 &> /dev/null
383 log_test $? 0 "IPv4 fibmatch"
384 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
385 log_test $? 0 "IPv6 fibmatch"
386
387 $IP route get fibmatch 198.51.100.2 | \
388 grep -q "linkdown"
389 log_test $? 1 "IPv4 no linkdown flag"
390 $IP -6 route get fibmatch 2001:db8:1::2 | \
391 grep -q "linkdown"
392 log_test $? 1 "IPv6 no linkdown flag"
393
394 set -e
395 $IP link set dev dummy0 carrier off
396 sleep 1
397 set +e
398
399 echo " Carrier down"
400 $IP route get fibmatch 198.51.100.2 &> /dev/null
401 log_test $? 0 "IPv4 fibmatch"
402 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
403 log_test $? 0 "IPv6 fibmatch"
404
405 $IP route get fibmatch 198.51.100.2 | \
406 grep -q "linkdown"
407 log_test $? 0 "IPv4 linkdown flag set"
408 $IP -6 route get fibmatch 2001:db8:1::2 | \
409 grep -q "linkdown"
410 log_test $? 0 "IPv6 linkdown flag set"
411
412 set -e
413 $IP address add 192.0.2.1/24 dev dummy0
414 $IP -6 address add 2001:db8:2::1/64 dev dummy0
415 set +e
416
417 echo " Second address added with carrier down"
418 $IP route get fibmatch 192.0.2.2 &> /dev/null
419 log_test $? 0 "IPv4 fibmatch"
420 $IP -6 route get fibmatch 2001:db8:2::2 &> /dev/null
421 log_test $? 0 "IPv6 fibmatch"
422
423 $IP route get fibmatch 192.0.2.2 | \
424 grep -q "linkdown"
425 log_test $? 0 "IPv4 linkdown flag set"
426 $IP -6 route get fibmatch 2001:db8:2::2 | \
427 grep -q "linkdown"
428 log_test $? 0 "IPv6 linkdown flag set"
429
430 cleanup
431}
432
433fib_carrier_test()
434{
435 fib_carrier_local_test
436 fib_carrier_unicast_test
437}
438
439fib_rp_filter_test()
440{
441 echo
442 echo "IPv4 rp_filter tests"
443
444 setup
445
446 set -e
447 ip netns add ns2
448 ip netns set ns2 auto
449
450 ip -netns ns2 link set dev lo up
451
452 $IP link add name veth1 type veth peer name veth2
453 $IP link set dev veth2 netns ns2
454 $IP address add 192.0.2.1/24 dev veth1
455 ip -netns ns2 address add 192.0.2.1/24 dev veth2
456 $IP link set dev veth1 up
457 ip -netns ns2 link set dev veth2 up
458
459 $IP link set dev lo address 52:54:00:6a:c7:5e
460 $IP link set dev veth1 address 52:54:00:6a:c7:5e
461 ip -netns ns2 link set dev lo address 52:54:00:6a:c7:5e
462 ip -netns ns2 link set dev veth2 address 52:54:00:6a:c7:5e
463
464 # 1. (ns2) redirect lo's egress to veth2's egress
465 ip netns exec ns2 tc qdisc add dev lo parent root handle 1: fq_codel
466 ip netns exec ns2 tc filter add dev lo parent 1: protocol arp basic \
467 action mirred egress redirect dev veth2
468 ip netns exec ns2 tc filter add dev lo parent 1: protocol ip basic \
469 action mirred egress redirect dev veth2
470
471 # 2. (ns1) redirect veth1's ingress to lo's ingress
472 $NS_EXEC tc qdisc add dev veth1 ingress
473 $NS_EXEC tc filter add dev veth1 ingress protocol arp basic \
474 action mirred ingress redirect dev lo
475 $NS_EXEC tc filter add dev veth1 ingress protocol ip basic \
476 action mirred ingress redirect dev lo
477
478 # 3. (ns1) redirect lo's egress to veth1's egress
479 $NS_EXEC tc qdisc add dev lo parent root handle 1: fq_codel
480 $NS_EXEC tc filter add dev lo parent 1: protocol arp basic \
481 action mirred egress redirect dev veth1
482 $NS_EXEC tc filter add dev lo parent 1: protocol ip basic \
483 action mirred egress redirect dev veth1
484
485 # 4. (ns2) redirect veth2's ingress to lo's ingress
486 ip netns exec ns2 tc qdisc add dev veth2 ingress
487 ip netns exec ns2 tc filter add dev veth2 ingress protocol arp basic \
488 action mirred ingress redirect dev lo
489 ip netns exec ns2 tc filter add dev veth2 ingress protocol ip basic \
490 action mirred ingress redirect dev lo
491
492 $NS_EXEC sysctl -qw net.ipv4.conf.all.rp_filter=1
493 $NS_EXEC sysctl -qw net.ipv4.conf.all.accept_local=1
494 $NS_EXEC sysctl -qw net.ipv4.conf.all.route_localnet=1
495 ip netns exec ns2 sysctl -qw net.ipv4.conf.all.rp_filter=1
496 ip netns exec ns2 sysctl -qw net.ipv4.conf.all.accept_local=1
497 ip netns exec ns2 sysctl -qw net.ipv4.conf.all.route_localnet=1
498 set +e
499
500 run_cmd "ip netns exec ns2 ping -w1 -c1 192.0.2.1"
501 log_test $? 0 "rp_filter passes local packets"
502
503 run_cmd "ip netns exec ns2 ping -w1 -c1 127.0.0.1"
504 log_test $? 0 "rp_filter passes loopback packets"
505
506 cleanup
507}
508
509################################################################################
510# Tests on nexthop spec
511
512# run 'ip route add' with given spec
513add_rt()
514{
515 local desc="$1"
516 local erc=$2
517 local vrf=$3
518 local pfx=$4
519 local gw=$5
520 local dev=$6
521 local cmd out rc
522
523 [ "$vrf" = "-" ] && vrf="default"
524 [ -n "$gw" ] && gw="via $gw"
525 [ -n "$dev" ] && dev="dev $dev"
526
527 cmd="$IP route add vrf $vrf $pfx $gw $dev"
528 if [ "$VERBOSE" = "1" ]; then
529 printf "\n COMMAND: $cmd\n"
530 fi
531
532 out=$(eval $cmd 2>&1)
533 rc=$?
534 if [ "$VERBOSE" = "1" -a -n "$out" ]; then
535 echo " $out"
536 fi
537 log_test $rc $erc "$desc"
538}
539
540fib4_nexthop()
541{
542 echo
543 echo "IPv4 nexthop tests"
544
545 echo "<<< write me >>>"
546}
547
548fib6_nexthop()
549{
550 local lldummy=$(get_linklocal dummy0)
551 local llv1=$(get_linklocal dummy0)
552
553 if [ -z "$lldummy" ]; then
554 echo "Failed to get linklocal address for dummy0"
555 return 1
556 fi
557 if [ -z "$llv1" ]; then
558 echo "Failed to get linklocal address for veth1"
559 return 1
560 fi
561
562 echo
563 echo "IPv6 nexthop tests"
564
565 add_rt "Directly connected nexthop, unicast address" 0 \
566 - 2001:db8:101::/64 2001:db8:1::2
567 add_rt "Directly connected nexthop, unicast address with device" 0 \
568 - 2001:db8:102::/64 2001:db8:1::2 "dummy0"
569 add_rt "Gateway is linklocal address" 0 \
570 - 2001:db8:103::1/64 $llv1 "veth0"
571
572 # fails because LL address requires a device
573 add_rt "Gateway is linklocal address, no device" 2 \
574 - 2001:db8:104::1/64 $llv1
575
576 # local address can not be a gateway
577 add_rt "Gateway can not be local unicast address" 2 \
578 - 2001:db8:105::/64 2001:db8:1::1
579 add_rt "Gateway can not be local unicast address, with device" 2 \
580 - 2001:db8:106::/64 2001:db8:1::1 "dummy0"
581 add_rt "Gateway can not be a local linklocal address" 2 \
582 - 2001:db8:107::1/64 $lldummy "dummy0"
583
584 # VRF tests
585 add_rt "Gateway can be local address in a VRF" 0 \
586 - 2001:db8:108::/64 2001:db8:51::2
587 add_rt "Gateway can be local address in a VRF, with device" 0 \
588 - 2001:db8:109::/64 2001:db8:51::2 "veth0"
589 add_rt "Gateway can be local linklocal address in a VRF" 0 \
590 - 2001:db8:110::1/64 $llv1 "veth0"
591
592 add_rt "Redirect to VRF lookup" 0 \
593 - 2001:db8:111::/64 "" "red"
594
595 add_rt "VRF route, gateway can be local address in default VRF" 0 \
596 red 2001:db8:112::/64 2001:db8:51::1
597
598 # local address in same VRF fails
599 add_rt "VRF route, gateway can not be a local address" 2 \
600 red 2001:db8:113::1/64 2001:db8:2::1
601 add_rt "VRF route, gateway can not be a local addr with device" 2 \
602 red 2001:db8:114::1/64 2001:db8:2::1 "dummy1"
603}
604
605# Default VRF:
606# dummy0 - 198.51.100.1/24 2001:db8:1::1/64
607# veth0 - 192.0.2.1/24 2001:db8:51::1/64
608#
609# VRF red:
610# dummy1 - 192.168.2.1/24 2001:db8:2::1/64
611# veth1 - 192.0.2.2/24 2001:db8:51::2/64
612#
613# [ dummy0 veth0 ]--[ veth1 dummy1 ]
614
615fib_nexthop_test()
616{
617 setup
618
619 set -e
620
621 $IP -4 rule add pref 32765 table local
622 $IP -4 rule del pref 0
623 $IP -6 rule add pref 32765 table local
624 $IP -6 rule del pref 0
625
626 $IP link add red type vrf table 1
627 $IP link set red up
628 $IP -4 route add vrf red unreachable default metric 4278198272
629 $IP -6 route add vrf red unreachable default metric 4278198272
630
631 $IP link add veth0 type veth peer name veth1
632 $IP link set dev veth0 up
633 $IP address add 192.0.2.1/24 dev veth0
634 $IP -6 address add 2001:db8:51::1/64 dev veth0
635
636 $IP link set dev veth1 vrf red up
637 $IP address add 192.0.2.2/24 dev veth1
638 $IP -6 address add 2001:db8:51::2/64 dev veth1
639
640 $IP link add dummy1 type dummy
641 $IP link set dev dummy1 vrf red up
642 $IP address add 192.168.2.1/24 dev dummy1
643 $IP -6 address add 2001:db8:2::1/64 dev dummy1
644 set +e
645
646 sleep 1
647 fib4_nexthop
648 fib6_nexthop
649
650 (
651 $IP link del dev dummy1
652 $IP link del veth0
653 $IP link del red
654 ) 2>/dev/null
655 cleanup
656}
657
658fib_suppress_test()
659{
660 echo
661 echo "FIB rule with suppress_prefixlength"
662 setup
663
664 $IP link add dummy1 type dummy
665 $IP link set dummy1 up
666 $IP -6 route add default dev dummy1
667 $IP -6 rule add table main suppress_prefixlength 0
668 ping -f -c 1000 -W 1 1234::1 >/dev/null 2>&1
669 $IP -6 rule del table main suppress_prefixlength 0
670 $IP link del dummy1
671
672 # If we got here without crashing, we're good.
673 log_test 0 0 "FIB rule suppress test"
674
675 cleanup
676}
677
678################################################################################
679# Tests on route add and replace
680
681run_cmd()
682{
683 local cmd="$1"
684 local out
685 local stderr="2>/dev/null"
686
687 if [ "$VERBOSE" = "1" ]; then
688 printf " COMMAND: $cmd\n"
689 stderr=
690 fi
691
692 out=$(eval $cmd $stderr)
693 rc=$?
694 if [ "$VERBOSE" = "1" -a -n "$out" ]; then
695 echo " $out"
696 fi
697
698 [ "$VERBOSE" = "1" ] && echo
699
700 return $rc
701}
702
703check_expected()
704{
705 local out="$1"
706 local expected="$2"
707 local rc=0
708
709 [ "${out}" = "${expected}" ] && return 0
710
711 if [ -z "${out}" ]; then
712 if [ "$VERBOSE" = "1" ]; then
713 printf "\nNo route entry found\n"
714 printf "Expected:\n"
715 printf " ${expected}\n"
716 fi
717 return 1
718 fi
719
720 # tricky way to convert output to 1-line without ip's
721 # messy '\'; this drops all extra white space
722 out=$(echo ${out})
723 if [ "${out}" != "${expected}" ]; then
724 rc=1
725 if [ "${VERBOSE}" = "1" ]; then
726 printf " Unexpected route entry. Have:\n"
727 printf " ${out}\n"
728 printf " Expected:\n"
729 printf " ${expected}\n\n"
730 fi
731 fi
732
733 return $rc
734}
735
736# add route for a prefix, flushing any existing routes first
737# expected to be the first step of a test
738add_route6()
739{
740 local pfx="$1"
741 local nh="$2"
742 local out
743
744 if [ "$VERBOSE" = "1" ]; then
745 echo
746 echo " ##################################################"
747 echo
748 fi
749
750 run_cmd "$IP -6 ro flush ${pfx}"
751 [ $? -ne 0 ] && exit 1
752
753 out=$($IP -6 ro ls match ${pfx})
754 if [ -n "$out" ]; then
755 echo "Failed to flush routes for prefix used for tests."
756 exit 1
757 fi
758
759 run_cmd "$IP -6 ro add ${pfx} ${nh}"
760 if [ $? -ne 0 ]; then
761 echo "Failed to add initial route for test."
762 exit 1
763 fi
764}
765
766# add initial route - used in replace route tests
767add_initial_route6()
768{
769 add_route6 "2001:db8:104::/64" "$1"
770}
771
772check_route6()
773{
774 local pfx
775 local expected="$1"
776 local out
777 local rc=0
778
779 set -- $expected
780 pfx=$1
781
782 out=$($IP -6 ro ls match ${pfx} | sed -e 's/ pref medium//')
783 check_expected "${out}" "${expected}"
784}
785
786route_cleanup()
787{
788 $IP li del red 2>/dev/null
789 $IP li del dummy1 2>/dev/null
790 $IP li del veth1 2>/dev/null
791 $IP li del veth3 2>/dev/null
792
793 cleanup &> /dev/null
794}
795
796route_setup()
797{
798 route_cleanup
799 setup
800
801 [ "${VERBOSE}" = "1" ] && set -x
802 set -e
803
804 ip netns add ns2
805 ip netns set ns2 auto
806 ip -netns ns2 link set dev lo up
807 ip netns exec ns2 sysctl -qw net.ipv4.ip_forward=1
808 ip netns exec ns2 sysctl -qw net.ipv6.conf.all.forwarding=1
809
810 $IP li add veth1 type veth peer name veth2
811 $IP li add veth3 type veth peer name veth4
812
813 $IP li set veth1 up
814 $IP li set veth3 up
815 $IP li set veth2 netns ns2 up
816 $IP li set veth4 netns ns2 up
817 ip -netns ns2 li add dummy1 type dummy
818 ip -netns ns2 li set dummy1 up
819
820 $IP -6 addr add 2001:db8:101::1/64 dev veth1 nodad
821 $IP -6 addr add 2001:db8:103::1/64 dev veth3 nodad
822 $IP addr add 172.16.101.1/24 dev veth1
823 $IP addr add 172.16.103.1/24 dev veth3
824
825 ip -netns ns2 -6 addr add 2001:db8:101::2/64 dev veth2 nodad
826 ip -netns ns2 -6 addr add 2001:db8:103::2/64 dev veth4 nodad
827 ip -netns ns2 -6 addr add 2001:db8:104::1/64 dev dummy1 nodad
828
829 ip -netns ns2 addr add 172.16.101.2/24 dev veth2
830 ip -netns ns2 addr add 172.16.103.2/24 dev veth4
831 ip -netns ns2 addr add 172.16.104.1/24 dev dummy1
832
833 set +e
834}
835
836# assumption is that basic add of a single path route works
837# otherwise just adding an address on an interface is broken
838ipv6_rt_add()
839{
840 local rc
841
842 echo
843 echo "IPv6 route add / append tests"
844
845 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
846 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
847 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2"
848 log_test $? 2 "Attempt to add duplicate route - gw"
849
850 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
851 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
852 run_cmd "$IP -6 ro add 2001:db8:104::/64 dev veth3"
853 log_test $? 2 "Attempt to add duplicate route - dev only"
854
855 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
856 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
857 run_cmd "$IP -6 ro add unreachable 2001:db8:104::/64"
858 log_test $? 2 "Attempt to add duplicate route - reject route"
859
860 # route append with same prefix adds a new route
861 # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
862 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
863 run_cmd "$IP -6 ro append 2001:db8:104::/64 via 2001:db8:103::2"
864 check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
865 log_test $? 0 "Append nexthop to existing route - gw"
866
867 # insert mpath directly
868 add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
869 check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
870 log_test $? 0 "Add multipath route"
871
872 add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
873 run_cmd "$IP -6 ro add 2001:db8:104::/64 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
874 log_test $? 2 "Attempt to add duplicate multipath route"
875
876 # insert of a second route without append but different metric
877 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
878 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2 metric 512"
879 rc=$?
880 if [ $rc -eq 0 ]; then
881 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::3 metric 256"
882 rc=$?
883 fi
884 log_test $rc 0 "Route add with different metrics"
885
886 run_cmd "$IP -6 ro del 2001:db8:104::/64 metric 512"
887 rc=$?
888 if [ $rc -eq 0 ]; then
889 check_route6 "2001:db8:104::/64 via 2001:db8:103::3 dev veth3 metric 256 2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024"
890 rc=$?
891 fi
892 log_test $rc 0 "Route delete with metric"
893}
894
895ipv6_rt_replace_single()
896{
897 # single path with single path
898 #
899 add_initial_route6 "via 2001:db8:101::2"
900 run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:103::2"
901 check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
902 log_test $? 0 "Single path with single path"
903
904 # single path with multipath
905 #
906 add_initial_route6 "nexthop via 2001:db8:101::2"
907 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::2"
908 check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::3 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
909 log_test $? 0 "Single path with multipath"
910
911 # single path with single path using MULTIPATH attribute
912 #
913 add_initial_route6 "via 2001:db8:101::2"
914 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:103::2"
915 check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
916 log_test $? 0 "Single path with single path via multipath attribute"
917
918 # route replace fails - invalid nexthop
919 add_initial_route6 "via 2001:db8:101::2"
920 run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:104::2"
921 if [ $? -eq 0 ]; then
922 # previous command is expected to fail so if it returns 0
923 # that means the test failed.
924 log_test 0 1 "Invalid nexthop"
925 else
926 check_route6 "2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024"
927 log_test $? 0 "Invalid nexthop"
928 fi
929
930 # replace non-existent route
931 # - note use of change versus replace since ip adds NLM_F_CREATE
932 # for replace
933 add_initial_route6 "via 2001:db8:101::2"
934 run_cmd "$IP -6 ro change 2001:db8:105::/64 via 2001:db8:101::2"
935 log_test $? 2 "Single path - replace of non-existent route"
936}
937
938ipv6_rt_replace_mpath()
939{
940 # multipath with multipath
941 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
942 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
943 check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::3 dev veth1 weight 1 nexthop via 2001:db8:103::3 dev veth3 weight 1"
944 log_test $? 0 "Multipath with multipath"
945
946 # multipath with single
947 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
948 run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:101::3"
949 check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
950 log_test $? 0 "Multipath with single path"
951
952 # multipath with single
953 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
954 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3"
955 check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
956 log_test $? 0 "Multipath with single path via multipath attribute"
957
958 # multipath with dev-only
959 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
960 run_cmd "$IP -6 ro replace 2001:db8:104::/64 dev veth1"
961 check_route6 "2001:db8:104::/64 dev veth1 metric 1024"
962 log_test $? 0 "Multipath with dev-only"
963
964 # route replace fails - invalid nexthop 1
965 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
966 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:111::3 nexthop via 2001:db8:103::3"
967 check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
968 log_test $? 0 "Multipath - invalid first nexthop"
969
970 # route replace fails - invalid nexthop 2
971 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
972 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:113::3"
973 check_route6 "2001:db8:104::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
974 log_test $? 0 "Multipath - invalid second nexthop"
975
976 # multipath non-existent route
977 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
978 run_cmd "$IP -6 ro change 2001:db8:105::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
979 log_test $? 2 "Multipath - replace of non-existent route"
980}
981
982ipv6_rt_replace()
983{
984 echo
985 echo "IPv6 route replace tests"
986
987 ipv6_rt_replace_single
988 ipv6_rt_replace_mpath
989}
990
991ipv6_route_test()
992{
993 route_setup
994
995 ipv6_rt_add
996 ipv6_rt_replace
997
998 route_cleanup
999}
1000
1001ip_addr_metric_check()
1002{
1003 ip addr help 2>&1 | grep -q metric
1004 if [ $? -ne 0 ]; then
1005 echo "iproute2 command does not support metric for addresses. Skipping test"
1006 return 1
1007 fi
1008
1009 return 0
1010}
1011
1012ipv6_addr_metric_test()
1013{
1014 local rc
1015
1016 echo
1017 echo "IPv6 prefix route tests"
1018
1019 ip_addr_metric_check || return 1
1020
1021 setup
1022
1023 set -e
1024 $IP li add dummy1 type dummy
1025 $IP li add dummy2 type dummy
1026 $IP li set dummy1 up
1027 $IP li set dummy2 up
1028
1029 # default entry is metric 256
1030 run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64"
1031 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64"
1032 set +e
1033
1034 check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 256 2001:db8:104::/64 dev dummy2 proto kernel metric 256"
1035 log_test $? 0 "Default metric"
1036
1037 set -e
1038 run_cmd "$IP -6 addr flush dev dummy1"
1039 run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64 metric 257"
1040 set +e
1041
1042 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 256 2001:db8:104::/64 dev dummy1 proto kernel metric 257"
1043 log_test $? 0 "User specified metric on first device"
1044
1045 set -e
1046 run_cmd "$IP -6 addr flush dev dummy2"
1047 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64 metric 258"
1048 set +e
1049
1050 check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 257 2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1051 log_test $? 0 "User specified metric on second device"
1052
1053 run_cmd "$IP -6 addr del dev dummy1 2001:db8:104::1/64 metric 257"
1054 rc=$?
1055 if [ $rc -eq 0 ]; then
1056 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1057 rc=$?
1058 fi
1059 log_test $rc 0 "Delete of address on first device"
1060
1061 run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::2/64 metric 259"
1062 rc=$?
1063 if [ $rc -eq 0 ]; then
1064 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1065 rc=$?
1066 fi
1067 log_test $rc 0 "Modify metric of address"
1068
1069 # verify prefix route removed on down
1070 run_cmd "ip netns exec ns1 sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1"
1071 run_cmd "$IP li set dev dummy2 down"
1072 rc=$?
1073 if [ $rc -eq 0 ]; then
1074 out=$($IP -6 ro ls match 2001:db8:104::/64)
1075 check_expected "${out}" ""
1076 rc=$?
1077 fi
1078 log_test $rc 0 "Prefix route removed on link down"
1079
1080 # verify prefix route re-inserted with assigned metric
1081 run_cmd "$IP li set dev dummy2 up"
1082 rc=$?
1083 if [ $rc -eq 0 ]; then
1084 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1085 rc=$?
1086 fi
1087 log_test $rc 0 "Prefix route with metric on link up"
1088
1089 # verify peer metric added correctly
1090 set -e
1091 run_cmd "$IP -6 addr flush dev dummy2"
1092 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::1 peer 2001:db8:104::2 metric 260"
1093 set +e
1094
1095 check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 260"
1096 log_test $? 0 "Set metric with peer route on local side"
1097 check_route6 "2001:db8:104::2 dev dummy2 proto kernel metric 260"
1098 log_test $? 0 "Set metric with peer route on peer side"
1099
1100 set -e
1101 run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::1 peer 2001:db8:104::3 metric 261"
1102 set +e
1103
1104 check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 261"
1105 log_test $? 0 "Modify metric and peer address on local side"
1106 check_route6 "2001:db8:104::3 dev dummy2 proto kernel metric 261"
1107 log_test $? 0 "Modify metric and peer address on peer side"
1108
1109 $IP li del dummy1
1110 $IP li del dummy2
1111 cleanup
1112}
1113
1114ipv6_route_metrics_test()
1115{
1116 local rc
1117
1118 echo
1119 echo "IPv6 routes with metrics"
1120
1121 route_setup
1122
1123 #
1124 # single path with metrics
1125 #
1126 run_cmd "$IP -6 ro add 2001:db8:111::/64 via 2001:db8:101::2 mtu 1400"
1127 rc=$?
1128 if [ $rc -eq 0 ]; then
1129 check_route6 "2001:db8:111::/64 via 2001:db8:101::2 dev veth1 metric 1024 mtu 1400"
1130 rc=$?
1131 fi
1132 log_test $rc 0 "Single path route with mtu metric"
1133
1134
1135 #
1136 # multipath via separate routes with metrics
1137 #
1138 run_cmd "$IP -6 ro add 2001:db8:112::/64 via 2001:db8:101::2 mtu 1400"
1139 run_cmd "$IP -6 ro append 2001:db8:112::/64 via 2001:db8:103::2"
1140 rc=$?
1141 if [ $rc -eq 0 ]; then
1142 check_route6 "2001:db8:112::/64 metric 1024 mtu 1400 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1143 rc=$?
1144 fi
1145 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on first"
1146
1147 # second route is coalesced to first to make a multipath route.
1148 # MTU of the second path is hidden from display!
1149 run_cmd "$IP -6 ro add 2001:db8:113::/64 via 2001:db8:101::2"
1150 run_cmd "$IP -6 ro append 2001:db8:113::/64 via 2001:db8:103::2 mtu 1400"
1151 rc=$?
1152 if [ $rc -eq 0 ]; then
1153 check_route6 "2001:db8:113::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1154 rc=$?
1155 fi
1156 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on 2nd"
1157
1158 run_cmd "$IP -6 ro del 2001:db8:113::/64 via 2001:db8:101::2"
1159 if [ $? -eq 0 ]; then
1160 check_route6 "2001:db8:113::/64 via 2001:db8:103::2 dev veth3 metric 1024 mtu 1400"
1161 log_test $? 0 " MTU of second leg"
1162 fi
1163
1164 #
1165 # multipath with metrics
1166 #
1167 run_cmd "$IP -6 ro add 2001:db8:115::/64 mtu 1400 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1168 rc=$?
1169 if [ $rc -eq 0 ]; then
1170 check_route6 "2001:db8:115::/64 metric 1024 mtu 1400 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1171 rc=$?
1172 fi
1173 log_test $rc 0 "Multipath route with mtu metric"
1174
1175 $IP -6 ro add 2001:db8:104::/64 via 2001:db8:101::2 mtu 1300
1176 run_cmd "ip netns exec ns1 ${ping6} -w1 -c1 -s 1500 2001:db8:104::1"
1177 log_test $? 0 "Using route with mtu metric"
1178
1179 run_cmd "$IP -6 ro add 2001:db8:114::/64 via 2001:db8:101::2 congctl lock foo"
1180 log_test $? 2 "Invalid metric (fails metric_convert)"
1181
1182 route_cleanup
1183}
1184
1185# add route for a prefix, flushing any existing routes first
1186# expected to be the first step of a test
1187add_route()
1188{
1189 local pfx="$1"
1190 local nh="$2"
1191 local out
1192
1193 if [ "$VERBOSE" = "1" ]; then
1194 echo
1195 echo " ##################################################"
1196 echo
1197 fi
1198
1199 run_cmd "$IP ro flush ${pfx}"
1200 [ $? -ne 0 ] && exit 1
1201
1202 out=$($IP ro ls match ${pfx})
1203 if [ -n "$out" ]; then
1204 echo "Failed to flush routes for prefix used for tests."
1205 exit 1
1206 fi
1207
1208 run_cmd "$IP ro add ${pfx} ${nh}"
1209 if [ $? -ne 0 ]; then
1210 echo "Failed to add initial route for test."
1211 exit 1
1212 fi
1213}
1214
1215# add initial route - used in replace route tests
1216add_initial_route()
1217{
1218 add_route "172.16.104.0/24" "$1"
1219}
1220
1221check_route()
1222{
1223 local pfx
1224 local expected="$1"
1225 local out
1226
1227 set -- $expected
1228 pfx=$1
1229 [ "${pfx}" = "unreachable" ] && pfx=$2
1230
1231 out=$($IP ro ls match ${pfx})
1232 check_expected "${out}" "${expected}"
1233}
1234
1235# assumption is that basic add of a single path route works
1236# otherwise just adding an address on an interface is broken
1237ipv4_rt_add()
1238{
1239 local rc
1240
1241 echo
1242 echo "IPv4 route add / append tests"
1243
1244 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1245 add_route "172.16.104.0/24" "via 172.16.101.2"
1246 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2"
1247 log_test $? 2 "Attempt to add duplicate route - gw"
1248
1249 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1250 add_route "172.16.104.0/24" "via 172.16.101.2"
1251 run_cmd "$IP ro add 172.16.104.0/24 dev veth3"
1252 log_test $? 2 "Attempt to add duplicate route - dev only"
1253
1254 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1255 add_route "172.16.104.0/24" "via 172.16.101.2"
1256 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1257 log_test $? 2 "Attempt to add duplicate route - reject route"
1258
1259 # iproute2 prepend only sets NLM_F_CREATE
1260 # - adds a new route; does NOT convert existing route to ECMP
1261 add_route "172.16.104.0/24" "via 172.16.101.2"
1262 run_cmd "$IP ro prepend 172.16.104.0/24 via 172.16.103.2"
1263 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3 172.16.104.0/24 via 172.16.101.2 dev veth1"
1264 log_test $? 0 "Add new nexthop for existing prefix"
1265
1266 # route append with same prefix adds a new route
1267 # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
1268 add_route "172.16.104.0/24" "via 172.16.101.2"
1269 run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1270 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 via 172.16.103.2 dev veth3"
1271 log_test $? 0 "Append nexthop to existing route - gw"
1272
1273 add_route "172.16.104.0/24" "via 172.16.101.2"
1274 run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1275 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 dev veth3 scope link"
1276 log_test $? 0 "Append nexthop to existing route - dev only"
1277
1278 add_route "172.16.104.0/24" "via 172.16.101.2"
1279 run_cmd "$IP ro append unreachable 172.16.104.0/24"
1280 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 unreachable 172.16.104.0/24"
1281 log_test $? 0 "Append nexthop to existing route - reject route"
1282
1283 run_cmd "$IP ro flush 172.16.104.0/24"
1284 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1285 run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1286 check_route "unreachable 172.16.104.0/24 172.16.104.0/24 via 172.16.103.2 dev veth3"
1287 log_test $? 0 "Append nexthop to existing reject route - gw"
1288
1289 run_cmd "$IP ro flush 172.16.104.0/24"
1290 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1291 run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1292 check_route "unreachable 172.16.104.0/24 172.16.104.0/24 dev veth3 scope link"
1293 log_test $? 0 "Append nexthop to existing reject route - dev only"
1294
1295 # insert mpath directly
1296 add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1297 check_route "172.16.104.0/24 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1298 log_test $? 0 "add multipath route"
1299
1300 add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1301 run_cmd "$IP ro add 172.16.104.0/24 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1302 log_test $? 2 "Attempt to add duplicate multipath route"
1303
1304 # insert of a second route without append but different metric
1305 add_route "172.16.104.0/24" "via 172.16.101.2"
1306 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2 metric 512"
1307 rc=$?
1308 if [ $rc -eq 0 ]; then
1309 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.3 metric 256"
1310 rc=$?
1311 fi
1312 log_test $rc 0 "Route add with different metrics"
1313
1314 run_cmd "$IP ro del 172.16.104.0/24 metric 512"
1315 rc=$?
1316 if [ $rc -eq 0 ]; then
1317 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 via 172.16.103.3 dev veth3 metric 256"
1318 rc=$?
1319 fi
1320 log_test $rc 0 "Route delete with metric"
1321}
1322
1323ipv4_rt_replace_single()
1324{
1325 # single path with single path
1326 #
1327 add_initial_route "via 172.16.101.2"
1328 run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.103.2"
1329 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1330 log_test $? 0 "Single path with single path"
1331
1332 # single path with multipath
1333 #
1334 add_initial_route "nexthop via 172.16.101.2"
1335 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.2"
1336 check_route "172.16.104.0/24 nexthop via 172.16.101.3 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1337 log_test $? 0 "Single path with multipath"
1338
1339 # single path with reject
1340 #
1341 add_initial_route "nexthop via 172.16.101.2"
1342 run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1343 check_route "unreachable 172.16.104.0/24"
1344 log_test $? 0 "Single path with reject route"
1345
1346 # single path with single path using MULTIPATH attribute
1347 #
1348 add_initial_route "via 172.16.101.2"
1349 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.103.2"
1350 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1351 log_test $? 0 "Single path with single path via multipath attribute"
1352
1353 # route replace fails - invalid nexthop
1354 add_initial_route "via 172.16.101.2"
1355 run_cmd "$IP ro replace 172.16.104.0/24 via 2001:db8:104::2"
1356 if [ $? -eq 0 ]; then
1357 # previous command is expected to fail so if it returns 0
1358 # that means the test failed.
1359 log_test 0 1 "Invalid nexthop"
1360 else
1361 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1"
1362 log_test $? 0 "Invalid nexthop"
1363 fi
1364
1365 # replace non-existent route
1366 # - note use of change versus replace since ip adds NLM_F_CREATE
1367 # for replace
1368 add_initial_route "via 172.16.101.2"
1369 run_cmd "$IP ro change 172.16.105.0/24 via 172.16.101.2"
1370 log_test $? 2 "Single path - replace of non-existent route"
1371}
1372
1373ipv4_rt_replace_mpath()
1374{
1375 # multipath with multipath
1376 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1377 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1378 check_route "172.16.104.0/24 nexthop via 172.16.101.3 dev veth1 weight 1 nexthop via 172.16.103.3 dev veth3 weight 1"
1379 log_test $? 0 "Multipath with multipath"
1380
1381 # multipath with single
1382 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1383 run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.101.3"
1384 check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
1385 log_test $? 0 "Multipath with single path"
1386
1387 # multipath with single
1388 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1389 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3"
1390 check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
1391 log_test $? 0 "Multipath with single path via multipath attribute"
1392
1393 # multipath with reject
1394 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1395 run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1396 check_route "unreachable 172.16.104.0/24"
1397 log_test $? 0 "Multipath with reject route"
1398
1399 # route replace fails - invalid nexthop 1
1400 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1401 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.111.3 nexthop via 172.16.103.3"
1402 check_route "172.16.104.0/24 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1403 log_test $? 0 "Multipath - invalid first nexthop"
1404
1405 # route replace fails - invalid nexthop 2
1406 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1407 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.113.3"
1408 check_route "172.16.104.0/24 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1409 log_test $? 0 "Multipath - invalid second nexthop"
1410
1411 # multipath non-existent route
1412 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1413 run_cmd "$IP ro change 172.16.105.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1414 log_test $? 2 "Multipath - replace of non-existent route"
1415}
1416
1417ipv4_rt_replace()
1418{
1419 echo
1420 echo "IPv4 route replace tests"
1421
1422 ipv4_rt_replace_single
1423 ipv4_rt_replace_mpath
1424}
1425
1426ipv4_route_test()
1427{
1428 route_setup
1429
1430 ipv4_rt_add
1431 ipv4_rt_replace
1432
1433 route_cleanup
1434}
1435
1436ipv4_addr_metric_test()
1437{
1438 local rc
1439
1440 echo
1441 echo "IPv4 prefix route tests"
1442
1443 ip_addr_metric_check || return 1
1444
1445 setup
1446
1447 set -e
1448 $IP li add dummy1 type dummy
1449 $IP li add dummy2 type dummy
1450 $IP li set dummy1 up
1451 $IP li set dummy2 up
1452
1453 # default entry is metric 256
1454 run_cmd "$IP addr add dev dummy1 172.16.104.1/24"
1455 run_cmd "$IP addr add dev dummy2 172.16.104.2/24"
1456 set +e
1457
1458 check_route "172.16.104.0/24 dev dummy1 proto kernel scope link src 172.16.104.1 172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2"
1459 log_test $? 0 "Default metric"
1460
1461 set -e
1462 run_cmd "$IP addr flush dev dummy1"
1463 run_cmd "$IP addr add dev dummy1 172.16.104.1/24 metric 257"
1464 set +e
1465
1466 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 172.16.104.0/24 dev dummy1 proto kernel scope link src 172.16.104.1 metric 257"
1467 log_test $? 0 "User specified metric on first device"
1468
1469 set -e
1470 run_cmd "$IP addr flush dev dummy2"
1471 run_cmd "$IP addr add dev dummy2 172.16.104.2/24 metric 258"
1472 set +e
1473
1474 check_route "172.16.104.0/24 dev dummy1 proto kernel scope link src 172.16.104.1 metric 257 172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258"
1475 log_test $? 0 "User specified metric on second device"
1476
1477 run_cmd "$IP addr del dev dummy1 172.16.104.1/24 metric 257"
1478 rc=$?
1479 if [ $rc -eq 0 ]; then
1480 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258"
1481 rc=$?
1482 fi
1483 log_test $rc 0 "Delete of address on first device"
1484
1485 run_cmd "$IP addr change dev dummy2 172.16.104.2/24 metric 259"
1486 rc=$?
1487 if [ $rc -eq 0 ]; then
1488 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1489 rc=$?
1490 fi
1491 log_test $rc 0 "Modify metric of address"
1492
1493 # verify prefix route removed on down
1494 run_cmd "$IP li set dev dummy2 down"
1495 rc=$?
1496 if [ $rc -eq 0 ]; then
1497 out=$($IP ro ls match 172.16.104.0/24)
1498 check_expected "${out}" ""
1499 rc=$?
1500 fi
1501 log_test $rc 0 "Prefix route removed on link down"
1502
1503 # verify prefix route re-inserted with assigned metric
1504 run_cmd "$IP li set dev dummy2 up"
1505 rc=$?
1506 if [ $rc -eq 0 ]; then
1507 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1508 rc=$?
1509 fi
1510 log_test $rc 0 "Prefix route with metric on link up"
1511
1512 # explicitly check for metric changes on edge scenarios
1513 run_cmd "$IP addr flush dev dummy2"
1514 run_cmd "$IP addr add dev dummy2 172.16.104.0/24 metric 259"
1515 run_cmd "$IP addr change dev dummy2 172.16.104.0/24 metric 260"
1516 rc=$?
1517 if [ $rc -eq 0 ]; then
1518 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.0 metric 260"
1519 rc=$?
1520 fi
1521 log_test $rc 0 "Modify metric of .0/24 address"
1522
1523 run_cmd "$IP addr flush dev dummy2"
1524 run_cmd "$IP addr add dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 260"
1525 rc=$?
1526 if [ $rc -eq 0 ]; then
1527 check_route "172.16.104.2 dev dummy2 proto kernel scope link src 172.16.104.1 metric 260"
1528 rc=$?
1529 fi
1530 log_test $rc 0 "Set metric of address with peer route"
1531
1532 run_cmd "$IP addr change dev dummy2 172.16.104.1/32 peer 172.16.104.3 metric 261"
1533 rc=$?
1534 if [ $rc -eq 0 ]; then
1535 check_route "172.16.104.3 dev dummy2 proto kernel scope link src 172.16.104.1 metric 261"
1536 rc=$?
1537 fi
1538 log_test $rc 0 "Modify metric and peer address for peer route"
1539
1540 $IP li del dummy1
1541 $IP li del dummy2
1542 cleanup
1543}
1544
1545ipv4_route_metrics_test()
1546{
1547 local rc
1548
1549 echo
1550 echo "IPv4 route add / append tests"
1551
1552 route_setup
1553
1554 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 mtu 1400"
1555 rc=$?
1556 if [ $rc -eq 0 ]; then
1557 check_route "172.16.111.0/24 via 172.16.101.2 dev veth1 mtu 1400"
1558 rc=$?
1559 fi
1560 log_test $rc 0 "Single path route with mtu metric"
1561
1562
1563 run_cmd "$IP ro add 172.16.112.0/24 mtu 1400 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1564 rc=$?
1565 if [ $rc -eq 0 ]; then
1566 check_route "172.16.112.0/24 mtu 1400 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1567 rc=$?
1568 fi
1569 log_test $rc 0 "Multipath route with mtu metric"
1570
1571 $IP ro add 172.16.104.0/24 via 172.16.101.2 mtu 1300
1572 run_cmd "ip netns exec ns1 ping -w1 -c1 -s 1500 172.16.104.1"
1573 log_test $? 0 "Using route with mtu metric"
1574
1575 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 congctl lock foo"
1576 log_test $? 2 "Invalid metric (fails metric_convert)"
1577
1578 route_cleanup
1579}
1580
1581ipv4_route_v6_gw_test()
1582{
1583 local rc
1584
1585 echo
1586 echo "IPv4 route with IPv6 gateway tests"
1587
1588 route_setup
1589 sleep 2
1590
1591 #
1592 # single path route
1593 #
1594 run_cmd "$IP ro add 172.16.104.0/24 via inet6 2001:db8:101::2"
1595 rc=$?
1596 log_test $rc 0 "Single path route with IPv6 gateway"
1597 if [ $rc -eq 0 ]; then
1598 check_route "172.16.104.0/24 via inet6 2001:db8:101::2 dev veth1"
1599 fi
1600
1601 run_cmd "ip netns exec ns1 ping -w1 -c1 172.16.104.1"
1602 log_test $rc 0 "Single path route with IPv6 gateway - ping"
1603
1604 run_cmd "$IP ro del 172.16.104.0/24 via inet6 2001:db8:101::2"
1605 rc=$?
1606 log_test $rc 0 "Single path route delete"
1607 if [ $rc -eq 0 ]; then
1608 check_route "172.16.112.0/24"
1609 fi
1610
1611 #
1612 # multipath - v6 then v4
1613 #
1614 run_cmd "$IP ro add 172.16.104.0/24 nexthop via inet6 2001:db8:101::2 dev veth1 nexthop via 172.16.103.2 dev veth3"
1615 rc=$?
1616 log_test $rc 0 "Multipath route add - v6 nexthop then v4"
1617 if [ $rc -eq 0 ]; then
1618 check_route "172.16.104.0/24 nexthop via inet6 2001:db8:101::2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1619 fi
1620
1621 run_cmd "$IP ro del 172.16.104.0/24 nexthop via 172.16.103.2 dev veth3 nexthop via inet6 2001:db8:101::2 dev veth1"
1622 log_test $? 2 " Multipath route delete - nexthops in wrong order"
1623
1624 run_cmd "$IP ro del 172.16.104.0/24 nexthop via inet6 2001:db8:101::2 dev veth1 nexthop via 172.16.103.2 dev veth3"
1625 log_test $? 0 " Multipath route delete exact match"
1626
1627 #
1628 # multipath - v4 then v6
1629 #
1630 run_cmd "$IP ro add 172.16.104.0/24 nexthop via 172.16.103.2 dev veth3 nexthop via inet6 2001:db8:101::2 dev veth1"
1631 rc=$?
1632 log_test $rc 0 "Multipath route add - v4 nexthop then v6"
1633 if [ $rc -eq 0 ]; then
1634 check_route "172.16.104.0/24 nexthop via 172.16.103.2 dev veth3 weight 1 nexthop via inet6 2001:db8:101::2 dev veth1 weight 1"
1635 fi
1636
1637 run_cmd "$IP ro del 172.16.104.0/24 nexthop via inet6 2001:db8:101::2 dev veth1 nexthop via 172.16.103.2 dev veth3"
1638 log_test $? 2 " Multipath route delete - nexthops in wrong order"
1639
1640 run_cmd "$IP ro del 172.16.104.0/24 nexthop via 172.16.103.2 dev veth3 nexthop via inet6 2001:db8:101::2 dev veth1"
1641 log_test $? 0 " Multipath route delete exact match"
1642
1643 route_cleanup
1644}
1645
1646################################################################################
1647# usage
1648
1649usage()
1650{
1651 cat <<EOF
1652usage: ${0##*/} OPTS
1653
1654 -t <test> Test(s) to run (default: all)
1655 (options: $TESTS)
1656 -p Pause on fail
1657 -P Pause after each test before cleanup
1658 -v verbose mode (show commands and output)
1659EOF
1660}
1661
1662################################################################################
1663# main
1664
1665trap cleanup EXIT
1666
1667while getopts :t:pPhv o
1668do
1669 case $o in
1670 t) TESTS=$OPTARG;;
1671 p) PAUSE_ON_FAIL=yes;;
1672 P) PAUSE=yes;;
1673 v) VERBOSE=$(($VERBOSE + 1));;
1674 h) usage; exit 0;;
1675 *) usage; exit 1;;
1676 esac
1677done
1678
1679PEER_CMD="ip netns exec ${PEER_NS}"
1680
1681# make sure we don't pause twice
1682[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
1683
1684if [ "$(id -u)" -ne 0 ];then
1685 echo "SKIP: Need root privileges"
1686 exit $ksft_skip;
1687fi
1688
1689if [ ! -x "$(command -v ip)" ]; then
1690 echo "SKIP: Could not run test without ip tool"
1691 exit $ksft_skip
1692fi
1693
1694ip route help 2>&1 | grep -q fibmatch
1695if [ $? -ne 0 ]; then
1696 echo "SKIP: iproute2 too old, missing fibmatch"
1697 exit $ksft_skip
1698fi
1699
1700# start clean
1701cleanup &> /dev/null
1702
1703for t in $TESTS
1704do
1705 case $t in
1706 fib_unreg_test|unregister) fib_unreg_test;;
1707 fib_down_test|down) fib_down_test;;
1708 fib_carrier_test|carrier) fib_carrier_test;;
1709 fib_rp_filter_test|rp_filter) fib_rp_filter_test;;
1710 fib_nexthop_test|nexthop) fib_nexthop_test;;
1711 fib_suppress_test|suppress) fib_suppress_test;;
1712 ipv6_route_test|ipv6_rt) ipv6_route_test;;
1713 ipv4_route_test|ipv4_rt) ipv4_route_test;;
1714 ipv6_addr_metric) ipv6_addr_metric_test;;
1715 ipv4_addr_metric) ipv4_addr_metric_test;;
1716 ipv6_route_metrics) ipv6_route_metrics_test;;
1717 ipv4_route_metrics) ipv4_route_metrics_test;;
1718 ipv4_route_v6_gw) ipv4_route_v6_gw_test;;
1719
1720 help) echo "Test names: $TESTS"; exit 0;;
1721 esac
1722done
1723
1724if [ "$TESTS" != "none" ]; then
1725 printf "\nTests passed: %3d\n" ${nsuccess}
1726 printf "Tests failed: %3d\n" ${nfail}
1727fi
1728
1729exit $ret