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