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