Loading...
1#!/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 ipv4_del_addr ipv4_mangle ipv6_mangle ipv4_bcast_neigh"
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
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_rt_dsfield()
992{
993 echo
994 echo "IPv6 route with dsfield tests"
995
996 run_cmd "$IP -6 route flush 2001:db8:102::/64"
997
998 # IPv6 doesn't support routing based on dsfield
999 run_cmd "$IP -6 route add 2001:db8:102::/64 dsfield 0x04 via 2001:db8:101::2"
1000 log_test $? 2 "Reject route with dsfield"
1001}
1002
1003ipv6_route_test()
1004{
1005 route_setup
1006
1007 ipv6_rt_add
1008 ipv6_rt_replace
1009 ipv6_rt_dsfield
1010
1011 route_cleanup
1012}
1013
1014ip_addr_metric_check()
1015{
1016 ip addr help 2>&1 | grep -q metric
1017 if [ $? -ne 0 ]; then
1018 echo "iproute2 command does not support metric for addresses. Skipping test"
1019 return 1
1020 fi
1021
1022 return 0
1023}
1024
1025ipv6_addr_metric_test()
1026{
1027 local rc
1028
1029 echo
1030 echo "IPv6 prefix route tests"
1031
1032 ip_addr_metric_check || return 1
1033
1034 setup
1035
1036 set -e
1037 $IP li add dummy1 type dummy
1038 $IP li add dummy2 type dummy
1039 $IP li set dummy1 up
1040 $IP li set dummy2 up
1041
1042 # default entry is metric 256
1043 run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64"
1044 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64"
1045 set +e
1046
1047 check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 256 2001:db8:104::/64 dev dummy2 proto kernel metric 256"
1048 log_test $? 0 "Default metric"
1049
1050 set -e
1051 run_cmd "$IP -6 addr flush dev dummy1"
1052 run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64 metric 257"
1053 set +e
1054
1055 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 256 2001:db8:104::/64 dev dummy1 proto kernel metric 257"
1056 log_test $? 0 "User specified metric on first device"
1057
1058 set -e
1059 run_cmd "$IP -6 addr flush dev dummy2"
1060 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64 metric 258"
1061 set +e
1062
1063 check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 257 2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1064 log_test $? 0 "User specified metric on second device"
1065
1066 run_cmd "$IP -6 addr del dev dummy1 2001:db8:104::1/64 metric 257"
1067 rc=$?
1068 if [ $rc -eq 0 ]; then
1069 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1070 rc=$?
1071 fi
1072 log_test $rc 0 "Delete of address on first device"
1073
1074 run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::2/64 metric 259"
1075 rc=$?
1076 if [ $rc -eq 0 ]; then
1077 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1078 rc=$?
1079 fi
1080 log_test $rc 0 "Modify metric of address"
1081
1082 # verify prefix route removed on down
1083 run_cmd "ip netns exec ns1 sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1"
1084 run_cmd "$IP li set dev dummy2 down"
1085 rc=$?
1086 if [ $rc -eq 0 ]; then
1087 out=$($IP -6 ro ls match 2001:db8:104::/64)
1088 check_expected "${out}" ""
1089 rc=$?
1090 fi
1091 log_test $rc 0 "Prefix route removed on link down"
1092
1093 # verify prefix route re-inserted with assigned metric
1094 run_cmd "$IP li set dev dummy2 up"
1095 rc=$?
1096 if [ $rc -eq 0 ]; then
1097 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1098 rc=$?
1099 fi
1100 log_test $rc 0 "Prefix route with metric on link up"
1101
1102 # verify peer metric added correctly
1103 set -e
1104 run_cmd "$IP -6 addr flush dev dummy2"
1105 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::1 peer 2001:db8:104::2 metric 260"
1106 set +e
1107
1108 check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 260"
1109 log_test $? 0 "Set metric with peer route on local side"
1110 check_route6 "2001:db8:104::2 dev dummy2 proto kernel metric 260"
1111 log_test $? 0 "Set metric with peer route on peer side"
1112
1113 set -e
1114 run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::1 peer 2001:db8:104::3 metric 261"
1115 set +e
1116
1117 check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 261"
1118 log_test $? 0 "Modify metric and peer address on local side"
1119 check_route6 "2001:db8:104::3 dev dummy2 proto kernel metric 261"
1120 log_test $? 0 "Modify metric and peer address on peer side"
1121
1122 $IP li del dummy1
1123 $IP li del dummy2
1124 cleanup
1125}
1126
1127ipv6_route_metrics_test()
1128{
1129 local rc
1130
1131 echo
1132 echo "IPv6 routes with metrics"
1133
1134 route_setup
1135
1136 #
1137 # single path with metrics
1138 #
1139 run_cmd "$IP -6 ro add 2001:db8:111::/64 via 2001:db8:101::2 mtu 1400"
1140 rc=$?
1141 if [ $rc -eq 0 ]; then
1142 check_route6 "2001:db8:111::/64 via 2001:db8:101::2 dev veth1 metric 1024 mtu 1400"
1143 rc=$?
1144 fi
1145 log_test $rc 0 "Single path route with mtu metric"
1146
1147
1148 #
1149 # multipath via separate routes with metrics
1150 #
1151 run_cmd "$IP -6 ro add 2001:db8:112::/64 via 2001:db8:101::2 mtu 1400"
1152 run_cmd "$IP -6 ro append 2001:db8:112::/64 via 2001:db8:103::2"
1153 rc=$?
1154 if [ $rc -eq 0 ]; then
1155 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"
1156 rc=$?
1157 fi
1158 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on first"
1159
1160 # second route is coalesced to first to make a multipath route.
1161 # MTU of the second path is hidden from display!
1162 run_cmd "$IP -6 ro add 2001:db8:113::/64 via 2001:db8:101::2"
1163 run_cmd "$IP -6 ro append 2001:db8:113::/64 via 2001:db8:103::2 mtu 1400"
1164 rc=$?
1165 if [ $rc -eq 0 ]; then
1166 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"
1167 rc=$?
1168 fi
1169 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on 2nd"
1170
1171 run_cmd "$IP -6 ro del 2001:db8:113::/64 via 2001:db8:101::2"
1172 if [ $? -eq 0 ]; then
1173 check_route6 "2001:db8:113::/64 via 2001:db8:103::2 dev veth3 metric 1024 mtu 1400"
1174 log_test $? 0 " MTU of second leg"
1175 fi
1176
1177 #
1178 # multipath with metrics
1179 #
1180 run_cmd "$IP -6 ro add 2001:db8:115::/64 mtu 1400 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1181 rc=$?
1182 if [ $rc -eq 0 ]; then
1183 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"
1184 rc=$?
1185 fi
1186 log_test $rc 0 "Multipath route with mtu metric"
1187
1188 $IP -6 ro add 2001:db8:104::/64 via 2001:db8:101::2 mtu 1300
1189 run_cmd "ip netns exec ns1 ${ping6} -w1 -c1 -s 1500 2001:db8:104::1"
1190 log_test $? 0 "Using route with mtu metric"
1191
1192 run_cmd "$IP -6 ro add 2001:db8:114::/64 via 2001:db8:101::2 congctl lock foo"
1193 log_test $? 2 "Invalid metric (fails metric_convert)"
1194
1195 route_cleanup
1196}
1197
1198# add route for a prefix, flushing any existing routes first
1199# expected to be the first step of a test
1200add_route()
1201{
1202 local pfx="$1"
1203 local nh="$2"
1204 local out
1205
1206 if [ "$VERBOSE" = "1" ]; then
1207 echo
1208 echo " ##################################################"
1209 echo
1210 fi
1211
1212 run_cmd "$IP ro flush ${pfx}"
1213 [ $? -ne 0 ] && exit 1
1214
1215 out=$($IP ro ls match ${pfx})
1216 if [ -n "$out" ]; then
1217 echo "Failed to flush routes for prefix used for tests."
1218 exit 1
1219 fi
1220
1221 run_cmd "$IP ro add ${pfx} ${nh}"
1222 if [ $? -ne 0 ]; then
1223 echo "Failed to add initial route for test."
1224 exit 1
1225 fi
1226}
1227
1228# add initial route - used in replace route tests
1229add_initial_route()
1230{
1231 add_route "172.16.104.0/24" "$1"
1232}
1233
1234check_route()
1235{
1236 local pfx
1237 local expected="$1"
1238 local out
1239
1240 set -- $expected
1241 pfx=$1
1242 [ "${pfx}" = "unreachable" ] && pfx=$2
1243
1244 out=$($IP ro ls match ${pfx})
1245 check_expected "${out}" "${expected}"
1246}
1247
1248# assumption is that basic add of a single path route works
1249# otherwise just adding an address on an interface is broken
1250ipv4_rt_add()
1251{
1252 local rc
1253
1254 echo
1255 echo "IPv4 route add / append tests"
1256
1257 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1258 add_route "172.16.104.0/24" "via 172.16.101.2"
1259 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2"
1260 log_test $? 2 "Attempt to add duplicate route - gw"
1261
1262 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1263 add_route "172.16.104.0/24" "via 172.16.101.2"
1264 run_cmd "$IP ro add 172.16.104.0/24 dev veth3"
1265 log_test $? 2 "Attempt to add duplicate route - dev only"
1266
1267 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1268 add_route "172.16.104.0/24" "via 172.16.101.2"
1269 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1270 log_test $? 2 "Attempt to add duplicate route - reject route"
1271
1272 # iproute2 prepend only sets NLM_F_CREATE
1273 # - adds a new route; does NOT convert existing route to ECMP
1274 add_route "172.16.104.0/24" "via 172.16.101.2"
1275 run_cmd "$IP ro prepend 172.16.104.0/24 via 172.16.103.2"
1276 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"
1277 log_test $? 0 "Add new nexthop for existing prefix"
1278
1279 # route append with same prefix adds a new route
1280 # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
1281 add_route "172.16.104.0/24" "via 172.16.101.2"
1282 run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1283 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"
1284 log_test $? 0 "Append nexthop to existing route - gw"
1285
1286 add_route "172.16.104.0/24" "via 172.16.101.2"
1287 run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1288 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 dev veth3 scope link"
1289 log_test $? 0 "Append nexthop to existing route - dev only"
1290
1291 add_route "172.16.104.0/24" "via 172.16.101.2"
1292 run_cmd "$IP ro append unreachable 172.16.104.0/24"
1293 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 unreachable 172.16.104.0/24"
1294 log_test $? 0 "Append nexthop to existing route - reject route"
1295
1296 run_cmd "$IP ro flush 172.16.104.0/24"
1297 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1298 run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1299 check_route "unreachable 172.16.104.0/24 172.16.104.0/24 via 172.16.103.2 dev veth3"
1300 log_test $? 0 "Append nexthop to existing reject route - gw"
1301
1302 run_cmd "$IP ro flush 172.16.104.0/24"
1303 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1304 run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1305 check_route "unreachable 172.16.104.0/24 172.16.104.0/24 dev veth3 scope link"
1306 log_test $? 0 "Append nexthop to existing reject route - dev only"
1307
1308 # insert mpath directly
1309 add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1310 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"
1311 log_test $? 0 "add multipath route"
1312
1313 add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1314 run_cmd "$IP ro add 172.16.104.0/24 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1315 log_test $? 2 "Attempt to add duplicate multipath route"
1316
1317 # insert of a second route without append but different metric
1318 add_route "172.16.104.0/24" "via 172.16.101.2"
1319 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2 metric 512"
1320 rc=$?
1321 if [ $rc -eq 0 ]; then
1322 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.3 metric 256"
1323 rc=$?
1324 fi
1325 log_test $rc 0 "Route add with different metrics"
1326
1327 run_cmd "$IP ro del 172.16.104.0/24 metric 512"
1328 rc=$?
1329 if [ $rc -eq 0 ]; then
1330 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"
1331 rc=$?
1332 fi
1333 log_test $rc 0 "Route delete with metric"
1334}
1335
1336ipv4_rt_replace_single()
1337{
1338 # single path with single path
1339 #
1340 add_initial_route "via 172.16.101.2"
1341 run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.103.2"
1342 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1343 log_test $? 0 "Single path with single path"
1344
1345 # single path with multipath
1346 #
1347 add_initial_route "nexthop via 172.16.101.2"
1348 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.2"
1349 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"
1350 log_test $? 0 "Single path with multipath"
1351
1352 # single path with reject
1353 #
1354 add_initial_route "nexthop via 172.16.101.2"
1355 run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1356 check_route "unreachable 172.16.104.0/24"
1357 log_test $? 0 "Single path with reject route"
1358
1359 # single path with single path using MULTIPATH attribute
1360 #
1361 add_initial_route "via 172.16.101.2"
1362 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.103.2"
1363 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1364 log_test $? 0 "Single path with single path via multipath attribute"
1365
1366 # route replace fails - invalid nexthop
1367 add_initial_route "via 172.16.101.2"
1368 run_cmd "$IP ro replace 172.16.104.0/24 via 2001:db8:104::2"
1369 if [ $? -eq 0 ]; then
1370 # previous command is expected to fail so if it returns 0
1371 # that means the test failed.
1372 log_test 0 1 "Invalid nexthop"
1373 else
1374 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1"
1375 log_test $? 0 "Invalid nexthop"
1376 fi
1377
1378 # replace non-existent route
1379 # - note use of change versus replace since ip adds NLM_F_CREATE
1380 # for replace
1381 add_initial_route "via 172.16.101.2"
1382 run_cmd "$IP ro change 172.16.105.0/24 via 172.16.101.2"
1383 log_test $? 2 "Single path - replace of non-existent route"
1384}
1385
1386ipv4_rt_replace_mpath()
1387{
1388 # multipath with multipath
1389 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1390 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1391 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"
1392 log_test $? 0 "Multipath with multipath"
1393
1394 # multipath with single
1395 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1396 run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.101.3"
1397 check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
1398 log_test $? 0 "Multipath with single path"
1399
1400 # multipath with single
1401 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1402 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3"
1403 check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
1404 log_test $? 0 "Multipath with single path via multipath attribute"
1405
1406 # multipath with reject
1407 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1408 run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1409 check_route "unreachable 172.16.104.0/24"
1410 log_test $? 0 "Multipath with reject route"
1411
1412 # route replace fails - invalid nexthop 1
1413 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1414 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.111.3 nexthop via 172.16.103.3"
1415 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"
1416 log_test $? 0 "Multipath - invalid first nexthop"
1417
1418 # route replace fails - invalid nexthop 2
1419 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1420 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.113.3"
1421 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"
1422 log_test $? 0 "Multipath - invalid second nexthop"
1423
1424 # multipath non-existent route
1425 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1426 run_cmd "$IP ro change 172.16.105.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1427 log_test $? 2 "Multipath - replace of non-existent route"
1428}
1429
1430ipv4_rt_replace()
1431{
1432 echo
1433 echo "IPv4 route replace tests"
1434
1435 ipv4_rt_replace_single
1436 ipv4_rt_replace_mpath
1437}
1438
1439# checks that cached input route on VRF port is deleted
1440# when VRF is deleted
1441ipv4_local_rt_cache()
1442{
1443 run_cmd "ip addr add 10.0.0.1/32 dev lo"
1444 run_cmd "ip netns add test-ns"
1445 run_cmd "ip link add veth-outside type veth peer name veth-inside"
1446 run_cmd "ip link add vrf-100 type vrf table 1100"
1447 run_cmd "ip link set veth-outside master vrf-100"
1448 run_cmd "ip link set veth-inside netns test-ns"
1449 run_cmd "ip link set veth-outside up"
1450 run_cmd "ip link set vrf-100 up"
1451 run_cmd "ip route add 10.1.1.1/32 dev veth-outside table 1100"
1452 run_cmd "ip netns exec test-ns ip link set veth-inside up"
1453 run_cmd "ip netns exec test-ns ip addr add 10.1.1.1/32 dev veth-inside"
1454 run_cmd "ip netns exec test-ns ip route add 10.0.0.1/32 dev veth-inside"
1455 run_cmd "ip netns exec test-ns ip route add default via 10.0.0.1"
1456 run_cmd "ip netns exec test-ns ping 10.0.0.1 -c 1 -i 1"
1457 run_cmd "ip link delete vrf-100"
1458
1459 # if we do not hang test is a success
1460 log_test $? 0 "Cached route removed from VRF port device"
1461}
1462
1463ipv4_rt_dsfield()
1464{
1465 echo
1466 echo "IPv4 route with dsfield tests"
1467
1468 run_cmd "$IP route flush 172.16.102.0/24"
1469
1470 # New routes should reject dsfield options that interfere with ECN
1471 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x01 via 172.16.101.2"
1472 log_test $? 2 "Reject route with dsfield 0x01"
1473
1474 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x02 via 172.16.101.2"
1475 log_test $? 2 "Reject route with dsfield 0x02"
1476
1477 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x03 via 172.16.101.2"
1478 log_test $? 2 "Reject route with dsfield 0x03"
1479
1480 # A generic route that doesn't take DSCP into account
1481 run_cmd "$IP route add 172.16.102.0/24 via 172.16.101.2"
1482
1483 # A more specific route for DSCP 0x10
1484 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x10 via 172.16.103.2"
1485
1486 # DSCP 0x10 should match the specific route, no matter the ECN bits
1487 $IP route get fibmatch 172.16.102.1 dsfield 0x10 | \
1488 grep -q "via 172.16.103.2"
1489 log_test $? 0 "IPv4 route with DSCP and ECN:Not-ECT"
1490
1491 $IP route get fibmatch 172.16.102.1 dsfield 0x11 | \
1492 grep -q "via 172.16.103.2"
1493 log_test $? 0 "IPv4 route with DSCP and ECN:ECT(1)"
1494
1495 $IP route get fibmatch 172.16.102.1 dsfield 0x12 | \
1496 grep -q "via 172.16.103.2"
1497 log_test $? 0 "IPv4 route with DSCP and ECN:ECT(0)"
1498
1499 $IP route get fibmatch 172.16.102.1 dsfield 0x13 | \
1500 grep -q "via 172.16.103.2"
1501 log_test $? 0 "IPv4 route with DSCP and ECN:CE"
1502
1503 # Unknown DSCP should match the generic route, no matter the ECN bits
1504 $IP route get fibmatch 172.16.102.1 dsfield 0x14 | \
1505 grep -q "via 172.16.101.2"
1506 log_test $? 0 "IPv4 route with unknown DSCP and ECN:Not-ECT"
1507
1508 $IP route get fibmatch 172.16.102.1 dsfield 0x15 | \
1509 grep -q "via 172.16.101.2"
1510 log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(1)"
1511
1512 $IP route get fibmatch 172.16.102.1 dsfield 0x16 | \
1513 grep -q "via 172.16.101.2"
1514 log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(0)"
1515
1516 $IP route get fibmatch 172.16.102.1 dsfield 0x17 | \
1517 grep -q "via 172.16.101.2"
1518 log_test $? 0 "IPv4 route with unknown DSCP and ECN:CE"
1519
1520 # Null DSCP should match the generic route, no matter the ECN bits
1521 $IP route get fibmatch 172.16.102.1 dsfield 0x00 | \
1522 grep -q "via 172.16.101.2"
1523 log_test $? 0 "IPv4 route with no DSCP and ECN:Not-ECT"
1524
1525 $IP route get fibmatch 172.16.102.1 dsfield 0x01 | \
1526 grep -q "via 172.16.101.2"
1527 log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(1)"
1528
1529 $IP route get fibmatch 172.16.102.1 dsfield 0x02 | \
1530 grep -q "via 172.16.101.2"
1531 log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(0)"
1532
1533 $IP route get fibmatch 172.16.102.1 dsfield 0x03 | \
1534 grep -q "via 172.16.101.2"
1535 log_test $? 0 "IPv4 route with no DSCP and ECN:CE"
1536}
1537
1538ipv4_route_test()
1539{
1540 route_setup
1541
1542 ipv4_rt_add
1543 ipv4_rt_replace
1544 ipv4_local_rt_cache
1545 ipv4_rt_dsfield
1546
1547 route_cleanup
1548}
1549
1550ipv4_addr_metric_test()
1551{
1552 local rc
1553
1554 echo
1555 echo "IPv4 prefix route tests"
1556
1557 ip_addr_metric_check || return 1
1558
1559 setup
1560
1561 set -e
1562 $IP li add dummy1 type dummy
1563 $IP li add dummy2 type dummy
1564 $IP li set dummy1 up
1565 $IP li set dummy2 up
1566
1567 # default entry is metric 256
1568 run_cmd "$IP addr add dev dummy1 172.16.104.1/24"
1569 run_cmd "$IP addr add dev dummy2 172.16.104.2/24"
1570 set +e
1571
1572 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"
1573 log_test $? 0 "Default metric"
1574
1575 set -e
1576 run_cmd "$IP addr flush dev dummy1"
1577 run_cmd "$IP addr add dev dummy1 172.16.104.1/24 metric 257"
1578 set +e
1579
1580 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"
1581 log_test $? 0 "User specified metric on first device"
1582
1583 set -e
1584 run_cmd "$IP addr flush dev dummy2"
1585 run_cmd "$IP addr add dev dummy2 172.16.104.2/24 metric 258"
1586 set +e
1587
1588 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"
1589 log_test $? 0 "User specified metric on second device"
1590
1591 run_cmd "$IP addr del dev dummy1 172.16.104.1/24 metric 257"
1592 rc=$?
1593 if [ $rc -eq 0 ]; then
1594 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258"
1595 rc=$?
1596 fi
1597 log_test $rc 0 "Delete of address on first device"
1598
1599 run_cmd "$IP addr change dev dummy2 172.16.104.2/24 metric 259"
1600 rc=$?
1601 if [ $rc -eq 0 ]; then
1602 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1603 rc=$?
1604 fi
1605 log_test $rc 0 "Modify metric of address"
1606
1607 # verify prefix route removed on down
1608 run_cmd "$IP li set dev dummy2 down"
1609 rc=$?
1610 if [ $rc -eq 0 ]; then
1611 out=$($IP ro ls match 172.16.104.0/24)
1612 check_expected "${out}" ""
1613 rc=$?
1614 fi
1615 log_test $rc 0 "Prefix route removed on link down"
1616
1617 # verify prefix route re-inserted with assigned metric
1618 run_cmd "$IP li set dev dummy2 up"
1619 rc=$?
1620 if [ $rc -eq 0 ]; then
1621 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1622 rc=$?
1623 fi
1624 log_test $rc 0 "Prefix route with metric on link up"
1625
1626 # explicitly check for metric changes on edge scenarios
1627 run_cmd "$IP addr flush dev dummy2"
1628 run_cmd "$IP addr add dev dummy2 172.16.104.0/24 metric 259"
1629 run_cmd "$IP addr change dev dummy2 172.16.104.0/24 metric 260"
1630 rc=$?
1631 if [ $rc -eq 0 ]; then
1632 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.0 metric 260"
1633 rc=$?
1634 fi
1635 log_test $rc 0 "Modify metric of .0/24 address"
1636
1637 run_cmd "$IP addr flush dev dummy2"
1638 run_cmd "$IP addr add dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 260"
1639 rc=$?
1640 if [ $rc -eq 0 ]; then
1641 check_route "172.16.104.2 dev dummy2 proto kernel scope link src 172.16.104.1 metric 260"
1642 rc=$?
1643 fi
1644 log_test $rc 0 "Set metric of address with peer route"
1645
1646 run_cmd "$IP addr change dev dummy2 172.16.104.1/32 peer 172.16.104.3 metric 261"
1647 rc=$?
1648 if [ $rc -eq 0 ]; then
1649 check_route "172.16.104.3 dev dummy2 proto kernel scope link src 172.16.104.1 metric 261"
1650 rc=$?
1651 fi
1652 log_test $rc 0 "Modify metric and peer address for peer route"
1653
1654 $IP li del dummy1
1655 $IP li del dummy2
1656 cleanup
1657}
1658
1659ipv4_route_metrics_test()
1660{
1661 local rc
1662
1663 echo
1664 echo "IPv4 route add / append tests"
1665
1666 route_setup
1667
1668 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 mtu 1400"
1669 rc=$?
1670 if [ $rc -eq 0 ]; then
1671 check_route "172.16.111.0/24 via 172.16.101.2 dev veth1 mtu 1400"
1672 rc=$?
1673 fi
1674 log_test $rc 0 "Single path route with mtu metric"
1675
1676
1677 run_cmd "$IP ro add 172.16.112.0/24 mtu 1400 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1678 rc=$?
1679 if [ $rc -eq 0 ]; then
1680 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"
1681 rc=$?
1682 fi
1683 log_test $rc 0 "Multipath route with mtu metric"
1684
1685 $IP ro add 172.16.104.0/24 via 172.16.101.2 mtu 1300
1686 run_cmd "ip netns exec ns1 ping -w1 -c1 -s 1500 172.16.104.1"
1687 log_test $? 0 "Using route with mtu metric"
1688
1689 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 congctl lock foo"
1690 log_test $? 2 "Invalid metric (fails metric_convert)"
1691
1692 route_cleanup
1693}
1694
1695ipv4_del_addr_test()
1696{
1697 echo
1698 echo "IPv4 delete address route tests"
1699
1700 setup
1701
1702 set -e
1703 $IP li add dummy1 type dummy
1704 $IP li set dummy1 up
1705 $IP li add dummy2 type dummy
1706 $IP li set dummy2 up
1707 $IP li add red type vrf table 1111
1708 $IP li set red up
1709 $IP ro add vrf red unreachable default
1710 $IP li set dummy2 vrf red
1711
1712 $IP addr add dev dummy1 172.16.104.1/24
1713 $IP addr add dev dummy1 172.16.104.11/24
1714 $IP addr add dev dummy1 172.16.104.12/24
1715 $IP addr add dev dummy1 172.16.104.13/24
1716 $IP addr add dev dummy2 172.16.104.1/24
1717 $IP addr add dev dummy2 172.16.104.11/24
1718 $IP addr add dev dummy2 172.16.104.12/24
1719 $IP route add 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1720 $IP route add 172.16.106.0/24 dev lo src 172.16.104.12
1721 $IP route add table 0 172.16.107.0/24 via 172.16.104.2 src 172.16.104.13
1722 $IP route add vrf red 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1723 $IP route add vrf red 172.16.106.0/24 dev lo src 172.16.104.12
1724 set +e
1725
1726 # removing address from device in vrf should only remove route from vrf table
1727 echo " Regular FIB info"
1728
1729 $IP addr del dev dummy2 172.16.104.11/24
1730 $IP ro ls vrf red | grep -q 172.16.105.0/24
1731 log_test $? 1 "Route removed from VRF when source address deleted"
1732
1733 $IP ro ls | grep -q 172.16.105.0/24
1734 log_test $? 0 "Route in default VRF not removed"
1735
1736 $IP addr add dev dummy2 172.16.104.11/24
1737 $IP route add vrf red 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1738
1739 $IP addr del dev dummy1 172.16.104.11/24
1740 $IP ro ls | grep -q 172.16.105.0/24
1741 log_test $? 1 "Route removed in default VRF when source address deleted"
1742
1743 $IP ro ls vrf red | grep -q 172.16.105.0/24
1744 log_test $? 0 "Route in VRF is not removed by address delete"
1745
1746 # removing address from device in vrf should only remove route from vrf
1747 # table even when the associated fib info only differs in table ID
1748 echo " Identical FIB info with different table ID"
1749
1750 $IP addr del dev dummy2 172.16.104.12/24
1751 $IP ro ls vrf red | grep -q 172.16.106.0/24
1752 log_test $? 1 "Route removed from VRF when source address deleted"
1753
1754 $IP ro ls | grep -q 172.16.106.0/24
1755 log_test $? 0 "Route in default VRF not removed"
1756
1757 $IP addr add dev dummy2 172.16.104.12/24
1758 $IP route add vrf red 172.16.106.0/24 dev lo src 172.16.104.12
1759
1760 $IP addr del dev dummy1 172.16.104.12/24
1761 $IP ro ls | grep -q 172.16.106.0/24
1762 log_test $? 1 "Route removed in default VRF when source address deleted"
1763
1764 $IP ro ls vrf red | grep -q 172.16.106.0/24
1765 log_test $? 0 "Route in VRF is not removed by address delete"
1766
1767 # removing address from device in default vrf should remove route from
1768 # the default vrf even when route was inserted with a table ID of 0.
1769 echo " Table ID 0"
1770
1771 $IP addr del dev dummy1 172.16.104.13/24
1772 $IP ro ls | grep -q 172.16.107.0/24
1773 log_test $? 1 "Route removed in default VRF when source address deleted"
1774
1775 $IP li del dummy1
1776 $IP li del dummy2
1777 cleanup
1778}
1779
1780
1781ipv4_route_v6_gw_test()
1782{
1783 local rc
1784
1785 echo
1786 echo "IPv4 route with IPv6 gateway tests"
1787
1788 route_setup
1789 sleep 2
1790
1791 #
1792 # single path route
1793 #
1794 run_cmd "$IP ro add 172.16.104.0/24 via inet6 2001:db8:101::2"
1795 rc=$?
1796 log_test $rc 0 "Single path route with IPv6 gateway"
1797 if [ $rc -eq 0 ]; then
1798 check_route "172.16.104.0/24 via inet6 2001:db8:101::2 dev veth1"
1799 fi
1800
1801 run_cmd "ip netns exec ns1 ping -w1 -c1 172.16.104.1"
1802 log_test $rc 0 "Single path route with IPv6 gateway - ping"
1803
1804 run_cmd "$IP ro del 172.16.104.0/24 via inet6 2001:db8:101::2"
1805 rc=$?
1806 log_test $rc 0 "Single path route delete"
1807 if [ $rc -eq 0 ]; then
1808 check_route "172.16.112.0/24"
1809 fi
1810
1811 #
1812 # multipath - v6 then v4
1813 #
1814 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"
1815 rc=$?
1816 log_test $rc 0 "Multipath route add - v6 nexthop then v4"
1817 if [ $rc -eq 0 ]; then
1818 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"
1819 fi
1820
1821 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"
1822 log_test $? 2 " Multipath route delete - nexthops in wrong order"
1823
1824 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"
1825 log_test $? 0 " Multipath route delete exact match"
1826
1827 #
1828 # multipath - v4 then v6
1829 #
1830 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"
1831 rc=$?
1832 log_test $rc 0 "Multipath route add - v4 nexthop then v6"
1833 if [ $rc -eq 0 ]; then
1834 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"
1835 fi
1836
1837 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"
1838 log_test $? 2 " Multipath route delete - nexthops in wrong order"
1839
1840 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"
1841 log_test $? 0 " Multipath route delete exact match"
1842
1843 route_cleanup
1844}
1845
1846socat_check()
1847{
1848 if [ ! -x "$(command -v socat)" ]; then
1849 echo "socat command not found. Skipping test"
1850 return 1
1851 fi
1852
1853 return 0
1854}
1855
1856iptables_check()
1857{
1858 iptables -t mangle -L OUTPUT &> /dev/null
1859 if [ $? -ne 0 ]; then
1860 echo "iptables configuration not supported. Skipping test"
1861 return 1
1862 fi
1863
1864 return 0
1865}
1866
1867ip6tables_check()
1868{
1869 ip6tables -t mangle -L OUTPUT &> /dev/null
1870 if [ $? -ne 0 ]; then
1871 echo "ip6tables configuration not supported. Skipping test"
1872 return 1
1873 fi
1874
1875 return 0
1876}
1877
1878ipv4_mangle_test()
1879{
1880 local rc
1881
1882 echo
1883 echo "IPv4 mangling tests"
1884
1885 socat_check || return 1
1886 iptables_check || return 1
1887
1888 route_setup
1889 sleep 2
1890
1891 local tmp_file=$(mktemp)
1892 ip netns exec ns2 socat UDP4-LISTEN:54321,fork $tmp_file &
1893
1894 # Add a FIB rule and a route that will direct our connection to the
1895 # listening server.
1896 $IP rule add pref 100 ipproto udp sport 12345 dport 54321 table 123
1897 $IP route add table 123 172.16.101.0/24 dev veth1
1898
1899 # Add an unreachable route to the main table that will block our
1900 # connection in case the FIB rule is not hit.
1901 $IP route add unreachable 172.16.101.2/32
1902
1903 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
1904 log_test $? 0 " Connection with correct parameters"
1905
1906 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=11111"
1907 log_test $? 1 " Connection with incorrect parameters"
1908
1909 # Add a mangling rule and make sure connection is still successful.
1910 $NS_EXEC iptables -t mangle -A OUTPUT -j MARK --set-mark 1
1911
1912 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
1913 log_test $? 0 " Connection with correct parameters - mangling"
1914
1915 # Delete the mangling rule and make sure connection is still
1916 # successful.
1917 $NS_EXEC iptables -t mangle -D OUTPUT -j MARK --set-mark 1
1918
1919 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
1920 log_test $? 0 " Connection with correct parameters - no mangling"
1921
1922 # Verify connections were indeed successful on server side.
1923 [[ $(cat $tmp_file | wc -l) -eq 3 ]]
1924 log_test $? 0 " Connection check - server side"
1925
1926 $IP route del unreachable 172.16.101.2/32
1927 $IP route del table 123 172.16.101.0/24 dev veth1
1928 $IP rule del pref 100
1929
1930 { kill %% && wait %%; } 2>/dev/null
1931 rm $tmp_file
1932
1933 route_cleanup
1934}
1935
1936ipv6_mangle_test()
1937{
1938 local rc
1939
1940 echo
1941 echo "IPv6 mangling tests"
1942
1943 socat_check || return 1
1944 ip6tables_check || return 1
1945
1946 route_setup
1947 sleep 2
1948
1949 local tmp_file=$(mktemp)
1950 ip netns exec ns2 socat UDP6-LISTEN:54321,fork $tmp_file &
1951
1952 # Add a FIB rule and a route that will direct our connection to the
1953 # listening server.
1954 $IP -6 rule add pref 100 ipproto udp sport 12345 dport 54321 table 123
1955 $IP -6 route add table 123 2001:db8:101::/64 dev veth1
1956
1957 # Add an unreachable route to the main table that will block our
1958 # connection in case the FIB rule is not hit.
1959 $IP -6 route add unreachable 2001:db8:101::2/128
1960
1961 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
1962 log_test $? 0 " Connection with correct parameters"
1963
1964 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=11111"
1965 log_test $? 1 " Connection with incorrect parameters"
1966
1967 # Add a mangling rule and make sure connection is still successful.
1968 $NS_EXEC ip6tables -t mangle -A OUTPUT -j MARK --set-mark 1
1969
1970 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
1971 log_test $? 0 " Connection with correct parameters - mangling"
1972
1973 # Delete the mangling rule and make sure connection is still
1974 # successful.
1975 $NS_EXEC ip6tables -t mangle -D OUTPUT -j MARK --set-mark 1
1976
1977 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
1978 log_test $? 0 " Connection with correct parameters - no mangling"
1979
1980 # Verify connections were indeed successful on server side.
1981 [[ $(cat $tmp_file | wc -l) -eq 3 ]]
1982 log_test $? 0 " Connection check - server side"
1983
1984 $IP -6 route del unreachable 2001:db8:101::2/128
1985 $IP -6 route del table 123 2001:db8:101::/64 dev veth1
1986 $IP -6 rule del pref 100
1987
1988 { kill %% && wait %%; } 2>/dev/null
1989 rm $tmp_file
1990
1991 route_cleanup
1992}
1993
1994ip_neigh_get_check()
1995{
1996 ip neigh help 2>&1 | grep -q 'ip neigh get'
1997 if [ $? -ne 0 ]; then
1998 echo "iproute2 command does not support neigh get. Skipping test"
1999 return 1
2000 fi
2001
2002 return 0
2003}
2004
2005ipv4_bcast_neigh_test()
2006{
2007 local rc
2008
2009 echo
2010 echo "IPv4 broadcast neighbour tests"
2011
2012 ip_neigh_get_check || return 1
2013
2014 setup
2015
2016 set -e
2017 run_cmd "$IP neigh add 192.0.2.111 lladdr 00:11:22:33:44:55 nud perm dev dummy0"
2018 run_cmd "$IP neigh add 192.0.2.255 lladdr 00:11:22:33:44:55 nud perm dev dummy0"
2019
2020 run_cmd "$IP neigh get 192.0.2.111 dev dummy0"
2021 run_cmd "$IP neigh get 192.0.2.255 dev dummy0"
2022
2023 run_cmd "$IP address add 192.0.2.1/24 broadcast 192.0.2.111 dev dummy0"
2024
2025 run_cmd "$IP neigh add 203.0.113.111 nud failed dev dummy0"
2026 run_cmd "$IP neigh add 203.0.113.255 nud failed dev dummy0"
2027
2028 run_cmd "$IP neigh get 203.0.113.111 dev dummy0"
2029 run_cmd "$IP neigh get 203.0.113.255 dev dummy0"
2030
2031 run_cmd "$IP address add 203.0.113.1/24 broadcast 203.0.113.111 dev dummy0"
2032 set +e
2033
2034 run_cmd "$IP neigh get 192.0.2.111 dev dummy0"
2035 log_test $? 0 "Resolved neighbour for broadcast address"
2036
2037 run_cmd "$IP neigh get 192.0.2.255 dev dummy0"
2038 log_test $? 0 "Resolved neighbour for network broadcast address"
2039
2040 run_cmd "$IP neigh get 203.0.113.111 dev dummy0"
2041 log_test $? 2 "Unresolved neighbour for broadcast address"
2042
2043 run_cmd "$IP neigh get 203.0.113.255 dev dummy0"
2044 log_test $? 2 "Unresolved neighbour for network broadcast address"
2045
2046 cleanup
2047}
2048
2049################################################################################
2050# usage
2051
2052usage()
2053{
2054 cat <<EOF
2055usage: ${0##*/} OPTS
2056
2057 -t <test> Test(s) to run (default: all)
2058 (options: $TESTS)
2059 -p Pause on fail
2060 -P Pause after each test before cleanup
2061 -v verbose mode (show commands and output)
2062EOF
2063}
2064
2065################################################################################
2066# main
2067
2068while getopts :t:pPhv o
2069do
2070 case $o in
2071 t) TESTS=$OPTARG;;
2072 p) PAUSE_ON_FAIL=yes;;
2073 P) PAUSE=yes;;
2074 v) VERBOSE=$(($VERBOSE + 1));;
2075 h) usage; exit 0;;
2076 *) usage; exit 1;;
2077 esac
2078done
2079
2080PEER_CMD="ip netns exec ${PEER_NS}"
2081
2082# make sure we don't pause twice
2083[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
2084
2085if [ "$(id -u)" -ne 0 ];then
2086 echo "SKIP: Need root privileges"
2087 exit $ksft_skip;
2088fi
2089
2090if [ ! -x "$(command -v ip)" ]; then
2091 echo "SKIP: Could not run test without ip tool"
2092 exit $ksft_skip
2093fi
2094
2095ip route help 2>&1 | grep -q fibmatch
2096if [ $? -ne 0 ]; then
2097 echo "SKIP: iproute2 too old, missing fibmatch"
2098 exit $ksft_skip
2099fi
2100
2101# start clean
2102cleanup &> /dev/null
2103
2104for t in $TESTS
2105do
2106 case $t in
2107 fib_unreg_test|unregister) fib_unreg_test;;
2108 fib_down_test|down) fib_down_test;;
2109 fib_carrier_test|carrier) fib_carrier_test;;
2110 fib_rp_filter_test|rp_filter) fib_rp_filter_test;;
2111 fib_nexthop_test|nexthop) fib_nexthop_test;;
2112 fib_suppress_test|suppress) fib_suppress_test;;
2113 ipv6_route_test|ipv6_rt) ipv6_route_test;;
2114 ipv4_route_test|ipv4_rt) ipv4_route_test;;
2115 ipv6_addr_metric) ipv6_addr_metric_test;;
2116 ipv4_addr_metric) ipv4_addr_metric_test;;
2117 ipv4_del_addr) ipv4_del_addr_test;;
2118 ipv6_route_metrics) ipv6_route_metrics_test;;
2119 ipv4_route_metrics) ipv4_route_metrics_test;;
2120 ipv4_route_v6_gw) ipv4_route_v6_gw_test;;
2121 ipv4_mangle) ipv4_mangle_test;;
2122 ipv6_mangle) ipv6_mangle_test;;
2123 ipv4_bcast_neigh) ipv4_bcast_neigh_test;;
2124
2125 help) echo "Test names: $TESTS"; exit 0;;
2126 esac
2127done
2128
2129if [ "$TESTS" != "none" ]; then
2130 printf "\nTests passed: %3d\n" ${nsuccess}
2131 printf "Tests failed: %3d\n" ${nfail}
2132fi
2133
2134exit $ret
1#!/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.
6source lib.sh
7ret=0
8
9# all tests in this script. Can be overridden with -t option
10TESTS="unregister down carrier nexthop suppress ipv6_notify ipv4_notify \
11 ipv6_rt ipv4_rt ipv6_addr_metric ipv4_addr_metric ipv6_route_metrics \
12 ipv4_route_metrics ipv4_route_v6_gw rp_filter ipv4_del_addr \
13 ipv6_del_addr ipv4_mangle ipv6_mangle ipv4_bcast_neigh fib6_gc_test \
14 ipv4_mpath_list ipv6_mpath_list"
15
16VERBOSE=0
17PAUSE_ON_FAIL=no
18PAUSE=no
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 setup_ns ns1
55 IP="$(which ip) -netns $ns1"
56 NS_EXEC="$(which ip) netns exec $ns1"
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 cleanup_ns $ns1 $ns2
72}
73
74get_linklocal()
75{
76 local dev=$1
77 local addr
78
79 addr=$($IP -6 -br addr show dev ${dev} | \
80 awk '{
81 for (i = 3; i <= NF; ++i) {
82 if ($i ~ /^fe80/)
83 print $i
84 }
85 }'
86 )
87 addr=${addr/\/*}
88
89 [ -z "$addr" ] && return 1
90
91 echo $addr
92
93 return 0
94}
95
96fib_unreg_unicast_test()
97{
98 echo
99 echo "Single path route test"
100
101 setup
102
103 echo " Start point"
104 $IP route get fibmatch 198.51.100.2 &> /dev/null
105 log_test $? 0 "IPv4 fibmatch"
106 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
107 log_test $? 0 "IPv6 fibmatch"
108
109 set -e
110 $IP link del dev dummy0
111 set +e
112
113 echo " Nexthop device deleted"
114 $IP route get fibmatch 198.51.100.2 &> /dev/null
115 log_test $? 2 "IPv4 fibmatch - no route"
116 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
117 log_test $? 2 "IPv6 fibmatch - no route"
118
119 cleanup
120}
121
122fib_unreg_multipath_test()
123{
124
125 echo
126 echo "Multipath route test"
127
128 setup
129
130 set -e
131 $IP link add dummy1 type dummy
132 $IP link set dev dummy1 up
133 $IP address add 192.0.2.1/24 dev dummy1
134 $IP -6 address add 2001:db8:2::1/64 dev dummy1
135
136 $IP route add 203.0.113.0/24 \
137 nexthop via 198.51.100.2 dev dummy0 \
138 nexthop via 192.0.2.2 dev dummy1
139 $IP -6 route add 2001:db8:3::/64 \
140 nexthop via 2001:db8:1::2 dev dummy0 \
141 nexthop via 2001:db8:2::2 dev dummy1
142 set +e
143
144 echo " Start point"
145 $IP route get fibmatch 203.0.113.1 &> /dev/null
146 log_test $? 0 "IPv4 fibmatch"
147 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
148 log_test $? 0 "IPv6 fibmatch"
149
150 set -e
151 $IP link del dev dummy0
152 set +e
153
154 echo " One nexthop device deleted"
155 $IP route get fibmatch 203.0.113.1 &> /dev/null
156 log_test $? 2 "IPv4 - multipath route removed on delete"
157
158 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
159 # In IPv6 we do not flush the entire multipath route.
160 log_test $? 0 "IPv6 - multipath down to single path"
161
162 set -e
163 $IP link del dev dummy1
164 set +e
165
166 echo " Second nexthop device deleted"
167 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
168 log_test $? 2 "IPv6 - no route"
169
170 cleanup
171}
172
173fib_unreg_test()
174{
175 fib_unreg_unicast_test
176 fib_unreg_multipath_test
177}
178
179fib_down_unicast_test()
180{
181 echo
182 echo "Single path, admin down"
183
184 setup
185
186 echo " Start point"
187 $IP route get fibmatch 198.51.100.2 &> /dev/null
188 log_test $? 0 "IPv4 fibmatch"
189 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
190 log_test $? 0 "IPv6 fibmatch"
191
192 set -e
193 $IP link set dev dummy0 down
194 set +e
195
196 echo " Route deleted on down"
197 $IP route get fibmatch 198.51.100.2 &> /dev/null
198 log_test $? 2 "IPv4 fibmatch"
199 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
200 log_test $? 2 "IPv6 fibmatch"
201
202 cleanup
203}
204
205fib_down_multipath_test_do()
206{
207 local down_dev=$1
208 local up_dev=$2
209
210 $IP route get fibmatch 203.0.113.1 \
211 oif $down_dev &> /dev/null
212 log_test $? 2 "IPv4 fibmatch on down device"
213 $IP -6 route get fibmatch 2001:db8:3::1 \
214 oif $down_dev &> /dev/null
215 log_test $? 2 "IPv6 fibmatch on down device"
216
217 $IP route get fibmatch 203.0.113.1 \
218 oif $up_dev &> /dev/null
219 log_test $? 0 "IPv4 fibmatch on up device"
220 $IP -6 route get fibmatch 2001:db8:3::1 \
221 oif $up_dev &> /dev/null
222 log_test $? 0 "IPv6 fibmatch on up device"
223
224 $IP route get fibmatch 203.0.113.1 | \
225 grep $down_dev | grep -q "dead linkdown"
226 log_test $? 0 "IPv4 flags on down device"
227 $IP -6 route get fibmatch 2001:db8:3::1 | \
228 grep $down_dev | grep -q "dead linkdown"
229 log_test $? 0 "IPv6 flags on down device"
230
231 $IP route get fibmatch 203.0.113.1 | \
232 grep $up_dev | grep -q "dead linkdown"
233 log_test $? 1 "IPv4 flags on up device"
234 $IP -6 route get fibmatch 2001:db8:3::1 | \
235 grep $up_dev | grep -q "dead linkdown"
236 log_test $? 1 "IPv6 flags on up device"
237}
238
239fib_down_multipath_test()
240{
241 echo
242 echo "Admin down multipath"
243
244 setup
245
246 set -e
247 $IP link add dummy1 type dummy
248 $IP link set dev dummy1 up
249
250 $IP address add 192.0.2.1/24 dev dummy1
251 $IP -6 address add 2001:db8:2::1/64 dev dummy1
252
253 $IP route add 203.0.113.0/24 \
254 nexthop via 198.51.100.2 dev dummy0 \
255 nexthop via 192.0.2.2 dev dummy1
256 $IP -6 route add 2001:db8:3::/64 \
257 nexthop via 2001:db8:1::2 dev dummy0 \
258 nexthop via 2001:db8:2::2 dev dummy1
259 set +e
260
261 echo " Verify start point"
262 $IP route get fibmatch 203.0.113.1 &> /dev/null
263 log_test $? 0 "IPv4 fibmatch"
264
265 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
266 log_test $? 0 "IPv6 fibmatch"
267
268 set -e
269 $IP link set dev dummy0 down
270 set +e
271
272 echo " One device down, one up"
273 fib_down_multipath_test_do "dummy0" "dummy1"
274
275 set -e
276 $IP link set dev dummy0 up
277 $IP link set dev dummy1 down
278 set +e
279
280 echo " Other device down and up"
281 fib_down_multipath_test_do "dummy1" "dummy0"
282
283 set -e
284 $IP link set dev dummy0 down
285 set +e
286
287 echo " Both devices down"
288 $IP route get fibmatch 203.0.113.1 &> /dev/null
289 log_test $? 2 "IPv4 fibmatch"
290 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
291 log_test $? 2 "IPv6 fibmatch"
292
293 $IP link del dev dummy1
294 cleanup
295}
296
297fib_down_test()
298{
299 fib_down_unicast_test
300 fib_down_multipath_test
301}
302
303# Local routes should not be affected when carrier changes.
304fib_carrier_local_test()
305{
306 echo
307 echo "Local carrier tests - single path"
308
309 setup
310
311 set -e
312 $IP link set dev dummy0 carrier on
313 set +e
314
315 echo " Start point"
316 $IP route get fibmatch 198.51.100.1 &> /dev/null
317 log_test $? 0 "IPv4 fibmatch"
318 $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
319 log_test $? 0 "IPv6 fibmatch"
320
321 $IP route get fibmatch 198.51.100.1 | \
322 grep -q "linkdown"
323 log_test $? 1 "IPv4 - no linkdown flag"
324 $IP -6 route get fibmatch 2001:db8:1::1 | \
325 grep -q "linkdown"
326 log_test $? 1 "IPv6 - no linkdown flag"
327
328 set -e
329 $IP link set dev dummy0 carrier off
330 sleep 1
331 set +e
332
333 echo " Carrier off on nexthop"
334 $IP route get fibmatch 198.51.100.1 &> /dev/null
335 log_test $? 0 "IPv4 fibmatch"
336 $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
337 log_test $? 0 "IPv6 fibmatch"
338
339 $IP route get fibmatch 198.51.100.1 | \
340 grep -q "linkdown"
341 log_test $? 1 "IPv4 - linkdown flag set"
342 $IP -6 route get fibmatch 2001:db8:1::1 | \
343 grep -q "linkdown"
344 log_test $? 1 "IPv6 - linkdown flag set"
345
346 set -e
347 $IP address add 192.0.2.1/24 dev dummy0
348 $IP -6 address add 2001:db8:2::1/64 dev dummy0
349 set +e
350
351 echo " Route to local address with carrier down"
352 $IP route get fibmatch 192.0.2.1 &> /dev/null
353 log_test $? 0 "IPv4 fibmatch"
354 $IP -6 route get fibmatch 2001:db8:2::1 &> /dev/null
355 log_test $? 0 "IPv6 fibmatch"
356
357 $IP route get fibmatch 192.0.2.1 | \
358 grep -q "linkdown"
359 log_test $? 1 "IPv4 linkdown flag set"
360 $IP -6 route get fibmatch 2001:db8:2::1 | \
361 grep -q "linkdown"
362 log_test $? 1 "IPv6 linkdown flag set"
363
364 cleanup
365}
366
367fib_carrier_unicast_test()
368{
369 ret=0
370
371 echo
372 echo "Single path route carrier test"
373
374 setup
375
376 set -e
377 $IP link set dev dummy0 carrier on
378 set +e
379
380 echo " Start point"
381 $IP route get fibmatch 198.51.100.2 &> /dev/null
382 log_test $? 0 "IPv4 fibmatch"
383 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
384 log_test $? 0 "IPv6 fibmatch"
385
386 $IP route get fibmatch 198.51.100.2 | \
387 grep -q "linkdown"
388 log_test $? 1 "IPv4 no linkdown flag"
389 $IP -6 route get fibmatch 2001:db8:1::2 | \
390 grep -q "linkdown"
391 log_test $? 1 "IPv6 no linkdown flag"
392
393 set -e
394 $IP link set dev dummy0 carrier off
395 sleep 1
396 set +e
397
398 echo " Carrier down"
399 $IP route get fibmatch 198.51.100.2 &> /dev/null
400 log_test $? 0 "IPv4 fibmatch"
401 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
402 log_test $? 0 "IPv6 fibmatch"
403
404 $IP route get fibmatch 198.51.100.2 | \
405 grep -q "linkdown"
406 log_test $? 0 "IPv4 linkdown flag set"
407 $IP -6 route get fibmatch 2001:db8:1::2 | \
408 grep -q "linkdown"
409 log_test $? 0 "IPv6 linkdown flag set"
410
411 set -e
412 $IP address add 192.0.2.1/24 dev dummy0
413 $IP -6 address add 2001:db8:2::1/64 dev dummy0
414 set +e
415
416 echo " Second address added with carrier down"
417 $IP route get fibmatch 192.0.2.2 &> /dev/null
418 log_test $? 0 "IPv4 fibmatch"
419 $IP -6 route get fibmatch 2001:db8:2::2 &> /dev/null
420 log_test $? 0 "IPv6 fibmatch"
421
422 $IP route get fibmatch 192.0.2.2 | \
423 grep -q "linkdown"
424 log_test $? 0 "IPv4 linkdown flag set"
425 $IP -6 route get fibmatch 2001:db8:2::2 | \
426 grep -q "linkdown"
427 log_test $? 0 "IPv6 linkdown flag set"
428
429 cleanup
430}
431
432fib_carrier_test()
433{
434 fib_carrier_local_test
435 fib_carrier_unicast_test
436}
437
438fib_rp_filter_test()
439{
440 echo
441 echo "IPv4 rp_filter tests"
442
443 setup
444
445 set -e
446 setup_ns ns2
447
448 $IP link add name veth1 type veth peer name veth2
449 $IP link set dev veth2 netns $ns2
450 $IP address add 192.0.2.1/24 dev veth1
451 ip -netns $ns2 address add 192.0.2.1/24 dev veth2
452 $IP link set dev veth1 up
453 ip -netns $ns2 link set dev veth2 up
454
455 $IP link set dev lo address 52:54:00:6a:c7:5e
456 $IP link set dev veth1 address 52:54:00:6a:c7:5e
457 ip -netns $ns2 link set dev lo address 52:54:00:6a:c7:5e
458 ip -netns $ns2 link set dev veth2 address 52:54:00:6a:c7:5e
459
460 # 1. (ns2) redirect lo's egress to veth2's egress
461 ip netns exec $ns2 tc qdisc add dev lo parent root handle 1: fq_codel
462 ip netns exec $ns2 tc filter add dev lo parent 1: protocol arp basic \
463 action mirred egress redirect dev veth2
464 ip netns exec $ns2 tc filter add dev lo parent 1: protocol ip basic \
465 action mirred egress redirect dev veth2
466
467 # 2. (ns1) redirect veth1's ingress to lo's ingress
468 $NS_EXEC tc qdisc add dev veth1 ingress
469 $NS_EXEC tc filter add dev veth1 ingress protocol arp basic \
470 action mirred ingress redirect dev lo
471 $NS_EXEC tc filter add dev veth1 ingress protocol ip basic \
472 action mirred ingress redirect dev lo
473
474 # 3. (ns1) redirect lo's egress to veth1's egress
475 $NS_EXEC tc qdisc add dev lo parent root handle 1: fq_codel
476 $NS_EXEC tc filter add dev lo parent 1: protocol arp basic \
477 action mirred egress redirect dev veth1
478 $NS_EXEC tc filter add dev lo parent 1: protocol ip basic \
479 action mirred egress redirect dev veth1
480
481 # 4. (ns2) redirect veth2's ingress to lo's ingress
482 ip netns exec $ns2 tc qdisc add dev veth2 ingress
483 ip netns exec $ns2 tc filter add dev veth2 ingress protocol arp basic \
484 action mirred ingress redirect dev lo
485 ip netns exec $ns2 tc filter add dev veth2 ingress protocol ip basic \
486 action mirred ingress redirect dev lo
487
488 $NS_EXEC sysctl -qw net.ipv4.conf.all.rp_filter=1
489 $NS_EXEC sysctl -qw net.ipv4.conf.all.accept_local=1
490 $NS_EXEC sysctl -qw net.ipv4.conf.all.route_localnet=1
491 ip netns exec $ns2 sysctl -qw net.ipv4.conf.all.rp_filter=1
492 ip netns exec $ns2 sysctl -qw net.ipv4.conf.all.accept_local=1
493 ip netns exec $ns2 sysctl -qw net.ipv4.conf.all.route_localnet=1
494 set +e
495
496 run_cmd "ip netns exec $ns2 ping -w1 -c1 192.0.2.1"
497 log_test $? 0 "rp_filter passes local packets"
498
499 run_cmd "ip netns exec $ns2 ping -w1 -c1 127.0.0.1"
500 log_test $? 0 "rp_filter passes loopback packets"
501
502 cleanup
503}
504
505################################################################################
506# Tests on nexthop spec
507
508# run 'ip route add' with given spec
509add_rt()
510{
511 local desc="$1"
512 local erc=$2
513 local vrf=$3
514 local pfx=$4
515 local gw=$5
516 local dev=$6
517 local cmd out rc
518
519 [ "$vrf" = "-" ] && vrf="default"
520 [ -n "$gw" ] && gw="via $gw"
521 [ -n "$dev" ] && dev="dev $dev"
522
523 cmd="$IP route add vrf $vrf $pfx $gw $dev"
524 if [ "$VERBOSE" = "1" ]; then
525 printf "\n COMMAND: $cmd\n"
526 fi
527
528 out=$(eval $cmd 2>&1)
529 rc=$?
530 if [ "$VERBOSE" = "1" -a -n "$out" ]; then
531 echo " $out"
532 fi
533 log_test $rc $erc "$desc"
534}
535
536fib4_nexthop()
537{
538 echo
539 echo "IPv4 nexthop tests"
540
541 echo "<<< write me >>>"
542}
543
544fib6_nexthop()
545{
546 local lldummy=$(get_linklocal dummy0)
547 local llv1=$(get_linklocal dummy0)
548
549 if [ -z "$lldummy" ]; then
550 echo "Failed to get linklocal address for dummy0"
551 return 1
552 fi
553 if [ -z "$llv1" ]; then
554 echo "Failed to get linklocal address for veth1"
555 return 1
556 fi
557
558 echo
559 echo "IPv6 nexthop tests"
560
561 add_rt "Directly connected nexthop, unicast address" 0 \
562 - 2001:db8:101::/64 2001:db8:1::2
563 add_rt "Directly connected nexthop, unicast address with device" 0 \
564 - 2001:db8:102::/64 2001:db8:1::2 "dummy0"
565 add_rt "Gateway is linklocal address" 0 \
566 - 2001:db8:103::1/64 $llv1 "veth0"
567
568 # fails because LL address requires a device
569 add_rt "Gateway is linklocal address, no device" 2 \
570 - 2001:db8:104::1/64 $llv1
571
572 # local address can not be a gateway
573 add_rt "Gateway can not be local unicast address" 2 \
574 - 2001:db8:105::/64 2001:db8:1::1
575 add_rt "Gateway can not be local unicast address, with device" 2 \
576 - 2001:db8:106::/64 2001:db8:1::1 "dummy0"
577 add_rt "Gateway can not be a local linklocal address" 2 \
578 - 2001:db8:107::1/64 $lldummy "dummy0"
579
580 # VRF tests
581 add_rt "Gateway can be local address in a VRF" 0 \
582 - 2001:db8:108::/64 2001:db8:51::2
583 add_rt "Gateway can be local address in a VRF, with device" 0 \
584 - 2001:db8:109::/64 2001:db8:51::2 "veth0"
585 add_rt "Gateway can be local linklocal address in a VRF" 0 \
586 - 2001:db8:110::1/64 $llv1 "veth0"
587
588 add_rt "Redirect to VRF lookup" 0 \
589 - 2001:db8:111::/64 "" "red"
590
591 add_rt "VRF route, gateway can be local address in default VRF" 0 \
592 red 2001:db8:112::/64 2001:db8:51::1
593
594 # local address in same VRF fails
595 add_rt "VRF route, gateway can not be a local address" 2 \
596 red 2001:db8:113::1/64 2001:db8:2::1
597 add_rt "VRF route, gateway can not be a local addr with device" 2 \
598 red 2001:db8:114::1/64 2001:db8:2::1 "dummy1"
599}
600
601# Default VRF:
602# dummy0 - 198.51.100.1/24 2001:db8:1::1/64
603# veth0 - 192.0.2.1/24 2001:db8:51::1/64
604#
605# VRF red:
606# dummy1 - 192.168.2.1/24 2001:db8:2::1/64
607# veth1 - 192.0.2.2/24 2001:db8:51::2/64
608#
609# [ dummy0 veth0 ]--[ veth1 dummy1 ]
610
611fib_nexthop_test()
612{
613 setup
614
615 set -e
616
617 $IP -4 rule add pref 32765 table local
618 $IP -4 rule del pref 0
619 $IP -6 rule add pref 32765 table local
620 $IP -6 rule del pref 0
621
622 $IP link add red type vrf table 1
623 $IP link set red up
624 $IP -4 route add vrf red unreachable default metric 4278198272
625 $IP -6 route add vrf red unreachable default metric 4278198272
626
627 $IP link add veth0 type veth peer name veth1
628 $IP link set dev veth0 up
629 $IP address add 192.0.2.1/24 dev veth0
630 $IP -6 address add 2001:db8:51::1/64 dev veth0
631
632 $IP link set dev veth1 vrf red up
633 $IP address add 192.0.2.2/24 dev veth1
634 $IP -6 address add 2001:db8:51::2/64 dev veth1
635
636 $IP link add dummy1 type dummy
637 $IP link set dev dummy1 vrf red up
638 $IP address add 192.168.2.1/24 dev dummy1
639 $IP -6 address add 2001:db8:2::1/64 dev dummy1
640 set +e
641
642 sleep 1
643 fib4_nexthop
644 fib6_nexthop
645
646 (
647 $IP link del dev dummy1
648 $IP link del veth0
649 $IP link del red
650 ) 2>/dev/null
651 cleanup
652}
653
654fib6_notify_test()
655{
656 setup
657
658 echo
659 echo "Fib6 info length calculation in route notify test"
660 set -e
661
662 for i in 10 20 30 40 50 60 70;
663 do
664 $IP link add dummy_$i type dummy
665 $IP link set dev dummy_$i up
666 $IP -6 address add 2001:$i::1/64 dev dummy_$i
667 done
668
669 $NS_EXEC ip monitor route &> errors.txt &
670 sleep 2
671
672 $IP -6 route add 2001::/64 \
673 nexthop via 2001:10::2 dev dummy_10 \
674 nexthop encap ip6 dst 2002::20 via 2001:20::2 dev dummy_20 \
675 nexthop encap ip6 dst 2002::30 via 2001:30::2 dev dummy_30 \
676 nexthop encap ip6 dst 2002::40 via 2001:40::2 dev dummy_40 \
677 nexthop encap ip6 dst 2002::50 via 2001:50::2 dev dummy_50 \
678 nexthop encap ip6 dst 2002::60 via 2001:60::2 dev dummy_60 \
679 nexthop encap ip6 dst 2002::70 via 2001:70::2 dev dummy_70
680
681 set +e
682
683 err=`cat errors.txt |grep "Message too long"`
684 if [ -z "$err" ];then
685 ret=0
686 else
687 ret=1
688 fi
689
690 log_test $ret 0 "ipv6 route add notify"
691
692 kill_process %%
693
694 #rm errors.txt
695
696 cleanup &> /dev/null
697}
698
699
700fib_notify_test()
701{
702 setup
703
704 echo
705 echo "Fib4 info length calculation in route notify test"
706
707 set -e
708
709 for i in 10 20 30 40 50 60 70;
710 do
711 $IP link add dummy_$i type dummy
712 $IP link set dev dummy_$i up
713 $IP address add 20.20.$i.2/24 dev dummy_$i
714 done
715
716 $NS_EXEC ip monitor route &> errors.txt &
717 sleep 2
718
719 $IP route add 10.0.0.0/24 \
720 nexthop via 20.20.10.1 dev dummy_10 \
721 nexthop encap ip dst 192.168.10.20 via 20.20.20.1 dev dummy_20 \
722 nexthop encap ip dst 192.168.10.30 via 20.20.30.1 dev dummy_30 \
723 nexthop encap ip dst 192.168.10.40 via 20.20.40.1 dev dummy_40 \
724 nexthop encap ip dst 192.168.10.50 via 20.20.50.1 dev dummy_50 \
725 nexthop encap ip dst 192.168.10.60 via 20.20.60.1 dev dummy_60 \
726 nexthop encap ip dst 192.168.10.70 via 20.20.70.1 dev dummy_70
727
728 set +e
729
730 err=`cat errors.txt |grep "Message too long"`
731 if [ -z "$err" ];then
732 ret=0
733 else
734 ret=1
735 fi
736
737 log_test $ret 0 "ipv4 route add notify"
738
739 kill_process %%
740
741 rm errors.txt
742
743 cleanup &> /dev/null
744}
745
746# Create a new dummy_10 to remove all associated routes.
747reset_dummy_10()
748{
749 $IP link del dev dummy_10
750
751 $IP link add dummy_10 type dummy
752 $IP link set dev dummy_10 up
753 $IP -6 address add 2001:10::1/64 dev dummy_10
754}
755
756check_rt_num()
757{
758 local expected=$1
759 local num=$2
760
761 if [ $num -ne $expected ]; then
762 echo "FAIL: Expected $expected routes, got $num"
763 ret=1
764 else
765 ret=0
766 fi
767}
768
769check_rt_num_clean()
770{
771 local expected=$1
772 local num=$2
773
774 if [ $num -ne $expected ]; then
775 log_test 1 0 "expected $expected routes, got $num"
776 set +e
777 cleanup &> /dev/null
778 return 1
779 fi
780 return 0
781}
782
783fib6_gc_test()
784{
785 setup
786
787 echo
788 echo "Fib6 garbage collection test"
789 set -e
790
791 EXPIRE=5
792 GC_WAIT_TIME=$((EXPIRE * 2 + 2))
793
794 # Check expiration of routes every $EXPIRE seconds (GC)
795 $NS_EXEC sysctl -wq net.ipv6.route.gc_interval=$EXPIRE
796
797 $IP link add dummy_10 type dummy
798 $IP link set dev dummy_10 up
799 $IP -6 address add 2001:10::1/64 dev dummy_10
800
801 $NS_EXEC sysctl -wq net.ipv6.route.flush=1
802
803 # Temporary routes
804 for i in $(seq 1 5); do
805 # Expire route after $EXPIRE seconds
806 $IP -6 route add 2001:20::$i \
807 via 2001:10::2 dev dummy_10 expires $EXPIRE
808 done
809 sleep $GC_WAIT_TIME
810 $NS_EXEC sysctl -wq net.ipv6.route.flush=1
811 check_rt_num 0 $($IP -6 route list |grep expires|wc -l)
812 log_test $ret 0 "ipv6 route garbage collection"
813
814 reset_dummy_10
815
816 # Permanent routes
817 for i in $(seq 1 5); do
818 $IP -6 route add 2001:30::$i \
819 via 2001:10::2 dev dummy_10
820 done
821 # Temporary routes
822 for i in $(seq 1 5); do
823 # Expire route after $EXPIRE seconds
824 $IP -6 route add 2001:20::$i \
825 via 2001:10::2 dev dummy_10 expires $EXPIRE
826 done
827 # Wait for GC
828 sleep $GC_WAIT_TIME
829 check_rt_num 0 $($IP -6 route list |grep expires|wc -l)
830 log_test $ret 0 "ipv6 route garbage collection (with permanent routes)"
831
832 reset_dummy_10
833
834 # Permanent routes
835 for i in $(seq 1 5); do
836 $IP -6 route add 2001:20::$i \
837 via 2001:10::2 dev dummy_10
838 done
839 # Replace with temporary routes
840 for i in $(seq 1 5); do
841 # Expire route after $EXPIRE seconds
842 $IP -6 route replace 2001:20::$i \
843 via 2001:10::2 dev dummy_10 expires $EXPIRE
844 done
845 # Wait for GC
846 sleep $GC_WAIT_TIME
847 check_rt_num 0 $($IP -6 route list |grep expires|wc -l)
848 log_test $ret 0 "ipv6 route garbage collection (replace with expires)"
849
850 reset_dummy_10
851
852 # Temporary routes
853 for i in $(seq 1 5); do
854 # Expire route after $EXPIRE seconds
855 $IP -6 route add 2001:20::$i \
856 via 2001:10::2 dev dummy_10 expires $EXPIRE
857 done
858 # Replace with permanent routes
859 for i in $(seq 1 5); do
860 $IP -6 route replace 2001:20::$i \
861 via 2001:10::2 dev dummy_10
862 done
863 check_rt_num_clean 0 $($IP -6 route list |grep expires|wc -l) || return
864
865 # Wait for GC
866 sleep $GC_WAIT_TIME
867 check_rt_num 5 $($IP -6 route list |grep -v expires|grep 2001:20::|wc -l)
868 log_test $ret 0 "ipv6 route garbage collection (replace with permanent)"
869
870 # ra6 is required for the next test. (ipv6toolkit)
871 if [ ! -x "$(command -v ra6)" ]; then
872 echo "SKIP: ra6 not found."
873 set +e
874 cleanup &> /dev/null
875 return
876 fi
877
878 # Delete dummy_10 and remove all routes
879 $IP link del dev dummy_10
880
881 # Create a pair of veth devices to send a RA message from one
882 # device to another.
883 $IP link add veth1 type veth peer name veth2
884 $IP link set dev veth1 up
885 $IP link set dev veth2 up
886 $IP -6 address add 2001:10::1/64 dev veth1 nodad
887 $IP -6 address add 2001:10::2/64 dev veth2 nodad
888
889 # Make veth1 ready to receive RA messages.
890 $NS_EXEC sysctl -wq net.ipv6.conf.veth1.accept_ra=2
891
892 # Send a RA message with a route from veth2 to veth1.
893 $NS_EXEC ra6 -i veth2 -d 2001:10::1 -t $EXPIRE
894
895 # Wait for the RA message.
896 sleep 1
897
898 # systemd may mess up the test. You syould make sure that
899 # systemd-networkd.service and systemd-networkd.socket are stopped.
900 check_rt_num_clean 1 $($IP -6 route list|grep expires|wc -l) || return
901
902 # Wait for GC
903 sleep $GC_WAIT_TIME
904 check_rt_num 0 $($IP -6 route list |grep expires|wc -l)
905 log_test $ret 0 "ipv6 route garbage collection (RA message)"
906
907 set +e
908
909 cleanup &> /dev/null
910}
911
912fib_suppress_test()
913{
914 echo
915 echo "FIB rule with suppress_prefixlength"
916 setup
917
918 $IP link add dummy1 type dummy
919 $IP link set dummy1 up
920 $IP -6 route add default dev dummy1
921 $IP -6 rule add table main suppress_prefixlength 0
922 ping -f -c 1000 -W 1 1234::1 >/dev/null 2>&1
923 $IP -6 rule del table main suppress_prefixlength 0
924 $IP link del dummy1
925
926 # If we got here without crashing, we're good.
927 log_test 0 0 "FIB rule suppress test"
928
929 cleanup
930}
931
932################################################################################
933# Tests on route add and replace
934
935run_cmd()
936{
937 local cmd="$1"
938 local out
939 local stderr="2>/dev/null"
940
941 if [ "$VERBOSE" = "1" ]; then
942 printf " COMMAND: $cmd\n"
943 stderr=
944 fi
945
946 out=$(eval $cmd $stderr)
947 rc=$?
948 if [ "$VERBOSE" = "1" -a -n "$out" ]; then
949 echo " $out"
950 fi
951
952 [ "$VERBOSE" = "1" ] && echo
953
954 return $rc
955}
956
957check_expected()
958{
959 local out="$1"
960 local expected="$2"
961 local rc=0
962
963 [ "${out}" = "${expected}" ] && return 0
964
965 if [ -z "${out}" ]; then
966 if [ "$VERBOSE" = "1" ]; then
967 printf "\nNo route entry found\n"
968 printf "Expected:\n"
969 printf " ${expected}\n"
970 fi
971 return 1
972 fi
973
974 # tricky way to convert output to 1-line without ip's
975 # messy '\'; this drops all extra white space
976 out=$(echo ${out})
977 if [ "${out}" != "${expected}" ]; then
978 rc=1
979 if [ "${VERBOSE}" = "1" ]; then
980 printf " Unexpected route entry. Have:\n"
981 printf " ${out}\n"
982 printf " Expected:\n"
983 printf " ${expected}\n\n"
984 fi
985 fi
986
987 return $rc
988}
989
990# add route for a prefix, flushing any existing routes first
991# expected to be the first step of a test
992add_route6()
993{
994 local pfx="$1"
995 local nh="$2"
996 local out
997
998 if [ "$VERBOSE" = "1" ]; then
999 echo
1000 echo " ##################################################"
1001 echo
1002 fi
1003
1004 run_cmd "$IP -6 ro flush ${pfx}"
1005 [ $? -ne 0 ] && exit 1
1006
1007 out=$($IP -6 ro ls match ${pfx})
1008 if [ -n "$out" ]; then
1009 echo "Failed to flush routes for prefix used for tests."
1010 exit 1
1011 fi
1012
1013 run_cmd "$IP -6 ro add ${pfx} ${nh}"
1014 if [ $? -ne 0 ]; then
1015 echo "Failed to add initial route for test."
1016 exit 1
1017 fi
1018}
1019
1020# add initial route - used in replace route tests
1021add_initial_route6()
1022{
1023 add_route6 "2001:db8:104::/64" "$1"
1024}
1025
1026check_route6()
1027{
1028 local pfx
1029 local expected="$1"
1030 local out
1031 local rc=0
1032
1033 set -- $expected
1034 pfx=$1
1035
1036 out=$($IP -6 ro ls match ${pfx} | sed -e 's/ pref medium//')
1037 check_expected "${out}" "${expected}"
1038}
1039
1040route_cleanup()
1041{
1042 $IP li del red 2>/dev/null
1043 $IP li del dummy1 2>/dev/null
1044 $IP li del veth1 2>/dev/null
1045 $IP li del veth3 2>/dev/null
1046
1047 cleanup &> /dev/null
1048}
1049
1050route_setup()
1051{
1052 route_cleanup
1053 setup
1054
1055 [ "${VERBOSE}" = "1" ] && set -x
1056 set -e
1057
1058 setup_ns ns2
1059 ip netns exec $ns2 sysctl -qw net.ipv4.ip_forward=1
1060 ip netns exec $ns2 sysctl -qw net.ipv6.conf.all.forwarding=1
1061
1062 $IP li add veth1 type veth peer name veth2
1063 $IP li add veth3 type veth peer name veth4
1064
1065 $IP li set veth1 up
1066 $IP li set veth3 up
1067 $IP li set veth2 netns $ns2 up
1068 $IP li set veth4 netns $ns2 up
1069 ip -netns $ns2 li add dummy1 type dummy
1070 ip -netns $ns2 li set dummy1 up
1071
1072 $IP -6 addr add 2001:db8:101::1/64 dev veth1 nodad
1073 $IP -6 addr add 2001:db8:103::1/64 dev veth3 nodad
1074 $IP addr add 172.16.101.1/24 dev veth1
1075 $IP addr add 172.16.103.1/24 dev veth3
1076
1077 ip -netns $ns2 -6 addr add 2001:db8:101::2/64 dev veth2 nodad
1078 ip -netns $ns2 -6 addr add 2001:db8:103::2/64 dev veth4 nodad
1079 ip -netns $ns2 -6 addr add 2001:db8:104::1/64 dev dummy1 nodad
1080
1081 ip -netns $ns2 addr add 172.16.101.2/24 dev veth2
1082 ip -netns $ns2 addr add 172.16.103.2/24 dev veth4
1083 ip -netns $ns2 addr add 172.16.104.1/24 dev dummy1
1084
1085 set +e
1086}
1087
1088# assumption is that basic add of a single path route works
1089# otherwise just adding an address on an interface is broken
1090ipv6_rt_add()
1091{
1092 local rc
1093
1094 echo
1095 echo "IPv6 route add / append tests"
1096
1097 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1098 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1099 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2"
1100 log_test $? 2 "Attempt to add duplicate route - gw"
1101
1102 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1103 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1104 run_cmd "$IP -6 ro add 2001:db8:104::/64 dev veth3"
1105 log_test $? 2 "Attempt to add duplicate route - dev only"
1106
1107 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1108 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1109 run_cmd "$IP -6 ro add unreachable 2001:db8:104::/64"
1110 log_test $? 2 "Attempt to add duplicate route - reject route"
1111
1112 # route append with same prefix adds a new route
1113 # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
1114 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1115 run_cmd "$IP -6 ro append 2001:db8:104::/64 via 2001:db8:103::2"
1116 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"
1117 log_test $? 0 "Append nexthop to existing route - gw"
1118
1119 # insert mpath directly
1120 add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1121 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"
1122 log_test $? 0 "Add multipath route"
1123
1124 add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1125 run_cmd "$IP -6 ro add 2001:db8:104::/64 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1126 log_test $? 2 "Attempt to add duplicate multipath route"
1127
1128 # insert of a second route without append but different metric
1129 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1130 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2 metric 512"
1131 rc=$?
1132 if [ $rc -eq 0 ]; then
1133 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::3 metric 256"
1134 rc=$?
1135 fi
1136 log_test $rc 0 "Route add with different metrics"
1137
1138 run_cmd "$IP -6 ro del 2001:db8:104::/64 metric 512"
1139 rc=$?
1140 if [ $rc -eq 0 ]; then
1141 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"
1142 rc=$?
1143 fi
1144 log_test $rc 0 "Route delete with metric"
1145}
1146
1147ipv6_rt_replace_single()
1148{
1149 # single path with single path
1150 #
1151 add_initial_route6 "via 2001:db8:101::2"
1152 run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:103::2"
1153 check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
1154 log_test $? 0 "Single path with single path"
1155
1156 # single path with multipath
1157 #
1158 add_initial_route6 "nexthop via 2001:db8:101::2"
1159 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::2"
1160 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"
1161 log_test $? 0 "Single path with multipath"
1162
1163 # single path with single path using MULTIPATH attribute
1164 #
1165 add_initial_route6 "via 2001:db8:101::2"
1166 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:103::2"
1167 check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
1168 log_test $? 0 "Single path with single path via multipath attribute"
1169
1170 # route replace fails - invalid nexthop
1171 add_initial_route6 "via 2001:db8:101::2"
1172 run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:104::2"
1173 if [ $? -eq 0 ]; then
1174 # previous command is expected to fail so if it returns 0
1175 # that means the test failed.
1176 log_test 0 1 "Invalid nexthop"
1177 else
1178 check_route6 "2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024"
1179 log_test $? 0 "Invalid nexthop"
1180 fi
1181
1182 # replace non-existent route
1183 # - note use of change versus replace since ip adds NLM_F_CREATE
1184 # for replace
1185 add_initial_route6 "via 2001:db8:101::2"
1186 run_cmd "$IP -6 ro change 2001:db8:105::/64 via 2001:db8:101::2"
1187 log_test $? 2 "Single path - replace of non-existent route"
1188}
1189
1190ipv6_rt_replace_mpath()
1191{
1192 # multipath with multipath
1193 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1194 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
1195 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"
1196 log_test $? 0 "Multipath with multipath"
1197
1198 # multipath with single
1199 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1200 run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:101::3"
1201 check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
1202 log_test $? 0 "Multipath with single path"
1203
1204 # multipath with single
1205 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1206 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3"
1207 check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
1208 log_test $? 0 "Multipath with single path via multipath attribute"
1209
1210 # multipath with dev-only
1211 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1212 run_cmd "$IP -6 ro replace 2001:db8:104::/64 dev veth1"
1213 check_route6 "2001:db8:104::/64 dev veth1 metric 1024"
1214 log_test $? 0 "Multipath with dev-only"
1215
1216 # route replace fails - invalid nexthop 1
1217 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1218 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:111::3 nexthop via 2001:db8:103::3"
1219 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"
1220 log_test $? 0 "Multipath - invalid first nexthop"
1221
1222 # route replace fails - invalid nexthop 2
1223 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1224 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:113::3"
1225 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"
1226 log_test $? 0 "Multipath - invalid second nexthop"
1227
1228 # multipath non-existent route
1229 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1230 run_cmd "$IP -6 ro change 2001:db8:105::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
1231 log_test $? 2 "Multipath - replace of non-existent route"
1232}
1233
1234ipv6_rt_replace()
1235{
1236 echo
1237 echo "IPv6 route replace tests"
1238
1239 ipv6_rt_replace_single
1240 ipv6_rt_replace_mpath
1241}
1242
1243ipv6_rt_dsfield()
1244{
1245 echo
1246 echo "IPv6 route with dsfield tests"
1247
1248 run_cmd "$IP -6 route flush 2001:db8:102::/64"
1249
1250 # IPv6 doesn't support routing based on dsfield
1251 run_cmd "$IP -6 route add 2001:db8:102::/64 dsfield 0x04 via 2001:db8:101::2"
1252 log_test $? 2 "Reject route with dsfield"
1253}
1254
1255ipv6_route_test()
1256{
1257 route_setup
1258
1259 ipv6_rt_add
1260 ipv6_rt_replace
1261 ipv6_rt_dsfield
1262
1263 route_cleanup
1264}
1265
1266ip_addr_metric_check()
1267{
1268 ip addr help 2>&1 | grep -q metric
1269 if [ $? -ne 0 ]; then
1270 echo "iproute2 command does not support metric for addresses. Skipping test"
1271 return 1
1272 fi
1273
1274 return 0
1275}
1276
1277ipv6_addr_metric_test()
1278{
1279 local rc
1280
1281 echo
1282 echo "IPv6 prefix route tests"
1283
1284 ip_addr_metric_check || return 1
1285
1286 setup
1287
1288 set -e
1289 $IP li add dummy1 type dummy
1290 $IP li add dummy2 type dummy
1291 $IP li set dummy1 up
1292 $IP li set dummy2 up
1293
1294 # default entry is metric 256
1295 run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64"
1296 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64"
1297 set +e
1298
1299 check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 256 2001:db8:104::/64 dev dummy2 proto kernel metric 256"
1300 log_test $? 0 "Default metric"
1301
1302 set -e
1303 run_cmd "$IP -6 addr flush dev dummy1"
1304 run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64 metric 257"
1305 set +e
1306
1307 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 256 2001:db8:104::/64 dev dummy1 proto kernel metric 257"
1308 log_test $? 0 "User specified metric on first device"
1309
1310 set -e
1311 run_cmd "$IP -6 addr flush dev dummy2"
1312 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64 metric 258"
1313 set +e
1314
1315 check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 257 2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1316 log_test $? 0 "User specified metric on second device"
1317
1318 run_cmd "$IP -6 addr del dev dummy1 2001:db8:104::1/64 metric 257"
1319 rc=$?
1320 if [ $rc -eq 0 ]; then
1321 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1322 rc=$?
1323 fi
1324 log_test $rc 0 "Delete of address on first device"
1325
1326 run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::2/64 metric 259"
1327 rc=$?
1328 if [ $rc -eq 0 ]; then
1329 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1330 rc=$?
1331 fi
1332 log_test $rc 0 "Modify metric of address"
1333
1334 # verify prefix route removed on down
1335 run_cmd "ip netns exec $ns1 sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1"
1336 run_cmd "$IP li set dev dummy2 down"
1337 rc=$?
1338 if [ $rc -eq 0 ]; then
1339 out=$($IP -6 ro ls match 2001:db8:104::/64)
1340 check_expected "${out}" ""
1341 rc=$?
1342 fi
1343 log_test $rc 0 "Prefix route removed on link down"
1344
1345 # verify prefix route re-inserted with assigned metric
1346 run_cmd "$IP li set dev dummy2 up"
1347 rc=$?
1348 if [ $rc -eq 0 ]; then
1349 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1350 rc=$?
1351 fi
1352 log_test $rc 0 "Prefix route with metric on link up"
1353
1354 # verify peer metric added correctly
1355 set -e
1356 run_cmd "$IP -6 addr flush dev dummy2"
1357 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::1 peer 2001:db8:104::2 metric 260"
1358 set +e
1359
1360 check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 260"
1361 log_test $? 0 "Set metric with peer route on local side"
1362 check_route6 "2001:db8:104::2 dev dummy2 proto kernel metric 260"
1363 log_test $? 0 "Set metric with peer route on peer side"
1364
1365 set -e
1366 run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::1 peer 2001:db8:104::3 metric 261"
1367 set +e
1368
1369 check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 261"
1370 log_test $? 0 "Modify metric and peer address on local side"
1371 check_route6 "2001:db8:104::3 dev dummy2 proto kernel metric 261"
1372 log_test $? 0 "Modify metric and peer address on peer side"
1373
1374 $IP li del dummy1
1375 $IP li del dummy2
1376 cleanup
1377}
1378
1379ipv6_route_metrics_test()
1380{
1381 local rc
1382
1383 echo
1384 echo "IPv6 routes with metrics"
1385
1386 route_setup
1387
1388 #
1389 # single path with metrics
1390 #
1391 run_cmd "$IP -6 ro add 2001:db8:111::/64 via 2001:db8:101::2 mtu 1400"
1392 rc=$?
1393 if [ $rc -eq 0 ]; then
1394 check_route6 "2001:db8:111::/64 via 2001:db8:101::2 dev veth1 metric 1024 mtu 1400"
1395 rc=$?
1396 fi
1397 log_test $rc 0 "Single path route with mtu metric"
1398
1399
1400 #
1401 # multipath via separate routes with metrics
1402 #
1403 run_cmd "$IP -6 ro add 2001:db8:112::/64 via 2001:db8:101::2 mtu 1400"
1404 run_cmd "$IP -6 ro append 2001:db8:112::/64 via 2001:db8:103::2"
1405 rc=$?
1406 if [ $rc -eq 0 ]; then
1407 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"
1408 rc=$?
1409 fi
1410 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on first"
1411
1412 # second route is coalesced to first to make a multipath route.
1413 # MTU of the second path is hidden from display!
1414 run_cmd "$IP -6 ro add 2001:db8:113::/64 via 2001:db8:101::2"
1415 run_cmd "$IP -6 ro append 2001:db8:113::/64 via 2001:db8:103::2 mtu 1400"
1416 rc=$?
1417 if [ $rc -eq 0 ]; then
1418 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"
1419 rc=$?
1420 fi
1421 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on 2nd"
1422
1423 run_cmd "$IP -6 ro del 2001:db8:113::/64 via 2001:db8:101::2"
1424 if [ $? -eq 0 ]; then
1425 check_route6 "2001:db8:113::/64 via 2001:db8:103::2 dev veth3 metric 1024 mtu 1400"
1426 log_test $? 0 " MTU of second leg"
1427 fi
1428
1429 #
1430 # multipath with metrics
1431 #
1432 run_cmd "$IP -6 ro add 2001:db8:115::/64 mtu 1400 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1433 rc=$?
1434 if [ $rc -eq 0 ]; then
1435 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"
1436 rc=$?
1437 fi
1438 log_test $rc 0 "Multipath route with mtu metric"
1439
1440 $IP -6 ro add 2001:db8:104::/64 via 2001:db8:101::2 mtu 1300
1441 run_cmd "ip netns exec $ns1 ${ping6} -w1 -c1 -s 1500 2001:db8:104::1"
1442 log_test $? 0 "Using route with mtu metric"
1443
1444 run_cmd "$IP -6 ro add 2001:db8:114::/64 via 2001:db8:101::2 congctl lock foo"
1445 log_test $? 2 "Invalid metric (fails metric_convert)"
1446
1447 route_cleanup
1448}
1449
1450# add route for a prefix, flushing any existing routes first
1451# expected to be the first step of a test
1452add_route()
1453{
1454 local pfx="$1"
1455 local nh="$2"
1456 local out
1457
1458 if [ "$VERBOSE" = "1" ]; then
1459 echo
1460 echo " ##################################################"
1461 echo
1462 fi
1463
1464 run_cmd "$IP ro flush ${pfx}"
1465 [ $? -ne 0 ] && exit 1
1466
1467 out=$($IP ro ls match ${pfx})
1468 if [ -n "$out" ]; then
1469 echo "Failed to flush routes for prefix used for tests."
1470 exit 1
1471 fi
1472
1473 run_cmd "$IP ro add ${pfx} ${nh}"
1474 if [ $? -ne 0 ]; then
1475 echo "Failed to add initial route for test."
1476 exit 1
1477 fi
1478}
1479
1480# add initial route - used in replace route tests
1481add_initial_route()
1482{
1483 add_route "172.16.104.0/24" "$1"
1484}
1485
1486check_route()
1487{
1488 local pfx
1489 local expected="$1"
1490 local out
1491
1492 set -- $expected
1493 pfx=$1
1494 [ "${pfx}" = "unreachable" ] && pfx=$2
1495
1496 out=$($IP ro ls match ${pfx})
1497 check_expected "${out}" "${expected}"
1498}
1499
1500# assumption is that basic add of a single path route works
1501# otherwise just adding an address on an interface is broken
1502ipv4_rt_add()
1503{
1504 local rc
1505
1506 echo
1507 echo "IPv4 route add / append tests"
1508
1509 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1510 add_route "172.16.104.0/24" "via 172.16.101.2"
1511 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2"
1512 log_test $? 2 "Attempt to add duplicate route - gw"
1513
1514 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1515 add_route "172.16.104.0/24" "via 172.16.101.2"
1516 run_cmd "$IP ro add 172.16.104.0/24 dev veth3"
1517 log_test $? 2 "Attempt to add duplicate route - dev only"
1518
1519 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1520 add_route "172.16.104.0/24" "via 172.16.101.2"
1521 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1522 log_test $? 2 "Attempt to add duplicate route - reject route"
1523
1524 # iproute2 prepend only sets NLM_F_CREATE
1525 # - adds a new route; does NOT convert existing route to ECMP
1526 add_route "172.16.104.0/24" "via 172.16.101.2"
1527 run_cmd "$IP ro prepend 172.16.104.0/24 via 172.16.103.2"
1528 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"
1529 log_test $? 0 "Add new nexthop for existing prefix"
1530
1531 # route append with same prefix adds a new route
1532 # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
1533 add_route "172.16.104.0/24" "via 172.16.101.2"
1534 run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1535 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"
1536 log_test $? 0 "Append nexthop to existing route - gw"
1537
1538 add_route "172.16.104.0/24" "via 172.16.101.2"
1539 run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1540 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 dev veth3 scope link"
1541 log_test $? 0 "Append nexthop to existing route - dev only"
1542
1543 add_route "172.16.104.0/24" "via 172.16.101.2"
1544 run_cmd "$IP ro append unreachable 172.16.104.0/24"
1545 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 unreachable 172.16.104.0/24"
1546 log_test $? 0 "Append nexthop to existing route - reject route"
1547
1548 run_cmd "$IP ro flush 172.16.104.0/24"
1549 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1550 run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1551 check_route "unreachable 172.16.104.0/24 172.16.104.0/24 via 172.16.103.2 dev veth3"
1552 log_test $? 0 "Append nexthop to existing reject route - gw"
1553
1554 run_cmd "$IP ro flush 172.16.104.0/24"
1555 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1556 run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1557 check_route "unreachable 172.16.104.0/24 172.16.104.0/24 dev veth3 scope link"
1558 log_test $? 0 "Append nexthop to existing reject route - dev only"
1559
1560 # insert mpath directly
1561 add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1562 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"
1563 log_test $? 0 "add multipath route"
1564
1565 add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1566 run_cmd "$IP ro add 172.16.104.0/24 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1567 log_test $? 2 "Attempt to add duplicate multipath route"
1568
1569 # insert of a second route without append but different metric
1570 add_route "172.16.104.0/24" "via 172.16.101.2"
1571 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2 metric 512"
1572 rc=$?
1573 if [ $rc -eq 0 ]; then
1574 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.3 metric 256"
1575 rc=$?
1576 fi
1577 log_test $rc 0 "Route add with different metrics"
1578
1579 run_cmd "$IP ro del 172.16.104.0/24 metric 512"
1580 rc=$?
1581 if [ $rc -eq 0 ]; then
1582 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"
1583 rc=$?
1584 fi
1585 log_test $rc 0 "Route delete with metric"
1586}
1587
1588ipv4_rt_replace_single()
1589{
1590 # single path with single path
1591 #
1592 add_initial_route "via 172.16.101.2"
1593 run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.103.2"
1594 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1595 log_test $? 0 "Single path with single path"
1596
1597 # single path with multipath
1598 #
1599 add_initial_route "nexthop via 172.16.101.2"
1600 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.2"
1601 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"
1602 log_test $? 0 "Single path with multipath"
1603
1604 # single path with reject
1605 #
1606 add_initial_route "nexthop via 172.16.101.2"
1607 run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1608 check_route "unreachable 172.16.104.0/24"
1609 log_test $? 0 "Single path with reject route"
1610
1611 # single path with single path using MULTIPATH attribute
1612 #
1613 add_initial_route "via 172.16.101.2"
1614 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.103.2"
1615 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1616 log_test $? 0 "Single path with single path via multipath attribute"
1617
1618 # route replace fails - invalid nexthop
1619 add_initial_route "via 172.16.101.2"
1620 run_cmd "$IP ro replace 172.16.104.0/24 via 2001:db8:104::2"
1621 if [ $? -eq 0 ]; then
1622 # previous command is expected to fail so if it returns 0
1623 # that means the test failed.
1624 log_test 0 1 "Invalid nexthop"
1625 else
1626 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1"
1627 log_test $? 0 "Invalid nexthop"
1628 fi
1629
1630 # replace non-existent route
1631 # - note use of change versus replace since ip adds NLM_F_CREATE
1632 # for replace
1633 add_initial_route "via 172.16.101.2"
1634 run_cmd "$IP ro change 172.16.105.0/24 via 172.16.101.2"
1635 log_test $? 2 "Single path - replace of non-existent route"
1636}
1637
1638ipv4_rt_replace_mpath()
1639{
1640 # multipath with multipath
1641 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1642 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1643 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"
1644 log_test $? 0 "Multipath with multipath"
1645
1646 # multipath with single
1647 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1648 run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.101.3"
1649 check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
1650 log_test $? 0 "Multipath with single path"
1651
1652 # multipath with single
1653 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1654 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3"
1655 check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
1656 log_test $? 0 "Multipath with single path via multipath attribute"
1657
1658 # multipath with reject
1659 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1660 run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1661 check_route "unreachable 172.16.104.0/24"
1662 log_test $? 0 "Multipath with reject route"
1663
1664 # route replace fails - invalid nexthop 1
1665 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1666 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.111.3 nexthop via 172.16.103.3"
1667 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"
1668 log_test $? 0 "Multipath - invalid first nexthop"
1669
1670 # route replace fails - invalid nexthop 2
1671 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1672 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.113.3"
1673 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"
1674 log_test $? 0 "Multipath - invalid second nexthop"
1675
1676 # multipath non-existent route
1677 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1678 run_cmd "$IP ro change 172.16.105.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1679 log_test $? 2 "Multipath - replace of non-existent route"
1680}
1681
1682ipv4_rt_replace()
1683{
1684 echo
1685 echo "IPv4 route replace tests"
1686
1687 ipv4_rt_replace_single
1688 ipv4_rt_replace_mpath
1689}
1690
1691# checks that cached input route on VRF port is deleted
1692# when VRF is deleted
1693ipv4_local_rt_cache()
1694{
1695 run_cmd "ip addr add 10.0.0.1/32 dev lo"
1696 run_cmd "setup_ns test-ns"
1697 run_cmd "ip link add veth-outside type veth peer name veth-inside"
1698 run_cmd "ip link add vrf-100 type vrf table 1100"
1699 run_cmd "ip link set veth-outside master vrf-100"
1700 run_cmd "ip link set veth-inside netns $test-ns"
1701 run_cmd "ip link set veth-outside up"
1702 run_cmd "ip link set vrf-100 up"
1703 run_cmd "ip route add 10.1.1.1/32 dev veth-outside table 1100"
1704 run_cmd "ip netns exec $test-ns ip link set veth-inside up"
1705 run_cmd "ip netns exec $test-ns ip addr add 10.1.1.1/32 dev veth-inside"
1706 run_cmd "ip netns exec $test-ns ip route add 10.0.0.1/32 dev veth-inside"
1707 run_cmd "ip netns exec $test-ns ip route add default via 10.0.0.1"
1708 run_cmd "ip netns exec $test-ns ping 10.0.0.1 -c 1 -i 1"
1709 run_cmd "ip link delete vrf-100"
1710
1711 # if we do not hang test is a success
1712 log_test $? 0 "Cached route removed from VRF port device"
1713}
1714
1715ipv4_rt_dsfield()
1716{
1717 echo
1718 echo "IPv4 route with dsfield tests"
1719
1720 run_cmd "$IP route flush 172.16.102.0/24"
1721
1722 # New routes should reject dsfield options that interfere with ECN
1723 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x01 via 172.16.101.2"
1724 log_test $? 2 "Reject route with dsfield 0x01"
1725
1726 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x02 via 172.16.101.2"
1727 log_test $? 2 "Reject route with dsfield 0x02"
1728
1729 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x03 via 172.16.101.2"
1730 log_test $? 2 "Reject route with dsfield 0x03"
1731
1732 # A generic route that doesn't take DSCP into account
1733 run_cmd "$IP route add 172.16.102.0/24 via 172.16.101.2"
1734
1735 # A more specific route for DSCP 0x10
1736 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x10 via 172.16.103.2"
1737
1738 # DSCP 0x10 should match the specific route, no matter the ECN bits
1739 $IP route get fibmatch 172.16.102.1 dsfield 0x10 | \
1740 grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
1741 log_test $? 0 "IPv4 route with DSCP and ECN:Not-ECT"
1742
1743 $IP route get fibmatch 172.16.102.1 dsfield 0x11 | \
1744 grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
1745 log_test $? 0 "IPv4 route with DSCP and ECN:ECT(1)"
1746
1747 $IP route get fibmatch 172.16.102.1 dsfield 0x12 | \
1748 grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
1749 log_test $? 0 "IPv4 route with DSCP and ECN:ECT(0)"
1750
1751 $IP route get fibmatch 172.16.102.1 dsfield 0x13 | \
1752 grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
1753 log_test $? 0 "IPv4 route with DSCP and ECN:CE"
1754
1755 # Unknown DSCP should match the generic route, no matter the ECN bits
1756 $IP route get fibmatch 172.16.102.1 dsfield 0x14 | \
1757 grep -q "172.16.102.0/24 via 172.16.101.2"
1758 log_test $? 0 "IPv4 route with unknown DSCP and ECN:Not-ECT"
1759
1760 $IP route get fibmatch 172.16.102.1 dsfield 0x15 | \
1761 grep -q "172.16.102.0/24 via 172.16.101.2"
1762 log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(1)"
1763
1764 $IP route get fibmatch 172.16.102.1 dsfield 0x16 | \
1765 grep -q "172.16.102.0/24 via 172.16.101.2"
1766 log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(0)"
1767
1768 $IP route get fibmatch 172.16.102.1 dsfield 0x17 | \
1769 grep -q "172.16.102.0/24 via 172.16.101.2"
1770 log_test $? 0 "IPv4 route with unknown DSCP and ECN:CE"
1771
1772 # Null DSCP should match the generic route, no matter the ECN bits
1773 $IP route get fibmatch 172.16.102.1 dsfield 0x00 | \
1774 grep -q "172.16.102.0/24 via 172.16.101.2"
1775 log_test $? 0 "IPv4 route with no DSCP and ECN:Not-ECT"
1776
1777 $IP route get fibmatch 172.16.102.1 dsfield 0x01 | \
1778 grep -q "172.16.102.0/24 via 172.16.101.2"
1779 log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(1)"
1780
1781 $IP route get fibmatch 172.16.102.1 dsfield 0x02 | \
1782 grep -q "172.16.102.0/24 via 172.16.101.2"
1783 log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(0)"
1784
1785 $IP route get fibmatch 172.16.102.1 dsfield 0x03 | \
1786 grep -q "172.16.102.0/24 via 172.16.101.2"
1787 log_test $? 0 "IPv4 route with no DSCP and ECN:CE"
1788}
1789
1790ipv4_route_test()
1791{
1792 route_setup
1793
1794 ipv4_rt_add
1795 ipv4_rt_replace
1796 ipv4_local_rt_cache
1797 ipv4_rt_dsfield
1798
1799 route_cleanup
1800}
1801
1802ipv4_addr_metric_test()
1803{
1804 local rc
1805
1806 echo
1807 echo "IPv4 prefix route tests"
1808
1809 ip_addr_metric_check || return 1
1810
1811 setup
1812
1813 set -e
1814 $IP li add dummy1 type dummy
1815 $IP li add dummy2 type dummy
1816 $IP li set dummy1 up
1817 $IP li set dummy2 up
1818
1819 # default entry is metric 256
1820 run_cmd "$IP addr add dev dummy1 172.16.104.1/24"
1821 run_cmd "$IP addr add dev dummy2 172.16.104.2/24"
1822 set +e
1823
1824 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"
1825 log_test $? 0 "Default metric"
1826
1827 set -e
1828 run_cmd "$IP addr flush dev dummy1"
1829 run_cmd "$IP addr add dev dummy1 172.16.104.1/24 metric 257"
1830 set +e
1831
1832 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"
1833 log_test $? 0 "User specified metric on first device"
1834
1835 set -e
1836 run_cmd "$IP addr flush dev dummy2"
1837 run_cmd "$IP addr add dev dummy2 172.16.104.2/24 metric 258"
1838 set +e
1839
1840 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"
1841 log_test $? 0 "User specified metric on second device"
1842
1843 run_cmd "$IP addr del dev dummy1 172.16.104.1/24 metric 257"
1844 rc=$?
1845 if [ $rc -eq 0 ]; then
1846 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258"
1847 rc=$?
1848 fi
1849 log_test $rc 0 "Delete of address on first device"
1850
1851 run_cmd "$IP addr change dev dummy2 172.16.104.2/24 metric 259"
1852 rc=$?
1853 if [ $rc -eq 0 ]; then
1854 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1855 rc=$?
1856 fi
1857 log_test $rc 0 "Modify metric of address"
1858
1859 # verify prefix route removed on down
1860 run_cmd "$IP li set dev dummy2 down"
1861 rc=$?
1862 if [ $rc -eq 0 ]; then
1863 out=$($IP ro ls match 172.16.104.0/24)
1864 check_expected "${out}" ""
1865 rc=$?
1866 fi
1867 log_test $rc 0 "Prefix route removed on link down"
1868
1869 # verify prefix route re-inserted with assigned metric
1870 run_cmd "$IP li set dev dummy2 up"
1871 rc=$?
1872 if [ $rc -eq 0 ]; then
1873 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1874 rc=$?
1875 fi
1876 log_test $rc 0 "Prefix route with metric on link up"
1877
1878 # explicitly check for metric changes on edge scenarios
1879 run_cmd "$IP addr flush dev dummy2"
1880 run_cmd "$IP addr add dev dummy2 172.16.104.0/24 metric 259"
1881 run_cmd "$IP addr change dev dummy2 172.16.104.0/24 metric 260"
1882 rc=$?
1883 if [ $rc -eq 0 ]; then
1884 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.0 metric 260"
1885 rc=$?
1886 fi
1887 log_test $rc 0 "Modify metric of .0/24 address"
1888
1889 run_cmd "$IP addr flush dev dummy2"
1890 run_cmd "$IP addr add dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 260"
1891 rc=$?
1892 if [ $rc -eq 0 ]; then
1893 check_route "172.16.104.2 dev dummy2 proto kernel scope link src 172.16.104.1 metric 260"
1894 rc=$?
1895 fi
1896 log_test $rc 0 "Set metric of address with peer route"
1897
1898 run_cmd "$IP addr change dev dummy2 172.16.104.1/32 peer 172.16.104.3 metric 261"
1899 rc=$?
1900 if [ $rc -eq 0 ]; then
1901 check_route "172.16.104.3 dev dummy2 proto kernel scope link src 172.16.104.1 metric 261"
1902 rc=$?
1903 fi
1904 log_test $rc 0 "Modify metric and peer address for peer route"
1905
1906 $IP li del dummy1
1907 $IP li del dummy2
1908 cleanup
1909}
1910
1911ipv4_route_metrics_test()
1912{
1913 local rc
1914
1915 echo
1916 echo "IPv4 route add / append tests"
1917
1918 route_setup
1919
1920 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 mtu 1400"
1921 rc=$?
1922 if [ $rc -eq 0 ]; then
1923 check_route "172.16.111.0/24 via 172.16.101.2 dev veth1 mtu 1400"
1924 rc=$?
1925 fi
1926 log_test $rc 0 "Single path route with mtu metric"
1927
1928
1929 run_cmd "$IP ro add 172.16.112.0/24 mtu 1400 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1930 rc=$?
1931 if [ $rc -eq 0 ]; then
1932 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"
1933 rc=$?
1934 fi
1935 log_test $rc 0 "Multipath route with mtu metric"
1936
1937 $IP ro add 172.16.104.0/24 via 172.16.101.2 mtu 1300
1938 run_cmd "ip netns exec $ns1 ping -w1 -c1 -s 1500 172.16.104.1"
1939 log_test $? 0 "Using route with mtu metric"
1940
1941 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 congctl lock foo"
1942 log_test $? 2 "Invalid metric (fails metric_convert)"
1943
1944 route_cleanup
1945}
1946
1947ipv4_del_addr_test()
1948{
1949 echo
1950 echo "IPv4 delete address route tests"
1951
1952 setup
1953
1954 set -e
1955 $IP li add dummy1 type dummy
1956 $IP li set dummy1 up
1957 $IP li add dummy2 type dummy
1958 $IP li set dummy2 up
1959 $IP li add red type vrf table 1111
1960 $IP li set red up
1961 $IP ro add vrf red unreachable default
1962 $IP li set dummy2 vrf red
1963
1964 $IP addr add dev dummy1 172.16.104.1/24
1965 $IP addr add dev dummy1 172.16.104.11/24
1966 $IP addr add dev dummy1 172.16.104.12/24
1967 $IP addr add dev dummy1 172.16.104.13/24
1968 $IP addr add dev dummy2 172.16.104.1/24
1969 $IP addr add dev dummy2 172.16.104.11/24
1970 $IP addr add dev dummy2 172.16.104.12/24
1971 $IP route add 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1972 $IP route add 172.16.106.0/24 dev lo src 172.16.104.12
1973 $IP route add table 0 172.16.107.0/24 via 172.16.104.2 src 172.16.104.13
1974 $IP route add vrf red 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1975 $IP route add vrf red 172.16.106.0/24 dev lo src 172.16.104.12
1976 set +e
1977
1978 # removing address from device in vrf should only remove route from vrf table
1979 echo " Regular FIB info"
1980
1981 $IP addr del dev dummy2 172.16.104.11/24
1982 $IP ro ls vrf red | grep -q 172.16.105.0/24
1983 log_test $? 1 "Route removed from VRF when source address deleted"
1984
1985 $IP ro ls | grep -q 172.16.105.0/24
1986 log_test $? 0 "Route in default VRF not removed"
1987
1988 $IP addr add dev dummy2 172.16.104.11/24
1989 $IP route add vrf red 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1990
1991 $IP addr del dev dummy1 172.16.104.11/24
1992 $IP ro ls | grep -q 172.16.105.0/24
1993 log_test $? 1 "Route removed in default VRF when source address deleted"
1994
1995 $IP ro ls vrf red | grep -q 172.16.105.0/24
1996 log_test $? 0 "Route in VRF is not removed by address delete"
1997
1998 # removing address from device in vrf should only remove route from vrf
1999 # table even when the associated fib info only differs in table ID
2000 echo " Identical FIB info with different table ID"
2001
2002 $IP addr del dev dummy2 172.16.104.12/24
2003 $IP ro ls vrf red | grep -q 172.16.106.0/24
2004 log_test $? 1 "Route removed from VRF when source address deleted"
2005
2006 $IP ro ls | grep -q 172.16.106.0/24
2007 log_test $? 0 "Route in default VRF not removed"
2008
2009 $IP addr add dev dummy2 172.16.104.12/24
2010 $IP route add vrf red 172.16.106.0/24 dev lo src 172.16.104.12
2011
2012 $IP addr del dev dummy1 172.16.104.12/24
2013 $IP ro ls | grep -q 172.16.106.0/24
2014 log_test $? 1 "Route removed in default VRF when source address deleted"
2015
2016 $IP ro ls vrf red | grep -q 172.16.106.0/24
2017 log_test $? 0 "Route in VRF is not removed by address delete"
2018
2019 # removing address from device in default vrf should remove route from
2020 # the default vrf even when route was inserted with a table ID of 0.
2021 echo " Table ID 0"
2022
2023 $IP addr del dev dummy1 172.16.104.13/24
2024 $IP ro ls | grep -q 172.16.107.0/24
2025 log_test $? 1 "Route removed in default VRF when source address deleted"
2026
2027 $IP li del dummy1
2028 $IP li del dummy2
2029 cleanup
2030}
2031
2032ipv6_del_addr_test()
2033{
2034 echo
2035 echo "IPv6 delete address route tests"
2036
2037 setup
2038
2039 set -e
2040 for i in $(seq 6); do
2041 $IP li add dummy${i} up type dummy
2042 done
2043
2044 $IP li add red up type vrf table 1111
2045 $IP ro add vrf red unreachable default
2046 for i in $(seq 4 6); do
2047 $IP li set dummy${i} vrf red
2048 done
2049
2050 $IP addr add dev dummy1 fe80::1/128
2051 $IP addr add dev dummy1 2001:db8:101::1/64
2052 $IP addr add dev dummy1 2001:db8:101::10/64
2053 $IP addr add dev dummy1 2001:db8:101::11/64
2054 $IP addr add dev dummy1 2001:db8:101::12/64
2055 $IP addr add dev dummy1 2001:db8:101::13/64
2056 $IP addr add dev dummy1 2001:db8:101::14/64
2057 $IP addr add dev dummy1 2001:db8:101::15/64
2058 $IP addr add dev dummy2 fe80::1/128
2059 $IP addr add dev dummy2 2001:db8:101::1/64
2060 $IP addr add dev dummy2 2001:db8:101::11/64
2061 $IP addr add dev dummy3 fe80::1/128
2062
2063 $IP addr add dev dummy4 2001:db8:101::1/64
2064 $IP addr add dev dummy4 2001:db8:101::10/64
2065 $IP addr add dev dummy4 2001:db8:101::11/64
2066 $IP addr add dev dummy4 2001:db8:101::12/64
2067 $IP addr add dev dummy4 2001:db8:101::13/64
2068 $IP addr add dev dummy4 2001:db8:101::14/64
2069 $IP addr add dev dummy5 2001:db8:101::1/64
2070 $IP addr add dev dummy5 2001:db8:101::11/64
2071
2072 # Single device using src address
2073 $IP route add 2001:db8:110::/64 dev dummy3 src 2001:db8:101::10
2074 # Two devices with the same source address
2075 $IP route add 2001:db8:111::/64 dev dummy3 src 2001:db8:101::11
2076 # VRF with single device using src address
2077 $IP route add vrf red 2001:db8:110::/64 dev dummy6 src 2001:db8:101::10
2078 # VRF with two devices using src address
2079 $IP route add vrf red 2001:db8:111::/64 dev dummy6 src 2001:db8:101::11
2080 # src address and nexthop dev in same VRF
2081 $IP route add 2001:db8:112::/64 dev dummy3 src 2001:db8:101::12
2082 $IP route add vrf red 2001:db8:112::/64 dev dummy6 src 2001:db8:101::12
2083 # src address and nexthop device in different VRF
2084 $IP route add 2001:db8:113::/64 dev lo src 2001:db8:101::13
2085 $IP route add vrf red 2001:db8:113::/64 dev lo src 2001:db8:101::13
2086 # table ID 0
2087 $IP route add table 0 2001:db8:115::/64 via 2001:db8:101::2 src 2001:db8:101::15
2088 # Link local source route
2089 $IP route add 2001:db8:116::/64 dev dummy2 src fe80::1
2090 $IP route add 2001:db8:117::/64 dev dummy3 src fe80::1
2091 set +e
2092
2093 echo " Single device using src address"
2094
2095 $IP addr del dev dummy1 2001:db8:101::10/64
2096 $IP -6 route show | grep -q "src 2001:db8:101::10 "
2097 log_test $? 1 "Prefsrc removed when src address removed on other device"
2098
2099 echo " Two devices with the same source address"
2100
2101 $IP addr del dev dummy1 2001:db8:101::11/64
2102 $IP -6 route show | grep -q "src 2001:db8:101::11 "
2103 log_test $? 0 "Prefsrc not removed when src address exist on other device"
2104
2105 $IP addr del dev dummy2 2001:db8:101::11/64
2106 $IP -6 route show | grep -q "src 2001:db8:101::11 "
2107 log_test $? 1 "Prefsrc removed when src address removed on all devices"
2108
2109 echo " VRF with single device using src address"
2110
2111 $IP addr del dev dummy4 2001:db8:101::10/64
2112 $IP -6 route show vrf red | grep -q "src 2001:db8:101::10 "
2113 log_test $? 1 "Prefsrc removed when src address removed on other device"
2114
2115 echo " VRF with two devices using src address"
2116
2117 $IP addr del dev dummy4 2001:db8:101::11/64
2118 $IP -6 route show vrf red | grep -q "src 2001:db8:101::11 "
2119 log_test $? 0 "Prefsrc not removed when src address exist on other device"
2120
2121 $IP addr del dev dummy5 2001:db8:101::11/64
2122 $IP -6 route show vrf red | grep -q "src 2001:db8:101::11 "
2123 log_test $? 1 "Prefsrc removed when src address removed on all devices"
2124
2125 echo " src address and nexthop dev in same VRF"
2126
2127 $IP addr del dev dummy4 2001:db8:101::12/64
2128 $IP -6 route show vrf red | grep -q "src 2001:db8:101::12 "
2129 log_test $? 1 "Prefsrc removed from VRF when source address deleted"
2130 $IP -6 route show | grep -q " src 2001:db8:101::12 "
2131 log_test $? 0 "Prefsrc in default VRF not removed"
2132
2133 $IP addr add dev dummy4 2001:db8:101::12/64
2134 $IP route replace vrf red 2001:db8:112::/64 dev dummy6 src 2001:db8:101::12
2135 $IP addr del dev dummy1 2001:db8:101::12/64
2136 $IP -6 route show vrf red | grep -q "src 2001:db8:101::12 "
2137 log_test $? 0 "Prefsrc not removed from VRF when source address exist"
2138 $IP -6 route show | grep -q " src 2001:db8:101::12 "
2139 log_test $? 1 "Prefsrc in default VRF removed"
2140
2141 echo " src address and nexthop device in different VRF"
2142
2143 $IP addr del dev dummy4 2001:db8:101::13/64
2144 $IP -6 route show vrf red | grep -q "src 2001:db8:101::13 "
2145 log_test $? 0 "Prefsrc not removed from VRF when nexthop dev in diff VRF"
2146 $IP -6 route show | grep -q "src 2001:db8:101::13 "
2147 log_test $? 0 "Prefsrc not removed in default VRF"
2148
2149 $IP addr add dev dummy4 2001:db8:101::13/64
2150 $IP addr del dev dummy1 2001:db8:101::13/64
2151 $IP -6 route show vrf red | grep -q "src 2001:db8:101::13 "
2152 log_test $? 1 "Prefsrc removed from VRF when nexthop dev in diff VRF"
2153 $IP -6 route show | grep -q "src 2001:db8:101::13 "
2154 log_test $? 1 "Prefsrc removed in default VRF"
2155
2156 echo " Table ID 0"
2157
2158 $IP addr del dev dummy1 2001:db8:101::15/64
2159 $IP -6 route show | grep -q "src 2001:db8:101::15"
2160 log_test $? 1 "Prefsrc removed from default VRF when source address deleted"
2161
2162 echo " Link local source route"
2163 $IP addr del dev dummy1 fe80::1/128
2164 $IP -6 route show | grep -q "2001:db8:116::/64 dev dummy2 src fe80::1"
2165 log_test $? 0 "Prefsrc not removed when delete ll addr from other dev"
2166 $IP addr del dev dummy2 fe80::1/128
2167 $IP -6 route show | grep -q "2001:db8:116::/64 dev dummy2 src fe80::1"
2168 log_test $? 1 "Prefsrc removed when delete ll addr"
2169 $IP -6 route show | grep -q "2001:db8:117::/64 dev dummy3 src fe80::1"
2170 log_test $? 0 "Prefsrc not removed when delete ll addr from other dev"
2171 $IP addr add dev dummy1 fe80::1/128
2172 $IP addr del dev dummy3 fe80::1/128
2173 $IP -6 route show | grep -q "2001:db8:117::/64 dev dummy3 src fe80::1"
2174 log_test $? 1 "Prefsrc removed even ll addr still exist on other dev"
2175
2176 for i in $(seq 6); do
2177 $IP li del dummy${i}
2178 done
2179 cleanup
2180}
2181
2182ipv4_route_v6_gw_test()
2183{
2184 local rc
2185
2186 echo
2187 echo "IPv4 route with IPv6 gateway tests"
2188
2189 route_setup
2190 sleep 2
2191
2192 #
2193 # single path route
2194 #
2195 run_cmd "$IP ro add 172.16.104.0/24 via inet6 2001:db8:101::2"
2196 rc=$?
2197 log_test $rc 0 "Single path route with IPv6 gateway"
2198 if [ $rc -eq 0 ]; then
2199 check_route "172.16.104.0/24 via inet6 2001:db8:101::2 dev veth1"
2200 fi
2201
2202 run_cmd "ip netns exec $ns1 ping -w1 -c1 172.16.104.1"
2203 log_test $rc 0 "Single path route with IPv6 gateway - ping"
2204
2205 run_cmd "$IP ro del 172.16.104.0/24 via inet6 2001:db8:101::2"
2206 rc=$?
2207 log_test $rc 0 "Single path route delete"
2208 if [ $rc -eq 0 ]; then
2209 check_route "172.16.112.0/24"
2210 fi
2211
2212 #
2213 # multipath - v6 then v4
2214 #
2215 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"
2216 rc=$?
2217 log_test $rc 0 "Multipath route add - v6 nexthop then v4"
2218 if [ $rc -eq 0 ]; then
2219 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"
2220 fi
2221
2222 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"
2223 log_test $? 2 " Multipath route delete - nexthops in wrong order"
2224
2225 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"
2226 log_test $? 0 " Multipath route delete exact match"
2227
2228 #
2229 # multipath - v4 then v6
2230 #
2231 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"
2232 rc=$?
2233 log_test $rc 0 "Multipath route add - v4 nexthop then v6"
2234 if [ $rc -eq 0 ]; then
2235 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"
2236 fi
2237
2238 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"
2239 log_test $? 2 " Multipath route delete - nexthops in wrong order"
2240
2241 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"
2242 log_test $? 0 " Multipath route delete exact match"
2243
2244 route_cleanup
2245}
2246
2247socat_check()
2248{
2249 if [ ! -x "$(command -v socat)" ]; then
2250 echo "socat command not found. Skipping test"
2251 return 1
2252 fi
2253
2254 return 0
2255}
2256
2257iptables_check()
2258{
2259 iptables -t mangle -L OUTPUT &> /dev/null
2260 if [ $? -ne 0 ]; then
2261 echo "iptables configuration not supported. Skipping test"
2262 return 1
2263 fi
2264
2265 return 0
2266}
2267
2268ip6tables_check()
2269{
2270 ip6tables -t mangle -L OUTPUT &> /dev/null
2271 if [ $? -ne 0 ]; then
2272 echo "ip6tables configuration not supported. Skipping test"
2273 return 1
2274 fi
2275
2276 return 0
2277}
2278
2279ipv4_mangle_test()
2280{
2281 local rc
2282
2283 echo
2284 echo "IPv4 mangling tests"
2285
2286 socat_check || return 1
2287 iptables_check || return 1
2288
2289 route_setup
2290 sleep 2
2291
2292 local tmp_file=$(mktemp)
2293 ip netns exec $ns2 socat UDP4-LISTEN:54321,fork $tmp_file &
2294
2295 # Add a FIB rule and a route that will direct our connection to the
2296 # listening server.
2297 $IP rule add pref 100 ipproto udp sport 12345 dport 54321 table 123
2298 $IP route add table 123 172.16.101.0/24 dev veth1
2299
2300 # Add an unreachable route to the main table that will block our
2301 # connection in case the FIB rule is not hit.
2302 $IP route add unreachable 172.16.101.2/32
2303
2304 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
2305 log_test $? 0 " Connection with correct parameters"
2306
2307 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=11111"
2308 log_test $? 1 " Connection with incorrect parameters"
2309
2310 # Add a mangling rule and make sure connection is still successful.
2311 $NS_EXEC iptables -t mangle -A OUTPUT -j MARK --set-mark 1
2312
2313 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
2314 log_test $? 0 " Connection with correct parameters - mangling"
2315
2316 # Delete the mangling rule and make sure connection is still
2317 # successful.
2318 $NS_EXEC iptables -t mangle -D OUTPUT -j MARK --set-mark 1
2319
2320 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
2321 log_test $? 0 " Connection with correct parameters - no mangling"
2322
2323 # Verify connections were indeed successful on server side.
2324 [[ $(cat $tmp_file | wc -l) -eq 3 ]]
2325 log_test $? 0 " Connection check - server side"
2326
2327 $IP route del unreachable 172.16.101.2/32
2328 $IP route del table 123 172.16.101.0/24 dev veth1
2329 $IP rule del pref 100
2330
2331 kill_process %%
2332 rm $tmp_file
2333
2334 route_cleanup
2335}
2336
2337ipv6_mangle_test()
2338{
2339 local rc
2340
2341 echo
2342 echo "IPv6 mangling tests"
2343
2344 socat_check || return 1
2345 ip6tables_check || return 1
2346
2347 route_setup
2348 sleep 2
2349
2350 local tmp_file=$(mktemp)
2351 ip netns exec $ns2 socat UDP6-LISTEN:54321,fork $tmp_file &
2352
2353 # Add a FIB rule and a route that will direct our connection to the
2354 # listening server.
2355 $IP -6 rule add pref 100 ipproto udp sport 12345 dport 54321 table 123
2356 $IP -6 route add table 123 2001:db8:101::/64 dev veth1
2357
2358 # Add an unreachable route to the main table that will block our
2359 # connection in case the FIB rule is not hit.
2360 $IP -6 route add unreachable 2001:db8:101::2/128
2361
2362 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
2363 log_test $? 0 " Connection with correct parameters"
2364
2365 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=11111"
2366 log_test $? 1 " Connection with incorrect parameters"
2367
2368 # Add a mangling rule and make sure connection is still successful.
2369 $NS_EXEC ip6tables -t mangle -A OUTPUT -j MARK --set-mark 1
2370
2371 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
2372 log_test $? 0 " Connection with correct parameters - mangling"
2373
2374 # Delete the mangling rule and make sure connection is still
2375 # successful.
2376 $NS_EXEC ip6tables -t mangle -D OUTPUT -j MARK --set-mark 1
2377
2378 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
2379 log_test $? 0 " Connection with correct parameters - no mangling"
2380
2381 # Verify connections were indeed successful on server side.
2382 [[ $(cat $tmp_file | wc -l) -eq 3 ]]
2383 log_test $? 0 " Connection check - server side"
2384
2385 $IP -6 route del unreachable 2001:db8:101::2/128
2386 $IP -6 route del table 123 2001:db8:101::/64 dev veth1
2387 $IP -6 rule del pref 100
2388
2389 kill_process %%
2390 rm $tmp_file
2391
2392 route_cleanup
2393}
2394
2395ip_neigh_get_check()
2396{
2397 ip neigh help 2>&1 | grep -q 'ip neigh get'
2398 if [ $? -ne 0 ]; then
2399 echo "iproute2 command does not support neigh get. Skipping test"
2400 return 1
2401 fi
2402
2403 return 0
2404}
2405
2406ipv4_bcast_neigh_test()
2407{
2408 local rc
2409
2410 echo
2411 echo "IPv4 broadcast neighbour tests"
2412
2413 ip_neigh_get_check || return 1
2414
2415 setup
2416
2417 set -e
2418 run_cmd "$IP neigh add 192.0.2.111 lladdr 00:11:22:33:44:55 nud perm dev dummy0"
2419 run_cmd "$IP neigh add 192.0.2.255 lladdr 00:11:22:33:44:55 nud perm dev dummy0"
2420
2421 run_cmd "$IP neigh get 192.0.2.111 dev dummy0"
2422 run_cmd "$IP neigh get 192.0.2.255 dev dummy0"
2423
2424 run_cmd "$IP address add 192.0.2.1/24 broadcast 192.0.2.111 dev dummy0"
2425
2426 run_cmd "$IP neigh add 203.0.113.111 nud failed dev dummy0"
2427 run_cmd "$IP neigh add 203.0.113.255 nud failed dev dummy0"
2428
2429 run_cmd "$IP neigh get 203.0.113.111 dev dummy0"
2430 run_cmd "$IP neigh get 203.0.113.255 dev dummy0"
2431
2432 run_cmd "$IP address add 203.0.113.1/24 broadcast 203.0.113.111 dev dummy0"
2433 set +e
2434
2435 run_cmd "$IP neigh get 192.0.2.111 dev dummy0"
2436 log_test $? 0 "Resolved neighbour for broadcast address"
2437
2438 run_cmd "$IP neigh get 192.0.2.255 dev dummy0"
2439 log_test $? 0 "Resolved neighbour for network broadcast address"
2440
2441 run_cmd "$IP neigh get 203.0.113.111 dev dummy0"
2442 log_test $? 2 "Unresolved neighbour for broadcast address"
2443
2444 run_cmd "$IP neigh get 203.0.113.255 dev dummy0"
2445 log_test $? 2 "Unresolved neighbour for network broadcast address"
2446
2447 cleanup
2448}
2449
2450mpath_dep_check()
2451{
2452 if [ ! -x "$(command -v mausezahn)" ]; then
2453 echo "mausezahn command not found. Skipping test"
2454 return 1
2455 fi
2456
2457 if [ ! -x "$(command -v jq)" ]; then
2458 echo "jq command not found. Skipping test"
2459 return 1
2460 fi
2461
2462 if [ ! -x "$(command -v bc)" ]; then
2463 echo "bc command not found. Skipping test"
2464 return 1
2465 fi
2466
2467 if [ ! -x "$(command -v perf)" ]; then
2468 echo "perf command not found. Skipping test"
2469 return 1
2470 fi
2471
2472 perf list fib:* | grep -q fib_table_lookup
2473 if [ $? -ne 0 ]; then
2474 echo "IPv4 FIB tracepoint not found. Skipping test"
2475 return 1
2476 fi
2477
2478 perf list fib6:* | grep -q fib6_table_lookup
2479 if [ $? -ne 0 ]; then
2480 echo "IPv6 FIB tracepoint not found. Skipping test"
2481 return 1
2482 fi
2483
2484 return 0
2485}
2486
2487link_stats_get()
2488{
2489 local ns=$1; shift
2490 local dev=$1; shift
2491 local dir=$1; shift
2492 local stat=$1; shift
2493
2494 ip -n $ns -j -s link show dev $dev \
2495 | jq '.[]["stats64"]["'$dir'"]["'$stat'"]'
2496}
2497
2498list_rcv_eval()
2499{
2500 local file=$1; shift
2501 local expected=$1; shift
2502
2503 local count=$(tail -n 1 $file | jq '.["counter-value"] | tonumber | floor')
2504 local ratio=$(echo "scale=2; $count / $expected" | bc -l)
2505 local res=$(echo "$ratio >= 0.95" | bc)
2506 [[ $res -eq 1 ]]
2507 log_test $? 0 "Multipath route hit ratio ($ratio)"
2508}
2509
2510ipv4_mpath_list_test()
2511{
2512 echo
2513 echo "IPv4 multipath list receive tests"
2514
2515 mpath_dep_check || return 1
2516
2517 route_setup
2518
2519 set -e
2520 run_cmd "ip netns exec $ns1 ethtool -K veth1 tcp-segmentation-offload off"
2521
2522 run_cmd "ip netns exec $ns2 bash -c \"echo 20000 > /sys/class/net/veth2/gro_flush_timeout\""
2523 run_cmd "ip netns exec $ns2 bash -c \"echo 1 > /sys/class/net/veth2/napi_defer_hard_irqs\""
2524 run_cmd "ip netns exec $ns2 ethtool -K veth2 generic-receive-offload on"
2525 run_cmd "ip -n $ns2 link add name nh1 up type dummy"
2526 run_cmd "ip -n $ns2 link add name nh2 up type dummy"
2527 run_cmd "ip -n $ns2 address add 172.16.201.1/24 dev nh1"
2528 run_cmd "ip -n $ns2 address add 172.16.202.1/24 dev nh2"
2529 run_cmd "ip -n $ns2 neigh add 172.16.201.2 lladdr 00:11:22:33:44:55 nud perm dev nh1"
2530 run_cmd "ip -n $ns2 neigh add 172.16.202.2 lladdr 00:aa:bb:cc:dd:ee nud perm dev nh2"
2531 run_cmd "ip -n $ns2 route add 203.0.113.0/24
2532 nexthop via 172.16.201.2 nexthop via 172.16.202.2"
2533 run_cmd "ip netns exec $ns2 sysctl -qw net.ipv4.fib_multipath_hash_policy=1"
2534 run_cmd "ip netns exec $ns2 sysctl -qw net.ipv4.conf.veth2.rp_filter=0"
2535 run_cmd "ip netns exec $ns2 sysctl -qw net.ipv4.conf.all.rp_filter=0"
2536 run_cmd "ip netns exec $ns2 sysctl -qw net.ipv4.conf.default.rp_filter=0"
2537 set +e
2538
2539 local dmac=$(ip -n $ns2 -j link show dev veth2 | jq -r '.[]["address"]')
2540 local tmp_file=$(mktemp)
2541 local cmd="ip netns exec $ns1 mausezahn veth1 -a own -b $dmac
2542 -A 172.16.101.1 -B 203.0.113.1 -t udp 'sp=12345,dp=0-65535' -q"
2543
2544 # Packets forwarded in a list using a multipath route must not reuse a
2545 # cached result so that a flow always hits the same nexthop. In other
2546 # words, the FIB lookup tracepoint needs to be triggered for every
2547 # packet.
2548 local t0_rx_pkts=$(link_stats_get $ns2 veth2 rx packets)
2549 run_cmd "perf stat -a -e fib:fib_table_lookup --filter 'err == 0' -j -o $tmp_file -- $cmd"
2550 local t1_rx_pkts=$(link_stats_get $ns2 veth2 rx packets)
2551 local diff=$(echo $t1_rx_pkts - $t0_rx_pkts | bc -l)
2552 list_rcv_eval $tmp_file $diff
2553
2554 rm $tmp_file
2555 route_cleanup
2556}
2557
2558ipv6_mpath_list_test()
2559{
2560 echo
2561 echo "IPv6 multipath list receive tests"
2562
2563 mpath_dep_check || return 1
2564
2565 route_setup
2566
2567 set -e
2568 run_cmd "ip netns exec $ns1 ethtool -K veth1 tcp-segmentation-offload off"
2569
2570 run_cmd "ip netns exec $ns2 bash -c \"echo 20000 > /sys/class/net/veth2/gro_flush_timeout\""
2571 run_cmd "ip netns exec $ns2 bash -c \"echo 1 > /sys/class/net/veth2/napi_defer_hard_irqs\""
2572 run_cmd "ip netns exec $ns2 ethtool -K veth2 generic-receive-offload on"
2573 run_cmd "ip -n $ns2 link add name nh1 up type dummy"
2574 run_cmd "ip -n $ns2 link add name nh2 up type dummy"
2575 run_cmd "ip -n $ns2 -6 address add 2001:db8:201::1/64 dev nh1"
2576 run_cmd "ip -n $ns2 -6 address add 2001:db8:202::1/64 dev nh2"
2577 run_cmd "ip -n $ns2 -6 neigh add 2001:db8:201::2 lladdr 00:11:22:33:44:55 nud perm dev nh1"
2578 run_cmd "ip -n $ns2 -6 neigh add 2001:db8:202::2 lladdr 00:aa:bb:cc:dd:ee nud perm dev nh2"
2579 run_cmd "ip -n $ns2 -6 route add 2001:db8:301::/64
2580 nexthop via 2001:db8:201::2 nexthop via 2001:db8:202::2"
2581 run_cmd "ip netns exec $ns2 sysctl -qw net.ipv6.fib_multipath_hash_policy=1"
2582 set +e
2583
2584 local dmac=$(ip -n $ns2 -j link show dev veth2 | jq -r '.[]["address"]')
2585 local tmp_file=$(mktemp)
2586 local cmd="ip netns exec $ns1 mausezahn -6 veth1 -a own -b $dmac
2587 -A 2001:db8:101::1 -B 2001:db8:301::1 -t udp 'sp=12345,dp=0-65535' -q"
2588
2589 # Packets forwarded in a list using a multipath route must not reuse a
2590 # cached result so that a flow always hits the same nexthop. In other
2591 # words, the FIB lookup tracepoint needs to be triggered for every
2592 # packet.
2593 local t0_rx_pkts=$(link_stats_get $ns2 veth2 rx packets)
2594 run_cmd "perf stat -a -e fib6:fib6_table_lookup --filter 'err == 0' -j -o $tmp_file -- $cmd"
2595 local t1_rx_pkts=$(link_stats_get $ns2 veth2 rx packets)
2596 local diff=$(echo $t1_rx_pkts - $t0_rx_pkts | bc -l)
2597 list_rcv_eval $tmp_file $diff
2598
2599 rm $tmp_file
2600 route_cleanup
2601}
2602
2603################################################################################
2604# usage
2605
2606usage()
2607{
2608 cat <<EOF
2609usage: ${0##*/} OPTS
2610
2611 -t <test> Test(s) to run (default: all)
2612 (options: $TESTS)
2613 -p Pause on fail
2614 -P Pause after each test before cleanup
2615 -v verbose mode (show commands and output)
2616EOF
2617}
2618
2619################################################################################
2620# main
2621
2622trap cleanup EXIT
2623
2624while getopts :t:pPhv o
2625do
2626 case $o in
2627 t) TESTS=$OPTARG;;
2628 p) PAUSE_ON_FAIL=yes;;
2629 P) PAUSE=yes;;
2630 v) VERBOSE=$(($VERBOSE + 1));;
2631 h) usage; exit 0;;
2632 *) usage; exit 1;;
2633 esac
2634done
2635
2636PEER_CMD="ip netns exec ${PEER_NS}"
2637
2638# make sure we don't pause twice
2639[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
2640
2641if [ "$(id -u)" -ne 0 ];then
2642 echo "SKIP: Need root privileges"
2643 exit $ksft_skip;
2644fi
2645
2646if [ ! -x "$(command -v ip)" ]; then
2647 echo "SKIP: Could not run test without ip tool"
2648 exit $ksft_skip
2649fi
2650
2651ip route help 2>&1 | grep -q fibmatch
2652if [ $? -ne 0 ]; then
2653 echo "SKIP: iproute2 too old, missing fibmatch"
2654 exit $ksft_skip
2655fi
2656
2657# start clean
2658cleanup &> /dev/null
2659
2660for t in $TESTS
2661do
2662 case $t in
2663 fib_unreg_test|unregister) fib_unreg_test;;
2664 fib_down_test|down) fib_down_test;;
2665 fib_carrier_test|carrier) fib_carrier_test;;
2666 fib_rp_filter_test|rp_filter) fib_rp_filter_test;;
2667 fib_nexthop_test|nexthop) fib_nexthop_test;;
2668 fib_notify_test|ipv4_notify) fib_notify_test;;
2669 fib6_notify_test|ipv6_notify) fib6_notify_test;;
2670 fib_suppress_test|suppress) fib_suppress_test;;
2671 ipv6_route_test|ipv6_rt) ipv6_route_test;;
2672 ipv4_route_test|ipv4_rt) ipv4_route_test;;
2673 ipv6_addr_metric) ipv6_addr_metric_test;;
2674 ipv4_addr_metric) ipv4_addr_metric_test;;
2675 ipv4_del_addr) ipv4_del_addr_test;;
2676 ipv6_del_addr) ipv6_del_addr_test;;
2677 ipv6_route_metrics) ipv6_route_metrics_test;;
2678 ipv4_route_metrics) ipv4_route_metrics_test;;
2679 ipv4_route_v6_gw) ipv4_route_v6_gw_test;;
2680 ipv4_mangle) ipv4_mangle_test;;
2681 ipv6_mangle) ipv6_mangle_test;;
2682 ipv4_bcast_neigh) ipv4_bcast_neigh_test;;
2683 fib6_gc_test|ipv6_gc) fib6_gc_test;;
2684 ipv4_mpath_list) ipv4_mpath_list_test;;
2685 ipv6_mpath_list) ipv6_mpath_list_test;;
2686
2687 help) echo "Test names: $TESTS"; exit 0;;
2688 esac
2689done
2690
2691if [ "$TESTS" != "none" ]; then
2692 printf "\nTests passed: %3d\n" ${nsuccess}
2693 printf "Tests failed: %3d\n" ${nfail}
2694fi
2695
2696exit $ret