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