1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4# This test is for checking IPv4 and IPv6 FIB behavior in response to 5# different events. 6 7ret=0 8# Kselftest framework requirement - SKIP code is 4. 9ksft_skip=4 10 11# all tests in this script. Can be overridden with -t option 12TESTS="unregister down carrier nexthop ipv6_rt ipv4_rt ipv6_addr_metric ipv4_addr_metric ipv6_route_metrics ipv4_route_metrics" 13VERBOSE=0 14PAUSE_ON_FAIL=no 15PAUSE=no 16IP="ip -netns ns1" 17 18log_test() 19{ 20 local rc=$1 21 local expected=$2 22 local msg="$3" 23 24 if [ ${rc} -eq ${expected} ]; then 25 printf " TEST: %-60s [ OK ]\n" "${msg}" 26 nsuccess=$((nsuccess+1)) 27 else 28 ret=1 29 nfail=$((nfail+1)) 30 printf " TEST: %-60s [FAIL]\n" "${msg}" 31 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then 32 echo 33 echo "hit enter to continue, 'q' to quit" 34 read a 35 [ "$a" = "q" ] && exit 1 36 fi 37 fi 38 39 if [ "${PAUSE}" = "yes" ]; then 40 echo 41 echo "hit enter to continue, 'q' to quit" 42 read a 43 [ "$a" = "q" ] && exit 1 44 fi 45} 46 47setup() 48{ 49 set -e 50 ip netns add ns1 51 $IP link set dev lo up 52 ip netns exec ns1 sysctl -qw net.ipv4.ip_forward=1 53 ip netns exec ns1 sysctl -qw net.ipv6.conf.all.forwarding=1 54 55 $IP link add dummy0 type dummy 56 $IP link set dev dummy0 up 57 $IP address add 198.51.100.1/24 dev dummy0 58 $IP -6 address add 2001:db8:1::1/64 dev dummy0 59 set +e 60 61} 62 63cleanup() 64{ 65 $IP link del dev dummy0 &> /dev/null 66 ip netns del ns1 67 ip netns del ns2 &> /dev/null 68} 69 70get_linklocal() 71{ 72 local dev=$1 73 local addr 74 75 addr=$($IP -6 -br addr show dev ${dev} | \ 76 awk '{ 77 for (i = 3; i <= NF; ++i) { 78 if ($i ~ /^fe80/) 79 print $i 80 } 81 }' 82 ) 83 addr=${addr/\/*} 84 85 [ -z "$addr" ] && return 1 86 87 echo $addr 88 89 return 0 90} 91 92fib_unreg_unicast_test() 93{ 94 echo 95 echo "Single path route test" 96 97 setup 98 99 echo " Start point" 100 $IP route get fibmatch 198.51.100.2 &> /dev/null 101 log_test $? 0 "IPv4 fibmatch" 102 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null 103 log_test $? 0 "IPv6 fibmatch" 104 105 set -e 106 $IP link del dev dummy0 107 set +e 108 109 echo " Nexthop device deleted" 110 $IP route get fibmatch 198.51.100.2 &> /dev/null 111 log_test $? 2 "IPv4 fibmatch - no route" 112 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null 113 log_test $? 2 "IPv6 fibmatch - no route" 114 115 cleanup 116} 117 118fib_unreg_multipath_test() 119{ 120 121 echo 122 echo "Multipath route test" 123 124 setup 125 126 set -e 127 $IP link add dummy1 type dummy 128 $IP link set dev dummy1 up 129 $IP address add 192.0.2.1/24 dev dummy1 130 $IP -6 address add 2001:db8:2::1/64 dev dummy1 131 132 $IP route add 203.0.113.0/24 \ 133 nexthop via 198.51.100.2 dev dummy0 \ 134 nexthop via 192.0.2.2 dev dummy1 135 $IP -6 route add 2001:db8:3::/64 \ 136 nexthop via 2001:db8:1::2 dev dummy0 \ 137 nexthop via 2001:db8:2::2 dev dummy1 138 set +e 139 140 echo " Start point" 141 $IP route get fibmatch 203.0.113.1 &> /dev/null 142 log_test $? 0 "IPv4 fibmatch" 143 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null 144 log_test $? 0 "IPv6 fibmatch" 145 146 set -e 147 $IP link del dev dummy0 148 set +e 149 150 echo " One nexthop device deleted" 151 $IP route get fibmatch 203.0.113.1 &> /dev/null 152 log_test $? 2 "IPv4 - multipath route removed on delete" 153 154 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null 155 # In IPv6 we do not flush the entire multipath route. 156 log_test $? 0 "IPv6 - multipath down to single path" 157 158 set -e 159 $IP link del dev dummy1 160 set +e 161 162 echo " Second nexthop device deleted" 163 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null 164 log_test $? 2 "IPv6 - no route" 165 166 cleanup 167} 168 169fib_unreg_test() 170{ 171 fib_unreg_unicast_test 172 fib_unreg_multipath_test 173} 174 175fib_down_unicast_test() 176{ 177 echo 178 echo "Single path, admin down" 179 180 setup 181 182 echo " Start point" 183 $IP route get fibmatch 198.51.100.2 &> /dev/null 184 log_test $? 0 "IPv4 fibmatch" 185 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null 186 log_test $? 0 "IPv6 fibmatch" 187 188 set -e 189 $IP link set dev dummy0 down 190 set +e 191 192 echo " Route deleted on down" 193 $IP route get fibmatch 198.51.100.2 &> /dev/null 194 log_test $? 2 "IPv4 fibmatch" 195 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null 196 log_test $? 2 "IPv6 fibmatch" 197 198 cleanup 199} 200 201fib_down_multipath_test_do() 202{ 203 local down_dev=$1 204 local up_dev=$2 205 206 $IP route get fibmatch 203.0.113.1 \ 207 oif $down_dev &> /dev/null 208 log_test $? 2 "IPv4 fibmatch on down device" 209 $IP -6 route get fibmatch 2001:db8:3::1 \ 210 oif $down_dev &> /dev/null 211 log_test $? 2 "IPv6 fibmatch on down device" 212 213 $IP route get fibmatch 203.0.113.1 \ 214 oif $up_dev &> /dev/null 215 log_test $? 0 "IPv4 fibmatch on up device" 216 $IP -6 route get fibmatch 2001:db8:3::1 \ 217 oif $up_dev &> /dev/null 218 log_test $? 0 "IPv6 fibmatch on up device" 219 220 $IP route get fibmatch 203.0.113.1 | \ 221 grep $down_dev | grep -q "dead linkdown" 222 log_test $? 0 "IPv4 flags on down device" 223 $IP -6 route get fibmatch 2001:db8:3::1 | \ 224 grep $down_dev | grep -q "dead linkdown" 225 log_test $? 0 "IPv6 flags on down device" 226 227 $IP route get fibmatch 203.0.113.1 | \ 228 grep $up_dev | grep -q "dead linkdown" 229 log_test $? 1 "IPv4 flags on up device" 230 $IP -6 route get fibmatch 2001:db8:3::1 | \ 231 grep $up_dev | grep -q "dead linkdown" 232 log_test $? 1 "IPv6 flags on up device" 233} 234 235fib_down_multipath_test() 236{ 237 echo 238 echo "Admin down multipath" 239 240 setup 241 242 set -e 243 $IP link add dummy1 type dummy 244 $IP link set dev dummy1 up 245 246 $IP address add 192.0.2.1/24 dev dummy1 247 $IP -6 address add 2001:db8:2::1/64 dev dummy1 248 249 $IP route add 203.0.113.0/24 \ 250 nexthop via 198.51.100.2 dev dummy0 \ 251 nexthop via 192.0.2.2 dev dummy1 252 $IP -6 route add 2001:db8:3::/64 \ 253 nexthop via 2001:db8:1::2 dev dummy0 \ 254 nexthop via 2001:db8:2::2 dev dummy1 255 set +e 256 257 echo " Verify start point" 258 $IP route get fibmatch 203.0.113.1 &> /dev/null 259 log_test $? 0 "IPv4 fibmatch" 260 261 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null 262 log_test $? 0 "IPv6 fibmatch" 263 264 set -e 265 $IP link set dev dummy0 down 266 set +e 267 268 echo " One device down, one up" 269 fib_down_multipath_test_do "dummy0" "dummy1" 270 271 set -e 272 $IP link set dev dummy0 up 273 $IP link set dev dummy1 down 274 set +e 275 276 echo " Other device down and up" 277 fib_down_multipath_test_do "dummy1" "dummy0" 278 279 set -e 280 $IP link set dev dummy0 down 281 set +e 282 283 echo " Both devices down" 284 $IP route get fibmatch 203.0.113.1 &> /dev/null 285 log_test $? 2 "IPv4 fibmatch" 286 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null 287 log_test $? 2 "IPv6 fibmatch" 288 289 $IP link del dev dummy1 290 cleanup 291} 292 293fib_down_test() 294{ 295 fib_down_unicast_test 296 fib_down_multipath_test 297} 298 299# Local routes should not be affected when carrier changes. 300fib_carrier_local_test() 301{ 302 echo 303 echo "Local carrier tests - single path" 304 305 setup 306 307 set -e 308 $IP link set dev dummy0 carrier on 309 set +e 310 311 echo " Start point" 312 $IP route get fibmatch 198.51.100.1 &> /dev/null 313 log_test $? 0 "IPv4 fibmatch" 314 $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null 315 log_test $? 0 "IPv6 fibmatch" 316 317 $IP route get fibmatch 198.51.100.1 | \ 318 grep -q "linkdown" 319 log_test $? 1 "IPv4 - no linkdown flag" 320 $IP -6 route get fibmatch 2001:db8:1::1 | \ 321 grep -q "linkdown" 322 log_test $? 1 "IPv6 - no linkdown flag" 323 324 set -e 325 $IP link set dev dummy0 carrier off 326 sleep 1 327 set +e 328 329 echo " Carrier off on nexthop" 330 $IP route get fibmatch 198.51.100.1 &> /dev/null 331 log_test $? 0 "IPv4 fibmatch" 332 $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null 333 log_test $? 0 "IPv6 fibmatch" 334 335 $IP route get fibmatch 198.51.100.1 | \ 336 grep -q "linkdown" 337 log_test $? 1 "IPv4 - linkdown flag set" 338 $IP -6 route get fibmatch 2001:db8:1::1 | \ 339 grep -q "linkdown" 340 log_test $? 1 "IPv6 - linkdown flag set" 341 342 set -e 343 $IP address add 192.0.2.1/24 dev dummy0 344 $IP -6 address add 2001:db8:2::1/64 dev dummy0 345 set +e 346 347 echo " Route to local address with carrier down" 348 $IP route get fibmatch 192.0.2.1 &> /dev/null 349 log_test $? 0 "IPv4 fibmatch" 350 $IP -6 route get fibmatch 2001:db8:2::1 &> /dev/null 351 log_test $? 0 "IPv6 fibmatch" 352 353 $IP route get fibmatch 192.0.2.1 | \ 354 grep -q "linkdown" 355 log_test $? 1 "IPv4 linkdown flag set" 356 $IP -6 route get fibmatch 2001:db8:2::1 | \ 357 grep -q "linkdown" 358 log_test $? 1 "IPv6 linkdown flag set" 359 360 cleanup 361} 362 363fib_carrier_unicast_test() 364{ 365 ret=0 366 367 echo 368 echo "Single path route carrier test" 369 370 setup 371 372 set -e 373 $IP link set dev dummy0 carrier on 374 set +e 375 376 echo " Start point" 377 $IP route get fibmatch 198.51.100.2 &> /dev/null 378 log_test $? 0 "IPv4 fibmatch" 379 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null 380 log_test $? 0 "IPv6 fibmatch" 381 382 $IP route get fibmatch 198.51.100.2 | \ 383 grep -q "linkdown" 384 log_test $? 1 "IPv4 no linkdown flag" 385 $IP -6 route get fibmatch 2001:db8:1::2 | \ 386 grep -q "linkdown" 387 log_test $? 1 "IPv6 no linkdown flag" 388 389 set -e 390 $IP link set dev dummy0 carrier off 391 set +e 392 393 echo " Carrier down" 394 $IP route get fibmatch 198.51.100.2 &> /dev/null 395 log_test $? 0 "IPv4 fibmatch" 396 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null 397 log_test $? 0 "IPv6 fibmatch" 398 399 $IP route get fibmatch 198.51.100.2 | \ 400 grep -q "linkdown" 401 log_test $? 0 "IPv4 linkdown flag set" 402 $IP -6 route get fibmatch 2001:db8:1::2 | \ 403 grep -q "linkdown" 404 log_test $? 0 "IPv6 linkdown flag set" 405 406 set -e 407 $IP address add 192.0.2.1/24 dev dummy0 408 $IP -6 address add 2001:db8:2::1/64 dev dummy0 409 set +e 410 411 echo " Second address added with carrier down" 412 $IP route get fibmatch 192.0.2.2 &> /dev/null 413 log_test $? 0 "IPv4 fibmatch" 414 $IP -6 route get fibmatch 2001:db8:2::2 &> /dev/null 415 log_test $? 0 "IPv6 fibmatch" 416 417 $IP route get fibmatch 192.0.2.2 | \ 418 grep -q "linkdown" 419 log_test $? 0 "IPv4 linkdown flag set" 420 $IP -6 route get fibmatch 2001:db8:2::2 | \ 421 grep -q "linkdown" 422 log_test $? 0 "IPv6 linkdown flag set" 423 424 cleanup 425} 426 427fib_carrier_test() 428{ 429 fib_carrier_local_test 430 fib_carrier_unicast_test 431} 432 433################################################################################ 434# Tests on nexthop spec 435 436# run 'ip route add' with given spec 437add_rt() 438{ 439 local desc="$1" 440 local erc=$2 441 local vrf=$3 442 local pfx=$4 443 local gw=$5 444 local dev=$6 445 local cmd out rc 446 447 [ "$vrf" = "-" ] && vrf="default" 448 [ -n "$gw" ] && gw="via $gw" 449 [ -n "$dev" ] && dev="dev $dev" 450 451 cmd="$IP route add vrf $vrf $pfx $gw $dev" 452 if [ "$VERBOSE" = "1" ]; then 453 printf "\n COMMAND: $cmd\n" 454 fi 455 456 out=$(eval $cmd 2>&1) 457 rc=$? 458 if [ "$VERBOSE" = "1" -a -n "$out" ]; then 459 echo " $out" 460 fi 461 log_test $rc $erc "$desc" 462} 463 464fib4_nexthop() 465{ 466 echo 467 echo "IPv4 nexthop tests" 468 469 echo "<<< write me >>>" 470} 471 472fib6_nexthop() 473{ 474 local lldummy=$(get_linklocal dummy0) 475 local llv1=$(get_linklocal dummy0) 476 477 if [ -z "$lldummy" ]; then 478 echo "Failed to get linklocal address for dummy0" 479 return 1 480 fi 481 if [ -z "$llv1" ]; then 482 echo "Failed to get linklocal address for veth1" 483 return 1 484 fi 485 486 echo 487 echo "IPv6 nexthop tests" 488 489 add_rt "Directly connected nexthop, unicast address" 0 \ 490 - 2001:db8:101::/64 2001:db8:1::2 491 add_rt "Directly connected nexthop, unicast address with device" 0 \ 492 - 2001:db8:102::/64 2001:db8:1::2 "dummy0" 493 add_rt "Gateway is linklocal address" 0 \ 494 - 2001:db8:103::1/64 $llv1 "veth0" 495 496 # fails because LL address requires a device 497 add_rt "Gateway is linklocal address, no device" 2 \ 498 - 2001:db8:104::1/64 $llv1 499 500 # local address can not be a gateway 501 add_rt "Gateway can not be local unicast address" 2 \ 502 - 2001:db8:105::/64 2001:db8:1::1 503 add_rt "Gateway can not be local unicast address, with device" 2 \ 504 - 2001:db8:106::/64 2001:db8:1::1 "dummy0" 505 add_rt "Gateway can not be a local linklocal address" 2 \ 506 - 2001:db8:107::1/64 $lldummy "dummy0" 507 508 # VRF tests 509 add_rt "Gateway can be local address in a VRF" 0 \ 510 - 2001:db8:108::/64 2001:db8:51::2 511 add_rt "Gateway can be local address in a VRF, with device" 0 \ 512 - 2001:db8:109::/64 2001:db8:51::2 "veth0" 513 add_rt "Gateway can be local linklocal address in a VRF" 0 \ 514 - 2001:db8:110::1/64 $llv1 "veth0" 515 516 add_rt "Redirect to VRF lookup" 0 \ 517 - 2001:db8:111::/64 "" "red" 518 519 add_rt "VRF route, gateway can be local address in default VRF" 0 \ 520 red 2001:db8:112::/64 2001:db8:51::1 521 522 # local address in same VRF fails 523 add_rt "VRF route, gateway can not be a local address" 2 \ 524 red 2001:db8:113::1/64 2001:db8:2::1 525 add_rt "VRF route, gateway can not be a local addr with device" 2 \ 526 red 2001:db8:114::1/64 2001:db8:2::1 "dummy1" 527} 528 529# Default VRF: 530# dummy0 - 198.51.100.1/24 2001:db8:1::1/64 531# veth0 - 192.0.2.1/24 2001:db8:51::1/64 532# 533# VRF red: 534# dummy1 - 192.168.2.1/24 2001:db8:2::1/64 535# veth1 - 192.0.2.2/24 2001:db8:51::2/64 536# 537# [ dummy0 veth0 ]--[ veth1 dummy1 ] 538 539fib_nexthop_test() 540{ 541 setup 542 543 set -e 544 545 $IP -4 rule add pref 32765 table local 546 $IP -4 rule del pref 0 547 $IP -6 rule add pref 32765 table local 548 $IP -6 rule del pref 0 549 550 $IP link add red type vrf table 1 551 $IP link set red up 552 $IP -4 route add vrf red unreachable default metric 4278198272 553 $IP -6 route add vrf red unreachable default metric 4278198272 554 555 $IP link add veth0 type veth peer name veth1 556 $IP link set dev veth0 up 557 $IP address add 192.0.2.1/24 dev veth0 558 $IP -6 address add 2001:db8:51::1/64 dev veth0 559 560 $IP link set dev veth1 vrf red up 561 $IP address add 192.0.2.2/24 dev veth1 562 $IP -6 address add 2001:db8:51::2/64 dev veth1 563 564 $IP link add dummy1 type dummy 565 $IP link set dev dummy1 vrf red up 566 $IP address add 192.168.2.1/24 dev dummy1 567 $IP -6 address add 2001:db8:2::1/64 dev dummy1 568 set +e 569 570 sleep 1 571 fib4_nexthop 572 fib6_nexthop 573 574 ( 575 $IP link del dev dummy1 576 $IP link del veth0 577 $IP link del red 578 ) 2>/dev/null 579 cleanup 580} 581 582################################################################################ 583# Tests on route add and replace 584 585run_cmd() 586{ 587 local cmd="$1" 588 local out 589 local stderr="2>/dev/null" 590 591 if [ "$VERBOSE" = "1" ]; then 592 printf " COMMAND: $cmd\n" 593 stderr= 594 fi 595 596 out=$(eval $cmd $stderr) 597 rc=$? 598 if [ "$VERBOSE" = "1" -a -n "$out" ]; then 599 echo " $out" 600 fi 601 602 [ "$VERBOSE" = "1" ] && echo 603 604 return $rc 605} 606 607# add route for a prefix, flushing any existing routes first 608# expected to be the first step of a test 609add_route6() 610{ 611 local pfx="$1" 612 local nh="$2" 613 local out 614 615 if [ "$VERBOSE" = "1" ]; then 616 echo 617 echo " ##################################################" 618 echo 619 fi 620 621 run_cmd "$IP -6 ro flush ${pfx}" 622 [ $? -ne 0 ] && exit 1 623 624 out=$($IP -6 ro ls match ${pfx}) 625 if [ -n "$out" ]; then 626 echo "Failed to flush routes for prefix used for tests." 627 exit 1 628 fi 629 630 run_cmd "$IP -6 ro add ${pfx} ${nh}" 631 if [ $? -ne 0 ]; then 632 echo "Failed to add initial route for test." 633 exit 1 634 fi 635} 636 637# add initial route - used in replace route tests 638add_initial_route6() 639{ 640 add_route6 "2001:db8:104::/64" "$1" 641} 642 643check_route6() 644{ 645 local pfx 646 local expected="$1" 647 local out 648 local rc=0 649 650 set -- $expected 651 pfx=$1 652 653 out=$($IP -6 ro ls match ${pfx} | sed -e 's/ pref medium//') 654 [ "${out}" = "${expected}" ] && return 0 655 656 if [ -z "${out}" ]; then 657 if [ "$VERBOSE" = "1" ]; then 658 printf "\nNo route entry found\n" 659 printf "Expected:\n" 660 printf " ${expected}\n" 661 fi 662 return 1 663 fi 664 665 # tricky way to convert output to 1-line without ip's 666 # messy '\'; this drops all extra white space 667 out=$(echo ${out}) 668 if [ "${out}" != "${expected}" ]; then 669 rc=1 670 if [ "${VERBOSE}" = "1" ]; then 671 printf " Unexpected route entry. Have:\n" 672 printf " ${out}\n" 673 printf " Expected:\n" 674 printf " ${expected}\n\n" 675 fi 676 fi 677 678 return $rc 679} 680 681route_cleanup() 682{ 683 $IP li del red 2>/dev/null 684 $IP li del dummy1 2>/dev/null 685 $IP li del veth1 2>/dev/null 686 $IP li del veth3 2>/dev/null 687 688 cleanup &> /dev/null 689} 690 691route_setup() 692{ 693 route_cleanup 694 setup 695 696 [ "${VERBOSE}" = "1" ] && set -x 697 set -e 698 699 ip netns add ns2 700 ip -netns ns2 link set dev lo up 701 ip netns exec ns2 sysctl -qw net.ipv4.ip_forward=1 702 ip netns exec ns2 sysctl -qw net.ipv6.conf.all.forwarding=1 703 704 $IP li add veth1 type veth peer name veth2 705 $IP li add veth3 type veth peer name veth4 706 707 $IP li set veth1 up 708 $IP li set veth3 up 709 $IP li set veth2 netns ns2 up 710 $IP li set veth4 netns ns2 up 711 ip -netns ns2 li add dummy1 type dummy 712 ip -netns ns2 li set dummy1 up 713 714 $IP -6 addr add 2001:db8:101::1/64 dev veth1 nodad 715 $IP -6 addr add 2001:db8:103::1/64 dev veth3 nodad 716 $IP addr add 172.16.101.1/24 dev veth1 717 $IP addr add 172.16.103.1/24 dev veth3 718 719 ip -netns ns2 -6 addr add 2001:db8:101::2/64 dev veth2 nodad 720 ip -netns ns2 -6 addr add 2001:db8:103::2/64 dev veth4 nodad 721 ip -netns ns2 -6 addr add 2001:db8:104::1/64 dev dummy1 nodad 722 723 ip -netns ns2 addr add 172.16.101.2/24 dev veth2 724 ip -netns ns2 addr add 172.16.103.2/24 dev veth4 725 ip -netns ns2 addr add 172.16.104.1/24 dev dummy1 726 727 set +ex 728} 729 730# assumption is that basic add of a single path route works 731# otherwise just adding an address on an interface is broken 732ipv6_rt_add() 733{ 734 local rc 735 736 echo 737 echo "IPv6 route add / append tests" 738 739 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL 740 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2" 741 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2" 742 log_test $? 2 "Attempt to add duplicate route - gw" 743 744 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL 745 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2" 746 run_cmd "$IP -6 ro add 2001:db8:104::/64 dev veth3" 747 log_test $? 2 "Attempt to add duplicate route - dev only" 748 749 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL 750 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2" 751 run_cmd "$IP -6 ro add unreachable 2001:db8:104::/64" 752 log_test $? 2 "Attempt to add duplicate route - reject route" 753 754 # route append with same prefix adds a new route 755 # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND 756 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2" 757 run_cmd "$IP -6 ro append 2001:db8:104::/64 via 2001:db8:103::2" 758 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" 759 log_test $? 0 "Append nexthop to existing route - gw" 760 761 # insert mpath directly 762 add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2" 763 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" 764 log_test $? 0 "Add multipath route" 765 766 add_route6 "2001:db8:104::/64" "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2" 767 run_cmd "$IP -6 ro add 2001:db8:104::/64 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2" 768 log_test $? 2 "Attempt to add duplicate multipath route" 769 770 # insert of a second route without append but different metric 771 add_route6 "2001:db8:104::/64" "via 2001:db8:101::2" 772 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::2 metric 512" 773 rc=$? 774 if [ $rc -eq 0 ]; then 775 run_cmd "$IP -6 ro add 2001:db8:104::/64 via 2001:db8:103::3 metric 256" 776 rc=$? 777 fi 778 log_test $rc 0 "Route add with different metrics" 779 780 run_cmd "$IP -6 ro del 2001:db8:104::/64 metric 512" 781 rc=$? 782 if [ $rc -eq 0 ]; then 783 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" 784 rc=$? 785 fi 786 log_test $rc 0 "Route delete with metric" 787} 788 789ipv6_rt_replace_single() 790{ 791 # single path with single path 792 # 793 add_initial_route6 "via 2001:db8:101::2" 794 run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:103::2" 795 check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024" 796 log_test $? 0 "Single path with single path" 797 798 # single path with multipath 799 # 800 add_initial_route6 "nexthop via 2001:db8:101::2" 801 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::2" 802 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" 803 log_test $? 0 "Single path with multipath" 804 805 # single path with single path using MULTIPATH attribute 806 # 807 add_initial_route6 "via 2001:db8:101::2" 808 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:103::2" 809 check_route6 "2001:db8:104::/64 via 2001:db8:103::2 dev veth3 metric 1024" 810 log_test $? 0 "Single path with single path via multipath attribute" 811 812 # route replace fails - invalid nexthop 813 add_initial_route6 "via 2001:db8:101::2" 814 run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:104::2" 815 if [ $? -eq 0 ]; then 816 # previous command is expected to fail so if it returns 0 817 # that means the test failed. 818 log_test 0 1 "Invalid nexthop" 819 else 820 check_route6 "2001:db8:104::/64 via 2001:db8:101::2 dev veth1 metric 1024" 821 log_test $? 0 "Invalid nexthop" 822 fi 823 824 # replace non-existent route 825 # - note use of change versus replace since ip adds NLM_F_CREATE 826 # for replace 827 add_initial_route6 "via 2001:db8:101::2" 828 run_cmd "$IP -6 ro change 2001:db8:105::/64 via 2001:db8:101::2" 829 log_test $? 2 "Single path - replace of non-existent route" 830} 831 832ipv6_rt_replace_mpath() 833{ 834 # multipath with multipath 835 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2" 836 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3" 837 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" 838 log_test $? 0 "Multipath with multipath" 839 840 # multipath with single 841 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2" 842 run_cmd "$IP -6 ro replace 2001:db8:104::/64 via 2001:db8:101::3" 843 check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024" 844 log_test $? 0 "Multipath with single path" 845 846 # multipath with single 847 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2" 848 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3" 849 check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024" 850 log_test $? 0 "Multipath with single path via multipath attribute" 851 852 # route replace fails - invalid nexthop 1 853 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2" 854 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:111::3 nexthop via 2001:db8:103::3" 855 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" 856 log_test $? 0 "Multipath - invalid first nexthop" 857 858 # route replace fails - invalid nexthop 2 859 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2" 860 run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:113::3" 861 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" 862 log_test $? 0 "Multipath - invalid second nexthop" 863 864 # multipath non-existent route 865 add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2" 866 run_cmd "$IP -6 ro change 2001:db8:105::/64 nexthop via 2001:db8:101::3 nexthop via 2001:db8:103::3" 867 log_test $? 2 "Multipath - replace of non-existent route" 868} 869 870ipv6_rt_replace() 871{ 872 echo 873 echo "IPv6 route replace tests" 874 875 ipv6_rt_replace_single 876 ipv6_rt_replace_mpath 877} 878 879ipv6_route_test() 880{ 881 route_setup 882 883 ipv6_rt_add 884 ipv6_rt_replace 885 886 route_cleanup 887} 888 889ip_addr_metric_check() 890{ 891 ip addr help 2>&1 | grep -q metric 892 if [ $? -ne 0 ]; then 893 echo "iproute2 command does not support metric for addresses. Skipping test" 894 return 1 895 fi 896 897 return 0 898} 899 900ipv6_addr_metric_test() 901{ 902 local rc 903 904 echo 905 echo "IPv6 prefix route tests" 906 907 ip_addr_metric_check || return 1 908 909 setup 910 911 set -e 912 $IP li add dummy1 type dummy 913 $IP li add dummy2 type dummy 914 $IP li set dummy1 up 915 $IP li set dummy2 up 916 917 # default entry is metric 256 918 run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64" 919 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64" 920 set +e 921 922 check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 256 2001:db8:104::/64 dev dummy2 proto kernel metric 256" 923 log_test $? 0 "Default metric" 924 925 set -e 926 run_cmd "$IP -6 addr flush dev dummy1" 927 run_cmd "$IP -6 addr add dev dummy1 2001:db8:104::1/64 metric 257" 928 set +e 929 930 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 256 2001:db8:104::/64 dev dummy1 proto kernel metric 257" 931 log_test $? 0 "User specified metric on first device" 932 933 set -e 934 run_cmd "$IP -6 addr flush dev dummy2" 935 run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::2/64 metric 258" 936 set +e 937 938 check_route6 "2001:db8:104::/64 dev dummy1 proto kernel metric 257 2001:db8:104::/64 dev dummy2 proto kernel metric 258" 939 log_test $? 0 "User specified metric on second device" 940 941 run_cmd "$IP -6 addr del dev dummy1 2001:db8:104::1/64 metric 257" 942 rc=$? 943 if [ $rc -eq 0 ]; then 944 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 258" 945 rc=$? 946 fi 947 log_test $rc 0 "Delete of address on first device" 948 949 run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::2/64 metric 259" 950 rc=$? 951 if [ $rc -eq 0 ]; then 952 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259" 953 rc=$? 954 fi 955 log_test $rc 0 "Modify metric of address" 956 957 # verify prefix route removed on down 958 run_cmd "ip netns exec ns1 sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1" 959 run_cmd "$IP li set dev dummy2 down" 960 rc=$? 961 if [ $rc -eq 0 ]; then 962 check_route6 "" 963 rc=$? 964 fi 965 log_test $rc 0 "Prefix route removed on link down" 966 967 # verify prefix route re-inserted with assigned metric 968 run_cmd "$IP li set dev dummy2 up" 969 rc=$? 970 if [ $rc -eq 0 ]; then 971 check_route6 "2001:db8:104::/64 dev dummy2 proto kernel metric 259" 972 rc=$? 973 fi 974 log_test $rc 0 "Prefix route with metric on link up" 975 976 $IP li del dummy1 977 $IP li del dummy2 978 cleanup 979} 980 981ipv6_route_metrics_test() 982{ 983 local rc 984 985 echo 986 echo "IPv6 routes with metrics" 987 988 route_setup 989 990 # 991 # single path with metrics 992 # 993 run_cmd "$IP -6 ro add 2001:db8:111::/64 via 2001:db8:101::2 mtu 1400" 994 rc=$? 995 if [ $rc -eq 0 ]; then 996 check_route6 "2001:db8:111::/64 via 2001:db8:101::2 dev veth1 metric 1024 mtu 1400" 997 rc=$? 998 fi 999 log_test $rc 0 "Single path route with mtu metric" 1000 1001 1002 # 1003 # multipath via separate routes with metrics 1004 # 1005 run_cmd "$IP -6 ro add 2001:db8:112::/64 via 2001:db8:101::2 mtu 1400" 1006 run_cmd "$IP -6 ro append 2001:db8:112::/64 via 2001:db8:103::2" 1007 rc=$? 1008 if [ $rc -eq 0 ]; then 1009 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" 1010 rc=$? 1011 fi 1012 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on first" 1013 1014 # second route is coalesced to first to make a multipath route. 1015 # MTU of the second path is hidden from display! 1016 run_cmd "$IP -6 ro add 2001:db8:113::/64 via 2001:db8:101::2" 1017 run_cmd "$IP -6 ro append 2001:db8:113::/64 via 2001:db8:103::2 mtu 1400" 1018 rc=$? 1019 if [ $rc -eq 0 ]; then 1020 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" 1021 rc=$? 1022 fi 1023 log_test $rc 0 "Multipath route via 2 single routes with mtu metric on 2nd" 1024 1025 run_cmd "$IP -6 ro del 2001:db8:113::/64 via 2001:db8:101::2" 1026 if [ $? -eq 0 ]; then 1027 check_route6 "2001:db8:113::/64 via 2001:db8:103::2 dev veth3 metric 1024 mtu 1400" 1028 log_test $? 0 " MTU of second leg" 1029 fi 1030 1031 # 1032 # multipath with metrics 1033 # 1034 run_cmd "$IP -6 ro add 2001:db8:115::/64 mtu 1400 nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2" 1035 rc=$? 1036 if [ $rc -eq 0 ]; then 1037 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" 1038 rc=$? 1039 fi 1040 log_test $rc 0 "Multipath route with mtu metric" 1041 1042 $IP -6 ro add 2001:db8:104::/64 via 2001:db8:101::2 mtu 1300 1043 run_cmd "ip netns exec ns1 ping6 -w1 -c1 -s 1500 2001:db8:104::1" 1044 log_test $? 0 "Using route with mtu metric" 1045 1046 run_cmd "$IP -6 ro add 2001:db8:114::/64 via 2001:db8:101::2 congctl lock foo" 1047 log_test $? 2 "Invalid metric (fails metric_convert)" 1048 1049 route_cleanup 1050} 1051 1052# add route for a prefix, flushing any existing routes first 1053# expected to be the first step of a test 1054add_route() 1055{ 1056 local pfx="$1" 1057 local nh="$2" 1058 local out 1059 1060 if [ "$VERBOSE" = "1" ]; then 1061 echo 1062 echo " ##################################################" 1063 echo 1064 fi 1065 1066 run_cmd "$IP ro flush ${pfx}" 1067 [ $? -ne 0 ] && exit 1 1068 1069 out=$($IP ro ls match ${pfx}) 1070 if [ -n "$out" ]; then 1071 echo "Failed to flush routes for prefix used for tests." 1072 exit 1 1073 fi 1074 1075 run_cmd "$IP ro add ${pfx} ${nh}" 1076 if [ $? -ne 0 ]; then 1077 echo "Failed to add initial route for test." 1078 exit 1 1079 fi 1080} 1081 1082# add initial route - used in replace route tests 1083add_initial_route() 1084{ 1085 add_route "172.16.104.0/24" "$1" 1086} 1087 1088check_route() 1089{ 1090 local pfx 1091 local expected="$1" 1092 local out 1093 local rc=0 1094 1095 set -- $expected 1096 pfx=$1 1097 [ "${pfx}" = "unreachable" ] && pfx=$2 1098 1099 out=$($IP ro ls match ${pfx}) 1100 [ "${out}" = "${expected}" ] && return 0 1101 1102 if [ -z "${out}" ]; then 1103 if [ "$VERBOSE" = "1" ]; then 1104 printf "\nNo route entry found\n" 1105 printf "Expected:\n" 1106 printf " ${expected}\n" 1107 fi 1108 return 1 1109 fi 1110 1111 # tricky way to convert output to 1-line without ip's 1112 # messy '\'; this drops all extra white space 1113 out=$(echo ${out}) 1114 if [ "${out}" != "${expected}" ]; then 1115 rc=1 1116 if [ "${VERBOSE}" = "1" ]; then 1117 printf " Unexpected route entry. Have:\n" 1118 printf " ${out}\n" 1119 printf " Expected:\n" 1120 printf " ${expected}\n\n" 1121 fi 1122 fi 1123 1124 return $rc 1125} 1126 1127# assumption is that basic add of a single path route works 1128# otherwise just adding an address on an interface is broken 1129ipv4_rt_add() 1130{ 1131 local rc 1132 1133 echo 1134 echo "IPv4 route add / append tests" 1135 1136 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL 1137 add_route "172.16.104.0/24" "via 172.16.101.2" 1138 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2" 1139 log_test $? 2 "Attempt to add duplicate route - gw" 1140 1141 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL 1142 add_route "172.16.104.0/24" "via 172.16.101.2" 1143 run_cmd "$IP ro add 172.16.104.0/24 dev veth3" 1144 log_test $? 2 "Attempt to add duplicate route - dev only" 1145 1146 # route add same prefix - fails with EEXISTS b/c ip adds NLM_F_EXCL 1147 add_route "172.16.104.0/24" "via 172.16.101.2" 1148 run_cmd "$IP ro add unreachable 172.16.104.0/24" 1149 log_test $? 2 "Attempt to add duplicate route - reject route" 1150 1151 # iproute2 prepend only sets NLM_F_CREATE 1152 # - adds a new route; does NOT convert existing route to ECMP 1153 add_route "172.16.104.0/24" "via 172.16.101.2" 1154 run_cmd "$IP ro prepend 172.16.104.0/24 via 172.16.103.2" 1155 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" 1156 log_test $? 0 "Add new nexthop for existing prefix" 1157 1158 # route append with same prefix adds a new route 1159 # - iproute2 sets NLM_F_CREATE | NLM_F_APPEND 1160 add_route "172.16.104.0/24" "via 172.16.101.2" 1161 run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2" 1162 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" 1163 log_test $? 0 "Append nexthop to existing route - gw" 1164 1165 add_route "172.16.104.0/24" "via 172.16.101.2" 1166 run_cmd "$IP ro append 172.16.104.0/24 dev veth3" 1167 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 172.16.104.0/24 dev veth3 scope link" 1168 log_test $? 0 "Append nexthop to existing route - dev only" 1169 1170 add_route "172.16.104.0/24" "via 172.16.101.2" 1171 run_cmd "$IP ro append unreachable 172.16.104.0/24" 1172 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1 unreachable 172.16.104.0/24" 1173 log_test $? 0 "Append nexthop to existing route - reject route" 1174 1175 run_cmd "$IP ro flush 172.16.104.0/24" 1176 run_cmd "$IP ro add unreachable 172.16.104.0/24" 1177 run_cmd "$IP ro append 172.16.104.0/24 via 172.16.103.2" 1178 check_route "unreachable 172.16.104.0/24 172.16.104.0/24 via 172.16.103.2 dev veth3" 1179 log_test $? 0 "Append nexthop to existing reject route - gw" 1180 1181 run_cmd "$IP ro flush 172.16.104.0/24" 1182 run_cmd "$IP ro add unreachable 172.16.104.0/24" 1183 run_cmd "$IP ro append 172.16.104.0/24 dev veth3" 1184 check_route "unreachable 172.16.104.0/24 172.16.104.0/24 dev veth3 scope link" 1185 log_test $? 0 "Append nexthop to existing reject route - dev only" 1186 1187 # insert mpath directly 1188 add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2" 1189 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" 1190 log_test $? 0 "add multipath route" 1191 1192 add_route "172.16.104.0/24" "nexthop via 172.16.101.2 nexthop via 172.16.103.2" 1193 run_cmd "$IP ro add 172.16.104.0/24 nexthop via 172.16.101.2 nexthop via 172.16.103.2" 1194 log_test $? 2 "Attempt to add duplicate multipath route" 1195 1196 # insert of a second route without append but different metric 1197 add_route "172.16.104.0/24" "via 172.16.101.2" 1198 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.2 metric 512" 1199 rc=$? 1200 if [ $rc -eq 0 ]; then 1201 run_cmd "$IP ro add 172.16.104.0/24 via 172.16.103.3 metric 256" 1202 rc=$? 1203 fi 1204 log_test $rc 0 "Route add with different metrics" 1205 1206 run_cmd "$IP ro del 172.16.104.0/24 metric 512" 1207 rc=$? 1208 if [ $rc -eq 0 ]; then 1209 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" 1210 rc=$? 1211 fi 1212 log_test $rc 0 "Route delete with metric" 1213} 1214 1215ipv4_rt_replace_single() 1216{ 1217 # single path with single path 1218 # 1219 add_initial_route "via 172.16.101.2" 1220 run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.103.2" 1221 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3" 1222 log_test $? 0 "Single path with single path" 1223 1224 # single path with multipath 1225 # 1226 add_initial_route "nexthop via 172.16.101.2" 1227 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.2" 1228 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" 1229 log_test $? 0 "Single path with multipath" 1230 1231 # single path with reject 1232 # 1233 add_initial_route "nexthop via 172.16.101.2" 1234 run_cmd "$IP ro replace unreachable 172.16.104.0/24" 1235 check_route "unreachable 172.16.104.0/24" 1236 log_test $? 0 "Single path with reject route" 1237 1238 # single path with single path using MULTIPATH attribute 1239 # 1240 add_initial_route "via 172.16.101.2" 1241 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.103.2" 1242 check_route "172.16.104.0/24 via 172.16.103.2 dev veth3" 1243 log_test $? 0 "Single path with single path via multipath attribute" 1244 1245 # route replace fails - invalid nexthop 1246 add_initial_route "via 172.16.101.2" 1247 run_cmd "$IP ro replace 172.16.104.0/24 via 2001:db8:104::2" 1248 if [ $? -eq 0 ]; then 1249 # previous command is expected to fail so if it returns 0 1250 # that means the test failed. 1251 log_test 0 1 "Invalid nexthop" 1252 else 1253 check_route "172.16.104.0/24 via 172.16.101.2 dev veth1" 1254 log_test $? 0 "Invalid nexthop" 1255 fi 1256 1257 # replace non-existent route 1258 # - note use of change versus replace since ip adds NLM_F_CREATE 1259 # for replace 1260 add_initial_route "via 172.16.101.2" 1261 run_cmd "$IP ro change 172.16.105.0/24 via 172.16.101.2" 1262 log_test $? 2 "Single path - replace of non-existent route" 1263} 1264 1265ipv4_rt_replace_mpath() 1266{ 1267 # multipath with multipath 1268 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2" 1269 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3" 1270 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" 1271 log_test $? 0 "Multipath with multipath" 1272 1273 # multipath with single 1274 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2" 1275 run_cmd "$IP ro replace 172.16.104.0/24 via 172.16.101.3" 1276 check_route "172.16.104.0/24 via 172.16.101.3 dev veth1" 1277 log_test $? 0 "Multipath with single path" 1278 1279 # multipath with single 1280 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2" 1281 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3" 1282 check_route "172.16.104.0/24 via 172.16.101.3 dev veth1" 1283 log_test $? 0 "Multipath with single path via multipath attribute" 1284 1285 # multipath with reject 1286 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2" 1287 run_cmd "$IP ro replace unreachable 172.16.104.0/24" 1288 check_route "unreachable 172.16.104.0/24" 1289 log_test $? 0 "Multipath with reject route" 1290 1291 # route replace fails - invalid nexthop 1 1292 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2" 1293 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.111.3 nexthop via 172.16.103.3" 1294 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" 1295 log_test $? 0 "Multipath - invalid first nexthop" 1296 1297 # route replace fails - invalid nexthop 2 1298 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2" 1299 run_cmd "$IP ro replace 172.16.104.0/24 nexthop via 172.16.101.3 nexthop via 172.16.113.3" 1300 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" 1301 log_test $? 0 "Multipath - invalid second nexthop" 1302 1303 # multipath non-existent route 1304 add_initial_route "nexthop via 172.16.101.2 nexthop via 172.16.103.2" 1305 run_cmd "$IP ro change 172.16.105.0/24 nexthop via 172.16.101.3 nexthop via 172.16.103.3" 1306 log_test $? 2 "Multipath - replace of non-existent route" 1307} 1308 1309ipv4_rt_replace() 1310{ 1311 echo 1312 echo "IPv4 route replace tests" 1313 1314 ipv4_rt_replace_single 1315 ipv4_rt_replace_mpath 1316} 1317 1318ipv4_route_test() 1319{ 1320 route_setup 1321 1322 ipv4_rt_add 1323 ipv4_rt_replace 1324 1325 route_cleanup 1326} 1327 1328ipv4_addr_metric_test() 1329{ 1330 local rc 1331 1332 echo 1333 echo "IPv4 prefix route tests" 1334 1335 ip_addr_metric_check || return 1 1336 1337 setup 1338 1339 set -e 1340 $IP li add dummy1 type dummy 1341 $IP li add dummy2 type dummy 1342 $IP li set dummy1 up 1343 $IP li set dummy2 up 1344 1345 # default entry is metric 256 1346 run_cmd "$IP addr add dev dummy1 172.16.104.1/24" 1347 run_cmd "$IP addr add dev dummy2 172.16.104.2/24" 1348 set +e 1349 1350 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" 1351 log_test $? 0 "Default metric" 1352 1353 set -e 1354 run_cmd "$IP addr flush dev dummy1" 1355 run_cmd "$IP addr add dev dummy1 172.16.104.1/24 metric 257" 1356 set +e 1357 1358 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" 1359 log_test $? 0 "User specified metric on first device" 1360 1361 set -e 1362 run_cmd "$IP addr flush dev dummy2" 1363 run_cmd "$IP addr add dev dummy2 172.16.104.2/24 metric 258" 1364 set +e 1365 1366 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" 1367 log_test $? 0 "User specified metric on second device" 1368 1369 run_cmd "$IP addr del dev dummy1 172.16.104.1/24 metric 257" 1370 rc=$? 1371 if [ $rc -eq 0 ]; then 1372 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 258" 1373 rc=$? 1374 fi 1375 log_test $rc 0 "Delete of address on first device" 1376 1377 run_cmd "$IP addr change dev dummy2 172.16.104.2/24 metric 259" 1378 rc=$? 1379 if [ $rc -eq 0 ]; then 1380 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259" 1381 rc=$? 1382 fi 1383 log_test $rc 0 "Modify metric of address" 1384 1385 # verify prefix route removed on down 1386 run_cmd "$IP li set dev dummy2 down" 1387 rc=$? 1388 if [ $rc -eq 0 ]; then 1389 check_route "" 1390 rc=$? 1391 fi 1392 log_test $rc 0 "Prefix route removed on link down" 1393 1394 # verify prefix route re-inserted with assigned metric 1395 run_cmd "$IP li set dev dummy2 up" 1396 rc=$? 1397 if [ $rc -eq 0 ]; then 1398 check_route "172.16.104.0/24 dev dummy2 proto kernel scope link src 172.16.104.2 metric 259" 1399 rc=$? 1400 fi 1401 log_test $rc 0 "Prefix route with metric on link up" 1402 1403 $IP li del dummy1 1404 $IP li del dummy2 1405 cleanup 1406} 1407 1408ipv4_route_metrics_test() 1409{ 1410 local rc 1411 1412 echo 1413 echo "IPv4 route add / append tests" 1414 1415 route_setup 1416 1417 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 mtu 1400" 1418 rc=$? 1419 if [ $rc -eq 0 ]; then 1420 check_route "172.16.111.0/24 via 172.16.101.2 dev veth1 mtu 1400" 1421 rc=$? 1422 fi 1423 log_test $rc 0 "Single path route with mtu metric" 1424 1425 1426 run_cmd "$IP ro add 172.16.112.0/24 mtu 1400 nexthop via 172.16.101.2 nexthop via 172.16.103.2" 1427 rc=$? 1428 if [ $rc -eq 0 ]; then 1429 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" 1430 rc=$? 1431 fi 1432 log_test $rc 0 "Multipath route with mtu metric" 1433 1434 $IP ro add 172.16.104.0/24 via 172.16.101.2 mtu 1300 1435 run_cmd "ip netns exec ns1 ping -w1 -c1 -s 1500 172.16.104.1" 1436 log_test $? 0 "Using route with mtu metric" 1437 1438 run_cmd "$IP ro add 172.16.111.0/24 via 172.16.101.2 congctl lock foo" 1439 log_test $? 2 "Invalid metric (fails metric_convert)" 1440 1441 route_cleanup 1442} 1443 1444 1445################################################################################ 1446# usage 1447 1448usage() 1449{ 1450 cat <<EOF 1451usage: ${0##*/} OPTS 1452 1453 -t <test> Test(s) to run (default: all) 1454 (options: $TESTS) 1455 -p Pause on fail 1456 -P Pause after each test before cleanup 1457 -v verbose mode (show commands and output) 1458EOF 1459} 1460 1461################################################################################ 1462# main 1463 1464while getopts :t:pPhv o 1465do 1466 case $o in 1467 t) TESTS=$OPTARG;; 1468 p) PAUSE_ON_FAIL=yes;; 1469 P) PAUSE=yes;; 1470 v) VERBOSE=$(($VERBOSE + 1));; 1471 h) usage; exit 0;; 1472 *) usage; exit 1;; 1473 esac 1474done 1475 1476PEER_CMD="ip netns exec ${PEER_NS}" 1477 1478# make sure we don't pause twice 1479[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no 1480 1481if [ "$(id -u)" -ne 0 ];then 1482 echo "SKIP: Need root privileges" 1483 exit $ksft_skip; 1484fi 1485 1486if [ ! -x "$(command -v ip)" ]; then 1487 echo "SKIP: Could not run test without ip tool" 1488 exit $ksft_skip 1489fi 1490 1491ip route help 2>&1 | grep -q fibmatch 1492if [ $? -ne 0 ]; then 1493 echo "SKIP: iproute2 too old, missing fibmatch" 1494 exit $ksft_skip 1495fi 1496 1497# start clean 1498cleanup &> /dev/null 1499 1500for t in $TESTS 1501do 1502 case $t in 1503 fib_unreg_test|unregister) fib_unreg_test;; 1504 fib_down_test|down) fib_down_test;; 1505 fib_carrier_test|carrier) fib_carrier_test;; 1506 fib_nexthop_test|nexthop) fib_nexthop_test;; 1507 ipv6_route_test|ipv6_rt) ipv6_route_test;; 1508 ipv4_route_test|ipv4_rt) ipv4_route_test;; 1509 ipv6_addr_metric) ipv6_addr_metric_test;; 1510 ipv4_addr_metric) ipv4_addr_metric_test;; 1511 ipv6_route_metrics) ipv6_route_metrics_test;; 1512 ipv4_route_metrics) ipv4_route_metrics_test;; 1513 1514 help) echo "Test names: $TESTS"; exit 0;; 1515 esac 1516done 1517 1518if [ "$TESTS" != "none" ]; then 1519 printf "\nTests passed: %3d\n" ${nsuccess} 1520 printf "Tests failed: %3d\n" ${nfail} 1521fi 1522 1523exit $ret 1524