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