1 #!/bin/bash 2 # SPDX-License-Identifier: GPL-2.0 3 # 4 # Test devlink-trap L3 drops functionality over mlxsw. Each registered L3 drop 5 # packet trap is tested to make sure it is triggered under the right 6 # conditions. 7 8 # +---------------------------------+ 9 # | H1 (vrf) | 10 # | + $h1 | 11 # | | 192.0.2.1/24 | 12 # | | 2001:db8:1::1/64 | 13 # | | | 14 # | | default via 192.0.2.2 | 15 # | | default via 2001:db8:1::2 | 16 # +----|----------------------------+ 17 # | 18 # +----|----------------------------------------------------------------------+ 19 # | SW | | 20 # | + $rp1 | 21 # | 192.0.2.2/24 | 22 # | 2001:db8:1::2/64 | 23 # | | 24 # | 2001:db8:2::2/64 | 25 # | 198.51.100.2/24 | 26 # | + $rp2 | 27 # | | | 28 # +----|----------------------------------------------------------------------+ 29 # | 30 # +----|----------------------------+ 31 # | | default via 198.51.100.2 | 32 # | | default via 2001:db8:2::2 | 33 # | | | 34 # | | 2001:db8:2::1/64 | 35 # | | 198.51.100.1/24 | 36 # | + $h2 | 37 # | H2 (vrf) | 38 # +---------------------------------+ 39 40 lib_dir=$(dirname $0)/../../../net/forwarding 41 42 ALL_TESTS=" 43 non_ip_test 44 uc_dip_over_mc_dmac_test 45 dip_is_loopback_test 46 sip_is_mc_test 47 sip_is_loopback_test 48 ip_header_corrupted_test 49 ipv4_sip_is_limited_bc_test 50 ipv6_mc_dip_reserved_scope_test 51 ipv6_mc_dip_interface_local_scope_test 52 blackhole_route_test 53 irif_disabled_test 54 erif_disabled_test 55 blackhole_nexthop_test 56 " 57 58 NUM_NETIFS=4 59 source $lib_dir/lib.sh 60 source $lib_dir/tc_common.sh 61 source $lib_dir/devlink_lib.sh 62 63 h1_create() 64 { 65 simple_if_init $h1 192.0.2.1/24 2001:db8:1::1/64 66 67 ip -4 route add default vrf v$h1 nexthop via 192.0.2.2 68 ip -6 route add default vrf v$h1 nexthop via 2001:db8:1::2 69 } 70 71 h1_destroy() 72 { 73 ip -6 route del default vrf v$h1 nexthop via 2001:db8:1::2 74 ip -4 route del default vrf v$h1 nexthop via 192.0.2.2 75 76 simple_if_fini $h1 192.0.2.1/24 2001:db8:1::1/64 77 } 78 79 h2_create() 80 { 81 simple_if_init $h2 $h2_ipv4/24 $h2_ipv6/64 82 83 ip -4 route add default vrf v$h2 nexthop via 198.51.100.2 84 ip -6 route add default vrf v$h2 nexthop via 2001:db8:2::2 85 } 86 87 h2_destroy() 88 { 89 ip -6 route del default vrf v$h2 nexthop via 2001:db8:2::2 90 ip -4 route del default vrf v$h2 nexthop via 198.51.100.2 91 92 simple_if_fini $h2 $h2_ipv4/24 $h2_ipv6/64 93 } 94 95 router_create() 96 { 97 ip link set dev $rp1 up 98 ip link set dev $rp2 up 99 100 tc qdisc add dev $rp2 clsact 101 102 __addr_add_del $rp1 add 192.0.2.2/24 2001:db8:1::2/64 103 __addr_add_del $rp2 add 198.51.100.2/24 2001:db8:2::2/64 104 } 105 106 router_destroy() 107 { 108 __addr_add_del $rp2 del 198.51.100.2/24 2001:db8:2::2/64 109 __addr_add_del $rp1 del 192.0.2.2/24 2001:db8:1::2/64 110 111 tc qdisc del dev $rp2 clsact 112 113 ip link set dev $rp2 down 114 ip link set dev $rp1 down 115 } 116 117 setup_prepare() 118 { 119 h1=${NETIFS[p1]} 120 rp1=${NETIFS[p2]} 121 122 rp2=${NETIFS[p3]} 123 h2=${NETIFS[p4]} 124 125 h1mac=$(mac_get $h1) 126 rp1mac=$(mac_get $rp1) 127 128 h1_ipv4=192.0.2.1 129 h2_ipv4=198.51.100.1 130 h1_ipv6=2001:db8:1::1 131 h2_ipv6=2001:db8:2::1 132 133 vrf_prepare 134 forwarding_enable 135 136 h1_create 137 h2_create 138 139 router_create 140 } 141 142 cleanup() 143 { 144 pre_cleanup 145 146 router_destroy 147 148 h2_destroy 149 h1_destroy 150 151 forwarding_restore 152 vrf_cleanup 153 } 154 155 ping_check() 156 { 157 trap_name=$1; shift 158 159 devlink_trap_action_set $trap_name "trap" 160 ping_do $h1 $h2_ipv4 161 check_err $? "Packets that should not be trapped were trapped" 162 devlink_trap_action_set $trap_name "drop" 163 } 164 165 non_ip_test() 166 { 167 local trap_name="non_ip" 168 local mz_pid 169 170 RET=0 171 172 ping_check $trap_name 173 174 tc filter add dev $rp2 egress protocol ip pref 1 handle 101 \ 175 flower dst_ip $h2_ipv4 action drop 176 177 # Generate non-IP packets to the router 178 $MZ $h1 -c 0 -p 100 -d 1msec -B $h2_ipv4 -q "$rp1mac $h1mac \ 179 00:00 de:ad:be:ef" & 180 mz_pid=$! 181 182 devlink_trap_drop_test $trap_name $rp2 101 183 184 log_test "Non IP" 185 186 devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101 187 } 188 189 __uc_dip_over_mc_dmac_test() 190 { 191 local desc=$1; shift 192 local proto=$1; shift 193 local dip=$1; shift 194 local flags=${1:-""}; shift 195 local trap_name="uc_dip_over_mc_dmac" 196 local dmac=01:02:03:04:05:06 197 local mz_pid 198 199 RET=0 200 201 ping_check $trap_name 202 203 tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \ 204 flower ip_proto udp src_port 54321 dst_port 12345 action drop 205 206 # Generate IP packets with a unicast IP and a multicast destination MAC 207 $MZ $h1 $flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -b $dmac \ 208 -B $dip -d 1msec -q & 209 mz_pid=$! 210 211 devlink_trap_drop_test $trap_name $rp2 101 212 213 log_test "Unicast destination IP over multicast destination MAC: $desc" 214 215 devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101 216 } 217 218 uc_dip_over_mc_dmac_test() 219 { 220 __uc_dip_over_mc_dmac_test "IPv4" "ip" $h2_ipv4 221 __uc_dip_over_mc_dmac_test "IPv6" "ipv6" $h2_ipv6 "-6" 222 } 223 224 __sip_is_loopback_test() 225 { 226 local desc=$1; shift 227 local proto=$1; shift 228 local sip=$1; shift 229 local dip=$1; shift 230 local flags=${1:-""}; shift 231 local trap_name="sip_is_loopback_address" 232 local mz_pid 233 234 RET=0 235 236 ping_check $trap_name 237 238 tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \ 239 flower src_ip $sip action drop 240 241 # Generate packets with loopback source IP 242 $MZ $h1 $flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -A $sip \ 243 -b $rp1mac -B $dip -d 1msec -q & 244 mz_pid=$! 245 246 devlink_trap_drop_test $trap_name $rp2 101 247 248 log_test "Source IP is loopback address: $desc" 249 250 devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101 251 } 252 253 sip_is_loopback_test() 254 { 255 __sip_is_loopback_test "IPv4" "ip" "127.0.0.0/8" $h2_ipv4 256 __sip_is_loopback_test "IPv6" "ipv6" "::1" $h2_ipv6 "-6" 257 } 258 259 __dip_is_loopback_test() 260 { 261 local desc=$1; shift 262 local proto=$1; shift 263 local dip=$1; shift 264 local flags=${1:-""}; shift 265 local trap_name="dip_is_loopback_address" 266 local mz_pid 267 268 RET=0 269 270 ping_check $trap_name 271 272 tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \ 273 flower dst_ip $dip action drop 274 275 # Generate packets with loopback destination IP 276 $MZ $h1 $flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -b $rp1mac \ 277 -B $dip -d 1msec -q & 278 mz_pid=$! 279 280 devlink_trap_drop_test $trap_name $rp2 101 281 282 log_test "Destination IP is loopback address: $desc" 283 284 devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101 285 } 286 287 dip_is_loopback_test() 288 { 289 __dip_is_loopback_test "IPv4" "ip" "127.0.0.0/8" 290 __dip_is_loopback_test "IPv6" "ipv6" "::1" "-6" 291 } 292 293 __sip_is_mc_test() 294 { 295 local desc=$1; shift 296 local proto=$1; shift 297 local sip=$1; shift 298 local dip=$1; shift 299 local flags=${1:-""}; shift 300 local trap_name="sip_is_mc" 301 local mz_pid 302 303 RET=0 304 305 ping_check $trap_name 306 307 tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \ 308 flower src_ip $sip action drop 309 310 # Generate packets with multicast source IP 311 $MZ $h1 $flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -A $sip \ 312 -b $rp1mac -B $dip -d 1msec -q & 313 mz_pid=$! 314 315 devlink_trap_drop_test $trap_name $rp2 101 316 317 log_test "Source IP is multicast: $desc" 318 319 devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101 320 } 321 322 sip_is_mc_test() 323 { 324 __sip_is_mc_test "IPv4" "ip" "239.1.1.1" $h2_ipv4 325 __sip_is_mc_test "IPv6" "ipv6" "FF02::2" $h2_ipv6 "-6" 326 } 327 328 ipv4_sip_is_limited_bc_test() 329 { 330 local trap_name="ipv4_sip_is_limited_bc" 331 local sip=255.255.255.255 332 local mz_pid 333 334 RET=0 335 336 ping_check $trap_name 337 338 tc filter add dev $rp2 egress protocol ip pref 1 handle 101 \ 339 flower src_ip $sip action drop 340 341 # Generate packets with limited broadcast source IP 342 $MZ $h1 -t udp "sp=54321,dp=12345" -c 0 -p 100 -A $sip -b $rp1mac \ 343 -B $h2_ipv4 -d 1msec -q & 344 mz_pid=$! 345 346 devlink_trap_drop_test $trap_name $rp2 101 347 348 log_test "IPv4 source IP is limited broadcast" 349 350 devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101 351 } 352 353 ipv4_payload_get() 354 { 355 local ipver=$1; shift 356 local ihl=$1; shift 357 local checksum=$1; shift 358 359 p=$(: 360 )"08:00:"$( : ETH type 361 )"$ipver"$( : IP version 362 )"$ihl:"$( : IHL 363 )"00:"$( : IP TOS 364 )"00:F4:"$( : IP total length 365 )"00:00:"$( : IP identification 366 )"20:00:"$( : IP flags + frag off 367 )"30:"$( : IP TTL 368 )"01:"$( : IP proto 369 )"$checksum:"$( : IP header csum 370 )"$h1_ipv4:"$( : IP saddr 371 )"$h2_ipv4:"$( : IP daddr 372 ) 373 echo $p 374 } 375 376 __ipv4_header_corrupted_test() 377 { 378 local desc=$1; shift 379 local ipver=$1; shift 380 local ihl=$1; shift 381 local checksum=$1; shift 382 local trap_name="ip_header_corrupted" 383 local payload 384 local mz_pid 385 386 RET=0 387 388 ping_check $trap_name 389 390 tc filter add dev $rp2 egress protocol ip pref 1 handle 101 \ 391 flower dst_ip $h2_ipv4 action drop 392 393 payload=$(ipv4_payload_get $ipver $ihl $checksum) 394 395 # Generate packets with corrupted IP header 396 $MZ $h1 -c 0 -d 1msec -a $h1mac -b $rp1mac -q p=$payload & 397 mz_pid=$! 398 399 devlink_trap_drop_test $trap_name $rp2 101 400 401 log_test "IP header corrupted: $desc: IPv4" 402 403 devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101 404 } 405 406 ipv6_payload_get() 407 { 408 local ipver=$1; shift 409 410 p=$(: 411 )"86:DD:"$( : ETH type 412 )"$ipver"$( : IP version 413 )"0:0:"$( : Traffic class 414 )"0:00:00:"$( : Flow label 415 )"00:00:"$( : Payload length 416 )"01:"$( : Next header 417 )"04:"$( : Hop limit 418 )"$h1_ipv6:"$( : IP saddr 419 )"$h2_ipv6:"$( : IP daddr 420 ) 421 echo $p 422 } 423 424 __ipv6_header_corrupted_test() 425 { 426 local desc=$1; shift 427 local ipver=$1; shift 428 local trap_name="ip_header_corrupted" 429 local payload 430 local mz_pid 431 432 RET=0 433 434 ping_check $trap_name 435 436 tc filter add dev $rp2 egress protocol ip pref 1 handle 101 \ 437 flower dst_ip $h2_ipv4 action drop 438 439 payload=$(ipv6_payload_get $ipver) 440 441 # Generate packets with corrupted IP header 442 $MZ $h1 -c 0 -d 1msec -a $h1mac -b $rp1mac -q p=$payload & 443 mz_pid=$! 444 445 devlink_trap_drop_test $trap_name $rp2 101 446 447 log_test "IP header corrupted: $desc: IPv6" 448 449 devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101 450 } 451 452 ip_header_corrupted_test() 453 { 454 # Each test uses one wrong value. The three values below are correct. 455 local ipv="4" 456 local ihl="5" 457 local checksum="00:F4" 458 459 __ipv4_header_corrupted_test "wrong IP version" 5 $ihl $checksum 460 __ipv4_header_corrupted_test "wrong IHL" $ipv 4 $checksum 461 __ipv4_header_corrupted_test "wrong checksum" $ipv $ihl "00:00" 462 __ipv6_header_corrupted_test "wrong IP version" 5 463 } 464 465 ipv6_mc_dip_reserved_scope_test() 466 { 467 local trap_name="ipv6_mc_dip_reserved_scope" 468 local dip=FF00:: 469 local mz_pid 470 471 RET=0 472 473 ping_check $trap_name 474 475 tc filter add dev $rp2 egress protocol ipv6 pref 1 handle 101 \ 476 flower dst_ip $dip action drop 477 478 # Generate packets with reserved scope destination IP 479 $MZ $h1 -6 -t udp "sp=54321,dp=12345" -c 0 -p 100 -b \ 480 "33:33:00:00:00:00" -B $dip -d 1msec -q & 481 mz_pid=$! 482 483 devlink_trap_drop_test $trap_name $rp2 101 484 485 log_test "IPv6 multicast destination IP reserved scope" 486 487 devlink_trap_drop_cleanup $mz_pid $rp2 "ipv6" 1 101 488 } 489 490 ipv6_mc_dip_interface_local_scope_test() 491 { 492 local trap_name="ipv6_mc_dip_interface_local_scope" 493 local dip=FF01:: 494 local mz_pid 495 496 RET=0 497 498 ping_check $trap_name 499 500 tc filter add dev $rp2 egress protocol ipv6 pref 1 handle 101 \ 501 flower dst_ip $dip action drop 502 503 # Generate packets with interface local scope destination IP 504 $MZ $h1 -6 -t udp "sp=54321,dp=12345" -c 0 -p 100 -b \ 505 "33:33:00:00:00:00" -B $dip -d 1msec -q & 506 mz_pid=$! 507 508 devlink_trap_drop_test $trap_name $rp2 101 509 510 log_test "IPv6 multicast destination IP interface-local scope" 511 512 devlink_trap_drop_cleanup $mz_pid $rp2 "ipv6" 1 101 513 } 514 515 __blackhole_route_test() 516 { 517 local flags=$1; shift 518 local subnet=$1; shift 519 local proto=$1; shift 520 local dip=$1; shift 521 local ip_proto=${1:-"icmp"}; shift 522 local trap_name="blackhole_route" 523 local mz_pid 524 525 RET=0 526 527 ping_check $trap_name 528 529 ip -$flags route add blackhole $subnet 530 tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \ 531 flower skip_hw dst_ip $dip ip_proto $ip_proto action drop 532 533 # Generate packets to the blackhole route 534 $MZ $h1 -$flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -b $rp1mac \ 535 -B $dip -d 1msec -q & 536 mz_pid=$! 537 538 devlink_trap_drop_test $trap_name $rp2 101 539 log_test "Blackhole route: IPv$flags" 540 541 devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101 542 ip -$flags route del blackhole $subnet 543 } 544 545 blackhole_route_test() 546 { 547 __blackhole_route_test "4" "198.51.100.0/30" "ip" $h2_ipv4 548 __blackhole_route_test "6" "2001:db8:2::/120" "ipv6" $h2_ipv6 "icmpv6" 549 } 550 551 irif_disabled_test() 552 { 553 local trap_name="irif_disabled" 554 local t0_packets t0_bytes 555 local t1_packets t1_bytes 556 local mz_pid 557 558 RET=0 559 560 ping_check $trap_name 561 562 devlink_trap_action_set $trap_name "trap" 563 564 # When RIF of a physical port ("Sub-port RIF") is destroyed, we first 565 # block the STP of the {Port, VLAN} so packets cannot get into the RIF. 566 # Using bridge enables us to see this trap because when bridge is 567 # destroyed, there is a small time window that packets can go into the 568 # RIF, while it is disabled. 569 ip link add dev br0 type bridge 570 ip link set dev $rp1 master br0 571 ip address flush dev $rp1 572 __addr_add_del br0 add 192.0.2.2/24 573 ip li set dev br0 up 574 575 t0_packets=$(devlink_trap_rx_packets_get $trap_name) 576 t0_bytes=$(devlink_trap_rx_bytes_get $trap_name) 577 578 # Generate packets to h2 through br0 RIF that will be removed later 579 $MZ $h1 -t udp "sp=54321,dp=12345" -c 0 -p 100 -a own -b $rp1mac \ 580 -B $h2_ipv4 -q & 581 mz_pid=$! 582 583 # Wait before removing br0 RIF to allow packets to go into the bridge. 584 sleep 1 585 586 # Flushing address will dismantle the RIF 587 ip address flush dev br0 588 589 t1_packets=$(devlink_trap_rx_packets_get $trap_name) 590 t1_bytes=$(devlink_trap_rx_bytes_get $trap_name) 591 592 if [[ $t0_packets -eq $t1_packets && $t0_bytes -eq $t1_bytes ]]; then 593 check_err 1 "Trap stats idle when packets should be trapped" 594 fi 595 596 log_test "Ingress RIF disabled" 597 598 kill $mz_pid && wait $mz_pid &> /dev/null 599 ip link set dev $rp1 nomaster 600 __addr_add_del $rp1 add 192.0.2.2/24 2001:db8:1::2/64 601 ip link del dev br0 type bridge 602 devlink_trap_action_set $trap_name "drop" 603 } 604 605 erif_disabled_test() 606 { 607 local trap_name="erif_disabled" 608 local t0_packets t0_bytes 609 local t1_packets t1_bytes 610 local mz_pid 611 612 RET=0 613 614 ping_check $trap_name 615 616 devlink_trap_action_set $trap_name "trap" 617 ip link add dev br0 type bridge 618 ip add flush dev $rp1 619 ip link set dev $rp1 master br0 620 __addr_add_del br0 add 192.0.2.2/24 621 ip link set dev br0 up 622 623 t0_packets=$(devlink_trap_rx_packets_get $trap_name) 624 t0_bytes=$(devlink_trap_rx_bytes_get $trap_name) 625 626 rp2mac=$(mac_get $rp2) 627 628 # Generate packets that should go out through br0 RIF that will be 629 # removed later 630 $MZ $h2 -t udp "sp=54321,dp=12345" -c 0 -p 100 -a own -b $rp2mac \ 631 -B 192.0.2.1 -q & 632 mz_pid=$! 633 634 sleep 5 635 # Unlinking the port from the bridge will disable the RIF associated 636 # with br0 as it is no longer an upper of any mlxsw port. 637 ip link set dev $rp1 nomaster 638 639 t1_packets=$(devlink_trap_rx_packets_get $trap_name) 640 t1_bytes=$(devlink_trap_rx_bytes_get $trap_name) 641 642 if [[ $t0_packets -eq $t1_packets && $t0_bytes -eq $t1_bytes ]]; then 643 check_err 1 "Trap stats idle when packets should be trapped" 644 fi 645 646 log_test "Egress RIF disabled" 647 648 kill $mz_pid && wait $mz_pid &> /dev/null 649 __addr_add_del $rp1 add 192.0.2.2/24 2001:db8:1::2/64 650 ip link del dev br0 type bridge 651 devlink_trap_action_set $trap_name "drop" 652 } 653 654 __blackhole_nexthop_test() 655 { 656 local flags=$1; shift 657 local subnet=$1; shift 658 local proto=$1; shift 659 local dip=$1; shift 660 local trap_name="blackhole_nexthop" 661 local mz_pid 662 663 RET=0 664 665 ip -$flags nexthop add id 1 blackhole 666 ip -$flags route add $subnet nhid 1 667 tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \ 668 flower skip_hw dst_ip $dip ip_proto udp action drop 669 670 # Generate packets to the blackhole nexthop 671 $MZ $h1 -$flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -b $rp1mac \ 672 -B $dip -d 1msec -q & 673 mz_pid=$! 674 675 devlink_trap_drop_test $trap_name $rp2 101 676 log_test "Blackhole nexthop: IPv$flags" 677 678 devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101 679 ip -$flags route del $subnet 680 ip -$flags nexthop del id 1 681 } 682 683 blackhole_nexthop_test() 684 { 685 __blackhole_nexthop_test "4" "198.51.100.0/30" "ip" $h2_ipv4 686 __blackhole_nexthop_test "6" "2001:db8:2::/120" "ipv6" $h2_ipv6 687 } 688 689 trap cleanup EXIT 690 691 setup_prepare 692 setup_wait 693 694 tests_run 695 696 exit $EXIT_STATUS
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.