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 9VERBOSE=${VERBOSE:=0} 10PAUSE_ON_FAIL=${PAUSE_ON_FAIL:=no} 11IP="ip -netns testns" 12 13log_test() 14{ 15 local rc=$1 16 local expected=$2 17 local msg="$3" 18 19 if [ ${rc} -eq ${expected} ]; then 20 printf " TEST: %-60s [ OK ]\n" "${msg}" 21 else 22 ret=1 23 printf " TEST: %-60s [FAIL]\n" "${msg}" 24 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then 25 echo 26 echo "hit enter to continue, 'q' to quit" 27 read a 28 [ "$a" = "q" ] && exit 1 29 fi 30 fi 31} 32 33setup() 34{ 35 set -e 36 ip netns add testns 37 $IP link set dev lo up 38 39 $IP link add dummy0 type dummy 40 $IP link set dev dummy0 up 41 $IP address add 198.51.100.1/24 dev dummy0 42 $IP -6 address add 2001:db8:1::1/64 dev dummy0 43 set +e 44 45} 46 47cleanup() 48{ 49 $IP link del dev dummy0 &> /dev/null 50 ip netns del testns 51} 52 53get_linklocal() 54{ 55 local dev=$1 56 local addr 57 58 addr=$($IP -6 -br addr show dev ${dev} | \ 59 awk '{ 60 for (i = 3; i <= NF; ++i) { 61 if ($i ~ /^fe80/) 62 print $i 63 } 64 }' 65 ) 66 addr=${addr/\/*} 67 68 [ -z "$addr" ] && return 1 69 70 echo $addr 71 72 return 0 73} 74 75fib_unreg_unicast_test() 76{ 77 echo 78 echo "Single path route test" 79 80 setup 81 82 echo " Start point" 83 $IP route get fibmatch 198.51.100.2 &> /dev/null 84 log_test $? 0 "IPv4 fibmatch" 85 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null 86 log_test $? 0 "IPv6 fibmatch" 87 88 set -e 89 $IP link del dev dummy0 90 set +e 91 92 echo " Nexthop device deleted" 93 $IP route get fibmatch 198.51.100.2 &> /dev/null 94 log_test $? 2 "IPv4 fibmatch - no route" 95 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null 96 log_test $? 2 "IPv6 fibmatch - no route" 97 98 cleanup 99} 100 101fib_unreg_multipath_test() 102{ 103 104 echo 105 echo "Multipath route test" 106 107 setup 108 109 set -e 110 $IP link add dummy1 type dummy 111 $IP link set dev dummy1 up 112 $IP address add 192.0.2.1/24 dev dummy1 113 $IP -6 address add 2001:db8:2::1/64 dev dummy1 114 115 $IP route add 203.0.113.0/24 \ 116 nexthop via 198.51.100.2 dev dummy0 \ 117 nexthop via 192.0.2.2 dev dummy1 118 $IP -6 route add 2001:db8:3::/64 \ 119 nexthop via 2001:db8:1::2 dev dummy0 \ 120 nexthop via 2001:db8:2::2 dev dummy1 121 set +e 122 123 echo " Start point" 124 $IP route get fibmatch 203.0.113.1 &> /dev/null 125 log_test $? 0 "IPv4 fibmatch" 126 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null 127 log_test $? 0 "IPv6 fibmatch" 128 129 set -e 130 $IP link del dev dummy0 131 set +e 132 133 echo " One nexthop device deleted" 134 $IP route get fibmatch 203.0.113.1 &> /dev/null 135 log_test $? 2 "IPv4 - multipath route removed on delete" 136 137 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null 138 # In IPv6 we do not flush the entire multipath route. 139 log_test $? 0 "IPv6 - multipath down to single path" 140 141 set -e 142 $IP link del dev dummy1 143 set +e 144 145 echo " Second nexthop device deleted" 146 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null 147 log_test $? 2 "IPv6 - no route" 148 149 cleanup 150} 151 152fib_unreg_test() 153{ 154 fib_unreg_unicast_test 155 fib_unreg_multipath_test 156} 157 158fib_down_unicast_test() 159{ 160 echo 161 echo "Single path, admin down" 162 163 setup 164 165 echo " Start point" 166 $IP route get fibmatch 198.51.100.2 &> /dev/null 167 log_test $? 0 "IPv4 fibmatch" 168 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null 169 log_test $? 0 "IPv6 fibmatch" 170 171 set -e 172 $IP link set dev dummy0 down 173 set +e 174 175 echo " Route deleted on down" 176 $IP route get fibmatch 198.51.100.2 &> /dev/null 177 log_test $? 2 "IPv4 fibmatch" 178 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null 179 log_test $? 2 "IPv6 fibmatch" 180 181 cleanup 182} 183 184fib_down_multipath_test_do() 185{ 186 local down_dev=$1 187 local up_dev=$2 188 189 $IP route get fibmatch 203.0.113.1 \ 190 oif $down_dev &> /dev/null 191 log_test $? 2 "IPv4 fibmatch on down device" 192 $IP -6 route get fibmatch 2001:db8:3::1 \ 193 oif $down_dev &> /dev/null 194 log_test $? 2 "IPv6 fibmatch on down device" 195 196 $IP route get fibmatch 203.0.113.1 \ 197 oif $up_dev &> /dev/null 198 log_test $? 0 "IPv4 fibmatch on up device" 199 $IP -6 route get fibmatch 2001:db8:3::1 \ 200 oif $up_dev &> /dev/null 201 log_test $? 0 "IPv6 fibmatch on up device" 202 203 $IP route get fibmatch 203.0.113.1 | \ 204 grep $down_dev | grep -q "dead linkdown" 205 log_test $? 0 "IPv4 flags on down device" 206 $IP -6 route get fibmatch 2001:db8:3::1 | \ 207 grep $down_dev | grep -q "dead linkdown" 208 log_test $? 0 "IPv6 flags on down device" 209 210 $IP route get fibmatch 203.0.113.1 | \ 211 grep $up_dev | grep -q "dead linkdown" 212 log_test $? 1 "IPv4 flags on up device" 213 $IP -6 route get fibmatch 2001:db8:3::1 | \ 214 grep $up_dev | grep -q "dead linkdown" 215 log_test $? 1 "IPv6 flags on up device" 216} 217 218fib_down_multipath_test() 219{ 220 echo 221 echo "Admin down multipath" 222 223 setup 224 225 set -e 226 $IP link add dummy1 type dummy 227 $IP link set dev dummy1 up 228 229 $IP address add 192.0.2.1/24 dev dummy1 230 $IP -6 address add 2001:db8:2::1/64 dev dummy1 231 232 $IP route add 203.0.113.0/24 \ 233 nexthop via 198.51.100.2 dev dummy0 \ 234 nexthop via 192.0.2.2 dev dummy1 235 $IP -6 route add 2001:db8:3::/64 \ 236 nexthop via 2001:db8:1::2 dev dummy0 \ 237 nexthop via 2001:db8:2::2 dev dummy1 238 set +e 239 240 echo " Verify start point" 241 $IP route get fibmatch 203.0.113.1 &> /dev/null 242 log_test $? 0 "IPv4 fibmatch" 243 244 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null 245 log_test $? 0 "IPv6 fibmatch" 246 247 set -e 248 $IP link set dev dummy0 down 249 set +e 250 251 echo " One device down, one up" 252 fib_down_multipath_test_do "dummy0" "dummy1" 253 254 set -e 255 $IP link set dev dummy0 up 256 $IP link set dev dummy1 down 257 set +e 258 259 echo " Other device down and up" 260 fib_down_multipath_test_do "dummy1" "dummy0" 261 262 set -e 263 $IP link set dev dummy0 down 264 set +e 265 266 echo " Both devices down" 267 $IP route get fibmatch 203.0.113.1 &> /dev/null 268 log_test $? 2 "IPv4 fibmatch" 269 $IP -6 route get fibmatch 2001:db8:3::1 &> /dev/null 270 log_test $? 2 "IPv6 fibmatch" 271 272 $IP link del dev dummy1 273 cleanup 274} 275 276fib_down_test() 277{ 278 fib_down_unicast_test 279 fib_down_multipath_test 280} 281 282# Local routes should not be affected when carrier changes. 283fib_carrier_local_test() 284{ 285 echo 286 echo "Local carrier tests - single path" 287 288 setup 289 290 set -e 291 $IP link set dev dummy0 carrier on 292 set +e 293 294 echo " Start point" 295 $IP route get fibmatch 198.51.100.1 &> /dev/null 296 log_test $? 0 "IPv4 fibmatch" 297 $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null 298 log_test $? 0 "IPv6 fibmatch" 299 300 $IP route get fibmatch 198.51.100.1 | \ 301 grep -q "linkdown" 302 log_test $? 1 "IPv4 - no linkdown flag" 303 $IP -6 route get fibmatch 2001:db8:1::1 | \ 304 grep -q "linkdown" 305 log_test $? 1 "IPv6 - no linkdown flag" 306 307 set -e 308 $IP link set dev dummy0 carrier off 309 sleep 1 310 set +e 311 312 echo " Carrier off on nexthop" 313 $IP route get fibmatch 198.51.100.1 &> /dev/null 314 log_test $? 0 "IPv4 fibmatch" 315 $IP -6 route get fibmatch 2001:db8:1::1 &> /dev/null 316 log_test $? 0 "IPv6 fibmatch" 317 318 $IP route get fibmatch 198.51.100.1 | \ 319 grep -q "linkdown" 320 log_test $? 1 "IPv4 - linkdown flag set" 321 $IP -6 route get fibmatch 2001:db8:1::1 | \ 322 grep -q "linkdown" 323 log_test $? 1 "IPv6 - linkdown flag set" 324 325 set -e 326 $IP address add 192.0.2.1/24 dev dummy0 327 $IP -6 address add 2001:db8:2::1/64 dev dummy0 328 set +e 329 330 echo " Route to local address with carrier down" 331 $IP route get fibmatch 192.0.2.1 &> /dev/null 332 log_test $? 0 "IPv4 fibmatch" 333 $IP -6 route get fibmatch 2001:db8:2::1 &> /dev/null 334 log_test $? 0 "IPv6 fibmatch" 335 336 $IP route get fibmatch 192.0.2.1 | \ 337 grep -q "linkdown" 338 log_test $? 1 "IPv4 linkdown flag set" 339 $IP -6 route get fibmatch 2001:db8:2::1 | \ 340 grep -q "linkdown" 341 log_test $? 1 "IPv6 linkdown flag set" 342 343 cleanup 344} 345 346fib_carrier_unicast_test() 347{ 348 ret=0 349 350 echo 351 echo "Single path route carrier test" 352 353 setup 354 355 set -e 356 $IP link set dev dummy0 carrier on 357 set +e 358 359 echo " Start point" 360 $IP route get fibmatch 198.51.100.2 &> /dev/null 361 log_test $? 0 "IPv4 fibmatch" 362 $IP -6 route get fibmatch 2001:db8:1::2 &> /dev/null 363 log_test $? 0 "IPv6 fibmatch" 364 365 $IP route get fibmatch 198.51.100.2 | \ 366 grep -q "linkdown" 367 log_test $? 1 "IPv4 no linkdown flag" 368 $IP -6 route get fibmatch 2001:db8:1::2 | \ 369 grep -q "linkdown" 370 log_test $? 1 "IPv6 no linkdown flag" 371 372 set -e 373 $IP link set dev dummy0 carrier off 374 set +e 375 376 echo " Carrier down" 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 $? 0 "IPv4 linkdown flag set" 385 $IP -6 route get fibmatch 2001:db8:1::2 | \ 386 grep -q "linkdown" 387 log_test $? 0 "IPv6 linkdown flag set" 388 389 set -e 390 $IP address add 192.0.2.1/24 dev dummy0 391 $IP -6 address add 2001:db8:2::1/64 dev dummy0 392 set +e 393 394 echo " Second address added with carrier down" 395 $IP route get fibmatch 192.0.2.2 &> /dev/null 396 log_test $? 0 "IPv4 fibmatch" 397 $IP -6 route get fibmatch 2001:db8:2::2 &> /dev/null 398 log_test $? 0 "IPv6 fibmatch" 399 400 $IP route get fibmatch 192.0.2.2 | \ 401 grep -q "linkdown" 402 log_test $? 0 "IPv4 linkdown flag set" 403 $IP -6 route get fibmatch 2001:db8:2::2 | \ 404 grep -q "linkdown" 405 log_test $? 0 "IPv6 linkdown flag set" 406 407 cleanup 408} 409 410fib_carrier_test() 411{ 412 fib_carrier_local_test 413 fib_carrier_unicast_test 414} 415 416################################################################################ 417# Tests on nexthop spec 418 419# run 'ip route add' with given spec 420add_rt() 421{ 422 local desc="$1" 423 local erc=$2 424 local vrf=$3 425 local pfx=$4 426 local gw=$5 427 local dev=$6 428 local cmd out rc 429 430 [ "$vrf" = "-" ] && vrf="default" 431 [ -n "$gw" ] && gw="via $gw" 432 [ -n "$dev" ] && dev="dev $dev" 433 434 cmd="$IP route add vrf $vrf $pfx $gw $dev" 435 if [ "$VERBOSE" = "1" ]; then 436 printf "\n COMMAND: $cmd\n" 437 fi 438 439 out=$(eval $cmd 2>&1) 440 rc=$? 441 if [ "$VERBOSE" = "1" -a -n "$out" ]; then 442 echo " $out" 443 fi 444 log_test $rc $erc "$desc" 445} 446 447fib4_nexthop() 448{ 449 echo 450 echo "IPv4 nexthop tests" 451 452 echo "<<< write me >>>" 453} 454 455fib6_nexthop() 456{ 457 local lldummy=$(get_linklocal dummy0) 458 local llv1=$(get_linklocal dummy0) 459 460 if [ -z "$lldummy" ]; then 461 echo "Failed to get linklocal address for dummy0" 462 return 1 463 fi 464 if [ -z "$llv1" ]; then 465 echo "Failed to get linklocal address for veth1" 466 return 1 467 fi 468 469 echo 470 echo "IPv6 nexthop tests" 471 472 add_rt "Directly connected nexthop, unicast address" 0 \ 473 - 2001:db8:101::/64 2001:db8:1::2 474 add_rt "Directly connected nexthop, unicast address with device" 0 \ 475 - 2001:db8:102::/64 2001:db8:1::2 "dummy0" 476 add_rt "Gateway is linklocal address" 0 \ 477 - 2001:db8:103::1/64 $llv1 "veth0" 478 479 # fails because LL address requires a device 480 add_rt "Gateway is linklocal address, no device" 2 \ 481 - 2001:db8:104::1/64 $llv1 482 483 # local address can not be a gateway 484 add_rt "Gateway can not be local unicast address" 2 \ 485 - 2001:db8:105::/64 2001:db8:1::1 486 add_rt "Gateway can not be local unicast address, with device" 2 \ 487 - 2001:db8:106::/64 2001:db8:1::1 "dummy0" 488 add_rt "Gateway can not be a local linklocal address" 2 \ 489 - 2001:db8:107::1/64 $lldummy "dummy0" 490 491 # VRF tests 492 add_rt "Gateway can be local address in a VRF" 0 \ 493 - 2001:db8:108::/64 2001:db8:51::2 494 add_rt "Gateway can be local address in a VRF, with device" 0 \ 495 - 2001:db8:109::/64 2001:db8:51::2 "veth0" 496 add_rt "Gateway can be local linklocal address in a VRF" 0 \ 497 - 2001:db8:110::1/64 $llv1 "veth0" 498 499 add_rt "Redirect to VRF lookup" 0 \ 500 - 2001:db8:111::/64 "" "red" 501 502 add_rt "VRF route, gateway can be local address in default VRF" 0 \ 503 red 2001:db8:112::/64 2001:db8:51::1 504 505 # local address in same VRF fails 506 add_rt "VRF route, gateway can not be a local address" 2 \ 507 red 2001:db8:113::1/64 2001:db8:2::1 508 add_rt "VRF route, gateway can not be a local addr with device" 2 \ 509 red 2001:db8:114::1/64 2001:db8:2::1 "dummy1" 510} 511 512# Default VRF: 513# dummy0 - 198.51.100.1/24 2001:db8:1::1/64 514# veth0 - 192.0.2.1/24 2001:db8:51::1/64 515# 516# VRF red: 517# dummy1 - 192.168.2.1/24 2001:db8:2::1/64 518# veth1 - 192.0.2.2/24 2001:db8:51::2/64 519# 520# [ dummy0 veth0 ]--[ veth1 dummy1 ] 521 522fib_nexthop_test() 523{ 524 setup 525 526 set -e 527 528 $IP -4 rule add pref 32765 table local 529 $IP -4 rule del pref 0 530 $IP -6 rule add pref 32765 table local 531 $IP -6 rule del pref 0 532 533 $IP link add red type vrf table 1 534 $IP link set red up 535 $IP -4 route add vrf red unreachable default metric 4278198272 536 $IP -6 route add vrf red unreachable default metric 4278198272 537 538 $IP link add veth0 type veth peer name veth1 539 $IP link set dev veth0 up 540 $IP address add 192.0.2.1/24 dev veth0 541 $IP -6 address add 2001:db8:51::1/64 dev veth0 542 543 $IP link set dev veth1 vrf red up 544 $IP address add 192.0.2.2/24 dev veth1 545 $IP -6 address add 2001:db8:51::2/64 dev veth1 546 547 $IP link add dummy1 type dummy 548 $IP link set dev dummy1 vrf red up 549 $IP address add 192.168.2.1/24 dev dummy1 550 $IP -6 address add 2001:db8:2::1/64 dev dummy1 551 set +e 552 553 sleep 1 554 fib4_nexthop 555 fib6_nexthop 556 557 ( 558 $IP link del dev dummy1 559 $IP link del veth0 560 $IP link del red 561 ) 2>/dev/null 562 cleanup 563} 564 565################################################################################ 566# 567 568fib_test() 569{ 570 if [ -n "$TEST" ]; then 571 eval $TEST 572 else 573 fib_unreg_test 574 fib_down_test 575 fib_carrier_test 576 fib_nexthop_test 577 fi 578} 579 580if [ "$(id -u)" -ne 0 ];then 581 echo "SKIP: Need root privileges" 582 exit 0 583fi 584 585if [ ! -x "$(command -v ip)" ]; then 586 echo "SKIP: Could not run test without ip tool" 587 exit 0 588fi 589 590ip route help 2>&1 | grep -q fibmatch 591if [ $? -ne 0 ]; then 592 echo "SKIP: iproute2 too old, missing fibmatch" 593 exit 0 594fi 595 596# start clean 597cleanup &> /dev/null 598 599fib_test 600 601exit $ret 602