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 116setup_prepare() 117{ 118 h1=${NETIFS[p1]} 119 rp1=${NETIFS[p2]} 120 121 rp2=${NETIFS[p3]} 122 h2=${NETIFS[p4]} 123 124 rp1mac=$(mac_get $rp1) 125 126 start_mcd 127 128 vrf_prepare 129 forwarding_enable 130 131 h1_create 132 h2_create 133 134 router_create 135} 136 137cleanup() 138{ 139 pre_cleanup 140 141 router_destroy 142 143 h2_destroy 144 h1_destroy 145 146 forwarding_restore 147 vrf_cleanup 148 149 kill_mcd 150} 151 152ping_check() 153{ 154 ping_do $h1 198.51.100.1 155 check_err $? "Packets that should not be trapped were trapped" 156} 157 158trap_action_check() 159{ 160 local trap_name=$1; shift 161 local expected_action=$1; shift 162 163 action=$(devlink_trap_action_get $trap_name) 164 if [ "$action" != $expected_action ]; then 165 check_err 1 "Trap $trap_name has wrong action: $action" 166 fi 167} 168 169mtu_value_is_too_small_test() 170{ 171 local trap_name="mtu_value_is_too_small" 172 local group_name="l3_drops" 173 local expected_action="trap" 174 local mz_pid 175 176 RET=0 177 178 ping_check $trap_name 179 trap_action_check $trap_name $expected_action 180 181 # type - Destination Unreachable 182 # code - Fragmentation Needed and Don't Fragment was Set 183 tc filter add dev $h1 ingress protocol ip pref 1 handle 101 \ 184 flower skip_hw ip_proto icmp type 3 code 4 action pass 185 186 mtu_set $rp2 1300 187 188 # Generate IP packets bigger than router's MTU with don't fragment 189 # flag on. 190 $MZ $h1 -t udp "sp=54321,dp=12345,df" -p 1400 -c 0 -d 1msec -b $rp1mac \ 191 -B 198.51.100.1 -q & 192 mz_pid=$! 193 194 devlink_trap_exception_test $trap_name $group_name 195 196 tc_check_packets_hitting "dev $h1 ingress" 101 197 check_err $? "Packets were not received to h1" 198 199 log_test "MTU value is too small" 200 201 mtu_restore $rp2 202 203 kill $mz_pid && wait $mz_pid &> /dev/null 204 tc filter del dev $h1 ingress protocol ip pref 1 handle 101 flower 205} 206 207__ttl_value_is_too_small_test() 208{ 209 local ttl_val=$1; shift 210 local trap_name="ttl_value_is_too_small" 211 local group_name="l3_drops" 212 local expected_action="trap" 213 local mz_pid 214 215 RET=0 216 217 ping_check $trap_name 218 trap_action_check $trap_name $expected_action 219 220 # type - Time Exceeded 221 # code - Time to Live exceeded in Transit 222 tc filter add dev $h1 ingress protocol ip pref 1 handle 101 \ 223 flower skip_hw ip_proto icmp type 11 code 0 action pass 224 225 # Generate IP packets with small TTL 226 $MZ $h1 -t udp "ttl=$ttl_val,sp=54321,dp=12345" -c 0 -d 1msec \ 227 -b $rp1mac -B 198.51.100.1 -q & 228 mz_pid=$! 229 230 devlink_trap_exception_test $trap_name $group_name 231 232 tc_check_packets_hitting "dev $h1 ingress" 101 233 check_err $? "Packets were not received to h1" 234 235 log_test "TTL value is too small: TTL=$ttl_val" 236 237 kill $mz_pid && wait $mz_pid &> /dev/null 238 tc filter del dev $h1 ingress protocol ip pref 1 handle 101 flower 239} 240 241ttl_value_is_too_small_test() 242{ 243 __ttl_value_is_too_small_test 0 244 __ttl_value_is_too_small_test 1 245} 246 247start_mcd() 248{ 249 SMCROUTEDIR="$(mktemp -d)" 250 for ((i = 1; i <= $NUM_NETIFS; ++i)); do 251 echo "phyint ${NETIFS[p$i]} enable" >> \ 252 $SMCROUTEDIR/$table_name.conf 253 done 254 255 $MCD -N -I $table_name -f $SMCROUTEDIR/$table_name.conf \ 256 -P $SMCROUTEDIR/$table_name.pid 257} 258 259kill_mcd() 260{ 261 pkill $MCD 262 rm -rf $SMCROUTEDIR 263} 264 265__mc_reverse_path_forwarding_test() 266{ 267 local desc=$1; shift 268 local src_ip=$1; shift 269 local dst_ip=$1; shift 270 local dst_mac=$1; shift 271 local proto=$1; shift 272 local flags=${1:-""}; shift 273 local trap_name="mc_reverse_path_forwarding" 274 local group_name="l3_drops" 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 $group_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 group_name="l3_drops" 326 local expected_action="trap" 327 local mz_pid 328 329 RET=0 330 331 ping_check $trap_name 332 trap_action_check $trap_name $expected_action 333 334 tc filter add dev $h1 ingress protocol $proto pref 1 handle 101 flower \ 335 skip_hw ip_proto $ip_proto type $type code $code action pass 336 337 ip route add unreachable $unreachable 338 339 # Generate pacekts to h2. The destination IP is unreachable. 340 $MZ $flags $h1 -t udp "sp=54321,dp=12345" -c 0 -d 1msec -b $rp1mac \ 341 -B $dst_ip -q & 342 mz_pid=$! 343 344 devlink_trap_exception_test $trap_name $group_name 345 346 tc_check_packets_hitting "dev $h1 ingress" 101 347 check_err $? "ICMP packet was not received to h1" 348 349 log_test "Reject route: $desc" 350 351 kill $mz_pid && wait $mz_pid &> /dev/null 352 ip route del unreachable $unreachable 353 tc filter del dev $h1 ingress protocol $proto pref 1 handle 101 flower 354} 355 356reject_route_test() 357{ 358 # type - Destination Unreachable 359 # code - Host Unreachable 360 __reject_route_test "IPv4" 198.51.100.1 "ip" "icmp" 3 1 \ 361 "198.51.100.0/26" 362 # type - Destination Unreachable 363 # code - No Route 364 __reject_route_test "IPv6" 2001:db8:2::1 "ipv6" "icmpv6" 1 0 \ 365 "2001:db8:2::0/66" "-6" 366} 367 368__host_miss_test() 369{ 370 local desc=$1; shift 371 local dip=$1; shift 372 local trap_name="unresolved_neigh" 373 local group_name="l3_drops" 374 local expected_action="trap" 375 local mz_pid 376 377 RET=0 378 379 ping_check $trap_name 380 trap_action_check $trap_name $expected_action 381 382 ip neigh flush dev $rp2 383 384 t0_packets=$(devlink_trap_rx_packets_get $trap_name) 385 386 # Generate packets to h2 (will incur a unresolved neighbor). 387 # The ping should pass and devlink counters should be increased. 388 ping_do $h1 $dip 389 check_err $? "ping failed: $desc" 390 391 t1_packets=$(devlink_trap_rx_packets_get $trap_name) 392 393 if [[ $t0_packets -eq $t1_packets ]]; then 394 check_err 1 "Trap counter did not increase" 395 fi 396 397 log_test "Unresolved neigh: host miss: $desc" 398} 399 400__invalid_nexthop_test() 401{ 402 local desc=$1; shift 403 local dip=$1; shift 404 local extra_add=$1; shift 405 local subnet=$1; shift 406 local via_add=$1; shift 407 local trap_name="unresolved_neigh" 408 local group_name="l3_drops" 409 local expected_action="trap" 410 local mz_pid 411 412 RET=0 413 414 ping_check $trap_name 415 trap_action_check $trap_name $expected_action 416 417 ip address add $extra_add/$subnet dev $h2 418 419 # Check that correct route does not trigger unresolved_neigh 420 ip $flags route add $dip via $extra_add dev $rp2 421 422 # Generate packets in order to discover all neighbours. 423 # Without it, counters of unresolved_neigh will be increased 424 # during neighbours discovery and the check below will fail 425 # for a wrong reason 426 ping_do $h1 $dip 427 428 t0_packets=$(devlink_trap_rx_packets_get $trap_name) 429 ping_do $h1 $dip 430 t1_packets=$(devlink_trap_rx_packets_get $trap_name) 431 432 if [[ $t0_packets -ne $t1_packets ]]; then 433 check_err 1 "Trap counter increased when it should not" 434 fi 435 436 ip $flags route del $dip via $extra_add dev $rp2 437 438 # Check that route to nexthop that does not exist trigger 439 # unresolved_neigh 440 ip $flags route add $dip via $via_add dev $h2 441 442 t0_packets=$(devlink_trap_rx_packets_get $trap_name) 443 ping_do $h1 $dip 444 t1_packets=$(devlink_trap_rx_packets_get $trap_name) 445 446 if [[ $t0_packets -eq $t1_packets ]]; then 447 check_err 1 "Trap counter did not increase" 448 fi 449 450 ip $flags route del $dip via $via_add dev $h2 451 ip address del $extra_add/$subnet dev $h2 452 log_test "Unresolved neigh: nexthop does not exist: $desc" 453} 454 455unresolved_neigh_test() 456{ 457 __host_miss_test "IPv4" 198.51.100.1 458 __host_miss_test "IPv6" 2001:db8:2::1 459 __invalid_nexthop_test "IPv4" 198.51.100.1 198.51.100.3 24 198.51.100.4 460 __invalid_nexthop_test "IPv6" 2001:db8:2::1 2001:db8:2::3 64 \ 461 2001:db8:2::4 462} 463 464vrf_without_routes_create() 465{ 466 # VRF creating makes the links to be down and then up again. 467 # By default, IPv6 address is not saved after link becomes down. 468 # Save IPv6 address using sysctl configuration. 469 sysctl_set net.ipv6.conf.$rp1.keep_addr_on_down 1 470 sysctl_set net.ipv6.conf.$rp2.keep_addr_on_down 1 471 472 ip link add dev vrf1 type vrf table 101 473 ip link set dev $rp1 master vrf1 474 ip link set dev $rp2 master vrf1 475 ip link set dev vrf1 up 476 477 # Wait for rp1 and rp2 to be up 478 setup_wait 479} 480 481vrf_without_routes_destroy() 482{ 483 ip link set dev $rp1 nomaster 484 ip link set dev $rp2 nomaster 485 ip link del dev vrf1 486 487 sysctl_restore net.ipv6.conf.$rp2.keep_addr_on_down 488 sysctl_restore net.ipv6.conf.$rp1.keep_addr_on_down 489 490 # Wait for interfaces to be up 491 setup_wait 492} 493 494ipv4_lpm_miss_test() 495{ 496 local trap_name="ipv4_lpm_miss" 497 local group_name="l3_drops" 498 local expected_action="trap" 499 local mz_pid 500 501 RET=0 502 503 ping_check $trap_name 504 trap_action_check $trap_name $expected_action 505 506 # Create a VRF without a default route 507 vrf_without_routes_create 508 509 # Generate packets through a VRF without a matching route. 510 $MZ $h1 -t udp "sp=54321,dp=12345" -c 0 -d 1msec -b $rp1mac \ 511 -B 203.0.113.1 -q & 512 mz_pid=$! 513 514 devlink_trap_exception_test $trap_name $group_name 515 516 log_test "LPM miss: IPv4" 517 518 kill $mz_pid && wait $mz_pid &> /dev/null 519 vrf_without_routes_destroy 520} 521 522ipv6_lpm_miss_test() 523{ 524 local trap_name="ipv6_lpm_miss" 525 local group_name="l3_drops" 526 local expected_action="trap" 527 local mz_pid 528 529 RET=0 530 531 ping_check $trap_name 532 trap_action_check $trap_name $expected_action 533 534 # Create a VRF without a default route 535 vrf_without_routes_create 536 537 # Generate packets through a VRF without a matching route. 538 $MZ -6 $h1 -t udp "sp=54321,dp=12345" -c 0 -d 1msec -b $rp1mac \ 539 -B 2001:db8::1 -q & 540 mz_pid=$! 541 542 devlink_trap_exception_test $trap_name $group_name 543 544 log_test "LPM miss: IPv6" 545 546 kill $mz_pid && wait $mz_pid &> /dev/null 547 vrf_without_routes_destroy 548} 549 550trap cleanup EXIT 551 552setup_prepare 553setup_wait 554 555tests_run 556 557exit $EXIT_STATUS 558