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 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 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 441 [ -z "$count" ] && count=1 442 443 if ! ip netns exec "$nsrouter" nft get element inet t "$setname" { "$iifname" . "$addr" . "$type" } |grep -q "counter packets $count";then 444 echo "FAIL: did not find $iifname . $addr . $type in $setname" 445 ip netns exec "$nsrouter" nft list set inet t "$setname" 446 ret=1 447 return 1 448 fi 449 450 # delete the entry, this allows to check if anything unexpected appeared 451 # at the end of the test run: all dynamic sets should be empty by then. 452 if ! ip netns exec "$nsrouter" nft delete element inet t "$setname" { "$iifname" . "$addr" . "$type" } ; then 453 echo "FAIL: can't delete $iifname . $addr . $type in $setname" 454 ip netns exec "$nsrouter" nft list set inet t "$setname" 455 ret=1 456 return 1 457 fi 458 459 return 0 460} 461 462check_local() 463{ 464 check_type $@ "local" 1 465} 466 467check_unicast() 468{ 469 check_type $@ "unicast" 1 470} 471 472check_rpf() 473{ 474 check_type $@ 475} 476 477check_fib_vrf_sets_empty() 478{ 479 local setname="" 480 local lret=0 481 482 # A non-empty set means that we have seen unexpected packets OR 483 # that a fib lookup provided unexpected results. 484 for setname in "fibif4" "fibif4iif" "fibif6" "fibif6iif" \ 485 "fibtype4" "fibtype4iif" "fibtype6" "fibtype6iif";do 486 if ip netns exec "$nsrouter" nft list set inet t "$setname" | grep -q elements;then 487 echo "FAIL: $setname not empty" 488 ip netns exec "$nsrouter" nft list set inet t "$setname" 489 ret=1 490 lret=1 491 fi 492 done 493 494 return $lret 495} 496 497check_fib_vrf_type() 498{ 499 local msg="$1" 500 501 local addr 502 # the incoming interface is always veth0. As its not linked to a VRF, 503 # the 'tvrf' device should NOT show up anywhere. 504 local ifname="veth0" 505 local lret=0 506 507 # local_veth0, local_veth1 508 for addr in "10.0.1.1" "10.0.2.1"; do 509 check_local fibtype4 "$ifname" "$addr" || lret=1 510 check_type fibif4 "$ifname" "$addr" "0" || lret=1 511 done 512 for addr in "dead:1::1" "dead:2::1";do 513 check_local fibtype6 "$ifname" "$addr" || lret=1 514 check_type fibif6 "$ifname" "$addr" "0" || lret=1 515 done 516 517 # when restricted to the incoming interface, 10.0.1.1 should 518 # be 'local', but 10.0.2.1 unicast. 519 check_local fibtype4iif "$ifname" "10.0.1.1" || lret=1 520 check_unicast fibtype4iif "$ifname" "10.0.2.1" || lret=1 521 522 # same for the ipv6 addresses. 523 check_local fibtype6iif "$ifname" "dead:1::1" || lret=1 524 check_unicast fibtype6iif "$ifname" "dead:2::1" || lret=1 525 526 # None of these addresses should find a valid route when restricting 527 # to the incoming interface (we ask for daddr - 10.0.1.1/2.1 are 528 # reachable via 'lo'. 529 for addr in "10.0.1.1" "10.0.2.1" "10.9.9.1" "10.9.9.2";do 530 check_type fibif4iif "$ifname" "$addr" "0" || lret=1 531 done 532 533 # expect default route (veth1), dummy0 is part of VRF but iif isn't. 534 for addr in "10.9.9.1" "10.9.9.2";do 535 check_unicast fibtype4 "$ifname" "$addr" || lret=1 536 check_unicast fibtype4iif "$ifname" "$addr" || lret=1 537 check_type fibif4 "$ifname" "$addr" "veth1" || lret=1 538 done 539 for addr in "dead:9::1" "dead:9::2";do 540 check_unicast fibtype6 "$ifname" "$addr" || lret=1 541 check_unicast fibtype6iif "$ifname" "$addr" || lret=1 542 check_type fibif6 "$ifname" "$addr" "veth1" || lret=1 543 done 544 545 # same for the IPv6 equivalent addresses. 546 for addr in "dead:1::1" "dead:2::1" "dead:9::1" "dead:9::2";do 547 check_type fibif6iif "$ifname" "$addr" "0" || lret=1 548 done 549 550 check_unicast fibtype4 "$ifname" "10.0.2.99" || lret=1 551 check_unicast fibtype4iif "$ifname" "10.0.2.99" || lret=1 552 check_unicast fibtype6 "$ifname" "dead:2::99" || lret=1 553 check_unicast fibtype6iif "$ifname" "dead:2::99" || lret=1 554 555 check_type fibif4 "$ifname" "10.0.2.99" "veth1" || lret=1 556 check_type fibif4iif "$ifname" "10.0.2.99" 0 || lret=1 557 check_type fibif6 "$ifname" "dead:2::99" "veth1" || lret=1 558 check_type fibif6iif "$ifname" "dead:2::99" 0 || lret=1 559 560 check_rpf fibif4 "$ifname" "10.0.1.99" "veth0" 5 || lret=1 561 check_rpf fibif4iif "$ifname" "10.0.1.99" "veth0" 5 || lret=1 562 check_rpf fibif6 "$ifname" "dead:1::99" "veth0" 5 || lret=1 563 check_rpf fibif6iif "$ifname" "dead:1::99" "veth0" 5 || lret=1 564 565 check_fib_vrf_sets_empty || lret=1 566 567 if [ $lret -eq 0 ];then 568 echo "PASS: $msg" 569 else 570 echo "FAIL: $msg" 571 ret=1 572 fi 573} 574 575check_fib_veth_vrf_type() 576{ 577 local msg="$1" 578 579 local addr 580 local ifname 581 local setname 582 local lret=0 583 584 # as veth0 is now part of tvrf interface, packets will be seen 585 # twice, once with iif veth0, then with iif tvrf. 586 587 for ifname in "veth0" "tvrf"; do 588 for addr in "10.0.1.1" "10.9.9.1"; do 589 check_local fibtype4 "$ifname" "$addr" || lret=1 590 # addr local, but nft_fib doesn't return routes with RTN_LOCAL. 591 check_type fibif4 "$ifname" "$addr" 0 || lret=1 592 check_type fibif4iif "$ifname" "$addr" 0 || lret=1 593 done 594 595 for addr in "dead:1::1" "dead:9::1"; do 596 check_local fibtype6 "$ifname" "$addr" || lret=1 597 # same, address is local but no route is returned for lo. 598 check_type fibif6 "$ifname" "$addr" 0 || lret=1 599 check_type fibif6iif "$ifname" "$addr" 0 || lret=1 600 done 601 602 for t in fibtype4 fibtype4iif; do 603 check_unicast "$t" "$ifname" 10.9.9.2 || lret=1 604 done 605 for t in fibtype6 fibtype6iif; do 606 check_unicast "$t" "$ifname" dead:9::2 || lret=1 607 done 608 609 check_unicast fibtype4iif "$ifname" "10.9.9.1" || lret=1 610 check_unicast fibtype6iif "$ifname" "dead:9::1" || lret=1 611 612 check_unicast fibtype4 "$ifname" "10.0.2.99" || lret=1 613 check_unicast fibtype4iif "$ifname" "10.0.2.99" || lret=1 614 615 check_unicast fibtype6 "$ifname" "dead:2::99" || lret=1 616 check_unicast fibtype6iif "$ifname" "dead:2::99" || lret=1 617 618 check_type fibif4 "$ifname" "10.0.2.99" "veth1" || lret=1 619 check_type fibif6 "$ifname" "dead:2::99" "veth1" || lret=1 620 check_type fibif4 "$ifname" "10.9.9.2" "dummy0" || lret=1 621 check_type fibif6 "$ifname" "dead:9::2" "dummy0" || lret=1 622 623 # restricted to iif -- MUST NOT provide result, its != $ifname. 624 check_type fibif4iif "$ifname" "10.0.2.99" 0 || lret=1 625 check_type fibif6iif "$ifname" "dead:2::99" 0 || lret=1 626 627 check_rpf fibif4 "$ifname" "10.0.1.99" "veth0" 4 || lret=1 628 check_rpf fibif6 "$ifname" "dead:1::99" "veth0" 4 || lret=1 629 check_rpf fibif4iif "$ifname" "10.0.1.99" "$ifname" 4 || lret=1 630 check_rpf fibif6iif "$ifname" "dead:1::99" "$ifname" 4 || lret=1 631 done 632 633 check_local fibtype4iif "veth0" "10.0.1.1" || lret=1 634 check_local fibtype6iif "veth0" "dead:1::1" || lret=1 635 636 check_unicast fibtype4iif "tvrf" "10.0.1.1" || lret=1 637 check_unicast fibtype6iif "tvrf" "dead:1::1" || lret=1 638 639 # 10.9.9.2 should not provide a result for iif veth, but 640 # should when iif is tvrf. 641 # This is because its reachable via dummy0 which is part of 642 # tvrf. iif veth0 MUST conceal the dummy0 result (i.e. return oif 0). 643 check_type fibif4iif "veth0" "10.9.9.2" 0 || lret=1 644 check_type fibif6iif "veth0" "dead:9::2" 0 || lret=1 645 646 check_type fibif4iif "tvrf" "10.9.9.2" "tvrf" || lret=1 647 check_type fibif6iif "tvrf" "dead:9::2" "tvrf" || lret=1 648 649 check_fib_vrf_sets_empty || lret=1 650 651 if [ $lret -eq 0 ];then 652 echo "PASS: $msg" 653 else 654 echo "FAIL: $msg" 655 ret=1 656 fi 657} 658 659# Extends nsrouter config by adding dummy0+vrf. 660# 661# 10.0.1.99 10.0.1.1 10.0.2.1 10.0.2.99 662# dead:1::99 dead:1::1 dead:2::1 dead:2::99 663# ns1 <-------> [ veth0 ] nsrouter [veth1] <-------> ns2 664# [dummy0] 665# 10.9.9.1 666# dead:9::1 667# [tvrf] 668test_fib_vrf() 669{ 670 local cntname="" 671 672 if ! test_fib_vrf_dev_add_dummy; then 673 [ $ret -eq 0 ] && ret=$ksft_skip 674 return 675 fi 676 677 ip -net "$nsrouter" addr add "10.9.9.1"/24 dev dummy0 678 ip -net "$nsrouter" addr add "dead:9::1"/64 dev dummy0 nodad 679 680 ip -net "$nsrouter" route add default via 10.0.2.99 681 ip -net "$nsrouter" route add default via dead:2::99 682 683 load_ruleset_vrf || return 684 685 # no echo reply for these addresses: The dummy interface is part of tvrf, 686 # but veth0 (incoming interface) isn't linked to it. 687 test_ping_unreachable "10.9.9.1" "dead:9::1" & 688 test_ping_unreachable "10.9.9.2" "dead:9::2" & 689 690 # expect replies from these. 691 test_ping "10.0.1.1" "dead:1::1" 692 test_ping "10.0.2.1" "dead:2::1" 693 test_ping "10.0.2.99" "dead:2::99" 694 695 wait 696 697 check_fib_vrf_type "fib expression address types match (iif not in vrf)" 698 699 # second round: this time, make veth0 (rx interface) part of the vrf. 700 # 10.9.9.1 / dead:9::1 become reachable from ns1, while ns2 701 # becomes unreachable. 702 ip -net "$nsrouter" link set veth0 master tvrf 703 ip -net "$nsrouter" addr add dead:1::1/64 dev veth0 nodad 704 705 # this reload should not be needed, but in case 706 # there is some error (missing or unexpected entry) this will prevent them 707 # from leaking into round 2. 708 load_ruleset_vrf || return 709 710 test_ping "10.0.1.1" "dead:1::1" 711 test_ping "10.9.9.1" "dead:9::1" 712 713 # ns2 should no longer be reachable (veth1 not in vrf) 714 test_ping_unreachable "10.0.2.99" "dead:2::99" & 715 716 # vrf via dummy0, but host doesn't exist 717 test_ping_unreachable "10.9.9.2" "dead:9::2" & 718 719 wait 720 721 check_fib_veth_vrf_type "fib expression address types match (iif in vrf)" 722} 723 724ip netns exec "$nsrouter" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null 725ip netns exec "$nsrouter" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null 726ip netns exec "$nsrouter" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null 727 728test_ping 10.0.2.1 dead:2::1 || exit 1 729check_drops 730 731test_ping 10.0.2.99 dead:2::99 || exit 1 732check_drops 733 734[ $ret -eq 0 ] && echo "PASS: fib expression did not cause unwanted packet drops" 735 736load_input_ruleset "$ns1" 737 738test_ping 127.0.0.1 ::1 739check_drops 740 741test_ping 10.0.1.99 dead:1::99 742check_drops 743 744[ $ret -eq 0 ] && echo "PASS: fib expression did not discard loopback packets" 745 746load_input_ruleset "$ns1" 747 748test_ping 127.0.0.1 ::1 || exit 1 749check_drops || exit 1 750 751test_ping 10.0.1.99 dead:1::99 || exit 1 752check_drops || exit 1 753 754echo "PASS: fib expression did not discard loopback packets" 755 756ip netns exec "$nsrouter" nft flush table inet filter 757 758ip -net "$ns1" route del default 759ip -net "$ns1" -6 route del default 760 761ip -net "$ns1" addr del 10.0.1.99/24 dev eth0 762ip -net "$ns1" addr del dead:1::99/64 dev eth0 763 764ip -net "$ns1" addr add 10.0.2.99/24 dev eth0 765ip -net "$ns1" addr add dead:2::99/64 dev eth0 nodad 766 767ip -net "$ns1" route add default via 10.0.2.1 768ip -net "$ns1" -6 route add default via dead:2::1 769 770ip -net "$nsrouter" addr add dead:2::1/64 dev veth0 nodad 771 772# switch to ruleset that doesn't log, this time 773# its expected that this does drop the packets. 774load_ruleset_count "$nsrouter" 775 776# ns1 has a default route, but nsrouter does not. 777# must not check return value, ping to 1.1.1.1 will 778# fail. 779check_fib_counter 0 "$nsrouter" 1.1.1.1 || exit 1 780check_fib_counter 0 "$nsrouter" 1c3::c01d || exit 1 781 782ip netns exec "$ns1" ping -W 0.5 -c 1 -q 1.1.1.1 > /dev/null 783check_fib_counter 1 "$nsrouter" 1.1.1.1 || exit 1 784 785ip netns exec "$ns1" ping -W 0.5 -i 0.1 -c 3 -q 1c3::c01d > /dev/null 786check_fib_counter 3 "$nsrouter" 1c3::c01d || exit 1 787 788# delete all rules 789ip netns exec "$ns1" nft flush ruleset 790ip netns exec "$ns2" nft flush ruleset 791ip netns exec "$nsrouter" nft flush ruleset 792 793ip -net "$ns1" addr add 10.0.1.99/24 dev eth0 794ip -net "$ns1" addr add dead:1::99/64 dev eth0 nodad 795 796ip -net "$ns1" addr del 10.0.2.99/24 dev eth0 797ip -net "$ns1" addr del dead:2::99/64 dev eth0 798 799ip -net "$nsrouter" addr del dead:2::1/64 dev veth0 800 801# ... pbr ruleset for the router, check iif+oif. 802if ! load_pbr_ruleset "$nsrouter";then 803 echo "SKIP: Could not load fib forward ruleset" 804 [ "$ret" -eq 0 ] && ret=$ksft_skip 805fi 806 807ip -net "$nsrouter" rule add from all table 128 808ip -net "$nsrouter" rule add from all iif veth0 table 129 809ip -net "$nsrouter" route add table 128 to 10.0.1.0/24 dev veth0 810ip -net "$nsrouter" route add table 129 to 10.0.2.0/24 dev veth1 811 812# drop main ipv4 table 813ip -net "$nsrouter" -4 rule delete table main 814 815if test_ping 10.0.2.99 dead:2::99;then 816 echo "PASS: fib expression forward check with policy based routing" 817else 818 echo "FAIL: fib expression forward check with policy based routing" 819 ret=1 820fi 821 822test_fib_type "policy routing" 823ip netns exec "$nsrouter" nft delete table ip filter 824ip netns exec "$nsrouter" nft delete table ip6 filter 825 826# Un-do policy routing changes 827ip -net "$nsrouter" rule del from all table 128 828ip -net "$nsrouter" rule del from all iif veth0 table 129 829 830ip -net "$nsrouter" route del table 128 to 10.0.1.0/24 dev veth0 831ip -net "$nsrouter" route del table 129 to 10.0.2.0/24 dev veth1 832 833ip -net "$ns1" -4 route del default 834ip -net "$ns1" -6 route del default 835 836ip -net "$ns1" -4 route add default via 10.0.1.1 837ip -net "$ns1" -6 route add default via dead:1::1 838 839ip -net "$nsrouter" -4 rule add from all table main priority 32766 840 841test_fib_type "default table" 842ip netns exec "$nsrouter" nft delete table ip filter 843ip netns exec "$nsrouter" nft delete table ip6 filter 844 845test_fib_vrf 846 847exit $ret 848