1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# Test devlink-trap L3 exceptions functionality over mlxsw. 5# Check all exception traps to make sure they are 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 mtu_value_is_too_small_test 44 ttl_value_is_too_small_test 45 mc_reverse_path_forwarding_test 46 reject_route_test 47 unresolved_neigh_test 48 ipv4_lpm_miss_test 49 ipv6_lpm_miss_test 50" 51 52NUM_NETIFS=4 53source $lib_dir/lib.sh 54source $lib_dir/tc_common.sh 55source $lib_dir/devlink_lib.sh 56 57require_command $MCD 58require_command $MC_CLI 59table_name=selftests 60 61h1_create() 62{ 63 simple_if_init $h1 192.0.2.1/24 2001:db8:1::1/64 64 65 ip -4 route add default vrf v$h1 nexthop via 192.0.2.2 66 ip -6 route add default vrf v$h1 nexthop via 2001:db8:1::2 67 68 tc qdisc add dev $h1 clsact 69} 70 71h1_destroy() 72{ 73 tc qdisc del dev $h1 clsact 74 75 ip -6 route del default vrf v$h1 nexthop via 2001:db8:1::2 76 ip -4 route del default vrf v$h1 nexthop via 192.0.2.2 77 78 simple_if_fini $h1 192.0.2.1/24 2001:db8:1::1/64 79} 80 81h2_create() 82{ 83 simple_if_init $h2 198.51.100.1/24 2001:db8:2::1/64 84 85 ip -4 route add default vrf v$h2 nexthop via 198.51.100.2 86 ip -6 route add default vrf v$h2 nexthop via 2001:db8:2::2 87} 88 89h2_destroy() 90{ 91 ip -6 route del default vrf v$h2 nexthop via 2001:db8:2::2 92 ip -4 route del default vrf v$h2 nexthop via 198.51.100.2 93 94 simple_if_fini $h2 198.51.100.1/24 2001:db8:2::1/64 95} 96 97router_create() 98{ 99 ip link set dev $rp1 up 100 ip link set dev $rp2 up 101 102 tc qdisc add dev $rp2 clsact 103 104 __addr_add_del $rp1 add 192.0.2.2/24 2001:db8:1::2/64 105 __addr_add_del $rp2 add 198.51.100.2/24 2001:db8:2::2/64 106} 107 108router_destroy() 109{ 110 __addr_add_del $rp2 del 198.51.100.2/24 2001:db8:2::2/64 111 __addr_add_del $rp1 del 192.0.2.2/24 2001:db8:1::2/64 112 113 tc qdisc del dev $rp2 clsact 114 115 ip link set dev $rp2 down 116 ip link set dev $rp1 down 117} 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_mcd 130 131 vrf_prepare 132 forwarding_enable 133 134 h1_create 135 h2_create 136 137 router_create 138} 139 140cleanup() 141{ 142 pre_cleanup 143 144 router_destroy 145 146 h2_destroy 147 h1_destroy 148 149 forwarding_restore 150 vrf_cleanup 151 152 kill_mcd 153} 154 155ping_check() 156{ 157 ping_do $h1 198.51.100.1 158 check_err $? "Packets that should not be trapped were trapped" 159} 160 161trap_action_check() 162{ 163 local trap_name=$1; shift 164 local expected_action=$1; shift 165 166 action=$(devlink_trap_action_get $trap_name) 167 if [ "$action" != $expected_action ]; then 168 check_err 1 "Trap $trap_name has wrong action: $action" 169 fi 170} 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_pid 177 178 RET=0 179 180 ping_check $trap_name 181 trap_action_check $trap_name $expected_action 182 183 # type - Destination Unreachable 184 # code - Fragmentation Needed and Don't Fragment was Set 185 tc filter add dev $h1 ingress protocol ip pref 1 handle 101 \ 186 flower skip_hw ip_proto icmp type 3 code 4 action pass 187 188 mtu_set $rp2 1300 189 190 # Generate IP packets bigger than router's MTU with don't fragment 191 # 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_name 197 198 tc_check_packets_hitting "dev $h1 ingress" 101 199 check_err $? "Packets were not received to h1" 200 201 log_test "MTU value is too small" 202 203 mtu_restore $rp2 204 205 kill $mz_pid && wait $mz_pid &> /dev/null 206 tc filter del dev $h1 ingress protocol ip pref 1 handle 101 flower 207} 208 209__ttl_value_is_too_small_test() 210{ 211 local ttl_val=$1; shift 212 local trap_name="ttl_value_is_too_small" 213 local expected_action="trap" 214 local mz_pid 215 216 RET=0 217 218 ping_check $trap_name 219 trap_action_check $trap_name $expected_action 220 221 # type - Time Exceeded 222 # code - Time to Live exceeded in Transit 223 tc filter add dev $h1 ingress protocol ip pref 1 handle 101 \ 224 flower skip_hw ip_proto icmp type 11 code 0 action pass 225 226 # Generate IP packets with small TTL 227 $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_name 232 233 tc_check_packets_hitting "dev $h1 ingress" 101 234 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/null 239 tc filter del dev $h1 ingress protocol ip pref 1 handle 101 flower 240} 241 242ttl_value_is_too_small_test() 243{ 244 __ttl_value_is_too_small_test 0 245 __ttl_value_is_too_small_test 1 246} 247 248start_mcd() 249{ 250 SMCROUTEDIR="$(mktemp -d)" 251 for ((i = 1; i <= $NUM_NETIFS; ++i)); do 252 echo "phyint ${NETIFS[p$i]} enable" >> \ 253 $SMCROUTEDIR/$table_name.conf 254 done 255 256 $MCD -N -I $table_name -f $SMCROUTEDIR/$table_name.conf \ 257 -P $SMCROUTEDIR/$table_name.pid 258} 259 260kill_mcd() 261{ 262 pkill $MCD 263 rm -rf $SMCROUTEDIR 264} 265 266__mc_reverse_path_forwarding_test() 267{ 268 local desc=$1; shift 269 local src_ip=$1; shift 270 local dst_ip=$1; shift 271 local dst_mac=$1; shift 272 local proto=$1; shift 273 local flags=${1:-""}; shift 274 local trap_name="mc_reverse_path_forwarding" 275 local expected_action="trap" 276 local mz_pid 277 278 RET=0 279 280 ping_check $trap_name 281 trap_action_check $trap_name $expected_action 282 283 tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \ 284 flower dst_ip $dst_ip ip_proto udp action drop 285 286 $MC_CLI -I $table_name add $rp1 $src_ip $dst_ip $rp2 287 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_name 296 297 tc_check_packets "dev $rp2 egress" 101 0 298 check_err $? "Packets were not dropped" 299 300 log_test "Multicast reverse path forwarding: $desc" 301 302 kill $mz_pid && wait $mz_pid &> /dev/null 303 tc filter del dev $rp2 egress protocol $proto pref 1 handle 101 flower 304} 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; shift 317 local dst_ip=$1; shift 318 local proto=$1; shift 319 local ip_proto=$1; shift 320 local type=$1; shift 321 local code=$1; shift 322 local unreachable=$1; shift 323 local flags=${1:-""}; shift 324 local trap_name="reject_route" 325 local expected_action="trap" 326 local mz_pid 327 328 RET=0 329 330 ping_check $trap_name 331 trap_action_check $trap_name $expected_action 332 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 pass 335 336 ip route add unreachable $unreachable 337 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_name 344 345 tc_check_packets_hitting "dev $h1 ingress" 101 346 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/null 351 ip route del unreachable $unreachable 352 tc filter del dev $h1 ingress protocol $proto pref 1 handle 101 flower 353} 354 355reject_route_test() 356{ 357 # type - Destination Unreachable 358 # code - Host Unreachable 359 __reject_route_test "IPv4" 198.51.100.1 "ip" "icmp" 3 1 \ 360 "198.51.100.0/26" 361 # type - Destination Unreachable 362 # code - No Route 363 __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; shift 370 local dip=$1; shift 371 local trap_name="unresolved_neigh" 372 local expected_action="trap" 373 local mz_pid 374 375 RET=0 376 377 ping_check $trap_name 378 trap_action_check $trap_name $expected_action 379 380 ip neigh flush dev $rp2 381 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 $dip 387 check_err $? "ping failed: $desc" 388 389 t1_packets=$(devlink_trap_rx_packets_get $trap_name) 390 391 if [[ $t0_packets -eq $t1_packets ]]; then 392 check_err 1 "Trap counter did not increase" 393 fi 394 395 log_test "Unresolved neigh: host miss: $desc" 396} 397 398__invalid_nexthop_test() 399{ 400 local desc=$1; shift 401 local dip=$1; shift 402 local extra_add=$1; shift 403 local subnet=$1; shift 404 local via_add=$1; shift 405 local trap_name="unresolved_neigh" 406 local expected_action="trap" 407 local mz_pid 408 409 RET=0 410 411 ping_check $trap_name 412 trap_action_check $trap_name $expected_action 413 414 ip address add $extra_add/$subnet dev $h2 415 416 # Check that correct route does not trigger unresolved_neigh 417 ip $flags route add $dip via $extra_add dev $rp2 418 419 # Generate packets in order to discover all neighbours. 420 # Without it, counters of unresolved_neigh will be increased 421 # during neighbours discovery and the check below will fail 422 # for a wrong reason 423 ping_do $h1 $dip 424 425 t0_packets=$(devlink_trap_rx_packets_get $trap_name) 426 ping_do $h1 $dip 427 t1_packets=$(devlink_trap_rx_packets_get $trap_name) 428 429 if [[ $t0_packets -ne $t1_packets ]]; then 430 check_err 1 "Trap counter increased when it should not" 431 fi 432 433 ip $flags route del $dip via $extra_add dev $rp2 434 435 # Check that route to nexthop that does not exist trigger 436 # unresolved_neigh 437 ip $flags route add $dip via $via_add dev $h2 438 439 t0_packets=$(devlink_trap_rx_packets_get $trap_name) 440 ping_do $h1 $dip 441 t1_packets=$(devlink_trap_rx_packets_get $trap_name) 442 443 if [[ $t0_packets -eq $t1_packets ]]; then 444 check_err 1 "Trap counter did not increase" 445 fi 446 447 ip $flags route del $dip via $via_add dev $h2 448 ip address del $extra_add/$subnet dev $h2 449 log_test "Unresolved neigh: nexthop does not exist: $desc" 450} 451 452__invalid_nexthop_bucket_test() 453{ 454 local desc=$1; shift 455 local dip=$1; shift 456 local via_add=$1; shift 457 local trap_name="unresolved_neigh" 458 459 RET=0 460 461 # Check that route to nexthop that does not exist triggers 462 # unresolved_neigh 463 ip nexthop add id 1 via $via_add dev $rp2 464 ip nexthop add id 10 group 1 type resilient buckets 32 465 ip route add $dip nhid 10 466 467 t0_packets=$(devlink_trap_rx_packets_get $trap_name) 468 ping_do $h1 $dip 469 t1_packets=$(devlink_trap_rx_packets_get $trap_name) 470 471 if [[ $t0_packets -eq $t1_packets ]]; then 472 check_err 1 "Trap counter did not increase" 473 fi 474 475 ip route del $dip nhid 10 476 ip nexthop del id 10 477 ip nexthop del id 1 478 log_test "Unresolved neigh: nexthop bucket does not exist: $desc" 479} 480 481unresolved_neigh_test() 482{ 483 __host_miss_test "IPv4" 198.51.100.1 484 __host_miss_test "IPv6" 2001:db8:2::1 485 __invalid_nexthop_test "IPv4" 198.51.100.1 198.51.100.3 24 198.51.100.4 486 __invalid_nexthop_test "IPv6" 2001:db8:2::1 2001:db8:2::3 64 \ 487 2001:db8:2::4 488 __invalid_nexthop_bucket_test "IPv4" 198.51.100.1 198.51.100.4 489 __invalid_nexthop_bucket_test "IPv6" 2001:db8:2::1 2001:db8:2::4 490} 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 1 498 sysctl_set net.ipv6.conf.$rp2.keep_addr_on_down 1 499 500 ip link add dev vrf1 type vrf table 101 501 ip link set dev $rp1 master vrf1 502 ip link set dev $rp2 master vrf1 503 ip link set dev vrf1 up 504 505 # Wait for rp1 and rp2 to be up 506 setup_wait 507} 508 509vrf_without_routes_destroy() 510{ 511 ip link set dev $rp1 nomaster 512 ip link set dev $rp2 nomaster 513 ip link del dev vrf1 514 515 sysctl_restore net.ipv6.conf.$rp2.keep_addr_on_down 516 sysctl_restore net.ipv6.conf.$rp1.keep_addr_on_down 517 518 # Wait for interfaces to be up 519 setup_wait 520} 521 522ipv4_lpm_miss_test() 523{ 524 local trap_name="ipv4_lpm_miss" 525 local expected_action="trap" 526 local mz_pid 527 528 RET=0 529 530 ping_check $trap_name 531 trap_action_check $trap_name $expected_action 532 533 # Create a VRF without a default route 534 vrf_without_routes_create 535 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_name 542 543 log_test "LPM miss: IPv4" 544 545 kill $mz_pid && wait $mz_pid &> /dev/null 546 vrf_without_routes_destroy 547} 548 549ipv6_lpm_miss_test() 550{ 551 local trap_name="ipv6_lpm_miss" 552 local expected_action="trap" 553 local mz_pid 554 555 RET=0 556 557 ping_check $trap_name 558 trap_action_check $trap_name $expected_action 559 560 # Create a VRF without a default route 561 vrf_without_routes_create 562 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_name 569 570 log_test "LPM miss: IPv6" 571 572 kill $mz_pid && wait $mz_pid &> /dev/null 573 vrf_without_routes_destroy 574} 575 576trap cleanup EXIT 577 578setup_prepare 579setup_wait 580 581tests_run 582 583exit $EXIT_STATUS 584