1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4# This test is for checking the A-TCAM and C-TCAM operation in Spectrum-2. 5# It tries to exercise as many code paths in the eRP state machine as 6# possible. 7 8lib_dir=$(dirname $0)/../../../../net/forwarding 9 10ALL_TESTS="single_mask_test identical_filters_test two_masks_test \ 11 multiple_masks_test ctcam_edge_cases_test delta_simple_test \ 12 delta_two_masks_one_key_test delta_simple_rehash_test \ 13 bloom_simple_test bloom_complex_test bloom_delta_test \ 14 max_erp_entries_test max_group_size_test collision_test" 15NUM_NETIFS=2 16source $lib_dir/lib.sh 17source $lib_dir/tc_common.sh 18source $lib_dir/devlink_lib.sh 19 20tcflags="skip_hw" 21 22h1_create() 23{ 24 simple_if_init $h1 192.0.2.1/24 198.51.100.1/24 25} 26 27h1_destroy() 28{ 29 simple_if_fini $h1 192.0.2.1/24 198.51.100.1/24 30} 31 32h2_create() 33{ 34 simple_if_init $h2 192.0.2.2/24 198.51.100.2/24 35 tc qdisc add dev $h2 clsact 36} 37 38h2_destroy() 39{ 40 tc qdisc del dev $h2 clsact 41 simple_if_fini $h2 192.0.2.2/24 198.51.100.2/24 42} 43 44tp_record() 45{ 46 local tracepoint=$1 47 local cmd=$2 48 49 perf record -q -e $tracepoint $cmd 50 return $? 51} 52 53tp_record_all() 54{ 55 local tracepoint=$1 56 local seconds=$2 57 58 perf record -a -q -e $tracepoint sleep $seconds 59 return $? 60} 61 62__tp_hit_count() 63{ 64 local tracepoint=$1 65 66 local perf_output=`perf script -F trace:event,trace` 67 return `echo $perf_output | grep "$tracepoint:" | wc -l` 68} 69 70tp_check_hits() 71{ 72 local tracepoint=$1 73 local count=$2 74 75 __tp_hit_count $tracepoint 76 if [[ "$?" -ne "$count" ]]; then 77 return 1 78 fi 79 return 0 80} 81 82tp_check_hits_any() 83{ 84 local tracepoint=$1 85 86 __tp_hit_count $tracepoint 87 if [[ "$?" -eq "0" ]]; then 88 return 1 89 fi 90 return 0 91} 92 93single_mask_test() 94{ 95 # When only a single mask is required, the device uses the master 96 # mask and not the eRP table. Verify that under this mode the right 97 # filter is matched 98 99 RET=0 100 101 tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \ 102 $tcflags dst_ip 192.0.2.2 action drop 103 104 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 105 -t ip -q 106 107 tc_check_packets "dev $h2 ingress" 101 1 108 check_err $? "Single filter - did not match" 109 110 tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \ 111 $tcflags dst_ip 198.51.100.2 action drop 112 113 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 114 -t ip -q 115 116 tc_check_packets "dev $h2 ingress" 101 2 117 check_err $? "Two filters - did not match highest priority" 118 119 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 198.51.100.1 -B 198.51.100.2 \ 120 -t ip -q 121 122 tc_check_packets "dev $h2 ingress" 102 1 123 check_err $? "Two filters - did not match lowest priority" 124 125 tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower 126 127 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 198.51.100.1 -B 198.51.100.2 \ 128 -t ip -q 129 130 tc_check_packets "dev $h2 ingress" 102 2 131 check_err $? "Single filter - did not match after delete" 132 133 tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower 134 135 log_test "single mask test ($tcflags)" 136} 137 138identical_filters_test() 139{ 140 # When two filters that only differ in their priority are used, 141 # one needs to be inserted into the C-TCAM. This test verifies 142 # that filters are correctly spilled to C-TCAM and that the right 143 # filter is matched 144 145 RET=0 146 147 tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \ 148 $tcflags dst_ip 192.0.2.2 action drop 149 tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \ 150 $tcflags dst_ip 192.0.2.2 action drop 151 152 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 153 -t ip -q 154 155 tc_check_packets "dev $h2 ingress" 101 1 156 check_err $? "Did not match A-TCAM filter" 157 158 tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower 159 160 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 161 -t ip -q 162 163 tc_check_packets "dev $h2 ingress" 102 1 164 check_err $? "Did not match C-TCAM filter after A-TCAM delete" 165 166 tc filter add dev $h2 ingress protocol ip pref 3 handle 103 flower \ 167 $tcflags dst_ip 192.0.2.2 action drop 168 169 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 170 -t ip -q 171 172 tc_check_packets "dev $h2 ingress" 102 2 173 check_err $? "Did not match C-TCAM filter after A-TCAM add" 174 175 tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower 176 177 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 178 -t ip -q 179 180 tc_check_packets "dev $h2 ingress" 103 1 181 check_err $? "Did not match A-TCAM filter after C-TCAM delete" 182 183 tc filter del dev $h2 ingress protocol ip pref 3 handle 103 flower 184 185 log_test "identical filters test ($tcflags)" 186} 187 188two_masks_test() 189{ 190 # When more than one mask is required, the eRP table is used. This 191 # test verifies that the eRP table is correctly allocated and used 192 193 RET=0 194 195 tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \ 196 $tcflags dst_ip 192.0.2.2 action drop 197 tc filter add dev $h2 ingress protocol ip pref 3 handle 103 flower \ 198 $tcflags dst_ip 192.0.0.0/8 action drop 199 200 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 201 -t ip -q 202 203 tc_check_packets "dev $h2 ingress" 101 1 204 check_err $? "Two filters - did not match highest priority" 205 206 tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower 207 208 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 209 -t ip -q 210 211 tc_check_packets "dev $h2 ingress" 103 1 212 check_err $? "Single filter - did not match" 213 214 tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \ 215 $tcflags dst_ip 192.0.2.0/24 action drop 216 217 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 218 -t ip -q 219 220 tc_check_packets "dev $h2 ingress" 102 1 221 check_err $? "Two filters - did not match highest priority after add" 222 223 tc filter del dev $h2 ingress protocol ip pref 3 handle 103 flower 224 tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower 225 226 log_test "two masks test ($tcflags)" 227} 228 229multiple_masks_test() 230{ 231 # The number of masks in a region is limited. Once the maximum 232 # number of masks has been reached filters that require new 233 # masks are spilled to the C-TCAM. This test verifies that 234 # spillage is performed correctly and that the right filter is 235 # matched 236 237 if [[ "$tcflags" != "skip_sw" ]]; then 238 return 0; 239 fi 240 241 local index 242 243 RET=0 244 245 NUM_MASKS=32 246 NUM_ERPS=16 247 BASE_INDEX=100 248 249 for i in $(eval echo {1..$NUM_MASKS}); do 250 index=$((BASE_INDEX - i)) 251 252 if ((i > NUM_ERPS)); then 253 exp_hits=1 254 err_msg="$i filters - C-TCAM spill did not happen when it was expected" 255 else 256 exp_hits=0 257 err_msg="$i filters - C-TCAM spill happened when it should not" 258 fi 259 260 tp_record "mlxsw:mlxsw_sp_acl_atcam_entry_add_ctcam_spill" \ 261 "tc filter add dev $h2 ingress protocol ip pref $index \ 262 handle $index \ 263 flower $tcflags \ 264 dst_ip 192.0.2.2/${i} src_ip 192.0.2.1/${i} \ 265 action drop" 266 tp_check_hits "mlxsw:mlxsw_sp_acl_atcam_entry_add_ctcam_spill" \ 267 $exp_hits 268 check_err $? "$err_msg" 269 270 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 \ 271 -B 192.0.2.2 -t ip -q 272 273 tc_check_packets "dev $h2 ingress" $index 1 274 check_err $? "$i filters - did not match highest priority (add)" 275 done 276 277 for i in $(eval echo {$NUM_MASKS..1}); do 278 index=$((BASE_INDEX - i)) 279 280 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 \ 281 -B 192.0.2.2 -t ip -q 282 283 tc_check_packets "dev $h2 ingress" $index 2 284 check_err $? "$i filters - did not match highest priority (del)" 285 286 tc filter del dev $h2 ingress protocol ip pref $index \ 287 handle $index flower 288 done 289 290 log_test "multiple masks test ($tcflags)" 291} 292 293ctcam_two_atcam_masks_test() 294{ 295 RET=0 296 297 # First case: C-TCAM is disabled when there are two A-TCAM masks. 298 # We push a filter into the C-TCAM by using two identical filters 299 # as in identical_filters_test() 300 301 # Filter goes into A-TCAM 302 tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \ 303 $tcflags dst_ip 192.0.2.2 action drop 304 # Filter goes into C-TCAM 305 tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \ 306 $tcflags dst_ip 192.0.2.2 action drop 307 # Filter goes into A-TCAM 308 tc filter add dev $h2 ingress protocol ip pref 3 handle 103 flower \ 309 $tcflags dst_ip 192.0.0.0/16 action drop 310 311 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 312 -t ip -q 313 314 tc_check_packets "dev $h2 ingress" 101 1 315 check_err $? "Did not match A-TCAM filter" 316 317 # Delete both A-TCAM and C-TCAM filters and make sure the remaining 318 # A-TCAM filter still works 319 tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower 320 tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower 321 322 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 323 -t ip -q 324 325 tc_check_packets "dev $h2 ingress" 103 1 326 check_err $? "Did not match A-TCAM filter" 327 328 tc filter del dev $h2 ingress protocol ip pref 3 handle 103 flower 329 330 log_test "ctcam with two atcam masks test ($tcflags)" 331} 332 333ctcam_one_atcam_mask_test() 334{ 335 RET=0 336 337 # Second case: C-TCAM is disabled when there is one A-TCAM mask. 338 # The test is similar to identical_filters_test() 339 340 # Filter goes into A-TCAM 341 tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \ 342 $tcflags dst_ip 192.0.2.2 action drop 343 # Filter goes into C-TCAM 344 tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \ 345 $tcflags dst_ip 192.0.2.2 action drop 346 347 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 348 -t ip -q 349 350 tc_check_packets "dev $h2 ingress" 101 1 351 check_err $? "Did not match C-TCAM filter" 352 353 tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower 354 355 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 356 -t ip -q 357 358 tc_check_packets "dev $h2 ingress" 102 1 359 check_err $? "Did not match A-TCAM filter" 360 361 tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower 362 363 log_test "ctcam with one atcam mask test ($tcflags)" 364} 365 366ctcam_no_atcam_masks_test() 367{ 368 RET=0 369 370 # Third case: C-TCAM is disabled when there are no A-TCAM masks 371 # This test exercises the code path that transitions the eRP table 372 # to its initial state after deleting the last C-TCAM mask 373 374 # Filter goes into A-TCAM 375 tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \ 376 $tcflags dst_ip 192.0.2.2 action drop 377 # Filter goes into C-TCAM 378 tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \ 379 $tcflags dst_ip 192.0.2.2 action drop 380 381 tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower 382 tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower 383 384 log_test "ctcam with no atcam masks test ($tcflags)" 385} 386 387ctcam_edge_cases_test() 388{ 389 # When the C-TCAM is disabled after deleting the last C-TCAM 390 # mask, we want to make sure the eRP state machine is put in 391 # the correct state 392 393 ctcam_two_atcam_masks_test 394 ctcam_one_atcam_mask_test 395 ctcam_no_atcam_masks_test 396} 397 398delta_simple_test() 399{ 400 # The first filter will create eRP, the second filter will fit into 401 # the first eRP with delta. Remove the first rule then and check that 402 # the eRP stays (referenced by the second filter). 403 404 RET=0 405 406 if [[ "$tcflags" != "skip_sw" ]]; then 407 return 0; 408 fi 409 410 tp_record "objagg:*" "tc filter add dev $h2 ingress protocol ip \ 411 pref 1 handle 101 flower $tcflags dst_ip 192.0.0.0/24 \ 412 action drop" 413 tp_check_hits "objagg:objagg_obj_root_create" 1 414 check_err $? "eRP was not created" 415 416 tp_record "objagg:*" "tc filter add dev $h2 ingress protocol ip \ 417 pref 2 handle 102 flower $tcflags dst_ip 192.0.2.2 \ 418 action drop" 419 tp_check_hits "objagg:objagg_obj_root_create" 0 420 check_err $? "eRP was incorrectly created" 421 tp_check_hits "objagg:objagg_obj_parent_assign" 1 422 check_err $? "delta was not created" 423 424 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 425 -t ip -q 426 427 tc_check_packets "dev $h2 ingress" 101 1 428 check_fail $? "Matched a wrong filter" 429 430 tc_check_packets "dev $h2 ingress" 102 1 431 check_err $? "Did not match on correct filter" 432 433 tp_record "objagg:*" "tc filter del dev $h2 ingress protocol ip \ 434 pref 1 handle 101 flower" 435 tp_check_hits "objagg:objagg_obj_root_destroy" 0 436 check_err $? "eRP was incorrectly destroyed" 437 tp_check_hits "objagg:objagg_obj_parent_unassign" 0 438 check_err $? "delta was incorrectly destroyed" 439 440 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 441 -t ip -q 442 443 tc_check_packets "dev $h2 ingress" 102 2 444 check_err $? "Did not match on correct filter after the first was removed" 445 446 tp_record "objagg:*" "tc filter del dev $h2 ingress protocol ip \ 447 pref 2 handle 102 flower" 448 tp_check_hits "objagg:objagg_obj_parent_unassign" 1 449 check_err $? "delta was not destroyed" 450 tp_check_hits "objagg:objagg_obj_root_destroy" 1 451 check_err $? "eRP was not destroyed" 452 453 log_test "delta simple test ($tcflags)" 454} 455 456delta_two_masks_one_key_test() 457{ 458 # If 2 keys are the same and only differ in mask in a way that 459 # they belong under the same ERP (second is delta of the first), 460 # there should be C-TCAM spill. 461 462 RET=0 463 464 if [[ "$tcflags" != "skip_sw" ]]; then 465 return 0; 466 fi 467 468 tp_record "mlxsw:*" "tc filter add dev $h2 ingress protocol ip \ 469 pref 1 handle 101 flower $tcflags dst_ip 192.0.2.0/24 \ 470 action drop" 471 tp_check_hits "mlxsw:mlxsw_sp_acl_atcam_entry_add_ctcam_spill" 0 472 check_err $? "incorrect C-TCAM spill while inserting the first rule" 473 474 tp_record "mlxsw:*" "tc filter add dev $h2 ingress protocol ip \ 475 pref 2 handle 102 flower $tcflags dst_ip 192.0.2.2 \ 476 action drop" 477 tp_check_hits "mlxsw:mlxsw_sp_acl_atcam_entry_add_ctcam_spill" 1 478 check_err $? "C-TCAM spill did not happen while inserting the second rule" 479 480 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 481 -t ip -q 482 483 tc_check_packets "dev $h2 ingress" 101 1 484 check_err $? "Did not match on correct filter" 485 486 tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower 487 488 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 489 -t ip -q 490 491 tc_check_packets "dev $h2 ingress" 102 1 492 check_err $? "Did not match on correct filter" 493 494 tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower 495 496 log_test "delta two masks one key test ($tcflags)" 497} 498 499delta_simple_rehash_test() 500{ 501 RET=0 502 503 if [[ "$tcflags" != "skip_sw" ]]; then 504 return 0; 505 fi 506 507 devlink dev param set $DEVLINK_DEV \ 508 name acl_region_rehash_interval cmode runtime value 0 509 check_err $? "Failed to set ACL region rehash interval" 510 511 tp_record_all mlxsw:mlxsw_sp_acl_tcam_vregion_rehash 7 512 tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_rehash 513 check_fail $? "Rehash trace was hit even when rehash should be disabled" 514 515 devlink dev param set $DEVLINK_DEV \ 516 name acl_region_rehash_interval cmode runtime value 3000 517 check_err $? "Failed to set ACL region rehash interval" 518 519 sleep 1 520 521 tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \ 522 $tcflags dst_ip 192.0.1.0/25 action drop 523 tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \ 524 $tcflags dst_ip 192.0.2.2 action drop 525 tc filter add dev $h2 ingress protocol ip pref 3 handle 103 flower \ 526 $tcflags dst_ip 192.0.3.0/24 action drop 527 528 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 529 -t ip -q 530 531 tc_check_packets "dev $h2 ingress" 101 1 532 check_fail $? "Matched a wrong filter" 533 534 tc_check_packets "dev $h2 ingress" 103 1 535 check_fail $? "Matched a wrong filter" 536 537 tc_check_packets "dev $h2 ingress" 102 1 538 check_err $? "Did not match on correct filter" 539 540 tp_record_all mlxsw:* 3 541 tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_rehash 542 check_err $? "Rehash trace was not hit" 543 tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate 544 check_err $? "Migrate trace was not hit" 545 tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate_end 546 check_err $? "Migrate end trace was not hit" 547 tp_record_all mlxsw:* 3 548 tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_rehash 549 check_err $? "Rehash trace was not hit" 550 tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate 551 check_fail $? "Migrate trace was hit when no migration should happen" 552 tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate_end 553 check_fail $? "Migrate end trace was hit when no migration should happen" 554 555 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 556 -t ip -q 557 558 tc_check_packets "dev $h2 ingress" 101 1 559 check_fail $? "Matched a wrong filter after rehash" 560 561 tc_check_packets "dev $h2 ingress" 103 1 562 check_fail $? "Matched a wrong filter after rehash" 563 564 tc_check_packets "dev $h2 ingress" 102 2 565 check_err $? "Did not match on correct filter after rehash" 566 567 tc filter del dev $h2 ingress protocol ip pref 3 handle 103 flower 568 tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower 569 tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower 570 571 log_test "delta simple rehash test ($tcflags)" 572} 573 574delta_simple_ipv6_rehash_test() 575{ 576 RET=0 577 578 if [[ "$tcflags" != "skip_sw" ]]; then 579 return 0; 580 fi 581 582 devlink dev param set $DEVLINK_DEV \ 583 name acl_region_rehash_interval cmode runtime value 0 584 check_err $? "Failed to set ACL region rehash interval" 585 586 tp_record_all mlxsw:mlxsw_sp_acl_tcam_vregion_rehash 7 587 tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_rehash 588 check_fail $? "Rehash trace was hit even when rehash should be disabled" 589 590 devlink dev param set $DEVLINK_DEV \ 591 name acl_region_rehash_interval cmode runtime value 3000 592 check_err $? "Failed to set ACL region rehash interval" 593 594 sleep 1 595 596 tc filter add dev $h2 ingress protocol ipv6 pref 1 handle 101 flower \ 597 $tcflags dst_ip 2001:db8:1::0/121 action drop 598 tc filter add dev $h2 ingress protocol ipv6 pref 2 handle 102 flower \ 599 $tcflags dst_ip 2001:db8:2::2 action drop 600 tc filter add dev $h2 ingress protocol ipv6 pref 3 handle 103 flower \ 601 $tcflags dst_ip 2001:db8:3::0/120 action drop 602 603 $MZ $h1 -6 -c 1 -p 64 -a $h1mac -b $h2mac \ 604 -A 2001:db8:2::1 -B 2001:db8:2::2 -t udp -q 605 606 tc_check_packets "dev $h2 ingress" 101 1 607 check_fail $? "Matched a wrong filter" 608 609 tc_check_packets "dev $h2 ingress" 103 1 610 check_fail $? "Matched a wrong filter" 611 612 tc_check_packets "dev $h2 ingress" 102 1 613 check_err $? "Did not match on correct filter" 614 615 tp_record_all mlxsw:* 3 616 tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_rehash 617 check_err $? "Rehash trace was not hit" 618 tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate 619 check_err $? "Migrate trace was not hit" 620 tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate_end 621 check_err $? "Migrate end trace was not hit" 622 tp_record_all mlxsw:* 3 623 tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_rehash 624 check_err $? "Rehash trace was not hit" 625 tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate 626 check_fail $? "Migrate trace was hit when no migration should happen" 627 tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_migrate_end 628 check_fail $? "Migrate end trace was hit when no migration should happen" 629 630 $MZ $h1 -6 -c 1 -p 64 -a $h1mac -b $h2mac \ 631 -A 2001:db8:2::1 -B 2001:db8:2::2 -t udp -q 632 633 tc_check_packets "dev $h2 ingress" 101 1 634 check_fail $? "Matched a wrong filter after rehash" 635 636 tc_check_packets "dev $h2 ingress" 103 1 637 check_fail $? "Matched a wrong filter after rehash" 638 639 tc_check_packets "dev $h2 ingress" 102 2 640 check_err $? "Did not match on correct filter after rehash" 641 642 tc filter del dev $h2 ingress protocol ipv6 pref 3 handle 103 flower 643 tc filter del dev $h2 ingress protocol ipv6 pref 2 handle 102 flower 644 tc filter del dev $h2 ingress protocol ipv6 pref 1 handle 101 flower 645 646 log_test "delta simple IPv6 rehash test ($tcflags)" 647} 648 649TEST_RULE_BASE=256 650declare -a test_rules_inserted 651 652test_rule_add() 653{ 654 local iface=$1 655 local tcflags=$2 656 local index=$3 657 658 if ! [ ${test_rules_inserted[$index]} ] ; then 659 test_rules_inserted[$index]=false 660 fi 661 if ${test_rules_inserted[$index]} ; then 662 return 663 fi 664 665 local number=$(( $index + $TEST_RULE_BASE )) 666 printf -v hexnumber '%x' $number 667 668 batch="${batch}filter add dev $iface ingress protocol ipv6 pref 1 \ 669 handle $number flower $tcflags \ 670 src_ip 2001:db8:1::$hexnumber action drop\n" 671 test_rules_inserted[$index]=true 672} 673 674test_rule_del() 675{ 676 local iface=$1 677 local index=$2 678 679 if ! [ ${test_rules_inserted[$index]} ] ; then 680 test_rules_inserted[$index]=false 681 fi 682 if ! ${test_rules_inserted[$index]} ; then 683 return 684 fi 685 686 local number=$(( $index + $TEST_RULE_BASE )) 687 printf -v hexnumber '%x' $number 688 689 batch="${batch}filter del dev $iface ingress protocol ipv6 pref 1 \ 690 handle $number flower\n" 691 test_rules_inserted[$index]=false 692} 693 694test_rule_add_or_remove() 695{ 696 local iface=$1 697 local tcflags=$2 698 local index=$3 699 700 if ! [ ${test_rules_inserted[$index]} ] ; then 701 test_rules_inserted[$index]=false 702 fi 703 if ${test_rules_inserted[$index]} ; then 704 test_rule_del $iface $index 705 else 706 test_rule_add $iface $tcflags $index 707 fi 708} 709 710test_rule_add_or_remove_random_batch() 711{ 712 local iface=$1 713 local tcflags=$2 714 local total_count=$3 715 local skip=0 716 local count=0 717 local MAXSKIP=20 718 local MAXCOUNT=20 719 720 for ((i=1;i<=total_count;i++)); do 721 if (( $skip == 0 )) && (($count == 0)); then 722 ((skip=$RANDOM % $MAXSKIP + 1)) 723 ((count=$RANDOM % $MAXCOUNT + 1)) 724 fi 725 if (( $skip != 0 )); then 726 ((skip-=1)) 727 else 728 ((count-=1)) 729 test_rule_add_or_remove $iface $tcflags $i 730 fi 731 done 732} 733 734delta_massive_ipv6_rehash_test() 735{ 736 RET=0 737 738 if [[ "$tcflags" != "skip_sw" ]]; then 739 return 0; 740 fi 741 742 devlink dev param set $DEVLINK_DEV \ 743 name acl_region_rehash_interval cmode runtime value 0 744 check_err $? "Failed to set ACL region rehash interval" 745 746 tp_record_all mlxsw:mlxsw_sp_acl_tcam_vregion_rehash 7 747 tp_check_hits_any mlxsw:mlxsw_sp_acl_tcam_vregion_rehash 748 check_fail $? "Rehash trace was hit even when rehash should be disabled" 749 750 RANDOM=4432897 751 declare batch="" 752 test_rule_add_or_remove_random_batch $h2 $tcflags 5000 753 754 echo -n -e $batch | tc -b - 755 756 declare batch="" 757 test_rule_add_or_remove_random_batch $h2 $tcflags 5000 758 759 devlink dev param set $DEVLINK_DEV \ 760 name acl_region_rehash_interval cmode runtime value 3000 761 check_err $? "Failed to set ACL region rehash interval" 762 763 sleep 1 764 765 tc filter add dev $h2 ingress protocol ipv6 pref 1 handle 101 flower \ 766 $tcflags dst_ip 2001:db8:1::0/121 action drop 767 tc filter add dev $h2 ingress protocol ipv6 pref 2 handle 102 flower \ 768 $tcflags dst_ip 2001:db8:2::2 action drop 769 tc filter add dev $h2 ingress protocol ipv6 pref 3 handle 103 flower \ 770 $tcflags dst_ip 2001:db8:3::0/120 action drop 771 772 $MZ $h1 -6 -c 1 -p 64 -a $h1mac -b $h2mac \ 773 -A 2001:db8:2::1 -B 2001:db8:2::2 -t udp -q 774 775 tc_check_packets "dev $h2 ingress" 101 1 776 check_fail $? "Matched a wrong filter" 777 778 tc_check_packets "dev $h2 ingress" 103 1 779 check_fail $? "Matched a wrong filter" 780 781 tc_check_packets "dev $h2 ingress" 102 1 782 check_err $? "Did not match on correct filter" 783 784 echo -n -e $batch | tc -b - 785 786 devlink dev param set $DEVLINK_DEV \ 787 name acl_region_rehash_interval cmode runtime value 0 788 check_err $? "Failed to set ACL region rehash interval" 789 790 $MZ $h1 -6 -c 1 -p 64 -a $h1mac -b $h2mac \ 791 -A 2001:db8:2::1 -B 2001:db8:2::2 -t udp -q 792 793 tc_check_packets "dev $h2 ingress" 101 1 794 check_fail $? "Matched a wrong filter after rehash" 795 796 tc_check_packets "dev $h2 ingress" 103 1 797 check_fail $? "Matched a wrong filter after rehash" 798 799 tc_check_packets "dev $h2 ingress" 102 2 800 check_err $? "Did not match on correct filter after rehash" 801 802 tc filter del dev $h2 ingress protocol ipv6 pref 3 handle 103 flower 803 tc filter del dev $h2 ingress protocol ipv6 pref 2 handle 102 flower 804 tc filter del dev $h2 ingress protocol ipv6 pref 1 handle 101 flower 805 806 declare batch="" 807 for i in {1..5000}; do 808 test_rule_del $h2 $tcflags $i 809 done 810 echo -e $batch | tc -b - 811 812 log_test "delta massive IPv6 rehash test ($tcflags)" 813} 814 815bloom_simple_test() 816{ 817 # Bloom filter requires that the eRP table is used. This test 818 # verifies that Bloom filter is not harming correctness of ACLs. 819 # First, make sure that eRP table is used and then set rule patterns 820 # which are distant enough and will result skipping a lookup after 821 # consulting the Bloom filter. Although some eRP lookups are skipped, 822 # the correct filter should be hit. 823 824 RET=0 825 826 tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \ 827 $tcflags dst_ip 192.0.2.2 action drop 828 tc filter add dev $h2 ingress protocol ip pref 5 handle 104 flower \ 829 $tcflags dst_ip 198.51.100.2 action drop 830 tc filter add dev $h2 ingress protocol ip pref 3 handle 103 flower \ 831 $tcflags dst_ip 192.0.0.0/8 action drop 832 833 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 834 -t ip -q 835 836 tc_check_packets "dev $h2 ingress" 101 1 837 check_err $? "Two filters - did not match highest priority" 838 839 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 198.51.100.1 -B 198.51.100.2 \ 840 -t ip -q 841 842 tc_check_packets "dev $h2 ingress" 104 1 843 check_err $? "Single filter - did not match" 844 845 tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower 846 847 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 848 -t ip -q 849 850 tc_check_packets "dev $h2 ingress" 103 1 851 check_err $? "Low prio filter - did not match" 852 853 tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \ 854 $tcflags dst_ip 198.0.0.0/8 action drop 855 856 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 198.51.100.1 -B 198.51.100.2 \ 857 -t ip -q 858 859 tc_check_packets "dev $h2 ingress" 102 1 860 check_err $? "Two filters - did not match highest priority after add" 861 862 tc filter del dev $h2 ingress protocol ip pref 3 handle 103 flower 863 tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower 864 tc filter del dev $h2 ingress protocol ip pref 5 handle 104 flower 865 866 log_test "bloom simple test ($tcflags)" 867} 868 869bloom_complex_test() 870{ 871 # Bloom filter index computation is affected from region ID, eRP 872 # ID and from the region key size. In order to exercise those parts 873 # of the Bloom filter code, use a series of regions, each with a 874 # different key size and send packet that should hit all of them. 875 local index 876 877 RET=0 878 NUM_CHAINS=4 879 BASE_INDEX=100 880 881 # Create chain with up to 2 key blocks (ip_proto only) 882 tc chain add dev $h2 ingress chain 1 protocol ip flower \ 883 ip_proto tcp &> /dev/null 884 # Create chain with 2-4 key blocks (ip_proto, src MAC) 885 tc chain add dev $h2 ingress chain 2 protocol ip flower \ 886 ip_proto tcp \ 887 src_mac 00:00:00:00:00:00/FF:FF:FF:FF:FF:FF &> /dev/null 888 # Create chain with 4-8 key blocks (ip_proto, src & dst MAC, IPv4 dest) 889 tc chain add dev $h2 ingress chain 3 protocol ip flower \ 890 ip_proto tcp \ 891 dst_mac 00:00:00:00:00:00/FF:FF:FF:FF:FF:FF \ 892 src_mac 00:00:00:00:00:00/FF:FF:FF:FF:FF:FF \ 893 dst_ip 0.0.0.0/32 &> /dev/null 894 # Default chain contains all fields and therefore is 8-12 key blocks 895 tc chain add dev $h2 ingress chain 4 896 897 # We need at least 2 rules in every region to have eRP table active 898 # so create a dummy rule per chain using a different pattern 899 for i in $(eval echo {0..$NUM_CHAINS}); do 900 index=$((BASE_INDEX - 1 - i)) 901 tc filter add dev $h2 ingress chain $i protocol ip \ 902 pref 2 handle $index flower \ 903 $tcflags ip_proto tcp action drop 904 done 905 906 # Add rules to test Bloom filter, each in a different chain 907 index=$BASE_INDEX 908 tc filter add dev $h2 ingress protocol ip \ 909 pref 1 handle $((++index)) flower \ 910 $tcflags dst_ip 192.0.0.0/16 action goto chain 1 911 tc filter add dev $h2 ingress chain 1 protocol ip \ 912 pref 1 handle $((++index)) flower \ 913 $tcflags action goto chain 2 914 tc filter add dev $h2 ingress chain 2 protocol ip \ 915 pref 1 handle $((++index)) flower \ 916 $tcflags src_mac $h1mac action goto chain 3 917 tc filter add dev $h2 ingress chain 3 protocol ip \ 918 pref 1 handle $((++index)) flower \ 919 $tcflags dst_ip 192.0.0.0/8 action goto chain 4 920 tc filter add dev $h2 ingress chain 4 protocol ip \ 921 pref 1 handle $((++index)) flower \ 922 $tcflags src_ip 192.0.2.0/24 action drop 923 924 # Send a packet that is supposed to hit all chains 925 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ 926 -t ip -q 927 928 for i in $(eval echo {0..$NUM_CHAINS}); do 929 index=$((BASE_INDEX + i + 1)) 930 tc_check_packets "dev $h2 ingress" $index 1 931 check_err $? "Did not match chain $i" 932 done 933 934 # Rules cleanup 935 for i in $(eval echo {$NUM_CHAINS..0}); do 936 index=$((BASE_INDEX - i - 1)) 937 tc filter del dev $h2 ingress chain $i \ 938 pref 2 handle $index flower 939 index=$((BASE_INDEX + i + 1)) 940 tc filter del dev $h2 ingress chain $i \ 941 pref 1 handle $index flower 942 done 943 944 # Chains cleanup 945 for i in $(eval echo {$NUM_CHAINS..1}); do 946 tc chain del dev $h2 ingress chain $i 947 done 948 949 log_test "bloom complex test ($tcflags)" 950} 951 952 953bloom_delta_test() 954{ 955 # When multiple masks are used, the eRP table is activated. When 956 # masks are close enough (delta) the masks reside on the same 957 # eRP table. This test verifies that the eRP table is correctly 958 # allocated and used in delta condition and that Bloom filter is 959 # still functional with delta. 960 961 RET=0 962 963 tc filter add dev $h2 ingress protocol ip pref 3 handle 103 flower \ 964 $tcflags dst_ip 192.1.0.0/16 action drop 965 966 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.1.2.1 -B 192.1.2.2 \ 967 -t ip -q 968 969 tc_check_packets "dev $h2 ingress" 103 1 970 check_err $? "Single filter - did not match" 971 972 tc filter add dev $h2 ingress protocol ip pref 2 handle 102 flower \ 973 $tcflags dst_ip 192.2.1.0/24 action drop 974 975 $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.2.1.1 -B 192.2.1.2 \ 976 -t ip -q 977 978 tc_check_packets "dev $h2 ingress" 102 1 979 check_err $? "Delta filters - did not match second filter" 980 981 tc filter del dev $h2 ingress protocol ip pref 3 handle 103 flower 982 tc filter del dev $h2 ingress protocol ip pref 2 handle 102 flower 983 984 log_test "bloom delta test ($tcflags)" 985} 986 987max_erp_entries_test() 988{ 989 # The number of eRP entries is limited. Once the maximum number of eRPs 990 # has been reached, filters cannot be added. This test verifies that 991 # when this limit is reached, inserstion fails without crashing. 992 993 RET=0 994 995 local num_masks=32 996 local num_regions=15 997 local chain_failed 998 local mask_failed 999 local ret 1000 1001 if [[ "$tcflags" != "skip_sw" ]]; then 1002 return 0; 1003 fi 1004 1005 for ((i=1; i < $num_regions; i++)); do 1006 for ((j=$num_masks; j >= 0; j--)); do 1007 tc filter add dev $h2 ingress chain $i protocol ip \ 1008 pref $i handle $j flower $tcflags \ 1009 dst_ip 192.1.0.0/$j &> /dev/null 1010 ret=$? 1011 1012 if [ $ret -ne 0 ]; then 1013 chain_failed=$i 1014 mask_failed=$j 1015 break 2 1016 fi 1017 done 1018 done 1019 1020 # We expect to exceed the maximum number of eRP entries, so that 1021 # insertion eventually fails. Otherwise, the test should be adjusted to 1022 # add more filters. 1023 check_fail $ret "expected to exceed number of eRP entries" 1024 1025 for ((; i >= 1; i--)); do 1026 for ((j=0; j <= $num_masks; j++)); do 1027 tc filter del dev $h2 ingress chain $i protocol ip \ 1028 pref $i handle $j flower &> /dev/null 1029 done 1030 done 1031 1032 log_test "max eRP entries test ($tcflags). " \ 1033 "max chain $chain_failed, mask $mask_failed" 1034} 1035 1036max_group_size_test() 1037{ 1038 # The number of ACLs in an ACL group is limited. Once the maximum 1039 # number of ACLs has been reached, filters cannot be added. This test 1040 # verifies that when this limit is reached, insertion fails without 1041 # crashing. 1042 1043 RET=0 1044 1045 local num_acls=32 1046 local max_size 1047 local ret 1048 1049 if [[ "$tcflags" != "skip_sw" ]]; then 1050 return 0; 1051 fi 1052 1053 for ((i=1; i < $num_acls; i++)); do 1054 if [[ $(( i % 2 )) == 1 ]]; then 1055 tc filter add dev $h2 ingress pref $i proto ipv4 \ 1056 flower $tcflags dst_ip 198.51.100.1/32 \ 1057 ip_proto tcp tcp_flags 0x01/0x01 \ 1058 action drop &> /dev/null 1059 else 1060 tc filter add dev $h2 ingress pref $i proto ipv6 \ 1061 flower $tcflags dst_ip 2001:db8:1::1/128 \ 1062 action drop &> /dev/null 1063 fi 1064 1065 ret=$? 1066 [[ $ret -ne 0 ]] && max_size=$((i - 1)) && break 1067 done 1068 1069 # We expect to exceed the maximum number of ACLs in a group, so that 1070 # insertion eventually fails. Otherwise, the test should be adjusted to 1071 # add more filters. 1072 check_fail $ret "expected to exceed number of ACLs in a group" 1073 1074 for ((; i >= 1; i--)); do 1075 if [[ $(( i % 2 )) == 1 ]]; then 1076 tc filter del dev $h2 ingress pref $i proto ipv4 \ 1077 flower $tcflags dst_ip 198.51.100.1/32 \ 1078 ip_proto tcp tcp_flags 0x01/0x01 \ 1079 action drop &> /dev/null 1080 else 1081 tc filter del dev $h2 ingress pref $i proto ipv6 \ 1082 flower $tcflags dst_ip 2001:db8:1::1/128 \ 1083 action drop &> /dev/null 1084 fi 1085 done 1086 1087 log_test "max ACL group size test ($tcflags). max size $max_size" 1088} 1089 1090collision_test() 1091{ 1092 # Filters cannot share an eRP if in the common unmasked part (i.e., 1093 # without the delta bits) they have the same values. If the driver does 1094 # not prevent such configuration (by spilling into the C-TCAM), then 1095 # multiple entries will be present in the device with the same key, 1096 # leading to collisions and a reduced scale. 1097 # 1098 # Create such a scenario and make sure all the filters are successfully 1099 # added. 1100 1101 RET=0 1102 1103 local ret 1104 1105 if [[ "$tcflags" != "skip_sw" ]]; then 1106 return 0; 1107 fi 1108 1109 # Add a single dst_ip/24 filter and multiple dst_ip/32 filters that all 1110 # have the same values in the common unmasked part (dst_ip/24). 1111 1112 tc filter add dev $h2 ingress pref 1 proto ipv4 handle 101 \ 1113 flower $tcflags dst_ip 198.51.100.0/24 \ 1114 action drop 1115 1116 for i in {0..255}; do 1117 tc filter add dev $h2 ingress pref 2 proto ipv4 \ 1118 handle $((102 + i)) \ 1119 flower $tcflags dst_ip 198.51.100.${i}/32 \ 1120 action drop 1121 ret=$? 1122 [[ $ret -ne 0 ]] && break 1123 done 1124 1125 check_err $ret "failed to add all the filters" 1126 1127 for i in {255..0}; do 1128 tc filter del dev $h2 ingress pref 2 proto ipv4 \ 1129 handle $((102 + i)) flower 1130 done 1131 1132 tc filter del dev $h2 ingress pref 1 proto ipv4 handle 101 flower 1133 1134 log_test "collision test ($tcflags)" 1135} 1136 1137setup_prepare() 1138{ 1139 h1=${NETIFS[p1]} 1140 h2=${NETIFS[p2]} 1141 h1mac=$(mac_get $h1) 1142 h2mac=$(mac_get $h2) 1143 1144 vrf_prepare 1145 1146 h1_create 1147 h2_create 1148} 1149 1150cleanup() 1151{ 1152 pre_cleanup 1153 1154 h2_destroy 1155 h1_destroy 1156 1157 vrf_cleanup 1158} 1159 1160trap cleanup EXIT 1161 1162setup_prepare 1163setup_wait 1164 1165tests_run 1166 1167if ! tc_offload_check; then 1168 check_err 1 "Could not test offloaded functionality" 1169 log_test "mlxsw-specific tests for tc flower" 1170 exit 1171else 1172 tcflags="skip_sw" 1173 tests_run 1174fi 1175 1176exit $EXIT_STATUS 1177