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 expected_action="trap" 173 local mz_pid 174 175 RET=0 176 177 ping_check $trap_name 178 trap_action_check $trap_name $expected_action 179 180 # type - Destination Unreachable 181 # code - Fragmentation Needed and Don't Fragment was Set 182 tc filter add dev $h1 ingress protocol ip pref 1 handle 101 \ 183 flower skip_hw ip_proto icmp type 3 code 4 action pass 184 185 mtu_set $rp2 1300 186 187 # Generate IP packets bigger than router's MTU with don't fragment 188 # flag on. 189 $MZ $h1 -t udp "sp=54321,dp=12345,df" -p 1400 -c 0 -d 1msec -b $rp1mac \ 190 -B 198.51.100.1 -q & 191 mz_pid=$! 192 193 devlink_trap_exception_test $trap_name 194 195 tc_check_packets_hitting "dev $h1 ingress" 101 196 check_err $? "Packets were not received to h1" 197 198 log_test "MTU value is too small" 199 200 mtu_restore $rp2 201 202 kill $mz_pid && wait $mz_pid &> /dev/null 203 tc filter del dev $h1 ingress protocol ip pref 1 handle 101 flower 204} 205 206__ttl_value_is_too_small_test() 207{ 208 local ttl_val=$1; shift 209 local trap_name="ttl_value_is_too_small" 210 local expected_action="trap" 211 local mz_pid 212 213 RET=0 214 215 ping_check $trap_name 216 trap_action_check $trap_name $expected_action 217 218 # type - Time Exceeded 219 # code - Time to Live exceeded in Transit 220 tc filter add dev $h1 ingress protocol ip pref 1 handle 101 \ 221 flower skip_hw ip_proto icmp type 11 code 0 action pass 222 223 # Generate IP packets with small TTL 224 $MZ $h1 -t udp "ttl=$ttl_val,sp=54321,dp=12345" -c 0 -d 1msec \ 225 -b $rp1mac -B 198.51.100.1 -q & 226 mz_pid=$! 227 228 devlink_trap_exception_test $trap_name 229 230 tc_check_packets_hitting "dev $h1 ingress" 101 231 check_err $? "Packets were not received to h1" 232 233 log_test "TTL value is too small: TTL=$ttl_val" 234 235 kill $mz_pid && wait $mz_pid &> /dev/null 236 tc filter del dev $h1 ingress protocol ip pref 1 handle 101 flower 237} 238 239ttl_value_is_too_small_test() 240{ 241 __ttl_value_is_too_small_test 0 242 __ttl_value_is_too_small_test 1 243} 244 245start_mcd() 246{ 247 SMCROUTEDIR="$(mktemp -d)" 248 for ((i = 1; i <= $NUM_NETIFS; ++i)); do 249 echo "phyint ${NETIFS[p$i]} enable" >> \ 250 $SMCROUTEDIR/$table_name.conf 251 done 252 253 $MCD -N -I $table_name -f $SMCROUTEDIR/$table_name.conf \ 254 -P $SMCROUTEDIR/$table_name.pid 255} 256 257kill_mcd() 258{ 259 pkill $MCD 260 rm -rf $SMCROUTEDIR 261} 262 263__mc_reverse_path_forwarding_test() 264{ 265 local desc=$1; shift 266 local src_ip=$1; shift 267 local dst_ip=$1; shift 268 local dst_mac=$1; shift 269 local proto=$1; shift 270 local flags=${1:-""}; shift 271 local trap_name="mc_reverse_path_forwarding" 272 local expected_action="trap" 273 local mz_pid 274 275 RET=0 276 277 ping_check $trap_name 278 trap_action_check $trap_name $expected_action 279 280 tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \ 281 flower dst_ip $dst_ip ip_proto udp action drop 282 283 $MC_CLI -I $table_name add $rp1 $src_ip $dst_ip $rp2 284 285 # Generate packets to multicast address. 286 $MZ $h2 $flags -t udp "sp=54321,dp=12345" -c 0 -p 128 \ 287 -a 00:11:22:33:44:55 -b $dst_mac \ 288 -A $src_ip -B $dst_ip -q & 289 290 mz_pid=$! 291 292 devlink_trap_exception_test $trap_name 293 294 tc_check_packets "dev $rp2 egress" 101 0 295 check_err $? "Packets were not dropped" 296 297 log_test "Multicast reverse path forwarding: $desc" 298 299 kill $mz_pid && wait $mz_pid &> /dev/null 300 tc filter del dev $rp2 egress protocol $proto pref 1 handle 101 flower 301} 302 303mc_reverse_path_forwarding_test() 304{ 305 __mc_reverse_path_forwarding_test "IPv4" "192.0.2.1" "225.1.2.3" \ 306 "01:00:5e:01:02:03" "ip" 307 __mc_reverse_path_forwarding_test "IPv6" "2001:db8:1::1" "ff0e::3" \ 308 "33:33:00:00:00:03" "ipv6" "-6" 309} 310 311__reject_route_test() 312{ 313 local desc=$1; shift 314 local dst_ip=$1; shift 315 local proto=$1; shift 316 local ip_proto=$1; shift 317 local type=$1; shift 318 local code=$1; shift 319 local unreachable=$1; shift 320 local flags=${1:-""}; shift 321 local trap_name="reject_route" 322 local expected_action="trap" 323 local mz_pid 324 325 RET=0 326 327 ping_check $trap_name 328 trap_action_check $trap_name $expected_action 329 330 tc filter add dev $h1 ingress protocol $proto pref 1 handle 101 flower \ 331 skip_hw ip_proto $ip_proto type $type code $code action pass 332 333 ip route add unreachable $unreachable 334 335 # Generate pacekts to h2. The destination IP is unreachable. 336 $MZ $flags $h1 -t udp "sp=54321,dp=12345" -c 0 -d 1msec -b $rp1mac \ 337 -B $dst_ip -q & 338 mz_pid=$! 339 340 devlink_trap_exception_test $trap_name 341 342 tc_check_packets_hitting "dev $h1 ingress" 101 343 check_err $? "ICMP packet was not received to h1" 344 345 log_test "Reject route: $desc" 346 347 kill $mz_pid && wait $mz_pid &> /dev/null 348 ip route del unreachable $unreachable 349 tc filter del dev $h1 ingress protocol $proto pref 1 handle 101 flower 350} 351 352reject_route_test() 353{ 354 # type - Destination Unreachable 355 # code - Host Unreachable 356 __reject_route_test "IPv4" 198.51.100.1 "ip" "icmp" 3 1 \ 357 "198.51.100.0/26" 358 # type - Destination Unreachable 359 # code - No Route 360 __reject_route_test "IPv6" 2001:db8:2::1 "ipv6" "icmpv6" 1 0 \ 361 "2001:db8:2::0/66" "-6" 362} 363 364__host_miss_test() 365{ 366 local desc=$1; shift 367 local dip=$1; shift 368 local trap_name="unresolved_neigh" 369 local expected_action="trap" 370 local mz_pid 371 372 RET=0 373 374 ping_check $trap_name 375 trap_action_check $trap_name $expected_action 376 377 ip neigh flush dev $rp2 378 379 t0_packets=$(devlink_trap_rx_packets_get $trap_name) 380 381 # Generate packets to h2 (will incur a unresolved neighbor). 382 # The ping should pass and devlink counters should be increased. 383 ping_do $h1 $dip 384 check_err $? "ping failed: $desc" 385 386 t1_packets=$(devlink_trap_rx_packets_get $trap_name) 387 388 if [[ $t0_packets -eq $t1_packets ]]; then 389 check_err 1 "Trap counter did not increase" 390 fi 391 392 log_test "Unresolved neigh: host miss: $desc" 393} 394 395__invalid_nexthop_test() 396{ 397 local desc=$1; shift 398 local dip=$1; shift 399 local extra_add=$1; shift 400 local subnet=$1; shift 401 local via_add=$1; shift 402 local trap_name="unresolved_neigh" 403 local expected_action="trap" 404 local mz_pid 405 406 RET=0 407 408 ping_check $trap_name 409 trap_action_check $trap_name $expected_action 410 411 ip address add $extra_add/$subnet dev $h2 412 413 # Check that correct route does not trigger unresolved_neigh 414 ip $flags route add $dip via $extra_add dev $rp2 415 416 # Generate packets in order to discover all neighbours. 417 # Without it, counters of unresolved_neigh will be increased 418 # during neighbours discovery and the check below will fail 419 # for a wrong reason 420 ping_do $h1 $dip 421 422 t0_packets=$(devlink_trap_rx_packets_get $trap_name) 423 ping_do $h1 $dip 424 t1_packets=$(devlink_trap_rx_packets_get $trap_name) 425 426 if [[ $t0_packets -ne $t1_packets ]]; then 427 check_err 1 "Trap counter increased when it should not" 428 fi 429 430 ip $flags route del $dip via $extra_add dev $rp2 431 432 # Check that route to nexthop that does not exist trigger 433 # unresolved_neigh 434 ip $flags route add $dip via $via_add dev $h2 435 436 t0_packets=$(devlink_trap_rx_packets_get $trap_name) 437 ping_do $h1 $dip 438 t1_packets=$(devlink_trap_rx_packets_get $trap_name) 439 440 if [[ $t0_packets -eq $t1_packets ]]; then 441 check_err 1 "Trap counter did not increase" 442 fi 443 444 ip $flags route del $dip via $via_add dev $h2 445 ip address del $extra_add/$subnet dev $h2 446 log_test "Unresolved neigh: nexthop does not exist: $desc" 447} 448 449unresolved_neigh_test() 450{ 451 __host_miss_test "IPv4" 198.51.100.1 452 __host_miss_test "IPv6" 2001:db8:2::1 453 __invalid_nexthop_test "IPv4" 198.51.100.1 198.51.100.3 24 198.51.100.4 454 __invalid_nexthop_test "IPv6" 2001:db8:2::1 2001:db8:2::3 64 \ 455 2001:db8:2::4 456} 457 458vrf_without_routes_create() 459{ 460 # VRF creating makes the links to be down and then up again. 461 # By default, IPv6 address is not saved after link becomes down. 462 # Save IPv6 address using sysctl configuration. 463 sysctl_set net.ipv6.conf.$rp1.keep_addr_on_down 1 464 sysctl_set net.ipv6.conf.$rp2.keep_addr_on_down 1 465 466 ip link add dev vrf1 type vrf table 101 467 ip link set dev $rp1 master vrf1 468 ip link set dev $rp2 master vrf1 469 ip link set dev vrf1 up 470 471 # Wait for rp1 and rp2 to be up 472 setup_wait 473} 474 475vrf_without_routes_destroy() 476{ 477 ip link set dev $rp1 nomaster 478 ip link set dev $rp2 nomaster 479 ip link del dev vrf1 480 481 sysctl_restore net.ipv6.conf.$rp2.keep_addr_on_down 482 sysctl_restore net.ipv6.conf.$rp1.keep_addr_on_down 483 484 # Wait for interfaces to be up 485 setup_wait 486} 487 488ipv4_lpm_miss_test() 489{ 490 local trap_name="ipv4_lpm_miss" 491 local expected_action="trap" 492 local mz_pid 493 494 RET=0 495 496 ping_check $trap_name 497 trap_action_check $trap_name $expected_action 498 499 # Create a VRF without a default route 500 vrf_without_routes_create 501 502 # Generate packets through a VRF without a matching route. 503 $MZ $h1 -t udp "sp=54321,dp=12345" -c 0 -d 1msec -b $rp1mac \ 504 -B 203.0.113.1 -q & 505 mz_pid=$! 506 507 devlink_trap_exception_test $trap_name 508 509 log_test "LPM miss: IPv4" 510 511 kill $mz_pid && wait $mz_pid &> /dev/null 512 vrf_without_routes_destroy 513} 514 515ipv6_lpm_miss_test() 516{ 517 local trap_name="ipv6_lpm_miss" 518 local expected_action="trap" 519 local mz_pid 520 521 RET=0 522 523 ping_check $trap_name 524 trap_action_check $trap_name $expected_action 525 526 # Create a VRF without a default route 527 vrf_without_routes_create 528 529 # Generate packets through a VRF without a matching route. 530 $MZ -6 $h1 -t udp "sp=54321,dp=12345" -c 0 -d 1msec -b $rp1mac \ 531 -B 2001:db8::1 -q & 532 mz_pid=$! 533 534 devlink_trap_exception_test $trap_name 535 536 log_test "LPM miss: IPv6" 537 538 kill $mz_pid && wait $mz_pid &> /dev/null 539 vrf_without_routes_destroy 540} 541 542trap cleanup EXIT 543 544setup_prepare 545setup_wait 546 547tests_run 548 549exit $EXIT_STATUS 550