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_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"
18 NS_EXEC="ip netns exec ns1"
20 which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
28 if [ ${rc} -eq ${expected} ]; then
29 printf " TEST: %-60s [ OK ]\n" "${msg}"
30 nsuccess=$((nsuccess+1))
34 printf " TEST: %-60s [FAIL]\n" "${msg}"
35 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
37 echo "hit enter to continue, 'q' to quit"
39 [ "$a" = "q" ] && exit 1
43 if [ "${PAUSE}" = "yes" ]; then
45 echo "hit enter to continue, 'q' to quit"
47 [ "$a" = "q" ] && exit 1
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
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
70 $IP link del dev dummy0 &> /dev/null
72 ip netns del ns2 &> /dev/null
80 addr=$($IP -6 -br addr show dev ${dev} | \
82 for (i = 3; i <= NF; ++i) {
90 [ -z "$addr" ] && return 1
97 fib_unreg_unicast_test()
100 echo "Single path route test"
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"
111 $IP link del dev dummy0
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"
123 fib_unreg_multipath_test()
127 echo "Multipath route test"
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
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
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"
152 $IP link del dev dummy0
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"
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"
164 $IP link del dev dummy1
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"
176 fib_unreg_unicast_test
177 fib_unreg_multipath_test
180 fib_down_unicast_test()
183 echo "Single path, admin down"
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"
194 $IP link set dev dummy0 down
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"
206 fib_down_multipath_test_do()
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"
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"
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"
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"
240 fib_down_multipath_test()
243 echo "Admin down multipath"
248 $IP link add dummy1 type dummy
249 $IP link set dev dummy1 up
251 $IP address add 192.0.2.1/24 dev dummy1
252 $IP -6 address add 2001:db8:2::1/64 dev dummy1
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
262 echo " Verify start point"
263 $IP route get fibmatch 203.0.113.1 &> /dev/null
264 log_test $? 0 "IPv4 fibmatch"
266 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null
267 log_test $? 0 "IPv6 fibmatch"
270 $IP link set dev dummy0 down
273 echo " One device down, one up"
274 fib_down_multipath_test_do "dummy0" "dummy1"
277 $IP link set dev dummy0 up
278 $IP link set dev dummy1 down
281 echo " Other device down and up"
282 fib_down_multipath_test_do "dummy1" "dummy0"
285 $IP link set dev dummy0 down
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"
294 $IP link del dev dummy1
300 fib_down_unicast_test
301 fib_down_multipath_test
304 # Local routes should not be affected when carrier changes.
305 fib_carrier_local_test()
308 echo "Local carrier tests - single path"
313 $IP link set dev dummy0 carrier on
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"
322 $IP route get fibmatch 198.51.100.1 | \
324 log_test $? 1 "IPv4 - no linkdown flag"
325 $IP -6 route get fibmatch 2001:db8:1::1 | \
327 log_test $? 1 "IPv6 - no linkdown flag"
330 $IP link set dev dummy0 carrier off
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"
340 $IP route get fibmatch 198.51.100.1 | \
342 log_test $? 1 "IPv4 - linkdown flag set"
343 $IP -6 route get fibmatch 2001:db8:1::1 | \
345 log_test $? 1 "IPv6 - linkdown flag set"
348 $IP address add 192.0.2.1/24 dev dummy0
349 $IP -6 address add 2001:db8:2::1/64 dev dummy0
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"
358 $IP route get fibmatch 192.0.2.1 | \
360 log_test $? 1 "IPv4 linkdown flag set"
361 $IP -6 route get fibmatch 2001:db8:2::1 | \
363 log_test $? 1 "IPv6 linkdown flag set"
368 fib_carrier_unicast_test()
373 echo "Single path route carrier test"
378 $IP link set dev dummy0 carrier on
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"
387 $IP route get fibmatch 198.51.100.2 | \
389 log_test $? 1 "IPv4 no linkdown flag"
390 $IP -6 route get fibmatch 2001:db8:1::2 | \
392 log_test $? 1 "IPv6 no linkdown flag"
395 $IP link set dev dummy0 carrier off
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"
405 $IP route get fibmatch 198.51.100.2 | \
407 log_test $? 0 "IPv4 linkdown flag set"
408 $IP -6 route get fibmatch 2001:db8:1::2 | \
410 log_test $? 0 "IPv6 linkdown flag set"
413 $IP address add 192.0.2.1/24 dev dummy0
414 $IP -6 address add 2001:db8:2::1/64 dev dummy0
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"
423 $IP route get fibmatch 192.0.2.2 | \
425 log_test $? 0 "IPv4 linkdown flag set"
426 $IP -6 route get fibmatch 2001:db8:2::2 | \
428 log_test $? 0 "IPv6 linkdown flag set"
435 fib_carrier_local_test
436 fib_carrier_unicast_test
442 echo "IPv4 rp_filter tests"
448 ip netns set ns2 auto
450 ip -netns ns2 link set dev lo up
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
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
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
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
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
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
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
500 run_cmd "ip netns exec ns2 ping -w1 -c1 192.0.2.1"
501 log_test $? 0 "rp_filter passes local packets"
503 run_cmd "ip netns exec ns2 ping -w1 -c1 127.0.0.1"
504 log_test $? 0 "rp_filter passes loopback packets"
509 ################################################################################
510 # Tests on nexthop spec
512 # run 'ip route add' with given spec
523 [ "$vrf" = "-" ] && vrf="default"
524 [ -n "$gw" ] && gw="via $gw"
525 [ -n "$dev" ] && dev="dev $dev"
527 cmd="$IP route add vrf $vrf $pfx $gw $dev"
528 if [ "$VERBOSE" = "1" ]; then
529 printf "\n COMMAND: $cmd\n"
532 out=$(eval $cmd 2>&1)
534 if [ "$VERBOSE" = "1" -a -n "$out" ]; then
537 log_test $rc $erc "$desc"
543 echo "IPv4 nexthop tests"
545 echo "<<< write me >>>"
550 local lldummy=$(get_linklocal dummy0)
551 local llv1=$(get_linklocal dummy0)
553 if [ -z "$lldummy" ]; then
554 echo "Failed to get linklocal address for dummy0"
557 if [ -z "$llv1" ]; then
558 echo "Failed to get linklocal address for veth1"
563 echo "IPv6 nexthop tests"
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"
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
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"
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"
592 add_rt "Redirect to VRF lookup" 0 \
593 - 2001:db8:111::/64 "" "red"
595 add_rt "VRF route, gateway can be local address in default VRF" 0 \
596 red 2001:db8:112::/64 2001:db8:51::1
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"
606 # dummy0 - 198.51.100.1/24 2001:db8:1::1/64
607 # veth0 - 192.0.2.1/24 2001:db8:51::1/64
610 # dummy1 - 192.168.2.1/24 2001:db8:2::1/64
611 # veth1 - 192.0.2.2/24 2001:db8:51::2/64
613 # [ dummy0 veth0 ]--[ veth1 dummy1 ]
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
626 $IP link add red type vrf table 1
628 $IP -4 route add vrf red unreachable default metric 4278198272
629 $IP -6 route add vrf red unreachable default metric 4278198272
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
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
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
651 $IP link del dev dummy1
661 echo "FIB rule with suppress_prefixlength"
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
672 # If we got here without crashing, we're good.
673 log_test 0 0 "FIB rule suppress test"
678 ################################################################################
679 # Tests on route add and replace
685 local stderr="2>/dev/null"
687 if [ "$VERBOSE" = "1" ]; then
688 printf " COMMAND: $cmd\n"
692 out=$(eval $cmd $stderr)
694 if [ "$VERBOSE" = "1" -a -n "$out" ]; then
698 [ "$VERBOSE" = "1" ] && echo
709 [ "${out}" = "${expected}" ] && return 0
711 if [ -z "${out}" ]; then
712 if [ "$VERBOSE" = "1" ]; then
713 printf "\nNo route entry found\n"
715 printf " ${expected}\n"
720 # tricky way to convert output to 1-line without ip's
721 # messy '\'; this drops all extra white space
723 if [ "${out}" != "${expected}" ]; then
725 if [ "${VERBOSE}" = "1" ]; then
726 printf " Unexpected route entry. Have:\n"
728 printf " Expected:\n"
729 printf " ${expected}\n\n"
736 # add route for a prefix, flushing any existing routes first
737 # expected to be the first step of a test
744 if [ "$VERBOSE" = "1" ]; then
746 echo " ##################################################"
750 run_cmd "$IP -6 ro flush ${pfx}"
751 [ $? -ne 0 ] && exit 1
753 out=$($IP -6 ro ls match ${pfx})
754 if [ -n "$out" ]; then
755 echo "Failed to flush routes for prefix used for tests."
759 run_cmd "$IP -6 ro add ${pfx} ${nh}"
760 if [ $? -ne 0 ]; then
761 echo "Failed to add initial route for test."
766 # add initial route - used in replace route tests
769 add_route6 "2001:db8:104::/64" "$1"
782 out=$($IP -6 ro ls match ${pfx} | sed -e 's/ pref medium//')
783 check_expected "${out}" "${expected}"
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
801 [ "${VERBOSE}" = "1" ] && set -x
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
810 $IP li add veth1 type veth peer name veth2
811 $IP li add veth3 type veth peer name veth4
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
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
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
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
836 # assumption is that basic add of a single path route works
837 # otherwise just adding an address on an interface is broken
843 echo "IPv6 route add / append tests"
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"
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"
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"
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"
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"
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"
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"
880 if [ $rc -eq 0 ]; then
881 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::3 metric 256"
884 log_test $rc 0 "Route add with different metrics"
886 run_cmd "$IP -6 ro del 2001:db8:104::/64 metric 512"
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"
892 log_test $rc 0 "Route delete with metric"
895 ipv6_rt_replace_single()
897 # single path with single path
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"
904 # single path with multipath
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"
911 # single path with single path using MULTIPATH attribute
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"
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"
926 check_route6 "2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024"
927 log_test $? 0 "Invalid nexthop"
930 # replace non-existent route
931 # - note use of change versus replace since ip adds NLM_F_CREATE
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"
938 ipv6_rt_replace_mpath()
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"
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"
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"
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"
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"
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"
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"
985 echo "IPv6 route replace tests"
987 ipv6_rt_replace_single
988 ipv6_rt_replace_mpath
1001 ip_addr_metric_check()
1003 ip addr help 2>&1 | grep -q metric
1004 if [ $? -ne 0 ]; then
1005 echo "iproute2 command does not support metric for addresses. Skipping test"
1012 ipv6_addr_metric_test()
1017 echo "IPv6 prefix route tests"
1019 ip_addr_metric_check || return 1
1024 $IP li add dummy1 type dummy
1025 $IP li add dummy2 type dummy
1026 $IP li set dummy1 up
1027 $IP li set dummy2 up
1029 # default entry is metric 256
1030 run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64"
1031 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64"
1034 check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 256 2001:db8:104::/64 dev dummy2 proto kernel metric 256"
1035 log_test $? 0 "Default metric"
1038 run_cmd "$IP -6 addr flush dev dummy1"
1039 run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64 metric 257"
1042 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 256 2001:db8:104::/64 dev dummy1 proto kernel metric 257"
1043 log_test $? 0 "User specified metric on first device"
1046 run_cmd "$IP -6 addr flush dev dummy2"
1047 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64 metric 258"
1050 check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 257 2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1051 log_test $? 0 "User specified metric on second device"
1053 run_cmd "$IP -6 addr del dev dummy1 2001:db8:104::1/64 metric 257"
1055 if [ $rc -eq 0 ]; then
1056 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 258"
1059 log_test $rc 0 "Delete of address on first device"
1061 run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::2/64 metric 259"
1063 if [ $rc -eq 0 ]; then
1064 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1067 log_test $rc 0 "Modify metric of address"
1069 # verify prefix route removed on down
1070 run_cmd "ip netns exec ns1 sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1"
1071 run_cmd "$IP li set dev dummy2 down"
1073 if [ $rc -eq 0 ]; then
1074 out=$($IP -6 ro ls match 2001:db8:104::/64)
1075 check_expected "${out}" ""
1078 log_test $rc 0 "Prefix route removed on link down"
1080 # verify prefix route re-inserted with assigned metric
1081 run_cmd "$IP li set dev dummy2 up"
1083 if [ $rc -eq 0 ]; then
1084 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259"
1087 log_test $rc 0 "Prefix route with metric on link up"
1089 # verify peer metric added correctly
1091 run_cmd "$IP -6 addr flush dev dummy2"
1092 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::1 peer 2001:db8:104::2 metric 260"
1095 check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 260"
1096 log_test $? 0 "Set metric with peer route on local side"
1097 check_route6 "2001:db8:104::2 dev dummy2 proto kernel metric 260"
1098 log_test $? 0 "Set metric with peer route on peer side"
1101 run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::1 peer 2001:db8:104::3 metric 261"
1104 check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 261"
1105 log_test $? 0 "Modify metric and peer address on local side"
1106 check_route6 "2001:db8:104::3 dev dummy2 proto kernel metric 261"
1107 log_test $? 0 "Modify metric and peer address on peer side"
1114 ipv6_route_metrics_test()
1119 echo "IPv6 routes with metrics"
1124 # single path with metrics
1126 run_cmd "$IP -6 ro add 2001:db8:111::/64 via 2001:db8:101::2 mtu 1400"
1128 if [ $rc -eq 0 ]; then
1129 check_route6 "2001:db8:111::/64 via 2001:db8:101::2 dev veth1 metric 1024 mtu 1400"
1132 log_test $rc 0 "Single path route with mtu metric"
1136 # multipath via separate routes with metrics
1138 run_cmd "$IP -6 ro add 2001:db8:112::/64 via 2001:db8:101::2 mtu 1400"
1139 run_cmd "$IP -6 ro append 2001:db8:112::/64 via 2001:db8:103::2"
1141 if [ $rc -eq 0 ]; then
1142 check_route6 "2001:db8:112::/64 metric 1024 mtu 1400 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1145 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on first"
1147 # second route is coalesced to first to make a multipath route.
1148 # MTU of the second path is hidden from display!
1149 run_cmd "$IP -6 ro add 2001:db8:113::/64 via 2001:db8:101::2"
1150 run_cmd "$IP -6 ro append 2001:db8:113::/64 via 2001:db8:103::2 mtu 1400"
1152 if [ $rc -eq 0 ]; then
1153 check_route6 "2001:db8:113::/64 metric 1024 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1156 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on 2nd"
1158 run_cmd "$IP -6 ro del 2001:db8:113::/64 via 2001:db8:101::2"
1159 if [ $? -eq 0 ]; then
1160 check_route6 "2001:db8:113::/64 via 2001:db8:103::2 dev veth3 metric 1024 mtu 1400"
1161 log_test $? 0 " MTU of second leg"
1165 # multipath with metrics
1167 run_cmd "$IP -6 ro add 2001:db8:115::/64 mtu 1400 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
1169 if [ $rc -eq 0 ]; then
1170 check_route6 "2001:db8:115::/64 metric 1024 mtu 1400 nexthop via 2001:db8:101::2 dev veth1 weight 1 nexthop via 2001:db8:103::2 dev veth3 weight 1"
1173 log_test $rc 0 "Multipath route with mtu metric"
1175 $IP -6 ro add 2001:db8:104::/64 via 2001:db8:101::2 mtu 1300
1176 run_cmd "ip netns exec ns1 ${ping6} -w1 -c1 -s 1500 2001:db8:104::1"
1177 log_test $? 0 "Using route with mtu metric"
1179 run_cmd "$IP -6 ro add 2001:db8:114::/64 via 2001:db8:101::2 congctl lock foo"
1180 log_test $? 2 "Invalid metric (fails metric_convert)"
1185 # add route for a prefix, flushing any existing routes first
1186 # expected to be the first step of a test
1193 if [ "$VERBOSE" = "1" ]; then
1195 echo " ##################################################"
1199 run_cmd "$IP ro flush ${pfx}"
1200 [ $? -ne 0 ] && exit 1
1202 out=$($IP ro ls match ${pfx})
1203 if [ -n "$out" ]; then
1204 echo "Failed to flush routes for prefix used for tests."
1208 run_cmd "$IP ro add ${pfx} ${nh}"
1209 if [ $? -ne 0 ]; then
1210 echo "Failed to add initial route for test."
1215 # add initial route - used in replace route tests
1218 add_route "172.16.104.0/24" "$1"
1229 [ "${pfx}" = "unreachable" ] && pfx=$2
1231 out=$($IP ro ls match ${pfx})
1232 check_expected "${out}" "${expected}"
1235 # assumption is that basic add of a single path route works
1236 # otherwise just adding an address on an interface is broken
1242 echo "IPv4 route add / append tests"
1244 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1245 add_route "172.16.104.0/24" "via 172.16.101.2"
1246 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2"
1247 log_test $? 2 "Attempt to add duplicate route - gw"
1249 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1250 add_route "172.16.104.0/24" "via 172.16.101.2"
1251 run_cmd "$IP ro add 172.16.104.0/24 dev veth3"
1252 log_test $? 2 "Attempt to add duplicate route - dev only"
1254 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL
1255 add_route "172.16.104.0/24" "via 172.16.101.2"
1256 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1257 log_test $? 2 "Attempt to add duplicate route - reject route"
1259 # iproute2 prepend only sets NLM_F_CREATE
1260 # - adds a new route; does NOT convert existing route to ECMP
1261 add_route "172.16.104.0/24" "via 172.16.101.2"
1262 run_cmd "$IP ro prepend 172.16.104.0/24 via 172.16.103.2"
1263 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3 172.16.104.0/24 via 172.16.101.2 dev veth1"
1264 log_test $? 0 "Add new nexthop for existing prefix"
1266 # route append with same prefix adds a new route
1267 # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND
1268 add_route "172.16.104.0/24" "via 172.16.101.2"
1269 run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1270 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 via 172.16.103.2 dev veth3"
1271 log_test $? 0 "Append nexthop to existing route - gw"
1273 add_route "172.16.104.0/24" "via 172.16.101.2"
1274 run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1275 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 dev veth3 scope link"
1276 log_test $? 0 "Append nexthop to existing route - dev only"
1278 add_route "172.16.104.0/24" "via 172.16.101.2"
1279 run_cmd "$IP ro append unreachable 172.16.104.0/24"
1280 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 unreachable 172.16.104.0/24"
1281 log_test $? 0 "Append nexthop to existing route - reject route"
1283 run_cmd "$IP ro flush 172.16.104.0/24"
1284 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1285 run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2"
1286 check_route "unreachable 172.16.104.0/24 172.16.104.0/24 via 172.16.103.2 dev veth3"
1287 log_test $? 0 "Append nexthop to existing reject route - gw"
1289 run_cmd "$IP ro flush 172.16.104.0/24"
1290 run_cmd "$IP ro add unreachable 172.16.104.0/24"
1291 run_cmd "$IP ro append 172.16.104.0/24 dev veth3"
1292 check_route "unreachable 172.16.104.0/24 172.16.104.0/24 dev veth3 scope link"
1293 log_test $? 0 "Append nexthop to existing reject route - dev only"
1295 # insert mpath directly
1296 add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1297 check_route "172.16.104.0/24 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1298 log_test $? 0 "add multipath route"
1300 add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1301 run_cmd "$IP ro add 172.16.104.0/24 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1302 log_test $? 2 "Attempt to add duplicate multipath route"
1304 # insert of a second route without append but different metric
1305 add_route "172.16.104.0/24" "via 172.16.101.2"
1306 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2 metric 512"
1308 if [ $rc -eq 0 ]; then
1309 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.3 metric 256"
1312 log_test $rc 0 "Route add with different metrics"
1314 run_cmd "$IP ro del 172.16.104.0/24 metric 512"
1316 if [ $rc -eq 0 ]; then
1317 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 via 172.16.103.3 dev veth3 metric 256"
1320 log_test $rc 0 "Route delete with metric"
1323 ipv4_rt_replace_single()
1325 # single path with single path
1327 add_initial_route "via 172.16.101.2"
1328 run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.103.2"
1329 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1330 log_test $? 0 "Single path with single path"
1332 # single path with multipath
1334 add_initial_route "nexthop via 172.16.101.2"
1335 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.2"
1336 check_route "172.16.104.0/24 nexthop via 172.16.101.3 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1337 log_test $? 0 "Single path with multipath"
1339 # single path with reject
1341 add_initial_route "nexthop via 172.16.101.2"
1342 run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1343 check_route "unreachable 172.16.104.0/24"
1344 log_test $? 0 "Single path with reject route"
1346 # single path with single path using MULTIPATH attribute
1348 add_initial_route "via 172.16.101.2"
1349 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.103.2"
1350 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3"
1351 log_test $? 0 "Single path with single path via multipath attribute"
1353 # route replace fails - invalid nexthop
1354 add_initial_route "via 172.16.101.2"
1355 run_cmd "$IP ro replace 172.16.104.0/24 via 2001:db8:104::2"
1356 if [ $? -eq 0 ]; then
1357 # previous command is expected to fail so if it returns 0
1358 # that means the test failed.
1359 log_test 0 1 "Invalid nexthop"
1361 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1"
1362 log_test $? 0 "Invalid nexthop"
1365 # replace non-existent route
1366 # - note use of change versus replace since ip adds NLM_F_CREATE
1368 add_initial_route "via 172.16.101.2"
1369 run_cmd "$IP ro change 172.16.105.0/24 via 172.16.101.2"
1370 log_test $? 2 "Single path - replace of non-existent route"
1373 ipv4_rt_replace_mpath()
1375 # multipath with multipath
1376 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1377 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1378 check_route "172.16.104.0/24 nexthop via 172.16.101.3 dev veth1 weight 1 nexthop via 172.16.103.3 dev veth3 weight 1"
1379 log_test $? 0 "Multipath with multipath"
1381 # multipath with single
1382 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1383 run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.101.3"
1384 check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
1385 log_test $? 0 "Multipath with single path"
1387 # multipath with single
1388 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1389 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3"
1390 check_route "172.16.104.0/24 via 172.16.101.3 dev veth1"
1391 log_test $? 0 "Multipath with single path via multipath attribute"
1393 # multipath with reject
1394 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1395 run_cmd "$IP ro replace unreachable 172.16.104.0/24"
1396 check_route "unreachable 172.16.104.0/24"
1397 log_test $? 0 "Multipath with reject route"
1399 # route replace fails - invalid nexthop 1
1400 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1401 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.111.3 nexthop via 172.16.103.3"
1402 check_route "172.16.104.0/24 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1403 log_test $? 0 "Multipath - invalid first nexthop"
1405 # route replace fails - invalid nexthop 2
1406 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1407 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.113.3"
1408 check_route "172.16.104.0/24 nexthop via 172.16.101.2 dev veth1 weight 1 nexthop via 172.16.103.2 dev veth3 weight 1"
1409 log_test $? 0 "Multipath - invalid second nexthop"
1411 # multipath non-existent route
1412 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1413 run_cmd "$IP ro change 172.16.105.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3"
1414 log_test $? 2 "Multipath - replace of non-existent route"
1420 echo "IPv4 route replace tests"
1422 ipv4_rt_replace_single
1423 ipv4_rt_replace_mpath
1426 # checks that cached input route on VRF port is deleted
1427 # when VRF is deleted
1428 ipv4_local_rt_cache()
1430 run_cmd "ip addr add 10.0.0.1/32 dev lo"
1431 run_cmd "ip netns add test-ns"
1432 run_cmd "ip link add veth-outside type veth peer name veth-inside"
1433 run_cmd "ip link add vrf-100 type vrf table 1100"
1434 run_cmd "ip link set veth-outside master vrf-100"
1435 run_cmd "ip link set veth-inside netns test-ns"
1436 run_cmd "ip link set veth-outside up"
1437 run_cmd "ip link set vrf-100 up"
1438 run_cmd "ip route add 10.1.1.1/32 dev veth-outside table 1100"
1439 run_cmd "ip netns exec test-ns ip link set veth-inside up"
1440 run_cmd "ip netns exec test-ns ip addr add 10.1.1.1/32 dev veth-inside"
1441 run_cmd "ip netns exec test-ns ip route add 10.0.0.1/32 dev veth-inside"
1442 run_cmd "ip netns exec test-ns ip route add default via 10.0.0.1"
1443 run_cmd "ip netns exec test-ns ping 10.0.0.1 -c 1 -i 1"
1444 run_cmd "ip link delete vrf-100"
1446 # if we do not hang test is a success
1447 log_test $? 0 "Cached route removed from VRF port device"
1461 ipv4_addr_metric_test()
1466 echo "IPv4 prefix route tests"
1468 ip_addr_metric_check || return 1
1473 $IP li add dummy1 type dummy
1474 $IP li add dummy2 type dummy
1475 $IP li set dummy1 up
1476 $IP li set dummy2 up
1478 # default entry is metric 256
1479 run_cmd "$IP addr add dev dummy1 172.16.104.1/24"
1480 run_cmd "$IP addr add dev dummy2 172.16.104.2/24"
1483 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"
1484 log_test $? 0 "Default metric"
1487 run_cmd "$IP addr flush dev dummy1"
1488 run_cmd "$IP addr add dev dummy1 172.16.104.1/24 metric 257"
1491 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"
1492 log_test $? 0 "User specified metric on first device"
1495 run_cmd "$IP addr flush dev dummy2"
1496 run_cmd "$IP addr add dev dummy2 172.16.104.2/24 metric 258"
1499 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"
1500 log_test $? 0 "User specified metric on second device"
1502 run_cmd "$IP addr del dev dummy1 172.16.104.1/24 metric 257"
1504 if [ $rc -eq 0 ]; then
1505 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258"
1508 log_test $rc 0 "Delete of address on first device"
1510 run_cmd "$IP addr change dev dummy2 172.16.104.2/24 metric 259"
1512 if [ $rc -eq 0 ]; then
1513 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1516 log_test $rc 0 "Modify metric of address"
1518 # verify prefix route removed on down
1519 run_cmd "$IP li set dev dummy2 down"
1521 if [ $rc -eq 0 ]; then
1522 out=$($IP ro ls match 172.16.104.0/24)
1523 check_expected "${out}" ""
1526 log_test $rc 0 "Prefix route removed on link down"
1528 # verify prefix route re-inserted with assigned metric
1529 run_cmd "$IP li set dev dummy2 up"
1531 if [ $rc -eq 0 ]; then
1532 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259"
1535 log_test $rc 0 "Prefix route with metric on link up"
1537 # explicitly check for metric changes on edge scenarios
1538 run_cmd "$IP addr flush dev dummy2"
1539 run_cmd "$IP addr add dev dummy2 172.16.104.0/24 metric 259"
1540 run_cmd "$IP addr change dev dummy2 172.16.104.0/24 metric 260"
1542 if [ $rc -eq 0 ]; then
1543 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.0 metric 260"
1546 log_test $rc 0 "Modify metric of .0/24 address"
1548 run_cmd "$IP addr flush dev dummy2"
1549 run_cmd "$IP addr add dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 260"
1551 if [ $rc -eq 0 ]; then
1552 check_route "172.16.104.2 dev dummy2 proto kernel scope link src 172.16.104.1 metric 260"
1555 log_test $rc 0 "Set metric of address with peer route"
1557 run_cmd "$IP addr change dev dummy2 172.16.104.1/32 peer 172.16.104.3 metric 261"
1559 if [ $rc -eq 0 ]; then
1560 check_route "172.16.104.3 dev dummy2 proto kernel scope link src 172.16.104.1 metric 261"
1563 log_test $rc 0 "Modify metric and peer address for peer route"
1570 ipv4_route_metrics_test()
1575 echo "IPv4 route add / append tests"
1579 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 mtu 1400"
1581 if [ $rc -eq 0 ]; then
1582 check_route "172.16.111.0/24 via 172.16.101.2 dev veth1 mtu 1400"
1585 log_test $rc 0 "Single path route with mtu metric"
1588 run_cmd "$IP ro add 172.16.112.0/24 mtu 1400 nexthop via 172.16.101.2 nexthop via 172.16.103.2"
1590 if [ $rc -eq 0 ]; then
1591 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"
1594 log_test $rc 0 "Multipath route with mtu metric"
1596 $IP ro add 172.16.104.0/24 via 172.16.101.2 mtu 1300
1597 run_cmd "ip netns exec ns1 ping -w1 -c1 -s 1500 172.16.104.1"
1598 log_test $? 0 "Using route with mtu metric"
1600 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 congctl lock foo"
1601 log_test $? 2 "Invalid metric (fails metric_convert)"
1606 ipv4_del_addr_test()
1609 echo "IPv4 delete address route tests"
1614 $IP li add dummy1 type dummy
1615 $IP li set dummy1 up
1616 $IP li add dummy2 type dummy
1617 $IP li set dummy2 up
1618 $IP li add red type vrf table 1111
1620 $IP ro add vrf red unreachable default
1621 $IP li set dummy2 vrf red
1623 $IP addr add dev dummy1 172.16.104.1/24
1624 $IP addr add dev dummy1 172.16.104.11/24
1625 $IP addr add dev dummy1 172.16.104.12/24
1626 $IP addr add dev dummy2 172.16.104.1/24
1627 $IP addr add dev dummy2 172.16.104.11/24
1628 $IP addr add dev dummy2 172.16.104.12/24
1629 $IP route add 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1630 $IP route add 172.16.106.0/24 dev lo src 172.16.104.12
1631 $IP route add vrf red 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1632 $IP route add vrf red 172.16.106.0/24 dev lo src 172.16.104.12
1635 # removing address from device in vrf should only remove route from vrf table
1636 echo " Regular FIB info"
1638 $IP addr del dev dummy2 172.16.104.11/24
1639 $IP ro ls vrf red | grep -q 172.16.105.0/24
1640 log_test $? 1 "Route removed from VRF when source address deleted"
1642 $IP ro ls | grep -q 172.16.105.0/24
1643 log_test $? 0 "Route in default VRF not removed"
1645 $IP addr add dev dummy2 172.16.104.11/24
1646 $IP route add vrf red 172.16.105.0/24 via 172.16.104.2 src 172.16.104.11
1648 $IP addr del dev dummy1 172.16.104.11/24
1649 $IP ro ls | grep -q 172.16.105.0/24
1650 log_test $? 1 "Route removed in default VRF when source address deleted"
1652 $IP ro ls vrf red | grep -q 172.16.105.0/24
1653 log_test $? 0 "Route in VRF is not removed by address delete"
1655 # removing address from device in vrf should only remove route from vrf
1656 # table even when the associated fib info only differs in table ID
1657 echo " Identical FIB info with different table ID"
1659 $IP addr del dev dummy2 172.16.104.12/24
1660 $IP ro ls vrf red | grep -q 172.16.106.0/24
1661 log_test $? 1 "Route removed from VRF when source address deleted"
1663 $IP ro ls | grep -q 172.16.106.0/24
1664 log_test $? 0 "Route in default VRF not removed"
1666 $IP addr add dev dummy2 172.16.104.12/24
1667 $IP route add vrf red 172.16.106.0/24 dev lo src 172.16.104.12
1669 $IP addr del dev dummy1 172.16.104.12/24
1670 $IP ro ls | grep -q 172.16.106.0/24
1671 log_test $? 1 "Route removed in default VRF when source address deleted"
1673 $IP ro ls vrf red | grep -q 172.16.106.0/24
1674 log_test $? 0 "Route in VRF is not removed by address delete"
1682 ipv4_route_v6_gw_test()
1687 echo "IPv4 route with IPv6 gateway tests"
1695 run_cmd "$IP ro add 172.16.104.0/24 via inet6 2001:db8:101::2"
1697 log_test $rc 0 "Single path route with IPv6 gateway"
1698 if [ $rc -eq 0 ]; then
1699 check_route "172.16.104.0/24 via inet6 2001:db8:101::2 dev veth1"
1702 run_cmd "ip netns exec ns1 ping -w1 -c1 172.16.104.1"
1703 log_test $rc 0 "Single path route with IPv6 gateway - ping"
1705 run_cmd "$IP ro del 172.16.104.0/24 via inet6 2001:db8:101::2"
1707 log_test $rc 0 "Single path route delete"
1708 if [ $rc -eq 0 ]; then
1709 check_route "172.16.112.0/24"
1713 # multipath - v6 then v4
1715 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"
1717 log_test $rc 0 "Multipath route add - v6 nexthop then v4"
1718 if [ $rc -eq 0 ]; then
1719 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"
1722 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"
1723 log_test $? 2 " Multipath route delete - nexthops in wrong order"
1725 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"
1726 log_test $? 0 " Multipath route delete exact match"
1729 # multipath - v4 then v6
1731 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"
1733 log_test $rc 0 "Multipath route add - v4 nexthop then v6"
1734 if [ $rc -eq 0 ]; then
1735 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"
1738 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"
1739 log_test $? 2 " Multipath route delete - nexthops in wrong order"
1741 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"
1742 log_test $? 0 " Multipath route delete exact match"
1749 if [ ! -x "$(command -v socat)" ]; then
1750 echo "socat command not found. Skipping test"
1759 iptables -t mangle -L OUTPUT &> /dev/null
1760 if [ $? -ne 0 ]; then
1761 echo "iptables configuration not supported. Skipping test"
1770 ip6tables -t mangle -L OUTPUT &> /dev/null
1771 if [ $? -ne 0 ]; then
1772 echo "ip6tables configuration not supported. Skipping test"
1784 echo "IPv4 mangling tests"
1786 socat_check || return 1
1787 iptables_check || return 1
1792 local tmp_file=$(mktemp)
1793 ip netns exec ns2 socat UDP4-LISTEN:54321,fork $tmp_file &
1795 # Add a FIB rule and a route that will direct our connection to the
1797 $IP rule add pref 100 ipproto udp sport 12345 dport 54321 table 123
1798 $IP route add table 123 172.16.101.0/24 dev veth1
1800 # Add an unreachable route to the main table that will block our
1801 # connection in case the FIB rule is not hit.
1802 $IP route add unreachable 172.16.101.2/32
1804 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
1805 log_test $? 0 " Connection with correct parameters"
1807 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=11111"
1808 log_test $? 1 " Connection with incorrect parameters"
1810 # Add a mangling rule and make sure connection is still successful.
1811 $NS_EXEC iptables -t mangle -A OUTPUT -j MARK --set-mark 1
1813 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
1814 log_test $? 0 " Connection with correct parameters - mangling"
1816 # Delete the mangling rule and make sure connection is still
1818 $NS_EXEC iptables -t mangle -D OUTPUT -j MARK --set-mark 1
1820 run_cmd "echo a | $NS_EXEC socat STDIN UDP4:172.16.101.2:54321,sourceport=12345"
1821 log_test $? 0 " Connection with correct parameters - no mangling"
1823 # Verify connections were indeed successful on server side.
1824 [[ $(cat $tmp_file | wc -l) -eq 3 ]]
1825 log_test $? 0 " Connection check - server side"
1827 $IP route del unreachable 172.16.101.2/32
1828 $IP route del table 123 172.16.101.0/24 dev veth1
1829 $IP rule del pref 100
1831 { kill %% && wait %%; } 2>/dev/null
1842 echo "IPv6 mangling tests"
1844 socat_check || return 1
1845 ip6tables_check || return 1
1850 local tmp_file=$(mktemp)
1851 ip netns exec ns2 socat UDP6-LISTEN:54321,fork $tmp_file &
1853 # Add a FIB rule and a route that will direct our connection to the
1855 $IP -6 rule add pref 100 ipproto udp sport 12345 dport 54321 table 123
1856 $IP -6 route add table 123 2001:db8:101::/64 dev veth1
1858 # Add an unreachable route to the main table that will block our
1859 # connection in case the FIB rule is not hit.
1860 $IP -6 route add unreachable 2001:db8:101::2/128
1862 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
1863 log_test $? 0 " Connection with correct parameters"
1865 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=11111"
1866 log_test $? 1 " Connection with incorrect parameters"
1868 # Add a mangling rule and make sure connection is still successful.
1869 $NS_EXEC ip6tables -t mangle -A OUTPUT -j MARK --set-mark 1
1871 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
1872 log_test $? 0 " Connection with correct parameters - mangling"
1874 # Delete the mangling rule and make sure connection is still
1876 $NS_EXEC ip6tables -t mangle -D OUTPUT -j MARK --set-mark 1
1878 run_cmd "echo a | $NS_EXEC socat STDIN UDP6:[2001:db8:101::2]:54321,sourceport=12345"
1879 log_test $? 0 " Connection with correct parameters - no mangling"
1881 # Verify connections were indeed successful on server side.
1882 [[ $(cat $tmp_file | wc -l) -eq 3 ]]
1883 log_test $? 0 " Connection check - server side"
1885 $IP -6 route del unreachable 2001:db8:101::2/128
1886 $IP -6 route del table 123 2001:db8:101::/64 dev veth1
1887 $IP -6 rule del pref 100
1889 { kill %% && wait %%; } 2>/dev/null
1895 ################################################################################
1901 usage: ${0##*/} OPTS
1903 -t <test> Test(s) to run (default: all)
1906 -P Pause after each test before cleanup
1907 -v verbose mode (show commands and output)
1911 ################################################################################
1914 while getopts :t:pPhv o
1918 p) PAUSE_ON_FAIL=yes;;
1920 v) VERBOSE=$(($VERBOSE + 1));;
1926 PEER_CMD="ip netns exec ${PEER_NS}"
1928 # make sure we don't pause twice
1929 [ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
1931 if [ "$(id -u)" -ne 0 ];then
1932 echo "SKIP: Need root privileges"
1936 if [ ! -x "$(command -v ip)" ]; then
1937 echo "SKIP: Could not run test without ip tool"
1941 ip route help 2>&1 | grep -q fibmatch
1942 if [ $? -ne 0 ]; then
1943 echo "SKIP: iproute2 too old, missing fibmatch"
1948 cleanup &> /dev/null
1953 fib_unreg_test|unregister) fib_unreg_test;;
1954 fib_down_test|down) fib_down_test;;
1955 fib_carrier_test|carrier) fib_carrier_test;;
1956 fib_rp_filter_test|rp_filter) fib_rp_filter_test;;
1957 fib_nexthop_test|nexthop) fib_nexthop_test;;
1958 fib_suppress_test|suppress) fib_suppress_test;;
1959 ipv6_route_test|ipv6_rt) ipv6_route_test;;
1960 ipv4_route_test|ipv4_rt) ipv4_route_test;;
1961 ipv6_addr_metric) ipv6_addr_metric_test;;
1962 ipv4_addr_metric) ipv4_addr_metric_test;;
1963 ipv4_del_addr) ipv4_del_addr_test;;
1964 ipv6_route_metrics) ipv6_route_metrics_test;;
1965 ipv4_route_metrics) ipv4_route_metrics_test;;
1966 ipv4_route_v6_gw) ipv4_route_v6_gw_test;;
1967 ipv4_mangle) ipv4_mangle_test;;
1968 ipv6_mangle) ipv6_mangle_test;;
1970 help) echo "Test names: $TESTS"; exit 0;;
1974 if [ "$TESTS" != "none" ]; then
1975 printf "\nTests passed: %3d\n" ${nsuccess}
1976 printf "Tests failed: %3d\n" ${nfail}