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