584 lines · bash
1#!/bin/bash2# SPDX-License-Identifier: GPL-2.03#4# Test devlink-trap L3 exceptions functionality over mlxsw.5# Check all exception traps to make sure they are triggered under the right6# 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/forwarding41 42ALL_TESTS="43 mtu_value_is_too_small_test44 ttl_value_is_too_small_test45 mc_reverse_path_forwarding_test46 reject_route_test47 unresolved_neigh_test48 ipv4_lpm_miss_test49 ipv6_lpm_miss_test50"51 52NUM_NETIFS=453source $lib_dir/lib.sh54source $lib_dir/tc_common.sh55source $lib_dir/devlink_lib.sh56 57require_command $MCD58require_command $MC_CLI59table_name=selftests60 61h1_create()62{63 simple_if_init $h1 192.0.2.1/24 2001:db8:1::1/6464 65 ip -4 route add default vrf v$h1 nexthop via 192.0.2.266 ip -6 route add default vrf v$h1 nexthop via 2001:db8:1::267 68 tc qdisc add dev $h1 clsact69}70 71h1_destroy()72{73 tc qdisc del dev $h1 clsact74 75 ip -6 route del default vrf v$h1 nexthop via 2001:db8:1::276 ip -4 route del default vrf v$h1 nexthop via 192.0.2.277 78 simple_if_fini $h1 192.0.2.1/24 2001:db8:1::1/6479}80 81h2_create()82{83 simple_if_init $h2 198.51.100.1/24 2001:db8:2::1/6484 85 ip -4 route add default vrf v$h2 nexthop via 198.51.100.286 ip -6 route add default vrf v$h2 nexthop via 2001:db8:2::287}88 89h2_destroy()90{91 ip -6 route del default vrf v$h2 nexthop via 2001:db8:2::292 ip -4 route del default vrf v$h2 nexthop via 198.51.100.293 94 simple_if_fini $h2 198.51.100.1/24 2001:db8:2::1/6495}96 97router_create()98{99 ip link set dev $rp1 up100 ip link set dev $rp2 up101 102 tc qdisc add dev $rp2 clsact103 104 __addr_add_del $rp1 add 192.0.2.2/24 2001:db8:1::2/64105 __addr_add_del $rp2 add 198.51.100.2/24 2001:db8:2::2/64106}107 108router_destroy()109{110 __addr_add_del $rp2 del 198.51.100.2/24 2001:db8:2::2/64111 __addr_add_del $rp1 del 192.0.2.2/24 2001:db8:1::2/64112 113 tc qdisc del dev $rp2 clsact114 115 ip link set dev $rp2 down116 ip link set dev $rp1 down117}118 119setup_prepare()120{121 h1=${NETIFS[p1]}122 rp1=${NETIFS[p2]}123 124 rp2=${NETIFS[p3]}125 h2=${NETIFS[p4]}126 127 rp1mac=$(mac_get $rp1)128 129 start_mcd130 131 vrf_prepare132 forwarding_enable133 134 h1_create135 h2_create136 137 router_create138}139 140cleanup()141{142 pre_cleanup143 144 router_destroy145 146 h2_destroy147 h1_destroy148 149 forwarding_restore150 vrf_cleanup151 152 kill_mcd153}154 155ping_check()156{157 ping_do $h1 198.51.100.1158 check_err $? "Packets that should not be trapped were trapped"159}160 161trap_action_check()162{163 local trap_name=$1; shift164 local expected_action=$1; shift165 166 action=$(devlink_trap_action_get $trap_name)167 if [ "$action" != $expected_action ]; then168 check_err 1 "Trap $trap_name has wrong action: $action"169 fi170}171 172mtu_value_is_too_small_test()173{174 local trap_name="mtu_value_is_too_small"175 local expected_action="trap"176 local mz_pid177 178 RET=0179 180 ping_check $trap_name181 trap_action_check $trap_name $expected_action182 183 # type - Destination Unreachable184 # code - Fragmentation Needed and Don't Fragment was Set185 tc filter add dev $h1 ingress protocol ip pref 1 handle 101 \186 flower skip_hw ip_proto icmp type 3 code 4 action pass187 188 mtu_set $rp2 1300189 190 # Generate IP packets bigger than router's MTU with don't fragment191 # flag on.192 $MZ $h1 -t udp "sp=54321,dp=12345,df" -p 1400 -c 0 -d 1msec -b $rp1mac \193 -B 198.51.100.1 -q &194 mz_pid=$!195 196 devlink_trap_exception_test $trap_name197 198 tc_check_packets_hitting "dev $h1 ingress" 101199 check_err $? "Packets were not received to h1"200 201 log_test "MTU value is too small"202 203 mtu_restore $rp2204 205 kill $mz_pid && wait $mz_pid &> /dev/null206 tc filter del dev $h1 ingress protocol ip pref 1 handle 101 flower207}208 209__ttl_value_is_too_small_test()210{211 local ttl_val=$1; shift212 local trap_name="ttl_value_is_too_small"213 local expected_action="trap"214 local mz_pid215 216 RET=0217 218 ping_check $trap_name219 trap_action_check $trap_name $expected_action220 221 # type - Time Exceeded222 # code - Time to Live exceeded in Transit223 tc filter add dev $h1 ingress protocol ip pref 1 handle 101 \224 flower skip_hw ip_proto icmp type 11 code 0 action pass225 226 # Generate IP packets with small TTL227 $MZ $h1 -t udp "ttl=$ttl_val,sp=54321,dp=12345" -c 0 -d 1msec \228 -b $rp1mac -B 198.51.100.1 -q &229 mz_pid=$!230 231 devlink_trap_exception_test $trap_name232 233 tc_check_packets_hitting "dev $h1 ingress" 101234 check_err $? "Packets were not received to h1"235 236 log_test "TTL value is too small: TTL=$ttl_val"237 238 kill $mz_pid && wait $mz_pid &> /dev/null239 tc filter del dev $h1 ingress protocol ip pref 1 handle 101 flower240}241 242ttl_value_is_too_small_test()243{244 __ttl_value_is_too_small_test 0245 __ttl_value_is_too_small_test 1246}247 248start_mcd()249{250 SMCROUTEDIR="$(mktemp -d)"251 for ((i = 1; i <= $NUM_NETIFS; ++i)); do252 echo "phyint ${NETIFS[p$i]} enable" >> \253 $SMCROUTEDIR/$table_name.conf254 done255 256 $MCD -N -I $table_name -f $SMCROUTEDIR/$table_name.conf \257 -P $SMCROUTEDIR/$table_name.pid258}259 260kill_mcd()261{262 pkill $MCD263 rm -rf $SMCROUTEDIR264}265 266__mc_reverse_path_forwarding_test()267{268 local desc=$1; shift269 local src_ip=$1; shift270 local dst_ip=$1; shift271 local dst_mac=$1; shift272 local proto=$1; shift273 local flags=${1:-""}; shift274 local trap_name="mc_reverse_path_forwarding"275 local expected_action="trap"276 local mz_pid277 278 RET=0279 280 ping_check $trap_name281 trap_action_check $trap_name $expected_action282 283 tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \284 flower dst_ip $dst_ip ip_proto udp action drop285 286 $MC_CLI -I $table_name add $rp1 $src_ip $dst_ip $rp2287 288 # Generate packets to multicast address.289 $MZ $h2 $flags -t udp "sp=54321,dp=12345" -c 0 -p 128 \290 -a 00:11:22:33:44:55 -b $dst_mac \291 -A $src_ip -B $dst_ip -q &292 293 mz_pid=$!294 295 devlink_trap_exception_test $trap_name296 297 tc_check_packets "dev $rp2 egress" 101 0298 check_err $? "Packets were not dropped"299 300 log_test "Multicast reverse path forwarding: $desc"301 302 kill $mz_pid && wait $mz_pid &> /dev/null303 tc filter del dev $rp2 egress protocol $proto pref 1 handle 101 flower304}305 306mc_reverse_path_forwarding_test()307{308 __mc_reverse_path_forwarding_test "IPv4" "192.0.2.1" "225.1.2.3" \309 "01:00:5e:01:02:03" "ip"310 __mc_reverse_path_forwarding_test "IPv6" "2001:db8:1::1" "ff0e::3" \311 "33:33:00:00:00:03" "ipv6" "-6"312}313 314__reject_route_test()315{316 local desc=$1; shift317 local dst_ip=$1; shift318 local proto=$1; shift319 local ip_proto=$1; shift320 local type=$1; shift321 local code=$1; shift322 local unreachable=$1; shift323 local flags=${1:-""}; shift324 local trap_name="reject_route"325 local expected_action="trap"326 local mz_pid327 328 RET=0329 330 ping_check $trap_name331 trap_action_check $trap_name $expected_action332 333 tc filter add dev $h1 ingress protocol $proto pref 1 handle 101 flower \334 skip_hw ip_proto $ip_proto type $type code $code action pass335 336 ip route add unreachable $unreachable337 338 # Generate pacekts to h2. The destination IP is unreachable.339 $MZ $flags $h1 -t udp "sp=54321,dp=12345" -c 0 -d 1msec -b $rp1mac \340 -B $dst_ip -q &341 mz_pid=$!342 343 devlink_trap_exception_test $trap_name344 345 tc_check_packets_hitting "dev $h1 ingress" 101346 check_err $? "ICMP packet was not received to h1"347 348 log_test "Reject route: $desc"349 350 kill $mz_pid && wait $mz_pid &> /dev/null351 ip route del unreachable $unreachable352 tc filter del dev $h1 ingress protocol $proto pref 1 handle 101 flower353}354 355reject_route_test()356{357 # type - Destination Unreachable358 # code - Host Unreachable359 __reject_route_test "IPv4" 198.51.100.1 "ip" "icmp" 3 1 \360 "198.51.100.0/26"361 # type - Destination Unreachable362 # code - No Route363 __reject_route_test "IPv6" 2001:db8:2::1 "ipv6" "icmpv6" 1 0 \364 "2001:db8:2::0/66" "-6"365}366 367__host_miss_test()368{369 local desc=$1; shift370 local dip=$1; shift371 local trap_name="unresolved_neigh"372 local expected_action="trap"373 local mz_pid374 375 RET=0376 377 ping_check $trap_name378 trap_action_check $trap_name $expected_action379 380 ip neigh flush dev $rp2381 382 t0_packets=$(devlink_trap_rx_packets_get $trap_name)383 384 # Generate packets to h2 (will incur a unresolved neighbor).385 # The ping should pass and devlink counters should be increased.386 ping_do $h1 $dip387 check_err $? "ping failed: $desc"388 389 t1_packets=$(devlink_trap_rx_packets_get $trap_name)390 391 if [[ $t0_packets -eq $t1_packets ]]; then392 check_err 1 "Trap counter did not increase"393 fi394 395 log_test "Unresolved neigh: host miss: $desc"396}397 398__invalid_nexthop_test()399{400 local desc=$1; shift401 local dip=$1; shift402 local extra_add=$1; shift403 local subnet=$1; shift404 local via_add=$1; shift405 local trap_name="unresolved_neigh"406 local expected_action="trap"407 local mz_pid408 409 RET=0410 411 ping_check $trap_name412 trap_action_check $trap_name $expected_action413 414 ip address add $extra_add/$subnet dev $h2415 416 # Check that correct route does not trigger unresolved_neigh417 ip $flags route add $dip via $extra_add dev $rp2418 419 # Generate packets in order to discover all neighbours.420 # Without it, counters of unresolved_neigh will be increased421 # during neighbours discovery and the check below will fail422 # for a wrong reason423 ping_do $h1 $dip424 425 t0_packets=$(devlink_trap_rx_packets_get $trap_name)426 ping_do $h1 $dip427 t1_packets=$(devlink_trap_rx_packets_get $trap_name)428 429 if [[ $t0_packets -ne $t1_packets ]]; then430 check_err 1 "Trap counter increased when it should not"431 fi432 433 ip $flags route del $dip via $extra_add dev $rp2434 435 # Check that route to nexthop that does not exist trigger436 # unresolved_neigh437 ip $flags route add $dip via $via_add dev $h2438 439 t0_packets=$(devlink_trap_rx_packets_get $trap_name)440 ping_do $h1 $dip441 t1_packets=$(devlink_trap_rx_packets_get $trap_name)442 443 if [[ $t0_packets -eq $t1_packets ]]; then444 check_err 1 "Trap counter did not increase"445 fi446 447 ip $flags route del $dip via $via_add dev $h2448 ip address del $extra_add/$subnet dev $h2449 log_test "Unresolved neigh: nexthop does not exist: $desc"450}451 452__invalid_nexthop_bucket_test()453{454 local desc=$1; shift455 local dip=$1; shift456 local via_add=$1; shift457 local trap_name="unresolved_neigh"458 459 RET=0460 461 # Check that route to nexthop that does not exist triggers462 # unresolved_neigh463 ip nexthop add id 1 via $via_add dev $rp2464 ip nexthop add id 10 group 1 type resilient buckets 32465 ip route add $dip nhid 10466 467 t0_packets=$(devlink_trap_rx_packets_get $trap_name)468 ping_do $h1 $dip469 t1_packets=$(devlink_trap_rx_packets_get $trap_name)470 471 if [[ $t0_packets -eq $t1_packets ]]; then472 check_err 1 "Trap counter did not increase"473 fi474 475 ip route del $dip nhid 10476 ip nexthop del id 10477 ip nexthop del id 1478 log_test "Unresolved neigh: nexthop bucket does not exist: $desc"479}480 481unresolved_neigh_test()482{483 __host_miss_test "IPv4" 198.51.100.1484 __host_miss_test "IPv6" 2001:db8:2::1485 __invalid_nexthop_test "IPv4" 198.51.100.1 198.51.100.3 24 198.51.100.4486 __invalid_nexthop_test "IPv6" 2001:db8:2::1 2001:db8:2::3 64 \487 2001:db8:2::4488 __invalid_nexthop_bucket_test "IPv4" 198.51.100.1 198.51.100.4489 __invalid_nexthop_bucket_test "IPv6" 2001:db8:2::1 2001:db8:2::4490}491 492vrf_without_routes_create()493{494 # VRF creating makes the links to be down and then up again.495 # By default, IPv6 address is not saved after link becomes down.496 # Save IPv6 address using sysctl configuration.497 sysctl_set net.ipv6.conf.$rp1.keep_addr_on_down 1498 sysctl_set net.ipv6.conf.$rp2.keep_addr_on_down 1499 500 ip link add dev vrf1 type vrf table 101501 ip link set dev $rp1 master vrf1502 ip link set dev $rp2 master vrf1503 ip link set dev vrf1 up504 505 # Wait for rp1 and rp2 to be up506 setup_wait507}508 509vrf_without_routes_destroy()510{511 ip link set dev $rp1 nomaster512 ip link set dev $rp2 nomaster513 ip link del dev vrf1514 515 sysctl_restore net.ipv6.conf.$rp2.keep_addr_on_down516 sysctl_restore net.ipv6.conf.$rp1.keep_addr_on_down517 518 # Wait for interfaces to be up519 setup_wait520}521 522ipv4_lpm_miss_test()523{524 local trap_name="ipv4_lpm_miss"525 local expected_action="trap"526 local mz_pid527 528 RET=0529 530 ping_check $trap_name531 trap_action_check $trap_name $expected_action532 533 # Create a VRF without a default route534 vrf_without_routes_create535 536 # Generate packets through a VRF without a matching route.537 $MZ $h1 -t udp "sp=54321,dp=12345" -c 0 -d 1msec -b $rp1mac \538 -B 203.0.113.1 -q &539 mz_pid=$!540 541 devlink_trap_exception_test $trap_name542 543 log_test "LPM miss: IPv4"544 545 kill $mz_pid && wait $mz_pid &> /dev/null546 vrf_without_routes_destroy547}548 549ipv6_lpm_miss_test()550{551 local trap_name="ipv6_lpm_miss"552 local expected_action="trap"553 local mz_pid554 555 RET=0556 557 ping_check $trap_name558 trap_action_check $trap_name $expected_action559 560 # Create a VRF without a default route561 vrf_without_routes_create562 563 # Generate packets through a VRF without a matching route.564 $MZ -6 $h1 -t udp "sp=54321,dp=12345" -c 0 -d 1msec -b $rp1mac \565 -B 2001:db8::1 -q &566 mz_pid=$!567 568 devlink_trap_exception_test $trap_name569 570 log_test "LPM miss: IPv6"571 572 kill $mz_pid && wait $mz_pid &> /dev/null573 vrf_without_routes_destroy574}575 576trap cleanup EXIT577 578setup_prepare579setup_wait580 581tests_run582 583exit $EXIT_STATUS584