2 # SPDX-License-Identifier: GPL-2.0
4 # This test is for checking IPv4 and IPv6 FIB behavior in response to
8 # Kselftest framework requirement - SKIP code is 4.
11 # all tests in this script. Can be overridden with -t option
12 TESTS="unregister down carrier nexthop suppress ipv6_notify ipv4_notify \
13 ipv6_rt ipv4_rt ipv6_addr_metric ipv4_addr_metric ipv6_route_metrics \
14 ipv4_route_metrics ipv4_route_v6_gw rp_filter ipv4_del_addr \
15 ipv6_del_addr ipv4_mangle ipv6_mangle ipv4_bcast_neigh fib6_gc_test \
16 ipv4_mpath_list ipv6_mpath_list"
21 IP="$(which ip) -netns ns1"
22 NS_EXEC="$(which ip) netns exec ns1"
24 which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
32 if [ ${rc} -eq ${expected} ]; then
33 printf " TEST: %-60s [ OK ]\n" "${msg}"
34 nsuccess=$((nsuccess+1))
38 printf " TEST: %-60s [FAIL]\n" "${msg}"
39 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
41 echo "hit enter to continue, 'q' to quit"
43 [ "$a" = "q" ] && exit 1
47 if [ "${PAUSE}" = "yes" ]; then
49 echo "hit enter to continue, 'q' to quit"
51 [ "$a" = "q" ] && exit 1
60 $IP link set dev lo up
61 ip netns exec ns1 sysctl -qw net.ipv4.ip_forward=1
62 ip netns exec ns1 sysctl -qw net.ipv6.conf.all.forwarding=1
64 $IP link add dummy0 type dummy
65 $IP link set dev dummy0 up
66 $IP address add 198.51.100.1/24 dev dummy0
67 $IP -6 address add 2001:db8:1::1/64 dev dummy0
74 $IP link del dev dummy0 &> /dev/null
75 ip netns del ns1 &> /dev/null
76 ip netns del ns2 &> /dev/null
84 addr=$($IP -6 -br addr show dev ${dev} | \
86 for (i = 3; i <= NF; ++i) {
94 [ -z "$addr" ] && return 1
101 fib_unreg_unicast_test()
104 echo "Single path route test"
109 $IP route get fibmatch 198.51.100.2 &> /dev/null
110 log_test $? 0 "IPv4 fibmatch"
111 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
112 log_test $? 0 "IPv6 fibmatch"
115 $IP link del dev dummy0
118 echo " Nexthop device deleted"
119 $IP route get fibmatch 198.51.100.2 &> /dev/null
120 log_test $? 2 "IPv4 fibmatch - no route"
121 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
122 log_test $? 2 "IPv6 fibmatch - no route"
127 fib_unreg_multipath_test()
131 echo "Multipath route test"
136 $IP link add dummy1 type dummy
137 $IP link set dev dummy1 up
138 $IP address add 192.0.2.1/24 dev dummy1
139 $IP -6 address add 2001:db8:2::1/64 dev dummy1
141 $IP route add 203.0.113.0/24 \
142 nexthop via 198.51.100.2 dev dummy0 \
143 nexthop via 192.0.2.2 dev dummy1
144 $IP -6 route add 2001:db8:3::/64 \
145 nexthop via 2001:db8:1::2 dev dummy0 \
146 nexthop via 2001:db8:2::2 dev dummy1
150 $IP route get fibmatch 203.0.113.1 &> /dev/null
151 log_test $? 0 "IPv4 fibmatch"
152 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
153 log_test $? 0 "IPv6 fibmatch"
156 $IP link del dev dummy0
159 echo " One nexthop device deleted"
160 $IP route get fibmatch 203.0.113.1 &> /dev/null
161 log_test $? 2 "IPv4 - multipath route removed on delete"
163 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
164 # In IPv6 we do not flush the entire multipath route.
165 log_test $? 0 "IPv6 - multipath down to single path"
168 $IP link del dev dummy1
171 echo " Second nexthop device deleted"
172 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
173 log_test $? 2 "IPv6 - no route"
180 fib_unreg_unicast_test
181 fib_unreg_multipath_test
184 fib_down_unicast_test()
187 echo "Single path, admin down"
192 $IP route get fibmatch 198.51.100.2 &> /dev/null
193 log_test $? 0 "IPv4 fibmatch"
194 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
195 log_test $? 0 "IPv6 fibmatch"
198 $IP link set dev dummy0 down
201 echo " Route deleted on down"
202 $IP route get fibmatch 198.51.100.2 &> /dev/null
203 log_test $? 2 "IPv4 fibmatch"
204 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
205 log_test $? 2 "IPv6 fibmatch"
210 fib_down_multipath_test_do()
215 $IP route get fibmatch 203.0.113.1 \
216 oif $down_dev &> /dev/null
217 log_test $? 2 "IPv4 fibmatch on down device"
218 $IP -6 route get fibmatch 2001:db8:3::1 \
219 oif $down_dev &> /dev/null
220 log_test $? 2 "IPv6 fibmatch on down device"
222 $IP route get fibmatch 203.0.113.1 \
223 oif $up_dev &> /dev/null
224 log_test $? 0 "IPv4 fibmatch on up device"
225 $IP -6 route get fibmatch 2001:db8:3::1 \
226 oif $up_dev &> /dev/null
227 log_test $? 0 "IPv6 fibmatch on up device"
229 $IP route get fibmatch 203.0.113.1 | \
230 grep $down_dev | grep -q "dead linkdown"
231 log_test $? 0 "IPv4 flags on down device"
232 $IP -6 route get fibmatch 2001:db8:3::1 | \
233 grep $down_dev | grep -q "dead linkdown"
234 log_test $? 0 "IPv6 flags on down device"
236 $IP route get fibmatch 203.0.113.1 | \
237 grep $up_dev | grep -q "dead linkdown"
238 log_test $? 1 "IPv4 flags on up device"
239 $IP -6 route get fibmatch 2001:db8:3::1 | \
240 grep $up_dev | grep -q "dead linkdown"
241 log_test $? 1 "IPv6 flags on up device"
244 fib_down_multipath_test()
247 echo "Admin down multipath"
252 $IP link add dummy1 type dummy
253 $IP link set dev dummy1 up
255 $IP address add 192.0.2.1/24 dev dummy1
256 $IP -6 address add 2001:db8:2::1/64 dev dummy1
258 $IP route add 203.0.113.0/24 \
259 nexthop via 198.51.100.2 dev dummy0 \
260 nexthop via 192.0.2.2 dev dummy1
261 $IP -6 route add 2001:db8:3::/64 \
262 nexthop via 2001:db8:1::2 dev dummy0 \
263 nexthop via 2001:db8:2::2 dev dummy1
266 echo " Verify start point"
267 $IP route get fibmatch 203.0.113.1 &> /dev/null
268 log_test $? 0 "IPv4 fibmatch"
270 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
271 log_test $? 0 "IPv6 fibmatch"
274 $IP link set dev dummy0 down
277 echo " One device down, one up"
278 fib_down_multipath_test_do "dummy0" "dummy1"
281 $IP link set dev dummy0 up
282 $IP link set dev dummy1 down
285 echo " Other device down and up"
286 fib_down_multipath_test_do "dummy1" "dummy0"
289 $IP link set dev dummy0 down
292 echo " Both devices down"
293 $IP route get fibmatch 203.0.113.1 &> /dev/null
294 log_test $? 2 "IPv4 fibmatch"
295 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
296 log_test $? 2 "IPv6 fibmatch"
298 $IP link del dev dummy1
304 fib_down_unicast_test
305 fib_down_multipath_test
308 # Local routes should not be affected when carrier changes.
309 fib_carrier_local_test()
312 echo "Local carrier tests - single path"
317 $IP link set dev dummy0 carrier on
321 $IP route get fibmatch 198.51.100.1 &> /dev/null
322 log_test $? 0 "IPv4 fibmatch"
323 $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
324 log_test $? 0 "IPv6 fibmatch"
326 $IP route get fibmatch 198.51.100.1 | \
328 log_test $? 1 "IPv4 - no linkdown flag"
329 $IP -6 route get fibmatch 2001:db8:1::1 | \
331 log_test $? 1 "IPv6 - no linkdown flag"
334 $IP link set dev dummy0 carrier off
338 echo " Carrier off on nexthop"
339 $IP route get fibmatch 198.51.100.1 &> /dev/null
340 log_test $? 0 "IPv4 fibmatch"
341 $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null
342 log_test $? 0 "IPv6 fibmatch"
344 $IP route get fibmatch 198.51.100.1 | \
346 log_test $? 1 "IPv4 - linkdown flag set"
347 $IP -6 route get fibmatch 2001:db8:1::1 | \
349 log_test $? 1 "IPv6 - linkdown flag set"
352 $IP address add 192.0.2.1/24 dev dummy0
353 $IP -6 address add 2001:db8:2::1/64 dev dummy0
356 echo " Route to local address with carrier down"
357 $IP route get fibmatch 192.0.2.1 &> /dev/null
358 log_test $? 0 "IPv4 fibmatch"
359 $IP -6 route get fibmatch 2001:db8:2::1 &> /dev/null
360 log_test $? 0 "IPv6 fibmatch"
362 $IP route get fibmatch 192.0.2.1 | \
364 log_test $? 1 "IPv4 linkdown flag set"
365 $IP -6 route get fibmatch 2001:db8:2::1 | \
367 log_test $? 1 "IPv6 linkdown flag set"
372 fib_carrier_unicast_test()
377 echo "Single path route carrier test"
382 $IP link set dev dummy0 carrier on
386 $IP route get fibmatch 198.51.100.2 &> /dev/null
387 log_test $? 0 "IPv4 fibmatch"
388 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
389 log_test $? 0 "IPv6 fibmatch"
391 $IP route get fibmatch 198.51.100.2 | \
393 log_test $? 1 "IPv4 no linkdown flag"
394 $IP -6 route get fibmatch 2001:db8:1::2 | \
396 log_test $? 1 "IPv6 no linkdown flag"
399 $IP link set dev dummy0 carrier off
404 $IP route get fibmatch 198.51.100.2 &> /dev/null
405 log_test $? 0 "IPv4 fibmatch"
406 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null
407 log_test $? 0 "IPv6 fibmatch"
409 $IP route get fibmatch 198.51.100.2 | \
411 log_test $? 0 "IPv4 linkdown flag set"
412 $IP -6 route get fibmatch 2001:db8:1::2 | \
414 log_test $? 0 "IPv6 linkdown flag set"
417 $IP address add 192.0.2.1/24 dev dummy0
418 $IP -6 address add 2001:db8:2::1/64 dev dummy0
421 echo " Second address added with carrier down"
422 $IP route get fibmatch 192.0.2.2 &> /dev/null
423 log_test $? 0 "IPv4 fibmatch"
424 $IP -6 route get fibmatch 2001:db8:2::2 &> /dev/null
425 log_test $? 0 "IPv6 fibmatch"
427 $IP route get fibmatch 192.0.2.2 | \
429 log_test $? 0 "IPv4 linkdown flag set"
430 $IP -6 route get fibmatch 2001:db8:2::2 | \
432 log_test $? 0 "IPv6 linkdown flag set"
439 fib_carrier_local_test
440 fib_carrier_unicast_test
446 echo "IPv4 rp_filter tests"
452 ip netns set ns2 auto
454 ip -netns ns2 link set dev lo up
456 $IP link add name veth1 type veth peer name veth2
457 $IP link set dev veth2 netns ns2
458 $IP address add 192.0.2.1/24 dev veth1
459 ip -netns ns2 address add 192.0.2.1/24 dev veth2
460 $IP link set dev veth1 up
461 ip -netns ns2 link set dev veth2 up
463 $IP link set dev lo address 52:54:00:6a:c7:5e
464 $IP link set dev veth1 address 52:54:00:6a:c7:5e
465 ip -netns ns2 link set dev lo address 52:54:00:6a:c7:5e
466 ip -netns ns2 link set dev veth2 address 52:54:00:6a:c7:5e
468 # 1. (ns2) redirect lo's egress to veth2's egress
469 ip netns exec ns2 tc qdisc add dev lo parent root handle 1: fq_codel
470 ip netns exec ns2 tc filter add dev lo parent 1: protocol arp basic \
471 action mirred egress redirect dev veth2
472 ip netns exec ns2 tc filter add dev lo parent 1: protocol ip basic \
473 action mirred egress redirect dev veth2
475 # 2. (ns1) redirect veth1's ingress to lo's ingress
476 $NS_EXEC tc qdisc add dev veth1 ingress
477 $NS_EXEC tc filter add dev veth1 ingress protocol arp basic \
478 action mirred ingress redirect dev lo
479 $NS_EXEC tc filter add dev veth1 ingress protocol ip basic \
480 action mirred ingress redirect dev lo
482 # 3. (ns1) redirect lo's egress to veth1's egress
483 $NS_EXEC tc qdisc add dev lo parent root handle 1: fq_codel
484 $NS_EXEC tc filter add dev lo parent 1: protocol arp basic \
485 action mirred egress redirect dev veth1
486 $NS_EXEC tc filter add dev lo parent 1: protocol ip basic \
487 action mirred egress redirect dev veth1
489 # 4. (ns2) redirect veth2's ingress to lo's ingress
490 ip netns exec ns2 tc qdisc add dev veth2 ingress
491 ip netns exec ns2 tc filter add dev veth2 ingress protocol arp basic \
492 action mirred ingress redirect dev lo
493 ip netns exec ns2 tc filter add dev veth2 ingress protocol ip basic \
494 action mirred ingress redirect dev lo
496 $NS_EXEC sysctl -qw net.ipv4.conf.all.rp_filter=1
497 $NS_EXEC sysctl -qw net.ipv4.conf.all.accept_local=1
498 $NS_EXEC sysctl -qw net.ipv4.conf.all.route_localnet=1
499 ip netns exec ns2 sysctl -qw net.ipv4.conf.all.rp_filter=1
500 ip netns exec ns2 sysctl -qw net.ipv4.conf.all.accept_local=1
501 ip netns exec ns2 sysctl -qw net.ipv4.conf.all.route_localnet=1
504 run_cmd "ip netns exec ns2 ping -w1 -c1 192.0.2.1"
505 log_test $? 0 "rp_filter passes local packets"
507 run_cmd "ip netns exec ns2 ping -w1 -c1 127.0.0.1"
508 log_test $? 0 "rp_filter passes loopback packets"
513 ################################################################################
514 # Tests on nexthop spec
516 # run 'ip route add' with given spec
527 [ "$vrf" = "-" ] && vrf="default"
528 [ -n "$gw" ] && gw="via $gw"
529 [ -n "$dev" ] && dev="dev $dev"
531 cmd="$IP route add vrf $vrf $pfx $gw $dev"
532 if [ "$VERBOSE" = "1" ]; then
533 printf "\n COMMAND: $cmd\n"
536 out=$(eval $cmd 2>&1)
538 if [ "$VERBOSE" = "1" -a -n "$out" ]; then
541 log_test $rc $erc "$desc"
547 echo "IPv4 nexthop tests"
549 echo "<<< write me >>>"
554 local lldummy=$(get_linklocal dummy0)
555 local llv1=$(get_linklocal dummy0)
557 if [ -z "$lldummy" ]; then
558 echo "Failed to get linklocal address for dummy0"
561 if [ -z "$llv1" ]; then
562 echo "Failed to get linklocal address for veth1"
567 echo "IPv6 nexthop tests"
569 add_rt "Directly connected nexthop, unicast address" 0 \
570 - 2001:db8:101::/64 2001:db8:1::2
571 add_rt "Directly connected nexthop, unicast address with device" 0 \
572 - 2001:db8:102::/64 2001:db8:1::2 "dummy0"
573 add_rt "Gateway is linklocal address" 0 \
574 - 2001:db8:103::1/64 $llv1 "veth0"
576 # fails because LL address requires a device
577 add_rt "Gateway is linklocal address, no device" 2 \
578 - 2001:db8:104::1/64 $llv1
580 # local address can not be a gateway
581 add_rt "Gateway can not be local unicast address" 2 \
582 - 2001:db8:105::/64 2001:db8:1::1
583 add_rt "Gateway can not be local unicast address, with device" 2 \
584 - 2001:db8:106::/64 2001:db8:1::1 "dummy0"
585 add_rt "Gateway can not be a local linklocal address" 2 \
586 - 2001:db8:107::1/64 $lldummy "dummy0"
589 add_rt "Gateway can be local address in a VRF" 0 \
590 - 2001:db8:108::/64 2001:db8:51::2
591 add_rt "Gateway can be local address in a VRF, with device" 0 \
592 - 2001:db8:109::/64 2001:db8:51::2 "veth0"
593 add_rt "Gateway can be local linklocal address in a VRF" 0 \
594 - 2001:db8:110::1/64 $llv1 "veth0"
596 add_rt "Redirect to VRF lookup" 0 \
597 - 2001:db8:111::/64 "" "red"
599 add_rt "VRF route, gateway can be local address in default VRF" 0 \
600 red 2001:db8:112::/64 2001:db8:51::1
602 # local address in same VRF fails
603 add_rt "VRF route, gateway can not be a local address" 2 \
604 red 2001:db8:113::1/64 2001:db8:2::1
605 add_rt "VRF route, gateway can not be a local addr with device" 2 \
606 red 2001:db8:114::1/64 2001:db8:2::1 "dummy1"
610 # dummy0 - 198.51.100.1/24 2001:db8:1::1/64
611 # veth0 - 192.0.2.1/24 2001:db8:51::1/64
614 # dummy1 - 192.168.2.1/24 2001:db8:2::1/64
615 # veth1 - 192.0.2.2/24 2001:db8:51::2/64
617 # [ dummy0 veth0 ]--[ veth1 dummy1 ]
625 $IP -4 rule add pref 32765 table local
626 $IP -4 rule del pref 0
627 $IP -6 rule add pref 32765 table local
628 $IP -6 rule del pref 0
630 $IP link add red type vrf table 1
632 $IP -4 route add vrf red unreachable default metric 4278198272
633 $IP -6 route add vrf red unreachable default metric 4278198272
635 $IP link add veth0 type veth peer name veth1
636 $IP link set dev veth0 up
637 $IP address add 192.0.2.1/24 dev veth0
638 $IP -6 address add 2001:db8:51::1/64 dev veth0
640 $IP link set dev veth1 vrf red up
641 $IP address add 192.0.2.2/24 dev veth1
642 $IP -6 address add 2001:db8:51::2/64 dev veth1
644 $IP link add dummy1 type dummy
645 $IP link set dev dummy1 vrf red up
646 $IP address add 192.168.2.1/24 dev dummy1
647 $IP -6 address add 2001:db8:2::1/64 dev dummy1
655 $IP link del dev dummy1
667 echo "Fib6 info length calculation in route notify test"
670 for i in 10 20 30 40 50 60 70;
672 $IP link add dummy_$i type dummy
673 $IP link set dev dummy_$i up
674 $IP -6 address add 2001:$i::1/64 dev dummy_$i
677 $NS_EXEC ip monitor route &> errors.txt &
680 $IP -6 route add 2001::/64 \
681 nexthop via 2001:10::2 dev dummy_10 \
682 nexthop encap ip6 dst 2002::20 via 2001:20::2 dev dummy_20 \
683 nexthop encap ip6 dst 2002::30 via 2001:30::2 dev dummy_30 \
684 nexthop encap ip6 dst 2002::40 via 2001:40::2 dev dummy_40 \
685 nexthop encap ip6 dst 2002::50 via 2001:50::2 dev dummy_50 \
686 nexthop encap ip6 dst 2002::60 via 2001:60::2 dev dummy_60 \
687 nexthop encap ip6 dst 2002::70 via 2001:70::2 dev dummy_70
691 err=`cat errors.txt |grep "Message too long"`
692 if [ -z "$err" ];then
698 log_test $ret 0 "ipv6 route add notify"
700 { kill %% && wait %%; } 2>/dev/null
713 echo "Fib4 info length calculation in route notify test"
717 for i in 10 20 30 40 50 60 70;
719 $IP link add dummy_$i type dummy
720 $IP link set dev dummy_$i up
721 $IP address add 20.20.$i.2/24 dev dummy_$i
724 $NS_EXEC ip monitor route &> errors.txt &
727 $IP route add 10.0.0.0/24 \
728 nexthop via 20.20.10.1 dev dummy_10 \
729 nexthop encap ip dst 192.168.10.20 via 20.20.20.1 dev dummy_20 \
730 nexthop encap ip dst 192.168.10.30 via 20.20.30.1 dev dummy_30 \
731 nexthop encap ip dst 192.168.10.40 via 20.20.40.1 dev dummy_40 \
732 nexthop encap ip dst 192.168.10.50 via 20.20.50.1 dev dummy_50 \
733 nexthop encap ip dst 192.168.10.60 via 20.20.60.1 dev dummy_60 \
734 nexthop encap ip dst 192.168.10.70 via 20.20.70.1 dev dummy_70
738 err=`cat errors.txt |grep "Message too long"`
739 if [ -z "$err" ];then
745 log_test $ret 0 "ipv4 route add notify"
747 { kill %% && wait %%; } 2>/dev/null
759 echo "Fib6 garbage collection test"
764 # Check expiration of routes every $EXPIRE seconds (GC)
765 $NS_EXEC sysctl -wq net.ipv6.route.gc_interval=$EXPIRE
767 $IP link add dummy_10 type dummy
768 $IP link set dev dummy_10 up
769 $IP -6 address add 2001:10::1/64 dev dummy_10
771 $NS_EXEC sysctl -wq net.ipv6.route.flush=1
774 for i in $(seq 1 1000); do
775 # Expire route after $EXPIRE seconds
776 $IP -6 route add 2001:20::$i \
777 via 2001:10::2 dev dummy_10 expires $EXPIRE
779 sleep $(($EXPIRE * 2))
780 N_EXP_SLEEP=$($IP -6 route list |grep expires|wc -l)
781 if [ $N_EXP_SLEEP -ne 0 ]; then
782 echo "FAIL: expected 0 routes with expires, got $N_EXP_SLEEP"
789 for i in $(seq 1 5000); do
790 $IP -6 route add 2001:30::$i \
791 via 2001:10::2 dev dummy_10
794 for i in $(seq 1 1000); do
795 # Expire route after $EXPIRE seconds
796 $IP -6 route add 2001:20::$i \
797 via 2001:10::2 dev dummy_10 expires $EXPIRE
799 sleep $(($EXPIRE * 2))
800 N_EXP_SLEEP=$($IP -6 route list |grep expires|wc -l)
801 if [ $N_EXP_SLEEP -ne 0 ]; then
802 echo "FAIL: expected 0 routes with expires," \
803 "got $N_EXP_SLEEP (5000 permanent routes)"
811 log_test $ret 0 "ipv6 route garbage collection"
819 echo "FIB rule with suppress_prefixlength"
822 $IP link add dummy1 type dummy
823 $IP link set dummy1 up
824 $IP -6 route add default dev dummy1
825 $IP -6 rule add table main suppress_prefixlength 0
826 ping -f -c 1000 -W 1 1234::1 >/dev/null 2>&1
827 $IP -6 rule del table main suppress_prefixlength 0
830 # If we got here without crashing, we're good.
831 log_test 0 0 "FIB rule suppress test"
836 ################################################################################
837 # Tests on route add and replace
843 local stderr="2>/dev/null"
845 if [ "$VERBOSE" = "1" ]; then
846 printf " COMMAND: $cmd\n"
850 out=$(eval $cmd $stderr)
852 if [ "$VERBOSE" = "1" -a -n "$out" ]; then
856 [ "$VERBOSE" = "1" ] && echo
867 [ "${out}" = "${expected}" ] && return 0
869 if [ -z "${out}" ]; then
870 if [ "$VERBOSE" = "1" ]; then
871 printf "\nNo route entry found\n"
873 printf " ${expected}\n"
878 # tricky way to convert output to 1-line without ip's
879 # messy '\'; this drops all extra white space
881 if [ "${out}" != "${expected}" ]; then
883 if [ "${VERBOSE}" = "1" ]; then
884 printf " Unexpected route entry. Have:\n"
886 printf " Expected:\n"
887 printf " ${expected}\n\n"
894 # add route for a prefix, flushing any existing routes first
895 # expected to be the first step of a test
902 if [ "$VERBOSE" = "1" ]; then
904 echo " ##################################################"
908 run_cmd "$IP -6 ro flush ${pfx}"
909 [ $? -ne 0 ] && exit 1
911 out=$($IP -6 ro ls match ${pfx})
912 if [ -n "$out" ]; then
913 echo "Failed to flush routes for prefix used for tests."
917 run_cmd "$IP -6 ro add ${pfx} ${nh}"
918 if [ $? -ne 0 ]; then
919 echo "Failed to add initial route for test."
924 # add initial route - used in replace route tests
927 add_route6 "2001:db8:104::/64" "$1"
940 out=$($IP -6 ro ls match ${pfx} | sed -e 's/ pref medium//')
941 check_expected "${out}" "${expected}"
946 $IP li del red 2>/dev/null
947 $IP li del dummy1 2>/dev/null
948 $IP li del veth1 2>/dev/null
949 $IP li del veth3 2>/dev/null
959 [ "${VERBOSE}" = "1" ] && set -x
963 ip netns set ns2 auto
964 ip -netns ns2 link set dev lo up
965 ip netns exec ns2 sysctl -qw net.ipv4.ip_forward=1
966 ip netns exec ns2 sysctl -qw net.ipv6.conf.all.forwarding=1
968 $IP li add veth1 type veth peer name veth2
969 $IP li add veth3 type veth peer name veth4
973 $IP li set veth2 netns ns2 up
974 $IP li set veth4 netns ns2 up
975 ip -netns ns2 li add dummy1 type dummy
976 ip -netns ns2 li set dummy1 up
978 $IP -6 addr add 2001:db8:101::1/64 dev veth1 nodad
979 $IP -6 addr add 2001:db8:103::1/64 dev veth3 nodad
980 $IP addr add 172.16.101.1/24 dev veth1
981 $IP addr add 172.16.103.1/24 dev veth3
983 ip -netns ns2 -6 addr add 2001:db8:101::2/64 dev veth2 nodad
984 ip -netns ns2 -6 addr add 2001:db8:103::2/64 dev veth4 nodad
985 ip -netns ns2 -6 addr add 2001:db8:104::1/64 dev dummy1 nodad
987 ip -netns ns2 addr add 172.16.101.2/24 dev veth2
988 ip -netns ns2 addr add 172.16.103.2/24 dev veth4
989 ip -netns ns2 addr add 172.16.104.1/24 dev dummy1
994 # assumption is that basic add of a single path route works
995 # otherwise just adding an address on an interface is broken
1001 echo "IPv6 route add / append tests"
1003 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1004 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1005 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2"
1006 log_test $? 2 "Attempt to add duplicate route - gw"
1008 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1009 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1010 run_cmd "$IP -6 ro add 2001:db8:104::/64 dev veth3"
1011 log_test $? 2 "Attempt to add duplicate route - dev only"
1013 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1014 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1015 run_cmd "$IP -6 ro add unreachable 2001:db8:104::/64"
1016 log_test $? 2 "Attempt to add duplicate route - reject route"
1018 # route append with same prefix adds a new route
1019 # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
1020 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1021 run_cmd "$IP -6 ro append 2001:db8:104::/64 via 2001:db8:103::2"
1022 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"
1023 log_test $? 0 "Append nexthop to existing route - gw"
1025 # insert mpath directly
1026 add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1027 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"
1028 log_test $? 0 "Add multipath route"
1030 add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1031 run_cmd "$IP -6 ro add 2001:db8:104::/64 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1032 log_test $? 2 "Attempt to add duplicate multipath route"
1034 # insert of a second route without append but different metric
1035 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2"
1036 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2 metric 512"
1038 if [ $rc -eq 0 ]; then
1039 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::3 metric 256"
1042 log_test $rc 0 "Route add with different metrics"
1044 run_cmd "$IP -6 ro del 2001:db8:104::/64 metric 512"
1046 if [ $rc -eq 0 ]; then
1047 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"
1050 log_test $rc 0 "Route delete with metric"
1053 ipv6_rt_replace_single()
1055 # single path with single path
1057 add_initial_route6 "via 2001:db8:101::2"
1058 run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:103::2"
1059 check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
1060 log_test $? 0 "Single path with single path"
1062 # single path with multipath
1064 add_initial_route6 "nexthop via 2001:db8:101::2"
1065 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::2"
1066 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"
1067 log_test $? 0 "Single path with multipath"
1069 # single path with single path using MULTIPATH attribute
1071 add_initial_route6 "via 2001:db8:101::2"
1072 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:103::2"
1073 check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024"
1074 log_test $? 0 "Single path with single path via multipath attribute"
1076 # route replace fails - invalid nexthop
1077 add_initial_route6 "via 2001:db8:101::2"
1078 run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:104::2"
1079 if [ $? -eq 0 ]; then
1080 # previous command is expected to fail so if it returns 0
1081 # that means the test failed.
1082 log_test 0 1 "Invalid nexthop"
1084 check_route6 "2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024"
1085 log_test $? 0 "Invalid nexthop"
1088 # replace non-existent route
1089 # - note use of change versus replace since ip adds NLM_F_CREATE
1091 add_initial_route6 "via 2001:db8:101::2"
1092 run_cmd "$IP -6 ro change 2001:db8:105::/64 via 2001:db8:101::2"
1093 log_test $? 2 "Single path - replace of non-existent route"
1096 ipv6_rt_replace_mpath()
1098 # multipath with multipath
1099 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1100 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
1101 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"
1102 log_test $? 0 "Multipath with multipath"
1104 # multipath with single
1105 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1106 run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:101::3"
1107 check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
1108 log_test $? 0 "Multipath with single path"
1110 # multipath with single
1111 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1112 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3"
1113 check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
1114 log_test $? 0 "Multipath with single path via multipath attribute"
1116 # multipath with dev-only
1117 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1118 run_cmd "$IP -6 ro replace 2001:db8:104::/64 dev veth1"
1119 check_route6 "2001:db8:104::/64 dev veth1 metric 1024"
1120 log_test $? 0 "Multipath with dev-only"
1122 # route replace fails - invalid nexthop 1
1123 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1124 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:111::3 nexthop via 2001:db8:103::3"
1125 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"
1126 log_test $? 0 "Multipath - invalid first nexthop"
1128 # route replace fails - invalid nexthop 2
1129 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1130 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:113::3"
1131 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"
1132 log_test $? 0 "Multipath - invalid second nexthop"
1134 # multipath non-existent route
1135 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1136 run_cmd "$IP -6 ro change 2001:db8:105::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3"
1137 log_test $? 2 "Multipath - replace of non-existent route"
1143 echo "IPv6 route replace tests"
1145 ipv6_rt_replace_single
1146 ipv6_rt_replace_mpath
1152 echo "IPv6 route with dsfield tests"
1154 run_cmd "$IP -6 route flush 2001:db8:102::/64"
1156 # IPv6 doesn't support routing based on dsfield
1157 run_cmd "$IP -6 route add 2001:db8:102::/64 dsfield 0x04 via 2001:db8:101::2"
1158 log_test $? 2 "Reject route with dsfield"
1172 ip_addr_metric_check()
1174 ip addr help 2>&1 | grep -q metric
1175 if [ $? -ne 0 ]; then
1176 echo "iproute2 command does not support metric for addresses. Skipping test"
1183 ipv6_addr_metric_test()
1188 echo "IPv6 prefix route tests"
1190 ip_addr_metric_check || return 1
1195 $IP li add dummy1 type dummy
1196 $IP li add dummy2 type dummy
1197 $IP li set dummy1 up
1198 $IP li set dummy2 up
1200 # default entry is metric 256
1201 run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64"
1202 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64"
1205 check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 256 2001:db8:104::/64 dev dummy2 proto kernel metric 256"
1206 log_test $? 0 "Default metric"
1209 run_cmd "$IP -6 addr flush dev dummy1"
1210 run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64 metric 257"
1213 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 256 2001:db8:104::/64 dev dummy1 proto kernel metric 257"
1214 log_test $? 0 "User specified metric on first device"
1217 run_cmd "$IP -6 addr flush dev dummy2"
1218 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64 metric 258"
1221 check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 257 2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1222 log_test $? 0 "User specified metric on second device"
1224 run_cmd "$IP -6 addr del dev dummy1 2001:db8:104::1/64 metric 257"
1226 if [ $rc -eq 0 ]; then
1227 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1230 log_test $rc 0 "Delete of address on first device"
1232 run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::2/64 metric 259"
1234 if [ $rc -eq 0 ]; then
1235 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1238 log_test $rc 0 "Modify metric of address"
1240 # verify prefix route removed on down
1241 run_cmd "ip netns exec ns1 sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1"
1242 run_cmd "$IP li set dev dummy2 down"
1244 if [ $rc -eq 0 ]; then
1245 out=$($IP -6 ro ls match 2001:db8:104::/64)
1246 check_expected "${out}" ""
1249 log_test $rc 0 "Prefix route removed on link down"
1251 # verify prefix route re-inserted with assigned metric
1252 run_cmd "$IP li set dev dummy2 up"
1254 if [ $rc -eq 0 ]; then
1255 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1258 log_test $rc 0 "Prefix route with metric on link up"
1260 # verify peer metric added correctly
1262 run_cmd "$IP -6 addr flush dev dummy2"
1263 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::1 peer 2001:db8:104::2 metric 260"
1266 check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 260"
1267 log_test $? 0 "Set metric with peer route on local side"
1268 check_route6 "2001:db8:104::2 dev dummy2 proto kernel metric 260"
1269 log_test $? 0 "Set metric with peer route on peer side"
1272 run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::1 peer 2001:db8:104::3 metric 261"
1275 check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 261"
1276 log_test $? 0 "Modify metric and peer address on local side"
1277 check_route6 "2001:db8:104::3 dev dummy2 proto kernel metric 261"
1278 log_test $? 0 "Modify metric and peer address on peer side"
1285 ipv6_route_metrics_test()
1290 echo "IPv6 routes with metrics"
1295 # single path with metrics
1297 run_cmd "$IP -6 ro add 2001:db8:111::/64 via 2001:db8:101::2 mtu 1400"
1299 if [ $rc -eq 0 ]; then
1300 check_route6 "2001:db8:111::/64 via 2001:db8:101::2 dev veth1 metric 1024 mtu 1400"
1303 log_test $rc 0 "Single path route with mtu metric"
1307 # multipath via separate routes with metrics
1309 run_cmd "$IP -6 ro add 2001:db8:112::/64 via 2001:db8:101::2 mtu 1400"
1310 run_cmd "$IP -6 ro append 2001:db8:112::/64 via 2001:db8:103::2"
1312 if [ $rc -eq 0 ]; then
1313 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"
1316 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on first"
1318 # second route is coalesced to first to make a multipath route.
1319 # MTU of the second path is hidden from display!
1320 run_cmd "$IP -6 ro add 2001:db8:113::/64 via 2001:db8:101::2"
1321 run_cmd "$IP -6 ro append 2001:db8:113::/64 via 2001:db8:103::2 mtu 1400"
1323 if [ $rc -eq 0 ]; then
1324 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"
1327 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on 2nd"
1329 run_cmd "$IP -6 ro del 2001:db8:113::/64 via 2001:db8:101::2"
1330 if [ $? -eq 0 ]; then
1331 check_route6 "2001:db8:113::/64 via 2001:db8:103::2 dev veth3 metric 1024 mtu 1400"
1332 log_test $? 0 " MTU of second leg"
1336 # multipath with metrics
1338 run_cmd "$IP -6 ro add 2001:db8:115::/64 mtu 1400 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1340 if [ $rc -eq 0 ]; then
1341 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"
1344 log_test $rc 0 "Multipath route with mtu metric"
1346 $IP -6 ro add 2001:db8:104::/64 via 2001:db8:101::2 mtu 1300
1347 run_cmd "ip netns exec ns1 ${ping6} -w1 -c1 -s 1500 2001:db8:104::1"
1348 log_test $? 0 "Using route with mtu metric"
1350 run_cmd "$IP -6 ro add 2001:db8:114::/64 via 2001:db8:101::2 congctl lock foo"
1351 log_test $? 2 "Invalid metric (fails metric_convert)"
1356 # add route for a prefix, flushing any existing routes first
1357 # expected to be the first step of a test
1364 if [ "$VERBOSE" = "1" ]; then
1366 echo " ##################################################"
1370 run_cmd "$IP ro flush ${pfx}"
1371 [ $? -ne 0 ] && exit 1
1373 out=$($IP ro ls match ${pfx})
1374 if [ -n "$out" ]; then
1375 echo "Failed to flush routes for prefix used for tests."
1379 run_cmd "$IP ro add ${pfx} ${nh}"
1380 if [ $? -ne 0 ]; then
1381 echo "Failed to add initial route for test."
1386 # add initial route - used in replace route tests
1389 add_route "172.16.104.0/24" "$1"
1400 [ "${pfx}" = "unreachable" ] && pfx=$2
1402 out=$($IP ro ls match ${pfx})
1403 check_expected "${out}" "${expected}"
1406 # assumption is that basic add of a single path route works
1407 # otherwise just adding an address on an interface is broken
1413 echo "IPv4 route add / append tests"
1415 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1416 add_route "172.16.104.0/24" "via 172.16.101.2"
1417 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2"
1418 log_test $? 2 "Attempt to add duplicate route - gw"
1420 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1421 add_route "172.16.104.0/24" "via 172.16.101.2"
1422 run_cmd "$IP ro add 172.16.104.0/24 dev veth3"
1423 log_test $? 2 "Attempt to add duplicate route - dev only"
1425 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1426 add_route "172.16.104.0/24" "via 172.16.101.2"
1427 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1428 log_test $? 2 "Attempt to add duplicate route - reject route"
1430 # iproute2 prepend only sets NLM_F_CREATE
1431 # - adds a new route; does NOT convert existing route to ECMP
1432 add_route "172.16.104.0/24" "via 172.16.101.2"
1433 run_cmd "$IP ro prepend 172.16.104.0/24 via 172.16.103.2"
1434 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"
1435 log_test $? 0 "Add new nexthop for existing prefix"
1437 # route append with same prefix adds a new route
1438 # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
1439 add_route "172.16.104.0/24" "via 172.16.101.2"
1440 run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1441 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"
1442 log_test $? 0 "Append nexthop to existing route - gw"
1444 add_route "172.16.104.0/24" "via 172.16.101.2"
1445 run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1446 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 dev veth3 scope link"
1447 log_test $? 0 "Append nexthop to existing route - dev only"
1449 add_route "172.16.104.0/24" "via 172.16.101.2"
1450 run_cmd "$IP ro append unreachable 172.16.104.0/24"
1451 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 unreachable 172.16.104.0/24"
1452 log_test $? 0 "Append nexthop to existing route - reject route"
1454 run_cmd "$IP ro flush 172.16.104.0/24"
1455 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1456 run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1457 check_route "unreachable 172.16.104.0/24 172.16.104.0/24 via 172.16.103.2 dev veth3"
1458 log_test $? 0 "Append nexthop to existing reject route - gw"
1460 run_cmd "$IP ro flush 172.16.104.0/24"
1461 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1462 run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1463 check_route "unreachable 172.16.104.0/24 172.16.104.0/24 dev veth3 scope link"
1464 log_test $? 0 "Append nexthop to existing reject route - dev only"
1466 # insert mpath directly
1467 add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1468 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"
1469 log_test $? 0 "add multipath route"
1471 add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1472 run_cmd "$IP ro add 172.16.104.0/24 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1473 log_test $? 2 "Attempt to add duplicate multipath route"
1475 # insert of a second route without append but different metric
1476 add_route "172.16.104.0/24" "via 172.16.101.2"
1477 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2 metric 512"
1479 if [ $rc -eq 0 ]; then
1480 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.3 metric 256"
1483 log_test $rc 0 "Route add with different metrics"
1485 run_cmd "$IP ro del 172.16.104.0/24 metric 512"
1487 if [ $rc -eq 0 ]; then
1488 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"
1491 log_test $rc 0 "Route delete with metric"
1494 ipv4_rt_replace_single()
1496 # single path with single path
1498 add_initial_route "via 172.16.101.2"
1499 run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.103.2"
1500 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1501 log_test $? 0 "Single path with single path"
1503 # single path with multipath
1505 add_initial_route "nexthop via 172.16.101.2"
1506 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.2"
1507 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"
1508 log_test $? 0 "Single path with multipath"
1510 # single path with reject
1512 add_initial_route "nexthop via 172.16.101.2"
1513 run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1514 check_route "unreachable 172.16.104.0/24"
1515 log_test $? 0 "Single path with reject route"
1517 # single path with single path using MULTIPATH attribute
1519 add_initial_route "via 172.16.101.2"
1520 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.103.2"
1521 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1522 log_test $? 0 "Single path with single path via multipath attribute"
1524 # route replace fails - invalid nexthop
1525 add_initial_route "via 172.16.101.2"
1526 run_cmd "$IP ro replace 172.16.104.0/24 via 2001:db8:104::2"
1527 if [ $? -eq 0 ]; then
1528 # previous command is expected to fail so if it returns 0
1529 # that means the test failed.
1530 log_test 0 1 "Invalid nexthop"
1532 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1"
1533 log_test $? 0 "Invalid nexthop"
1536 # replace non-existent route
1537 # - note use of change versus replace since ip adds NLM_F_CREATE
1539 add_initial_route "via 172.16.101.2"
1540 run_cmd "$IP ro change 172.16.105.0/24 via 172.16.101.2"
1541 log_test $? 2 "Single path - replace of non-existent route"
1544 ipv4_rt_replace_mpath()
1546 # multipath with multipath
1547 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1548 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1549 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"
1550 log_test $? 0 "Multipath with multipath"
1552 # multipath with single
1553 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1554 run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.101.3"
1555 check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
1556 log_test $? 0 "Multipath with single path"
1558 # multipath with single
1559 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1560 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3"
1561 check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
1562 log_test $? 0 "Multipath with single path via multipath attribute"
1564 # multipath with reject
1565 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1566 run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1567 check_route "unreachable 172.16.104.0/24"
1568 log_test $? 0 "Multipath with reject route"
1570 # route replace fails - invalid nexthop 1
1571 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1572 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.111.3 nexthop via 172.16.103.3"
1573 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"
1574 log_test $? 0 "Multipath - invalid first nexthop"
1576 # route replace fails - invalid nexthop 2
1577 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1578 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.113.3"
1579 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"
1580 log_test $? 0 "Multipath - invalid second nexthop"
1582 # multipath non-existent route
1583 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1584 run_cmd "$IP ro change 172.16.105.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1585 log_test $? 2 "Multipath - replace of non-existent route"
1591 echo "IPv4 route replace tests"
1593 ipv4_rt_replace_single
1594 ipv4_rt_replace_mpath
1597 # checks that cached input route on VRF port is deleted
1598 # when VRF is deleted
1599 ipv4_local_rt_cache()
1601 run_cmd "ip addr add 10.0.0.1/32 dev lo"
1602 run_cmd "ip netns add test-ns"
1603 run_cmd "ip link add veth-outside type veth peer name veth-inside"
1604 run_cmd "ip link add vrf-100 type vrf table 1100"
1605 run_cmd "ip link set veth-outside master vrf-100"
1606 run_cmd "ip link set veth-inside netns test-ns"
1607 run_cmd "ip link set veth-outside up"
1608 run_cmd "ip link set vrf-100 up"
1609 run_cmd "ip route add 10.1.1.1/32 dev veth-outside table 1100"
1610 run_cmd "ip netns exec test-ns ip link set veth-inside up"
1611 run_cmd "ip netns exec test-ns ip addr add 10.1.1.1/32 dev veth-inside"
1612 run_cmd "ip netns exec test-ns ip route add 10.0.0.1/32 dev veth-inside"
1613 run_cmd "ip netns exec test-ns ip route add default via 10.0.0.1"
1614 run_cmd "ip netns exec test-ns ping 10.0.0.1 -c 1 -i 1"
1615 run_cmd "ip link delete vrf-100"
1617 # if we do not hang test is a success
1618 log_test $? 0 "Cached route removed from VRF port device"
1624 echo "IPv4 route with dsfield tests"
1626 run_cmd "$IP route flush 172.16.102.0/24"
1628 # New routes should reject dsfield options that interfere with ECN
1629 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x01 via 172.16.101.2"
1630 log_test $? 2 "Reject route with dsfield 0x01"
1632 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x02 via 172.16.101.2"
1633 log_test $? 2 "Reject route with dsfield 0x02"
1635 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x03 via 172.16.101.2"
1636 log_test $? 2 "Reject route with dsfield 0x03"
1638 # A generic route that doesn't take DSCP into account
1639 run_cmd "$IP route add 172.16.102.0/24 via 172.16.101.2"
1641 # A more specific route for DSCP 0x10
1642 run_cmd "$IP route add 172.16.102.0/24 dsfield 0x10 via 172.16.103.2"
1644 # DSCP 0x10 should match the specific route, no matter the ECN bits
1645 $IP route get fibmatch 172.16.102.1 dsfield 0x10 | \
1646 grep -q "via 172.16.103.2"
1647 log_test $? 0 "IPv4 route with DSCP and ECN:Not-ECT"
1649 $IP route get fibmatch 172.16.102.1 dsfield 0x11 | \
1650 grep -q "via 172.16.103.2"
1651 log_test $? 0 "IPv4 route with DSCP and ECN:ECT(1)"
1653 $IP route get fibmatch 172.16.102.1 dsfield 0x12 | \
1654 grep -q "via 172.16.103.2"
1655 log_test $? 0 "IPv4 route with DSCP and ECN:ECT(0)"
1657 $IP route get fibmatch 172.16.102.1 dsfield 0x13 | \
1658 grep -q "via 172.16.103.2"
1659 log_test $? 0 "IPv4 route with DSCP and ECN:CE"
1661 # Unknown DSCP should match the generic route, no matter the ECN bits
1662 $IP route get fibmatch 172.16.102.1 dsfield 0x14 | \
1663 grep -q "via 172.16.101.2"
1664 log_test $? 0 "IPv4 route with unknown DSCP and ECN:Not-ECT"
1666 $IP route get fibmatch 172.16.102.1 dsfield 0x15 | \
1667 grep -q "via 172.16.101.2"
1668 log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(1)"
1670 $IP route get fibmatch 172.16.102.1 dsfield 0x16 | \
1671 grep -q "via 172.16.101.2"
1672 log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(0)"
1674 $IP route get fibmatch 172.16.102.1 dsfield 0x17 | \
1675 grep -q "via 172.16.101.2"
1676 log_test $? 0 "IPv4 route with unknown DSCP and ECN:CE"
1678 # Null DSCP should match the generic route, no matter the ECN bits
1679 $IP route get fibmatch 172.16.102.1 dsfield 0x00 | \
1680 grep -q "via 172.16.101.2"
1681 log_test $? 0 "IPv4 route with no DSCP and ECN:Not-ECT"
1683 $IP route get fibmatch 172.16.102.1 dsfield 0x01 | \
1684 grep -q "via 172.16.101.2"
1685 log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(1)"
1687 $IP route get fibmatch 172.16.102.1 dsfield 0x02 | \
1688 grep -q "via 172.16.101.2"
1689 log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(0)"
1691 $IP route get fibmatch 172.16.102.1 dsfield 0x03 | \
1692 grep -q "via 172.16.101.2"
1693 log_test $? 0 "IPv4 route with no DSCP and ECN:CE"
1708 ipv4_addr_metric_test()
1713 echo "IPv4 prefix route tests"
1715 ip_addr_metric_check || return 1
1720 $IP li add dummy1 type dummy
1721 $IP li add dummy2 type dummy
1722 $IP li set dummy1 up
1723 $IP li set dummy2 up
1725 # default entry is metric 256
1726 run_cmd "$IP addr add dev dummy1 172.16.104.1/24"
1727 run_cmd "$IP addr add dev dummy2 172.16.104.2/24"
1730 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"
1731 log_test $? 0 "Default metric"
1734 run_cmd "$IP addr flush dev dummy1"
1735 run_cmd "$IP addr add dev dummy1 172.16.104.1/24 metric 257"
1738 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"
1739 log_test $? 0 "User specified metric on first device"
1742 run_cmd "$IP addr flush dev dummy2"
1743 run_cmd "$IP addr add dev dummy2 172.16.104.2/24 metric 258"
1746 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"
1747 log_test $? 0 "User specified metric on second device"
1749 run_cmd "$IP addr del dev dummy1 172.16.104.1/24 metric 257"
1751 if [ $rc -eq 0 ]; then
1752 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258"
1755 log_test $rc 0 "Delete of address on first device"
1757 run_cmd "$IP addr change dev dummy2 172.16.104.2/24 metric 259"
1759 if [ $rc -eq 0 ]; then
1760 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1763 log_test $rc 0 "Modify metric of address"
1765 # verify prefix route removed on down
1766 run_cmd "$IP li set dev dummy2 down"
1768 if [ $rc -eq 0 ]; then
1769 out=$($IP ro ls match 172.16.104.0/24)
1770 check_expected "${out}" ""
1773 log_test $rc 0 "Prefix route removed on link down"
1775 # verify prefix route re-inserted with assigned metric
1776 run_cmd "$IP li set dev dummy2 up"
1778 if [ $rc -eq 0 ]; then
1779 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1782 log_test $rc 0 "Prefix route with metric on link up"
1784 # explicitly check for metric changes on edge scenarios
1785 run_cmd "$IP addr flush dev dummy2"
1786 run_cmd "$IP addr add dev dummy2 172.16.104.0/24 metric 259"
1787 run_cmd "$IP addr change dev dummy2 172.16.104.0/24 metric 260"
1789 if [ $rc -eq 0 ]; then
1790 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.0 metric 260"
1793 log_test $rc 0 "Modify metric of .0/24 address"
1795 run_cmd "$IP addr flush dev dummy2"
1796 run_cmd "$IP addr add dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 260"
1798 if [ $rc -eq 0 ]; then
1799 check_route "172.16.104.2 dev dummy2 proto kernel scope link src 172.16.104.1 metric 260"
1802 log_test $rc 0 "Set metric of address with peer route"
1804 run_cmd "$IP addr change dev dummy2 172.16.104.1/32 peer 172.16.104.3 metric 261"
1806 if [ $rc -eq 0 ]; then
1807 check_route "172.16.104.3 dev dummy2 proto kernel scope link src 172.16.104.1 metric 261"
1810 log_test $rc 0 "Modify metric and peer address for peer route"
1817 ipv4_route_metrics_test()
1822 echo "IPv4 route add / append tests"
1826 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 mtu 1400"
1828 if [ $rc -eq 0 ]; then
1829 check_route "172.16.111.0/24 via 172.16.101.2 dev veth1 mtu 1400"
1832 log_test $rc 0 "Single path route with mtu metric"
1835 run_cmd "$IP ro add 172.16.112.0/24 mtu 1400 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1837 if [ $rc -eq 0 ]; then
1838 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"
1841 log_test $rc 0 "Multipath route with mtu metric"
1843 $IP ro add 172.16.104.0/24 via 172.16.101.2 mtu 1300
1844 run_cmd "ip netns exec ns1 ping -w1 -c1 -s 1500 172.16.104.1"
1845 log_test $? 0 "Using route with mtu metric"
1847 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 congctl lock foo"
1848 log_test $? 2 "Invalid metric (fails metric_convert)"
1853 ipv4_del_addr_test()
1856 echo "IPv4 delete address route tests"
1861 $IP li add dummy1 type dummy
1862 $IP li set dummy1 up
1863 $IP li add dummy2 type dummy
1864 $IP li set dummy2 up
1865 $IP li add red type vrf table 1111
1867 $IP ro add vrf red unreachable default
1868 $IP li set dummy2 vrf red
1870 $IP addr add dev dummy1 172.16.104.1/24
1871 $IP addr add dev dummy1 172.16.104.11/24
1872 $IP addr add dev dummy1 172.16.104.12/24
1873 $IP addr add dev dummy1 172.16.104.13/24
1874 $IP addr add dev dummy2 172.16.104.1/24
1875 $IP addr add dev dummy2 172.16.104.11/24
1876 $IP addr add dev dummy2 172.16.104.12/24
1877 $IP route add 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1878 $IP route add 172.16.106.0/24 dev lo src 172.16.104.12
1879 $IP route add table 0 172.16.107.0/24 via 172.16.104.2 src 172.16.104.13
1880 $IP route add vrf red 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1881 $IP route add vrf red 172.16.106.0/24 dev lo src 172.16.104.12
1884 # removing address from device in vrf should only remove route from vrf table
1885 echo " Regular FIB info"
1887 $IP addr del dev dummy2 172.16.104.11/24
1888 $IP ro ls vrf red | grep -q 172.16.105.0/24
1889 log_test $? 1 "Route removed from VRF when source address deleted"
1891 $IP ro ls | grep -q 172.16.105.0/24
1892 log_test $? 0 "Route in default VRF not removed"
1894 $IP addr add dev dummy2 172.16.104.11/24
1895 $IP route add vrf red 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1897 $IP addr del dev dummy1 172.16.104.11/24
1898 $IP ro ls | grep -q 172.16.105.0/24
1899 log_test $? 1 "Route removed in default VRF when source address deleted"
1901 $IP ro ls vrf red | grep -q 172.16.105.0/24
1902 log_test $? 0 "Route in VRF is not removed by address delete"
1904 # removing address from device in vrf should only remove route from vrf
1905 # table even when the associated fib info only differs in table ID
1906 echo " Identical FIB info with different table ID"
1908 $IP addr del dev dummy2 172.16.104.12/24
1909 $IP ro ls vrf red | grep -q 172.16.106.0/24
1910 log_test $? 1 "Route removed from VRF when source address deleted"
1912 $IP ro ls | grep -q 172.16.106.0/24
1913 log_test $? 0 "Route in default VRF not removed"
1915 $IP addr add dev dummy2 172.16.104.12/24
1916 $IP route add vrf red 172.16.106.0/24 dev lo src 172.16.104.12
1918 $IP addr del dev dummy1 172.16.104.12/24
1919 $IP ro ls | grep -q 172.16.106.0/24
1920 log_test $? 1 "Route removed in default VRF when source address deleted"
1922 $IP ro ls vrf red | grep -q 172.16.106.0/24
1923 log_test $? 0 "Route in VRF is not removed by address delete"
1925 # removing address from device in default vrf should remove route from
1926 # the default vrf even when route was inserted with a table ID of 0.
1929 $IP addr del dev dummy1 172.16.104.13/24
1930 $IP ro ls | grep -q 172.16.107.0/24
1931 log_test $? 1 "Route removed in default VRF when source address deleted"
1938 ipv6_del_addr_test()
1941 echo "IPv6 delete address route tests"
1946 for i in $(seq 6); do
1947 $IP li add dummy${i} up type dummy
1950 $IP li add red up type vrf table 1111
1951 $IP ro add vrf red unreachable default
1952 for i in $(seq 4 6); do
1953 $IP li set dummy${i} vrf red
1956 $IP addr add dev dummy1 fe80::1/128
1957 $IP addr add dev dummy1 2001:db8:101::1/64
1958 $IP addr add dev dummy1 2001:db8:101::10/64
1959 $IP addr add dev dummy1 2001:db8:101::11/64
1960 $IP addr add dev dummy1 2001:db8:101::12/64
1961 $IP addr add dev dummy1 2001:db8:101::13/64
1962 $IP addr add dev dummy1 2001:db8:101::14/64
1963 $IP addr add dev dummy1 2001:db8:101::15/64
1964 $IP addr add dev dummy2 fe80::1/128
1965 $IP addr add dev dummy2 2001:db8:101::1/64
1966 $IP addr add dev dummy2 2001:db8:101::11/64
1967 $IP addr add dev dummy3 fe80::1/128
1969 $IP addr add dev dummy4 2001:db8:101::1/64
1970 $IP addr add dev dummy4 2001:db8:101::10/64
1971 $IP addr add dev dummy4 2001:db8:101::11/64
1972 $IP addr add dev dummy4 2001:db8:101::12/64
1973 $IP addr add dev dummy4 2001:db8:101::13/64
1974 $IP addr add dev dummy4 2001:db8:101::14/64
1975 $IP addr add dev dummy5 2001:db8:101::1/64
1976 $IP addr add dev dummy5 2001:db8:101::11/64
1978 # Single device using src address
1979 $IP route add 2001:db8:110::/64 dev dummy3 src 2001:db8:101::10
1980 # Two devices with the same source address
1981 $IP route add 2001:db8:111::/64 dev dummy3 src 2001:db8:101::11
1982 # VRF with single device using src address
1983 $IP route add vrf red 2001:db8:110::/64 dev dummy6 src 2001:db8:101::10
1984 # VRF with two devices using src address
1985 $IP route add vrf red 2001:db8:111::/64 dev dummy6 src 2001:db8:101::11
1986 # src address and nexthop dev in same VRF
1987 $IP route add 2001:db8:112::/64 dev dummy3 src 2001:db8:101::12
1988 $IP route add vrf red 2001:db8:112::/64 dev dummy6 src 2001:db8:101::12
1989 # src address and nexthop device in different VRF
1990 $IP route add 2001:db8:113::/64 dev lo src 2001:db8:101::13
1991 $IP route add vrf red 2001:db8:113::/64 dev lo src 2001:db8:101::13
1993 $IP route add table 0 2001:db8:115::/64 via 2001:db8:101::2 src 2001:db8:101::15
1994 # Link local source route
1995 $IP route add 2001:db8:116::/64 dev dummy2 src fe80::1
1996 $IP route add 2001:db8:117::/64 dev dummy3 src fe80::1
1999 echo " Single device using src address"
2001 $IP addr del dev dummy1 2001:db8:101::10/64
2002 $IP -6 route show | grep -q "src 2001:db8:101::10 "
2003 log_test $? 1 "Prefsrc removed when src address removed on other device"
2005 echo " Two devices with the same source address"
2007 $IP addr del dev dummy1 2001:db8:101::11/64
2008 $IP -6 route show | grep -q "src 2001:db8:101::11 "
2009 log_test $? 0 "Prefsrc not removed when src address exist on other device"
2011 $IP addr del dev dummy2 2001:db8:101::11/64
2012 $IP -6 route show | grep -q "src 2001:db8:101::11 "
2013 log_test $? 1 "Prefsrc removed when src address removed on all devices"
2015 echo " VRF with single device using src address"
2017 $IP addr del dev dummy4 2001:db8:101::10/64
2018 $IP -6 route show vrf red | grep -q "src 2001:db8:101::10 "
2019 log_test $? 1 "Prefsrc removed when src address removed on other device"
2021 echo " VRF with two devices using src address"
2023 $IP addr del dev dummy4 2001:db8:101::11/64
2024 $IP -6 route show vrf red | grep -q "src 2001:db8:101::11 "
2025 log_test $? 0 "Prefsrc not removed when src address exist on other device"
2027 $IP addr del dev dummy5 2001:db8:101::11/64
2028 $IP -6 route show vrf red | grep -q "src 2001:db8:101::11 "
2029 log_test $? 1 "Prefsrc removed when src address removed on all devices"
2031 echo " src address and nexthop dev in same VRF"
2033 $IP addr del dev dummy4 2001:db8:101::12/64
2034 $IP -6 route show vrf red | grep -q "src 2001:db8:101::12 "
2035 log_test $? 1 "Prefsrc removed from VRF when source address deleted"
2036 $IP -6 route show | grep -q " src 2001:db8:101::12 "
2037 log_test $? 0 "Prefsrc in default VRF not removed"
2039 $IP addr add dev dummy4 2001:db8:101::12/64
2040 $IP route replace vrf red 2001:db8:112::/64 dev dummy6 src 2001:db8:101::12
2041 $IP addr del dev dummy1 2001:db8:101::12/64
2042 $IP -6 route show vrf red | grep -q "src 2001:db8:101::12 "
2043 log_test $? 0 "Prefsrc not removed from VRF when source address exist"
2044 $IP -6 route show | grep -q " src 2001:db8:101::12 "
2045 log_test $? 1 "Prefsrc in default VRF removed"
2047 echo " src address and nexthop device in different VRF"
2049 $IP addr del dev dummy4 2001:db8:101::13/64
2050 $IP -6 route show vrf red | grep -q "src 2001:db8:101::13 "
2051 log_test $? 0 "Prefsrc not removed from VRF when nexthop dev in diff VRF"
2052 $IP -6 route show | grep -q "src 2001:db8:101::13 "
2053 log_test $? 0 "Prefsrc not removed in default VRF"
2055 $IP addr add dev dummy4 2001:db8:101::13/64
2056 $IP addr del dev dummy1 2001:db8:101::13/64
2057 $IP -6 route show vrf red | grep -q "src 2001:db8:101::13 "
2058 log_test $? 1 "Prefsrc removed from VRF when nexthop dev in diff VRF"
2059 $IP -6 route show | grep -q "src 2001:db8:101::13 "
2060 log_test $? 1 "Prefsrc removed in default VRF"
2064 $IP addr del dev dummy1 2001:db8:101::15/64
2065 $IP -6 route show | grep -q "src 2001:db8:101::15"
2066 log_test $? 1 "Prefsrc removed from default VRF when source address deleted"
2068 echo " Link local source route"
2069 $IP addr del dev dummy1 fe80::1/128
2070 $IP -6 route show | grep -q "2001:db8:116::/64 dev dummy2 src fe80::1"
2071 log_test $? 0 "Prefsrc not removed when delete ll addr from other dev"
2072 $IP addr del dev dummy2 fe80::1/128
2073 $IP -6 route show | grep -q "2001:db8:116::/64 dev dummy2 src fe80::1"
2074 log_test $? 1 "Prefsrc removed when delete ll addr"
2075 $IP -6 route show | grep -q "2001:db8:117::/64 dev dummy3 src fe80::1"
2076 log_test $? 0 "Prefsrc not removed when delete ll addr from other dev"
2077 $IP addr add dev dummy1 fe80::1/128
2078 $IP addr del dev dummy3 fe80::1/128
2079 $IP -6 route show | grep -q "2001:db8:117::/64 dev dummy3 src fe80::1"
2080 log_test $? 1 "Prefsrc removed even ll addr still exist on other dev"
2082 for i in $(seq 6); do
2083 $IP li del dummy${i}
2088 ipv4_route_v6_gw_test()
2093 echo "IPv4 route with IPv6 gateway tests"
2101 run_cmd "$IP ro add 172.16.104.0/24 via inet6 2001:db8:101::2"
2103 log_test $rc 0 "Single path route with IPv6 gateway"
2104 if [ $rc -eq 0 ]; then
2105 check_route "172.16.104.0/24 via inet6 2001:db8:101::2 dev veth1"
2108 run_cmd "ip netns exec ns1 ping -w1 -c1 172.16.104.1"
2109 log_test $rc 0 "Single path route with IPv6 gateway - ping"
2111 run_cmd "$IP ro del 172.16.104.0/24 via inet6 2001:db8:101::2"
2113 log_test $rc 0 "Single path route delete"
2114 if [ $rc -eq 0 ]; then
2115 check_route "172.16.112.0/24"
2119 # multipath - v6 then v4
2121 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"
2123 log_test $rc 0 "Multipath route add - v6 nexthop then v4"
2124 if [ $rc -eq 0 ]; then
2125 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"
2128 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"
2129 log_test $? 2 " Multipath route delete - nexthops in wrong order"
2131 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"
2132 log_test $? 0 " Multipath route delete exact match"
2135 # multipath - v4 then v6
2137 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"
2139 log_test $rc 0 "Multipath route add - v4 nexthop then v6"
2140 if [ $rc -eq 0 ]; then
2141 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"
2144 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"
2145 log_test $? 2 " Multipath route delete - nexthops in wrong order"
2147 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"
2148 log_test $? 0 " Multipath route delete exact match"
2155 if [ ! -x "$(command -v socat)" ]; then
2156 echo "socat command not found. Skipping test"
2165 iptables -t mangle -L OUTPUT &> /dev/null
2166 if [ $? -ne 0 ]; then
2167 echo "iptables configuration not supported. Skipping test"
2176 ip6tables -t mangle -L OUTPUT &> /dev/null
2177 if [ $? -ne 0 ]; then
2178 echo "ip6tables configuration not supported. Skipping test"
2190 echo "IPv4 mangling tests"
2192 socat_check || return 1
2193 iptables_check || return 1
2198 local tmp_file=$(mktemp)
2199 ip netns exec ns2 socat UDP4-LISTEN:54321,fork $tmp_file &
2201 # Add a FIB rule and a route that will direct our connection to the
2203 $IP rule add pref 100 ipproto udp sport 12345 dport 54321 table 123
2204 $IP route add table 123 172.16.101.0/24 dev veth1
2206 # Add an unreachable route to the main table that will block our
2207 # connection in case the FIB rule is not hit.
2208 $IP route add unreachable 172.16.101.2/32
2210 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
2211 log_test $? 0 " Connection with correct parameters"
2213 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=11111"
2214 log_test $? 1 " Connection with incorrect parameters"
2216 # Add a mangling rule and make sure connection is still successful.
2217 $NS_EXEC iptables -t mangle -A OUTPUT -j MARK --set-mark 1
2219 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
2220 log_test $? 0 " Connection with correct parameters - mangling"
2222 # Delete the mangling rule and make sure connection is still
2224 $NS_EXEC iptables -t mangle -D OUTPUT -j MARK --set-mark 1
2226 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
2227 log_test $? 0 " Connection with correct parameters - no mangling"
2229 # Verify connections were indeed successful on server side.
2230 [[ $(cat $tmp_file | wc -l) -eq 3 ]]
2231 log_test $? 0 " Connection check - server side"
2233 $IP route del unreachable 172.16.101.2/32
2234 $IP route del table 123 172.16.101.0/24 dev veth1
2235 $IP rule del pref 100
2237 { kill %% && wait %%; } 2>/dev/null
2248 echo "IPv6 mangling tests"
2250 socat_check || return 1
2251 ip6tables_check || return 1
2256 local tmp_file=$(mktemp)
2257 ip netns exec ns2 socat UDP6-LISTEN:54321,fork $tmp_file &
2259 # Add a FIB rule and a route that will direct our connection to the
2261 $IP -6 rule add pref 100 ipproto udp sport 12345 dport 54321 table 123
2262 $IP -6 route add table 123 2001:db8:101::/64 dev veth1
2264 # Add an unreachable route to the main table that will block our
2265 # connection in case the FIB rule is not hit.
2266 $IP -6 route add unreachable 2001:db8:101::2/128
2268 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
2269 log_test $? 0 " Connection with correct parameters"
2271 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=11111"
2272 log_test $? 1 " Connection with incorrect parameters"
2274 # Add a mangling rule and make sure connection is still successful.
2275 $NS_EXEC ip6tables -t mangle -A OUTPUT -j MARK --set-mark 1
2277 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
2278 log_test $? 0 " Connection with correct parameters - mangling"
2280 # Delete the mangling rule and make sure connection is still
2282 $NS_EXEC ip6tables -t mangle -D OUTPUT -j MARK --set-mark 1
2284 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
2285 log_test $? 0 " Connection with correct parameters - no mangling"
2287 # Verify connections were indeed successful on server side.
2288 [[ $(cat $tmp_file | wc -l) -eq 3 ]]
2289 log_test $? 0 " Connection check - server side"
2291 $IP -6 route del unreachable 2001:db8:101::2/128
2292 $IP -6 route del table 123 2001:db8:101::/64 dev veth1
2293 $IP -6 rule del pref 100
2295 { kill %% && wait %%; } 2>/dev/null
2301 ip_neigh_get_check()
2303 ip neigh help 2>&1 | grep -q 'ip neigh get'
2304 if [ $? -ne 0 ]; then
2305 echo "iproute2 command does not support neigh get. Skipping test"
2312 ipv4_bcast_neigh_test()
2317 echo "IPv4 broadcast neighbour tests"
2319 ip_neigh_get_check || return 1
2324 run_cmd "$IP neigh add 192.0.2.111 lladdr 00:11:22:33:44:55 nud perm dev dummy0"
2325 run_cmd "$IP neigh add 192.0.2.255 lladdr 00:11:22:33:44:55 nud perm dev dummy0"
2327 run_cmd "$IP neigh get 192.0.2.111 dev dummy0"
2328 run_cmd "$IP neigh get 192.0.2.255 dev dummy0"
2330 run_cmd "$IP address add 192.0.2.1/24 broadcast 192.0.2.111 dev dummy0"
2332 run_cmd "$IP neigh add 203.0.113.111 nud failed dev dummy0"
2333 run_cmd "$IP neigh add 203.0.113.255 nud failed dev dummy0"
2335 run_cmd "$IP neigh get 203.0.113.111 dev dummy0"
2336 run_cmd "$IP neigh get 203.0.113.255 dev dummy0"
2338 run_cmd "$IP address add 203.0.113.1/24 broadcast 203.0.113.111 dev dummy0"
2341 run_cmd "$IP neigh get 192.0.2.111 dev dummy0"
2342 log_test $? 0 "Resolved neighbour for broadcast address"
2344 run_cmd "$IP neigh get 192.0.2.255 dev dummy0"
2345 log_test $? 0 "Resolved neighbour for network broadcast address"
2347 run_cmd "$IP neigh get 203.0.113.111 dev dummy0"
2348 log_test $? 2 "Unresolved neighbour for broadcast address"
2350 run_cmd "$IP neigh get 203.0.113.255 dev dummy0"
2351 log_test $? 2 "Unresolved neighbour for network broadcast address"
2358 if [ ! -x "$(command -v mausezahn)" ]; then
2359 echo "mausezahn command not found. Skipping test"
2363 if [ ! -x "$(command -v jq)" ]; then
2364 echo "jq command not found. Skipping test"
2368 if [ ! -x "$(command -v bc)" ]; then
2369 echo "bc command not found. Skipping test"
2373 if [ ! -x "$(command -v perf)" ]; then
2374 echo "perf command not found. Skipping test"
2378 perf list fib:* | grep -q fib_table_lookup
2379 if [ $? -ne 0 ]; then
2380 echo "IPv4 FIB tracepoint not found. Skipping test"
2384 perf list fib6:* | grep -q fib6_table_lookup
2385 if [ $? -ne 0 ]; then
2386 echo "IPv6 FIB tracepoint not found. Skipping test"
2398 local stat=$1; shift
2400 ip -n $ns -j -s link show dev $dev \
2401 | jq '.[]["stats64"]["'$dir'"]["'$stat'"]'
2406 local file=$1; shift
2407 local expected=$1; shift
2409 local count=$(tail -n 1 $file | jq '.["counter-value"] | tonumber | floor')
2410 local ratio=$(echo "scale=2; $count / $expected" | bc -l)
2411 local res=$(echo "$ratio >= 0.95" | bc)
2413 log_test $? 0 "Multipath route hit ratio ($ratio)"
2416 ipv4_mpath_list_test()
2419 echo "IPv4 multipath list receive tests"
2421 mpath_dep_check || return 1
2426 run_cmd "ip netns exec ns1 ethtool -K veth1 tcp-segmentation-offload off"
2428 run_cmd "ip netns exec ns2 bash -c \"echo 20000 > /sys/class/net/veth2/gro_flush_timeout\""
2429 run_cmd "ip netns exec ns2 bash -c \"echo 1 > /sys/class/net/veth2/napi_defer_hard_irqs\""
2430 run_cmd "ip netns exec ns2 ethtool -K veth2 generic-receive-offload on"
2431 run_cmd "ip -n ns2 link add name nh1 up type dummy"
2432 run_cmd "ip -n ns2 link add name nh2 up type dummy"
2433 run_cmd "ip -n ns2 address add 172.16.201.1/24 dev nh1"
2434 run_cmd "ip -n ns2 address add 172.16.202.1/24 dev nh2"
2435 run_cmd "ip -n ns2 neigh add 172.16.201.2 lladdr 00:11:22:33:44:55 nud perm dev nh1"
2436 run_cmd "ip -n ns2 neigh add 172.16.202.2 lladdr 00:aa:bb:cc:dd:ee nud perm dev nh2"
2437 run_cmd "ip -n ns2 route add 203.0.113.0/24
2438 nexthop via 172.16.201.2 nexthop via 172.16.202.2"
2439 run_cmd "ip netns exec ns2 sysctl -qw net.ipv4.fib_multipath_hash_policy=1"
2442 local dmac=$(ip -n ns2 -j link show dev veth2 | jq -r '.[]["address"]')
2443 local tmp_file=$(mktemp)
2444 local cmd="ip netns exec ns1 mausezahn veth1 -a own -b $dmac
2445 -A 172.16.101.1 -B 203.0.113.1 -t udp 'sp=12345,dp=0-65535' -q"
2447 # Packets forwarded in a list using a multipath route must not reuse a
2448 # cached result so that a flow always hits the same nexthop. In other
2449 # words, the FIB lookup tracepoint needs to be triggered for every
2451 local t0_rx_pkts=$(link_stats_get ns2 veth2 rx packets)
2452 run_cmd "perf stat -e fib:fib_table_lookup --filter 'err == 0' -j -o $tmp_file -- $cmd"
2453 local t1_rx_pkts=$(link_stats_get ns2 veth2 rx packets)
2454 local diff=$(echo $t1_rx_pkts - $t0_rx_pkts | bc -l)
2455 list_rcv_eval $tmp_file $diff
2461 ipv6_mpath_list_test()
2464 echo "IPv6 multipath list receive tests"
2466 mpath_dep_check || return 1
2471 run_cmd "ip netns exec ns1 ethtool -K veth1 tcp-segmentation-offload off"
2473 run_cmd "ip netns exec ns2 bash -c \"echo 20000 > /sys/class/net/veth2/gro_flush_timeout\""
2474 run_cmd "ip netns exec ns2 bash -c \"echo 1 > /sys/class/net/veth2/napi_defer_hard_irqs\""
2475 run_cmd "ip netns exec ns2 ethtool -K veth2 generic-receive-offload on"
2476 run_cmd "ip -n ns2 link add name nh1 up type dummy"
2477 run_cmd "ip -n ns2 link add name nh2 up type dummy"
2478 run_cmd "ip -n ns2 -6 address add 2001:db8:201::1/64 dev nh1"
2479 run_cmd "ip -n ns2 -6 address add 2001:db8:202::1/64 dev nh2"
2480 run_cmd "ip -n ns2 -6 neigh add 2001:db8:201::2 lladdr 00:11:22:33:44:55 nud perm dev nh1"
2481 run_cmd "ip -n ns2 -6 neigh add 2001:db8:202::2 lladdr 00:aa:bb:cc:dd:ee nud perm dev nh2"
2482 run_cmd "ip -n ns2 -6 route add 2001:db8:301::/64
2483 nexthop via 2001:db8:201::2 nexthop via 2001:db8:202::2"
2484 run_cmd "ip netns exec ns2 sysctl -qw net.ipv6.fib_multipath_hash_policy=1"
2487 local dmac=$(ip -n ns2 -j link show dev veth2 | jq -r '.[]["address"]')
2488 local tmp_file=$(mktemp)
2489 local cmd="ip netns exec ns1 mausezahn -6 veth1 -a own -b $dmac
2490 -A 2001:db8:101::1 -B 2001:db8:301::1 -t udp 'sp=12345,dp=0-65535' -q"
2492 # Packets forwarded in a list using a multipath route must not reuse a
2493 # cached result so that a flow always hits the same nexthop. In other
2494 # words, the FIB lookup tracepoint needs to be triggered for every
2496 local t0_rx_pkts=$(link_stats_get ns2 veth2 rx packets)
2497 run_cmd "perf stat -e fib6:fib6_table_lookup --filter 'err == 0' -j -o $tmp_file -- $cmd"
2498 local t1_rx_pkts=$(link_stats_get ns2 veth2 rx packets)
2499 local diff=$(echo $t1_rx_pkts - $t0_rx_pkts | bc -l)
2500 list_rcv_eval $tmp_file $diff
2506 ################################################################################
2512 usage: ${0##*/} OPTS
2514 -t <test> Test(s) to run (default: all)
2517 -P Pause after each test before cleanup
2518 -v verbose mode (show commands and output)
2522 ################################################################################
2527 while getopts :t:pPhv o
2531 p) PAUSE_ON_FAIL=yes;;
2533 v) VERBOSE=$(($VERBOSE + 1));;
2539 PEER_CMD="ip netns exec ${PEER_NS}"
2541 # make sure we don't pause twice
2542 [ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
2544 if [ "$(id -u)" -ne 0 ];then
2545 echo "SKIP: Need root privileges"
2549 if [ ! -x "$(command -v ip)" ]; then
2550 echo "SKIP: Could not run test without ip tool"
2554 ip route help 2>&1 | grep -q fibmatch
2555 if [ $? -ne 0 ]; then
2556 echo "SKIP: iproute2 too old, missing fibmatch"
2561 cleanup &> /dev/null
2566 fib_unreg_test|unregister) fib_unreg_test;;
2567 fib_down_test|down) fib_down_test;;
2568 fib_carrier_test|carrier) fib_carrier_test;;
2569 fib_rp_filter_test|rp_filter) fib_rp_filter_test;;
2570 fib_nexthop_test|nexthop) fib_nexthop_test;;
2571 fib_notify_test|ipv4_notify) fib_notify_test;;
2572 fib6_notify_test|ipv6_notify) fib6_notify_test;;
2573 fib_suppress_test|suppress) fib_suppress_test;;
2574 ipv6_route_test|ipv6_rt) ipv6_route_test;;
2575 ipv4_route_test|ipv4_rt) ipv4_route_test;;
2576 ipv6_addr_metric) ipv6_addr_metric_test;;
2577 ipv4_addr_metric) ipv4_addr_metric_test;;
2578 ipv4_del_addr) ipv4_del_addr_test;;
2579 ipv6_del_addr) ipv6_del_addr_test;;
2580 ipv6_route_metrics) ipv6_route_metrics_test;;
2581 ipv4_route_metrics) ipv4_route_metrics_test;;
2582 ipv4_route_v6_gw) ipv4_route_v6_gw_test;;
2583 ipv4_mangle) ipv4_mangle_test;;
2584 ipv6_mangle) ipv6_mangle_test;;
2585 ipv4_bcast_neigh) ipv4_bcast_neigh_test;;
2586 fib6_gc_test|ipv6_gc) fib6_gc_test;;
2587 ipv4_mpath_list) ipv4_mpath_list_test;;
2588 ipv6_mpath_list) ipv6_mpath_list_test;;
2590 help) echo "Test names: $TESTS"; exit 0;;
2594 if [ "$TESTS" != "none" ]; then
2595 printf "\nTests passed: %3d\n" ${nsuccess}
2596 printf "Tests failed: %3d\n" ${nfail}