1#!/bin/bash 2# 3# This tests the fib expression. 4# 5# Kselftest framework requirement - SKIP code is 4. 6# 7# 10.0.1.99 10.0.1.1 10.0.2.1 10.0.2.99 8# dead:1::99 dead:1::1 dead:2::1 dead:2::99 9# ns1 <-------> [ veth0 ] nsrouter [veth1] <-------> ns2 10 11source lib.sh 12 13ret=0 14 15timeout=4 16 17log_netns=$(sysctl -n net.netfilter.nf_log_all_netns) 18 19cleanup() 20{ 21 cleanup_all_ns 22 23 [ "$log_netns" -eq 0 ] && sysctl -q net.netfilter.nf_log_all_netns=$log_netns 24} 25 26checktool "nft --version" "run test without nft" 27 28setup_ns nsrouter ns1 ns2 29 30trap cleanup EXIT 31 32if dmesg | grep -q ' nft_rpfilter: ';then 33 dmesg -c | grep ' nft_rpfilter: ' 34 echo "WARN: a previous test run has failed" 1>&2 35fi 36 37sysctl -q net.netfilter.nf_log_all_netns=1 38 39load_ruleset() { 40 local netns=$1 41 42ip netns exec "$netns" nft -f /dev/stdin <<EOF 43table inet filter { 44 chain prerouting { 45 type filter hook prerouting priority 0; policy accept; 46 fib saddr . iif oif missing counter log prefix "$netns nft_rpfilter: " drop 47 } 48} 49EOF 50} 51 52load_input_ruleset() { 53 local netns=$1 54 55ip netns exec "$netns" nft -f /dev/stdin <<EOF 56table inet filter { 57 chain input { 58 type filter hook input priority 0; policy accept; 59 fib saddr . iif oif missing counter log prefix "$netns nft_rpfilter: " drop 60 } 61} 62EOF 63} 64 65load_pbr_ruleset() { 66 local netns=$1 67 68ip netns exec "$netns" nft -f /dev/stdin <<EOF 69table inet filter { 70 chain forward { 71 type filter hook forward priority raw; 72 fib saddr . iif oif gt 0 accept 73 log drop 74 } 75} 76EOF 77} 78 79load_type_ruleset() { 80 local netns=$1 81 82 for family in ip ip6;do 83ip netns exec "$netns" nft -f /dev/stdin <<EOF 84table $family filter { 85 chain type_match_in { 86 fib daddr type local counter comment "daddr configured on other iface" 87 fib daddr . iif type local counter comment "daddr configured on iif" 88 fib daddr type unicast counter comment "daddr not local" 89 fib daddr . iif type unicast counter comment "daddr not configured on iif" 90 } 91 92 chain type_match_out { 93 fib daddr type unicast counter 94 fib daddr . oif type unicast counter 95 fib daddr type local counter 96 fib daddr . oif type local counter 97 } 98 99 chain prerouting { 100 type filter hook prerouting priority 0; 101 icmp type echo-request counter jump type_match_in 102 icmpv6 type echo-request counter jump type_match_in 103 } 104 105 chain input { 106 type filter hook input priority 0; 107 icmp type echo-request counter jump type_match_in 108 icmpv6 type echo-request counter jump type_match_in 109 } 110 111 chain forward { 112 type filter hook forward priority 0; 113 icmp type echo-request counter jump type_match_in 114 icmpv6 type echo-request counter jump type_match_in 115 } 116 117 chain output { 118 type filter hook output priority 0; 119 icmp type echo-request counter jump type_match_out 120 icmpv6 type echo-request counter jump type_match_out 121 } 122 123 chain postrouting { 124 type filter hook postrouting priority 0; 125 icmp type echo-request counter jump type_match_out 126 icmpv6 type echo-request counter jump type_match_out 127 } 128} 129EOF 130done 131} 132 133reload_type_ruleset() { 134 ip netns exec "$1" nft flush table ip filter 135 ip netns exec "$1" nft flush table ip6 filter 136 load_type_ruleset "$1" 137} 138 139check_fib_type_counter_family() { 140 local family="$1" 141 local want="$2" 142 local ns="$3" 143 local chain="$4" 144 local what="$5" 145 local errmsg="$6" 146 147 if ! ip netns exec "$ns" nft list chain "$family" filter "$chain" | grep "$what" | grep -q "packets $want";then 148 echo "Netns $ns $family fib type counter doesn't match expected packet count of $want for $what $errmsg" 1>&2 149 ip netns exec "$ns" nft list chain "$family" filter "$chain" 150 ret=1 151 return 1 152 fi 153 154 return 0 155} 156 157check_fib_type_counter() { 158 check_fib_type_counter_family "ip" "$@" || return 1 159 check_fib_type_counter_family "ip6" "$@" || return 1 160} 161 162load_ruleset_count() { 163 local netns=$1 164 165ip netns exec "$netns" nft -f /dev/stdin <<EOF 166table inet filter { 167 chain prerouting { 168 type filter hook prerouting priority 0; policy accept; 169 ip daddr 1.1.1.1 fib saddr . iif oif missing counter drop 170 ip6 daddr 1c3::c01d fib saddr . iif oif missing counter drop 171 } 172} 173EOF 174} 175 176check_drops() { 177 if dmesg | grep -q ' nft_rpfilter: ';then 178 dmesg | grep ' nft_rpfilter: ' 179 echo "FAIL: rpfilter did drop packets" 180 ret=1 181 return 1 182 fi 183 184 return 0 185} 186 187check_fib_counter() { 188 local want=$1 189 local ns=$2 190 local address=$3 191 192 if ! ip netns exec "$ns" nft list table inet filter | grep 'fib saddr . iif' | grep "$address" | grep -q "packets $want";then 193 echo "Netns $ns fib counter doesn't match expected packet count of $want for $address" 1>&2 194 ip netns exec "$ns" nft list table inet filter 195 return 1 196 fi 197 198 if [ "$want" -gt 0 ]; then 199 echo "PASS: fib expression did drop packets for $address" 200 fi 201 202 return 0 203} 204 205load_ruleset "$nsrouter" 206load_ruleset "$ns1" 207load_ruleset "$ns2" 208 209if ! ip link add veth0 netns "$nsrouter" type veth peer name eth0 netns "$ns1" > /dev/null 2>&1; then 210 echo "SKIP: No virtual ethernet pair device support in kernel" 211 exit $ksft_skip 212fi 213ip link add veth1 netns "$nsrouter" type veth peer name eth0 netns "$ns2" 214 215ip -net "$nsrouter" link set veth0 up 216ip -net "$nsrouter" addr add 10.0.1.1/24 dev veth0 217ip -net "$nsrouter" addr add dead:1::1/64 dev veth0 nodad 218 219ip -net "$nsrouter" link set veth1 up 220ip -net "$nsrouter" addr add 10.0.2.1/24 dev veth1 221ip -net "$nsrouter" addr add dead:2::1/64 dev veth1 nodad 222 223ip -net "$ns1" link set eth0 up 224ip -net "$ns2" link set eth0 up 225 226ip -net "$ns1" addr add 10.0.1.99/24 dev eth0 227ip -net "$ns1" addr add dead:1::99/64 dev eth0 nodad 228ip -net "$ns1" route add default via 10.0.1.1 229ip -net "$ns1" route add default via dead:1::1 230 231ip -net "$ns2" addr add 10.0.2.99/24 dev eth0 232ip -net "$ns2" addr add dead:2::99/64 dev eth0 nodad 233ip -net "$ns2" route add default via 10.0.2.1 234ip -net "$ns2" route add default via dead:2::1 235 236test_ping() { 237 local daddr4=$1 238 local daddr6=$2 239 240 if ! ip netns exec "$ns1" ping -c 1 -q "$daddr4" > /dev/null; then 241 check_drops 242 echo "FAIL: ${ns1} cannot reach $daddr4, ret $ret" 1>&2 243 return 1 244 fi 245 246 if ! ip netns exec "$ns1" ping -c 1 -q "$daddr6" > /dev/null; then 247 check_drops 248 echo "FAIL: ${ns1} cannot reach $daddr6, ret $ret" 1>&2 249 return 1 250 fi 251 252 return 0 253} 254 255test_ping_unreachable() { 256 local daddr4=$1 257 local daddr6=$2 258 259 if ip netns exec "$ns1" ping -c 1 -W 0.1 -q "$daddr4" > /dev/null; then 260 echo "FAIL: ${ns1} could reach $daddr4" 1>&2 261 return 1 262 fi 263 264 if ip netns exec "$ns1" ping -c 1 -W 0.1 -q "$daddr6" > /dev/null; then 265 echo "FAIL: ${ns1} could reach $daddr6" 1>&2 266 return 1 267 fi 268 269 return 0 270} 271 272test_fib_type() { 273 local notice="$1" 274 local errmsg="addr-on-if" 275 local lret=0 276 277 if ! load_type_ruleset "$nsrouter";then 278 echo "SKIP: Could not load fib type ruleset" 279 [ $ret -eq 0 ] && ret=$ksft_skip 280 return 281 fi 282 283 # makes router receive packet for addresses configured on incoming 284 # interface. 285 test_ping 10.0.1.1 dead:1::1 || return 1 286 287 # expectation: triggers all 'local' in prerouting/input. 288 check_fib_type_counter 2 "$nsrouter" "type_match_in" "fib daddr type local" "$errmsg" || lret=1 289 check_fib_type_counter 2 "$nsrouter" "type_match_in" "fib daddr . iif type local" "$errmsg" || lret=1 290 291 reload_type_ruleset "$nsrouter" 292 # makes router receive packet for address configured on a different (but local) 293 # interface. 294 test_ping 10.0.2.1 dead:2::1 || return 1 295 296 # expectation: triggers 'unicast' in prerouting/input for daddr . iif and local for 'daddr'. 297 errmsg="addr-on-host" 298 check_fib_type_counter 2 "$nsrouter" "type_match_in" "fib daddr type local" "$errmsg" || lret=1 299 check_fib_type_counter 2 "$nsrouter" "type_match_in" "fib daddr . iif type unicast" "$errmsg" || lret=1 300 301 reload_type_ruleset "$nsrouter" 302 test_ping 10.0.2.99 dead:2::99 || return 1 303 errmsg="addr-on-otherhost" 304 check_fib_type_counter 2 "$nsrouter" "type_match_in" "fib daddr type unicast" "$errmsg" || lret=1 305 check_fib_type_counter 2 "$nsrouter" "type_match_in" "fib daddr . iif type unicast" "$errmsg" || lret=1 306 307 if [ $lret -eq 0 ];then 308 echo "PASS: fib expression address types match ($notice)" 309 else 310 echo "FAIL: fib expression address types match ($notice)" 311 ret=1 312 fi 313} 314 315test_fib_vrf_dev_add_dummy() 316{ 317 if ! ip -net "$nsrouter" link add dummy0 type dummy ;then 318 echo "SKIP: VRF tests: dummy device type not supported" 319 return 1 320 fi 321 322 if ! ip -net "$nsrouter" link add tvrf type vrf table 9876;then 323 echo "SKIP: VRF tests: vrf device type not supported" 324 return 1 325 fi 326 327 ip -net "$nsrouter" link set dummy0 master tvrf 328 ip -net "$nsrouter" link set dummy0 up 329 ip -net "$nsrouter" link set tvrf up 330} 331 332load_ruleset_vrf() 333{ 334# Due to the many different possible combinations using named counters 335# or one-rule-per-expected-result is complex. 336# 337# Instead, add dynamic sets for the fib modes 338# (fib address type, fib output interface lookup .. ), 339# and then add the obtained fib results to them. 340# 341# The test is successful if the sets contain the expected results 342# and no unexpected extra entries existed. 343ip netns exec "$nsrouter" nft -f - <<EOF 344flush ruleset 345table inet t { 346 set fibif4 { 347 typeof meta iif . ip daddr . fib daddr oif 348 flags dynamic 349 counter 350 } 351 352 set fibif4iif { 353 typeof meta iif . ip daddr . fib daddr . iif oif 354 flags dynamic 355 counter 356 } 357 358 set fibif6 { 359 typeof meta iif . ip6 daddr . fib daddr oif 360 flags dynamic 361 counter 362 } 363 364 set fibif6iif { 365 typeof meta iif . ip6 daddr . fib daddr . iif oif 366 flags dynamic 367 counter 368 } 369 370 set fibtype4 { 371 typeof meta iif . ip daddr . fib daddr type 372 flags dynamic 373 counter 374 } 375 376 set fibtype4iif { 377 typeof meta iif . ip daddr . fib daddr . iif type 378 flags dynamic 379 counter 380 } 381 382 set fibtype6 { 383 typeof meta iif . ip6 daddr . fib daddr type 384 flags dynamic 385 counter 386 } 387 388 set fibtype6iif { 389 typeof meta iif . ip6 daddr . fib daddr . iif type 390 flags dynamic 391 counter 392 } 393 394 chain fib_test { 395 meta nfproto ipv4 jump { 396 add @fibif4 { meta iif . ip daddr . fib daddr oif } 397 add @fibif4iif { meta iif . ip daddr . fib daddr . iif oif } 398 add @fibtype4 { meta iif . ip daddr . fib daddr type } 399 add @fibtype4iif { meta iif . ip daddr . fib daddr . iif type } 400 401 add @fibif4 { meta iif . ip saddr . fib saddr oif } 402 add @fibif4iif { meta iif . ip saddr . fib saddr . iif oif } 403 } 404 405 meta nfproto ipv6 jump { 406 add @fibif6 { meta iif . ip6 daddr . fib daddr oif } 407 add @fibif6iif { meta iif . ip6 daddr . fib daddr . iif oif } 408 add @fibtype6 { meta iif . ip6 daddr . fib daddr type } 409 add @fibtype6iif { meta iif . ip6 daddr . fib daddr . iif type } 410 411 add @fibif6 { meta iif . ip6 saddr . fib saddr oif } 412 add @fibif6iif { meta iif . ip6 saddr . fib saddr . iif oif } 413 } 414 } 415 416 chain prerouting { 417 type filter hook prerouting priority 0; 418 icmp type echo-request counter jump fib_test 419 420 # neighbour discovery to be ignored. 421 icmpv6 type echo-request counter jump fib_test 422 } 423} 424EOF 425 426if [ $? -ne 0 ] ;then 427 echo "SKIP: Could not load ruleset for fib vrf test" 428 [ $ret -eq 0 ] && ret=$ksft_skip 429 return 1 430fi 431} 432 433check_type() 434{ 435 local setname="$1" 436 local iifname="$2" 437 local addr="$3" 438 local type="$4" 439 local count="$5" 440 local lret=0 441 442 [ -z "$count" ] && count=1 443 444 if ! ip netns exec "$nsrouter" nft get element inet t "$setname" { "$iifname" . "$addr" . "$type" } |grep -q "counter packets $count";then 445 echo "FAIL: did not find $iifname . $addr . $type in $setname with $count packets" 446 ip netns exec "$nsrouter" nft list set inet t "$setname" 447 ret=1 448 # do not fail right away, delete entry if it exists so later test that 449 # checks for unwanted keys don't get confused by this *expected* key. 450 lret=1 451 fi 452 453 # delete the entry, this allows to check if anything unexpected appeared 454 # at the end of the test run: all dynamic sets should be empty by then. 455 if ! ip netns exec "$nsrouter" nft delete element inet t "$setname" { "$iifname" . "$addr" . "$type" } ; then 456 echo "FAIL: can't delete $iifname . $addr . $type in $setname" 457 ip netns exec "$nsrouter" nft list set inet t "$setname" 458 ret=1 459 return 1 460 fi 461 462 return $lret 463} 464 465check_local() 466{ 467 check_type $@ "local" 1 468} 469 470check_unicast() 471{ 472 check_type $@ "unicast" 1 473} 474 475check_rpf() 476{ 477 check_type $@ 478} 479 480check_fib_vrf_sets_empty() 481{ 482 local setname="" 483 local lret=0 484 485 # A non-empty set means that we have seen unexpected packets OR 486 # that a fib lookup provided unexpected results. 487 for setname in "fibif4" "fibif4iif" "fibif6" "fibif6iif" \ 488 "fibtype4" "fibtype4iif" "fibtype6" "fibtype6iif";do 489 if ip netns exec "$nsrouter" nft list set inet t "$setname" | grep -q elements;then 490 echo "FAIL: $setname not empty" 491 ip netns exec "$nsrouter" nft list set inet t "$setname" 492 ret=1 493 lret=1 494 fi 495 done 496 497 return $lret 498} 499 500check_fib_vrf_type() 501{ 502 local msg="$1" 503 504 local addr 505 # the incoming interface is always veth0. As its not linked to a VRF, 506 # the 'tvrf' device should NOT show up anywhere. 507 local ifname="veth0" 508 local lret=0 509 510 # local_veth0, local_veth1 511 for addr in "10.0.1.1" "10.0.2.1"; do 512 check_local fibtype4 "$ifname" "$addr" || lret=1 513 check_type fibif4 "$ifname" "$addr" "0" || lret=1 514 done 515 for addr in "dead:1::1" "dead:2::1";do 516 check_local fibtype6 "$ifname" "$addr" || lret=1 517 check_type fibif6 "$ifname" "$addr" "0" || lret=1 518 done 519 520 # when restricted to the incoming interface, 10.0.1.1 should 521 # be 'local', but 10.0.2.1 unicast. 522 check_local fibtype4iif "$ifname" "10.0.1.1" || lret=1 523 check_unicast fibtype4iif "$ifname" "10.0.2.1" || lret=1 524 525 # same for the ipv6 addresses. 526 check_local fibtype6iif "$ifname" "dead:1::1" || lret=1 527 check_unicast fibtype6iif "$ifname" "dead:2::1" || lret=1 528 529 # None of these addresses should find a valid route when restricting 530 # to the incoming interface (we ask for daddr - 10.0.1.1/2.1 are 531 # reachable via 'lo'. 532 for addr in "10.0.1.1" "10.0.2.1" "10.9.9.1" "10.9.9.2";do 533 check_type fibif4iif "$ifname" "$addr" "0" || lret=1 534 done 535 536 # expect default route (veth1), dummy0 is part of VRF but iif isn't. 537 for addr in "10.9.9.1" "10.9.9.2";do 538 check_unicast fibtype4 "$ifname" "$addr" || lret=1 539 check_unicast fibtype4iif "$ifname" "$addr" || lret=1 540 check_type fibif4 "$ifname" "$addr" "veth1" || lret=1 541 done 542 for addr in "dead:9::1" "dead:9::2";do 543 check_unicast fibtype6 "$ifname" "$addr" || lret=1 544 check_unicast fibtype6iif "$ifname" "$addr" || lret=1 545 check_type fibif6 "$ifname" "$addr" "veth1" || lret=1 546 done 547 548 # same for the IPv6 equivalent addresses. 549 for addr in "dead:1::1" "dead:2::1" "dead:9::1" "dead:9::2";do 550 check_type fibif6iif "$ifname" "$addr" "0" || lret=1 551 done 552 553 check_unicast fibtype4 "$ifname" "10.0.2.99" || lret=1 554 check_unicast fibtype4iif "$ifname" "10.0.2.99" || lret=1 555 check_unicast fibtype6 "$ifname" "dead:2::99" || lret=1 556 check_unicast fibtype6iif "$ifname" "dead:2::99" || lret=1 557 558 check_type fibif4 "$ifname" "10.0.2.99" "veth1" || lret=1 559 check_type fibif4iif "$ifname" "10.0.2.99" 0 || lret=1 560 check_type fibif6 "$ifname" "dead:2::99" "veth1" || lret=1 561 check_type fibif6iif "$ifname" "dead:2::99" 0 || lret=1 562 563 check_rpf fibif4 "$ifname" "10.0.1.99" "veth0" 5 || lret=1 564 check_rpf fibif4iif "$ifname" "10.0.1.99" "veth0" 5 || lret=1 565 check_rpf fibif6 "$ifname" "dead:1::99" "veth0" 5 || lret=1 566 check_rpf fibif6iif "$ifname" "dead:1::99" "veth0" 5 || lret=1 567 568 check_fib_vrf_sets_empty || lret=1 569 570 if [ $lret -eq 0 ];then 571 echo "PASS: $msg" 572 else 573 echo "FAIL: $msg" 574 ret=1 575 fi 576} 577 578check_fib_veth_vrf_type() 579{ 580 local msg="$1" 581 582 local addr 583 local ifname 584 local setname 585 local lret=0 586 587 # as veth0 is now part of tvrf interface, packets will be seen 588 # twice, once with iif veth0, then with iif tvrf. 589 590 for ifname in "veth0" "tvrf"; do 591 for addr in "10.0.1.1" "10.9.9.1"; do 592 check_local fibtype4 "$ifname" "$addr" || lret=1 593 # addr local, but nft_fib doesn't return routes with RTN_LOCAL. 594 check_type fibif4 "$ifname" "$addr" 0 || lret=1 595 check_type fibif4iif "$ifname" "$addr" 0 || lret=1 596 done 597 598 for addr in "dead:1::1" "dead:9::1"; do 599 check_local fibtype6 "$ifname" "$addr" || lret=1 600 # same, address is local but no route is returned for lo. 601 check_type fibif6 "$ifname" "$addr" 0 || lret=1 602 check_type fibif6iif "$ifname" "$addr" 0 || lret=1 603 done 604 605 for t in fibtype4 fibtype4iif; do 606 check_unicast "$t" "$ifname" 10.9.9.2 || lret=1 607 done 608 for t in fibtype6 fibtype6iif; do 609 check_unicast "$t" "$ifname" dead:9::2 || lret=1 610 done 611 612 check_unicast fibtype4iif "$ifname" "10.9.9.1" || lret=1 613 check_unicast fibtype6iif "$ifname" "dead:9::1" || lret=1 614 615 check_unicast fibtype4 "$ifname" "10.0.2.99" || lret=1 616 check_unicast fibtype4iif "$ifname" "10.0.2.99" || lret=1 617 618 check_unicast fibtype6 "$ifname" "dead:2::99" || lret=1 619 check_unicast fibtype6iif "$ifname" "dead:2::99" || lret=1 620 621 check_type fibif4 "$ifname" "10.0.2.99" "veth1" || lret=1 622 check_type fibif6 "$ifname" "dead:2::99" "veth1" || lret=1 623 check_type fibif4 "$ifname" "10.9.9.2" "dummy0" || lret=1 624 check_type fibif6 "$ifname" "dead:9::2" "dummy0" || lret=1 625 626 # restricted to iif -- MUST NOT provide result, its != $ifname. 627 check_type fibif4iif "$ifname" "10.0.2.99" 0 || lret=1 628 check_type fibif6iif "$ifname" "dead:2::99" 0 || lret=1 629 630 check_rpf fibif4 "$ifname" "10.0.1.99" "veth0" 4 || lret=1 631 check_rpf fibif6 "$ifname" "dead:1::99" "veth0" 4 || lret=1 632 check_rpf fibif4iif "$ifname" "10.0.1.99" "$ifname" 4 || lret=1 633 check_rpf fibif6iif "$ifname" "dead:1::99" "$ifname" 4 || lret=1 634 done 635 636 check_local fibtype4iif "veth0" "10.0.1.1" || lret=1 637 check_local fibtype6iif "veth0" "dead:1::1" || lret=1 638 639 check_unicast fibtype4iif "tvrf" "10.0.1.1" || lret=1 640 check_unicast fibtype6iif "tvrf" "dead:1::1" || lret=1 641 642 # 10.9.9.2 should not provide a result for iif veth, but 643 # should when iif is tvrf. 644 # This is because its reachable via dummy0 which is part of 645 # tvrf. iif veth0 MUST conceal the dummy0 result (i.e. return oif 0). 646 check_type fibif4iif "veth0" "10.9.9.2" 0 || lret=1 647 check_type fibif6iif "veth0" "dead:9::2" 0 || lret=1 648 649 check_type fibif4iif "tvrf" "10.9.9.2" "tvrf" || lret=1 650 check_type fibif6iif "tvrf" "dead:9::2" "tvrf" || lret=1 651 652 check_fib_vrf_sets_empty || lret=1 653 654 if [ $lret -eq 0 ];then 655 echo "PASS: $msg" 656 else 657 echo "FAIL: $msg" 658 ret=1 659 fi 660} 661 662# Extends nsrouter config by adding dummy0+vrf. 663# 664# 10.0.1.99 10.0.1.1 10.0.2.1 10.0.2.99 665# dead:1::99 dead:1::1 dead:2::1 dead:2::99 666# ns1 <-------> [ veth0 ] nsrouter [veth1] <-------> ns2 667# [dummy0] 668# 10.9.9.1 669# dead:9::1 670# [tvrf] 671test_fib_vrf() 672{ 673 local cntname="" 674 675 if ! test_fib_vrf_dev_add_dummy; then 676 [ $ret -eq 0 ] && ret=$ksft_skip 677 return 678 fi 679 680 ip -net "$nsrouter" addr add "10.9.9.1"/24 dev dummy0 681 ip -net "$nsrouter" addr add "dead:9::1"/64 dev dummy0 nodad 682 683 ip -net "$nsrouter" route add default via 10.0.2.99 684 ip -net "$nsrouter" route add default via dead:2::99 685 686 load_ruleset_vrf || return 687 688 # no echo reply for these addresses: The dummy interface is part of tvrf, 689 # but veth0 (incoming interface) isn't linked to it. 690 test_ping_unreachable "10.9.9.1" "dead:9::1" & 691 test_ping_unreachable "10.9.9.2" "dead:9::2" & 692 693 # expect replies from these. 694 test_ping "10.0.1.1" "dead:1::1" 695 test_ping "10.0.2.1" "dead:2::1" 696 test_ping "10.0.2.99" "dead:2::99" 697 698 wait 699 700 check_fib_vrf_type "fib expression address types match (iif not in vrf)" 701 702 # second round: this time, make veth0 (rx interface) part of the vrf. 703 # 10.9.9.1 / dead:9::1 become reachable from ns1, while ns2 704 # becomes unreachable. 705 ip -net "$nsrouter" link set veth0 master tvrf 706 ip -net "$nsrouter" addr add dead:1::1/64 dev veth0 nodad 707 708 # this reload should not be needed, but in case 709 # there is some error (missing or unexpected entry) this will prevent them 710 # from leaking into round 2. 711 load_ruleset_vrf || return 712 713 test_ping "10.0.1.1" "dead:1::1" 714 test_ping "10.9.9.1" "dead:9::1" 715 716 # ns2 should no longer be reachable (veth1 not in vrf) 717 test_ping_unreachable "10.0.2.99" "dead:2::99" & 718 719 # vrf via dummy0, but host doesn't exist 720 test_ping_unreachable "10.9.9.2" "dead:9::2" & 721 722 wait 723 724 check_fib_veth_vrf_type "fib expression address types match (iif in vrf)" 725} 726 727ip netns exec "$nsrouter" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null 728ip netns exec "$nsrouter" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null 729ip netns exec "$nsrouter" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null 730 731test_ping 10.0.2.1 dead:2::1 || exit 1 732check_drops 733 734test_ping 10.0.2.99 dead:2::99 || exit 1 735check_drops 736 737[ $ret -eq 0 ] && echo "PASS: fib expression did not cause unwanted packet drops" 738 739load_input_ruleset "$ns1" 740 741test_ping 127.0.0.1 ::1 742check_drops 743 744test_ping 10.0.1.99 dead:1::99 745check_drops 746 747[ $ret -eq 0 ] && echo "PASS: fib expression did not discard loopback packets" 748 749load_input_ruleset "$ns1" 750 751test_ping 127.0.0.1 ::1 || exit 1 752check_drops || exit 1 753 754test_ping 10.0.1.99 dead:1::99 || exit 1 755check_drops || exit 1 756 757echo "PASS: fib expression did not discard loopback packets" 758 759ip netns exec "$nsrouter" nft flush table inet filter 760 761ip -net "$ns1" route del default 762ip -net "$ns1" -6 route del default 763 764ip -net "$ns1" addr del 10.0.1.99/24 dev eth0 765ip -net "$ns1" addr del dead:1::99/64 dev eth0 766 767ip -net "$ns1" addr add 10.0.2.99/24 dev eth0 768ip -net "$ns1" addr add dead:2::99/64 dev eth0 nodad 769 770ip -net "$ns1" route add default via 10.0.2.1 771ip -net "$ns1" -6 route add default via dead:2::1 772 773ip -net "$nsrouter" addr add dead:2::1/64 dev veth0 nodad 774 775# switch to ruleset that doesn't log, this time 776# its expected that this does drop the packets. 777load_ruleset_count "$nsrouter" 778 779# ns1 has a default route, but nsrouter does not. 780# must not check return value, ping to 1.1.1.1 will 781# fail. 782check_fib_counter 0 "$nsrouter" 1.1.1.1 || exit 1 783check_fib_counter 0 "$nsrouter" 1c3::c01d || exit 1 784 785ip netns exec "$ns1" ping -W 0.5 -c 1 -q 1.1.1.1 > /dev/null 786check_fib_counter 1 "$nsrouter" 1.1.1.1 || exit 1 787 788ip netns exec "$ns1" ping -W 0.5 -i 0.1 -c 3 -q 1c3::c01d > /dev/null 789check_fib_counter 3 "$nsrouter" 1c3::c01d || exit 1 790 791# delete all rules 792ip netns exec "$ns1" nft flush ruleset 793ip netns exec "$ns2" nft flush ruleset 794ip netns exec "$nsrouter" nft flush ruleset 795 796ip -net "$ns1" addr add 10.0.1.99/24 dev eth0 797ip -net "$ns1" addr add dead:1::99/64 dev eth0 nodad 798 799ip -net "$ns1" addr del 10.0.2.99/24 dev eth0 800ip -net "$ns1" addr del dead:2::99/64 dev eth0 801 802ip -net "$nsrouter" addr del dead:2::1/64 dev veth0 803 804# ... pbr ruleset for the router, check iif+oif. 805if ! load_pbr_ruleset "$nsrouter";then 806 echo "SKIP: Could not load fib forward ruleset" 807 [ "$ret" -eq 0 ] && ret=$ksft_skip 808fi 809 810ip -net "$nsrouter" rule add from all table 128 811ip -net "$nsrouter" rule add from all iif veth0 table 129 812ip -net "$nsrouter" route add table 128 to 10.0.1.0/24 dev veth0 813ip -net "$nsrouter" route add table 129 to 10.0.2.0/24 dev veth1 814 815# drop main ipv4 table 816ip -net "$nsrouter" -4 rule delete table main 817 818if test_ping 10.0.2.99 dead:2::99;then 819 echo "PASS: fib expression forward check with policy based routing" 820else 821 echo "FAIL: fib expression forward check with policy based routing" 822 ret=1 823fi 824 825test_fib_type "policy routing" 826ip netns exec "$nsrouter" nft delete table ip filter 827ip netns exec "$nsrouter" nft delete table ip6 filter 828 829# Un-do policy routing changes 830ip -net "$nsrouter" rule del from all table 128 831ip -net "$nsrouter" rule del from all iif veth0 table 129 832 833ip -net "$nsrouter" route del table 128 to 10.0.1.0/24 dev veth0 834ip -net "$nsrouter" route del table 129 to 10.0.2.0/24 dev veth1 835 836ip -net "$ns1" -4 route del default 837ip -net "$ns1" -6 route del default 838 839ip -net "$ns1" -4 route add default via 10.0.1.1 840ip -net "$ns1" -6 route add default via dead:1::1 841 842ip -net "$nsrouter" -4 rule add from all table main priority 32766 843 844test_fib_type "default table" 845ip netns exec "$nsrouter" nft delete table ip filter 846ip netns exec "$nsrouter" nft delete table ip6 filter 847 848test_fib_vrf 849 850exit $ret 851