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