tr_hash.c (74461B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * TRX Hash Table Tests. 8 * 9 * Insert/Lookup/Delete, hashing, bucket overflow tests. 10 */ 11 12 13 14 #include <soc/mem.h> 15 #include <soc/hash.h> 16 #include <shared/bsl.h> 17 #if defined(BCM_TRIUMPH_SUPPORT) /* DPPCOMPILEENABLE */ 18 #include <soc/triumph.h> 19 #endif /* DPPCOMPILEENABLE */ 20 #include <appl/diag/system.h> 21 #include <appl/test/tr_hash.h> 22 #include "testlist.h" 23 #include <bcm/init.h> 24 #include <bcm/l2.h> 25 #include <bcm/l3.h> 26 #include <bcm/stack.h> 27 #include <bcm/link.h> 28 #ifdef BCM_ESW_SUPPORT 29 #include <bcm_int/esw/firebolt.h> 30 #endif 31 #if defined(BCM_TRIUMPH_SUPPORT) 32 #include <bcm_int/esw/triumph.h> 33 #endif /* BCM_TRIUMPH_SUPPORT */ 34 #ifdef BCM_TRIDENT2_SUPPORT 35 #include <soc/trident2.h> 36 #endif /* BCM_TRIDENT2_SUPPORT */ 37 #ifdef BCM_TOMAHAWK_SUPPORT 38 #include <soc/tomahawk.h> 39 #endif /* BCM_TOMAHAWK_SUPPORT */ 40 #ifdef BCM_APACHE_SUPPORT 41 #include <soc/apache.h> 42 #endif /* BCM_APACHE_SUPPORT */ 43 #ifdef BCM_MONTEREY_SUPPORT 44 #include <soc/monterey.h> 45 #endif /* BCM_APACHE_SUPPORT */ 46 #ifdef BCM_TRIDENT3_SUPPORT 47 #include <soc/trident3.h> 48 #endif /* BCM_TRIDENT3_SUPPORT */ 49 #ifdef BCM_HELIX5_SUPPORT 50 #include <soc/helix5.h> 51 #endif /* BCM_HELIX5_SUPPORT */ 52 #ifdef BCM_TOMAHAWK3_SUPPORT 53 #include <soc/tomahawk3.h> 54 #endif /* BCM_TOMAHAWK3_SUPPORT */ 55 56 #include <appl/diag/progress.h> 57 58 #if defined (BCM_PETRA_SUPPORT) 59 #include <soc/dpp/mbcm.h> 60 #include <soc/dpp/ARAD/arad_api_action_cmd.h> 61 #include <soc/dpp/ARAD/arad_ingress_traffic_mgmt.h> 62 #include <soc/dpp/ARAD/arad_api_end2end_scheduler.h> 63 #endif 64 65 #if defined(BCM_ESW_SUPPORT) /* || defined (BCM_PETRA_SUPPORT) */ 66 67 68 /* 69 * work structure 70 */ 71 72 STATIC tr_hash_test_t tr_vlan_xlate_work[SOC_MAX_NUM_DEVICES]; 73 STATIC tr_hash_test_t tr_egr_vlan_xlate_work[SOC_MAX_NUM_DEVICES]; 74 #ifdef BCM_TRIUMPH_SUPPORT 75 STATIC tr_hash_test_t tr_mpls_work[SOC_MAX_NUM_DEVICES]; 76 #endif /* BCM_TRIUMPH_SUPPORT */ 77 78 /* 79 * Utility routines for testing 80 */ 81 82 void 83 tr_hash_time_start(tr_hash_testdata_t *ad) 84 { 85 ad->tm = SAL_TIME_DOUBLE(); 86 } 87 88 void 89 tr_hash_time_end(tr_hash_testdata_t *ad) 90 { 91 ad->tm = SAL_TIME_DOUBLE() - ad->tm; 92 if (ad->opt_verbose) { 93 cli_out(" time: %"COMPILER_DOUBLE_FORMAT" msec\n", ad->tm * 1000); 94 } 95 } 96 97 98 static int 99 tr_hash_bucket_search(int unit, tr_hash_testdata_t *ad, soc_mem_t mem, 100 int bucket, int bucket_size, int validf, void *expect, 101 int dual, int bank) 102 { 103 uint32 chip_entry[SOC_MAX_MEM_FIELD_WORDS]; 104 int ix, mem_table_index, iter_count; 105 int rv = -1; /* Assume failed unless we find it */ 106 107 if (dual == TRUE) { 108 iter_count = bucket_size / 2; 109 } else { 110 iter_count = bucket_size; 111 } 112 for (ix = 0; ix < iter_count; ix++) { 113 mem_table_index = (bucket * bucket_size) + ix; 114 if (bank) { 115 mem_table_index += (bucket_size / 2); 116 } 117 118 if (soc_mem_read(unit, mem, MEM_BLOCK_ANY, 119 mem_table_index, chip_entry) < 0) { 120 test_error(unit, 121 "Read failed at bucket %d, offset %d\n", 122 bucket, ix); 123 break; 124 } 125 126 if (validf != -1) { 127 int validv = 0; 128 if (soc_feature(unit, soc_feature_base_valid) && 129 validf == VALIDf) { 130 validv = soc_mem_field32_get(unit, mem, chip_entry, 131 BASE_VALID_0f) == 3 && 132 soc_mem_field32_get(unit, mem, chip_entry, 133 BASE_VALID_1f) == 7; 134 } else { 135 validv = soc_mem_field32_get(unit, mem, chip_entry, validf); 136 } 137 if (!validv) { 138 /* Valid bit unset, entry blank */ 139 continue; 140 } 141 } 142 143 if (soc_mem_compare_key(unit, mem, expect, &chip_entry) == 0) { 144 /* Found the matching entry */ 145 rv = 0; 146 break; 147 } 148 } 149 150 return rv; 151 } 152 153 /************************ START OF VLAN XLATE TESTS ************************/ 154 /* 155 * Test initialization routine used for Vlan xlate tests 156 */ 157 158 STATIC int 159 tr_vlan_xlate_test_init(int unit, tr_hash_testdata_t *ad, args_t *a) 160 { 161 int rv = -1, dual = 0; 162 parse_table_t pt; 163 uint32 hash_read = 0; 164 #if defined(BCM_ESW_SUPPORT) && defined(BCM_TRIDENT3_SUPPORT) 165 l2_entry_hash_control_entry_t xlate_hash_read; 166 #endif /* BCM_ESW_SUPPORT && BCM_TRIDENT3_SUPPORT */ 167 parse_table_init(unit, &pt); 168 169 parse_table_add(&pt, "Count", PQ_INT|PQ_DFL, 0, &ad->opt_count, NULL); 170 parse_table_add(&pt, "Verbose", PQ_BOOL|PQ_DFL, 0, &ad->opt_verbose, NULL); 171 parse_table_add(&pt, "Reset", PQ_BOOL|PQ_DFL, 0, &ad->opt_reset, NULL); 172 parse_table_add(&pt, "Hash", PQ_INT|PQ_DFL, 0, &ad->opt_hash, NULL); 173 parse_table_add(&pt, "DualHash", PQ_INT|PQ_DFL, 0, &ad->opt_dual_hash, NULL); 174 parse_table_add(&pt, "DualEnable", PQ_INT|PQ_DFL, 0, &dual, NULL); 175 parse_table_add(&pt, "BaseOVID", PQ_INT|PQ_DFL, 0, &ad->opt_base_ovid, NULL); 176 parse_table_add(&pt, "BaseIVID", PQ_INT|PQ_DFL, 0, &ad->opt_base_ivid, NULL); 177 parse_table_add(&pt, "VidIncrement", PQ_INT|PQ_DFL, 0, 178 &ad->opt_vid_inc, NULL); 179 180 /* Test the obvious parsings before wasting time with malloc */ 181 if (parse_arg_eq(a, &pt) < 0) { 182 test_error(unit, 183 "%s: Error: Invalid option: %s\n", ARG_CMD(a), 184 ARG_CUR(a) ? ARG_CUR(a) : "*"); 185 goto done; 186 } 187 188 if (ad->opt_count < 1) { 189 test_error(unit, "Illegal count %d\n", ad->opt_count); 190 goto done; 191 } 192 193 if (ad->opt_hash >= ad->hash_count) { 194 test_error(unit, "Illegal hash selection %d\n", ad->opt_hash); 195 goto done; 196 } 197 198 if (dual == 1) { 199 if (ad->opt_dual_hash >= ad->hash_count) { 200 test_error(unit, "Illegal dual hash selection %d\n", ad->opt_dual_hash); 201 goto done; 202 } 203 } else { 204 ad->opt_dual_hash = -1; 205 } 206 207 if (ad->opt_base_ovid >= (1 << 12)) { 208 test_error(unit, "Out of range Outer VLAN ID selection %d\n", 209 ad->opt_base_ovid); 210 goto done; 211 } 212 213 if (ad->opt_base_ivid >= (1 << 12)) { 214 test_error(unit, "Out of range Inner VLAN ID selection %d\n", 215 ad->opt_base_ivid); 216 goto done; 217 } 218 219 /* 220 * Re-initialize chip to ensure tables are clear 221 * at start of test. 222 */ 223 224 if (ad->opt_reset) { 225 BCM_IF_ERROR_RETURN(bcm_linkscan_enable_set(unit, 0)); 226 if (soc_reset_init(unit) < 0) { 227 test_error(unit, "SOC initialization failed\n"); 228 goto done; 229 } 230 231 if (soc_misc_init(unit) < 0) { 232 test_error(unit, "MISC initialization failed\n"); 233 goto done; 234 } 235 236 if (soc_mmu_init(unit) < 0) { 237 test_error(unit, "MMU initialization failed\n"); 238 goto done; 239 } 240 #if defined (BCM_PETRA_SUPPORT) 241 242 if (mbcm_dpp_init(unit) < 0) { 243 test_error(unit, "BCM initialization failed\n"); 244 goto done; 245 } 246 #else 247 if (mbcm_init(unit) < 0) { 248 test_error(unit, "BCM initialization failed\n"); 249 goto done; 250 } 251 #endif 252 } 253 254 #if defined(BCM_ESW_SUPPORT) 255 #if defined(BCM_TRIDENT3_SUPPORT) 256 if (soc_feature(unit, soc_feature_base_valid)) { 257 if (soc_mem_read(unit, VLAN_XLATE_1_HASH_CONTROLm, MEM_BLOCK_ALL, 258 0, &xlate_hash_read) < 0) { 259 test_error(unit, "Hash Control read failed\n"); 260 goto done; 261 } 262 sal_memcpy(&ad->save_xlate_hash_control, &xlate_hash_read, 263 sizeof(xlate_hash_read)); 264 } else 265 #endif /* BCM_TRIDENT3_SUPPORT */ 266 { 267 if (READ_VLAN_XLATE_HASH_CONTROLr(unit, &hash_read) < 0) { 268 test_error(unit, "Hash select read failed\n"); 269 goto done; 270 } 271 } 272 #endif 273 ad->save_hash_control = hash_read; 274 #if defined(BCM_ESW_SUPPORT) 275 276 if (!(soc_feature(unit, soc_feature_base_valid))) { 277 soc_reg_field_set(unit, VLAN_XLATE_HASH_CONTROLr, &hash_read, 278 HASH_SELECT_Af, ad->opt_hash); 279 if (ad->opt_dual_hash != -1) { 280 soc_reg_field_set(unit, VLAN_XLATE_HASH_CONTROLr, &hash_read, 281 HASH_SELECT_Bf, ad->opt_dual_hash); 282 } else { 283 soc_reg_field_set(unit, VLAN_XLATE_HASH_CONTROLr, &hash_read, 284 HASH_SELECT_Bf, ad->opt_hash); 285 } 286 287 if (WRITE_VLAN_XLATE_HASH_CONTROLr(unit, hash_read) < 0) { 288 test_error(unit, "Hash select setting failed\n"); 289 goto done; 290 } 291 } 292 #endif 293 rv = 0; 294 295 done: 296 297 parse_arg_eq_done(&pt); 298 return rv; 299 } 300 301 STATIC void 302 tr_vlan_xlate_hash_setup(int unit, tr_hash_test_t *dw) 303 { 304 tr_hash_testdata_t *ad; 305 soc_mem_t mem = VLAN_XLATEm; 306 307 if (dw->lw_set_up) { 308 return; 309 } 310 311 dw->lw_set_up = TRUE; 312 dw->lw_unit = unit; 313 314 #ifdef BCM_TRIDENT3_SUPPORT 315 if (SOC_MEM_IS_VALID(unit, VLAN_XLATE_1_DOUBLEm)) { 316 mem = VLAN_XLATE_1_DOUBLEm; 317 } 318 #endif /* BCM_TRIDENT3_SUPPORT */ 319 dw->lp_hash.mem = mem; 320 dw->lp_ov.mem = mem; 321 322 /* Hash */ 323 ad = &dw->lp_hash; 324 #if defined(BCM_ESW_SUPPORT) 325 ad->opt_count = soc_mem_index_count(unit, mem); 326 #elif defined(BCM_PETRA_SUPPORT) 327 ad->opt_count = soc_mem_index_count(unit, EGQ_VLAN_TABLEm); 328 #endif 329 #ifdef BCM_TRIDENT2_SUPPORT 330 if (soc_feature(unit, soc_feature_extended_hash)) { 331 ad->opt_hash = FB_HASH_CRC32_LOWER; 332 ad->opt_dual_hash = FB_HASH_CRC32_UPPER; 333 } else 334 #endif /* BCM_TRIDENT2_SUPPORT */ 335 { 336 ad->opt_hash = FB_HASH_CRC16_LOWER; 337 ad->opt_dual_hash = -1; 338 } 339 ad->hash_count = FB_HASH_COUNT; 340 ad->opt_base_ovid = 0; 341 ad->opt_base_ivid = 0; 342 ad->opt_vid_inc = 1; 343 344 /* Overflow */ 345 ad = &dw->lp_ov; 346 347 ad->opt_count = 2048; 348 ad->opt_hash = TR_DEFAULT_HASH; 349 ad->opt_dual_hash = -1; 350 ad->hash_count = FB_HASH_COUNT; 351 ad->opt_base_ovid = 0; 352 ad->opt_base_ivid = 0; 353 ad->opt_vid_inc = 1; 354 } 355 356 /* Individual test init wrappers */ 357 int 358 tr_vlan_xlate_hash_test_init(int unit, args_t *a, void **p) 359 { 360 tr_hash_test_t *dw = &tr_vlan_xlate_work[unit]; 361 tr_hash_testdata_t *dp = &dw->lp_hash; 362 int rv; 363 364 tr_vlan_xlate_hash_setup(unit, dw); 365 366 /* Set working data to hash */ 367 dw->lp_cur = dp; 368 369 if ((rv = tr_vlan_xlate_test_init(unit, dp, a)) < 0) { 370 return rv; 371 } else { 372 *p = dp; 373 } 374 375 return 0; 376 } 377 378 int 379 tr_vlan_xlate_ov_test_init(int unit, args_t *a, void **p) 380 { 381 tr_hash_test_t *dw = &tr_vlan_xlate_work[unit]; 382 tr_hash_testdata_t *dp = &dw->lp_ov; 383 int rv; 384 385 tr_vlan_xlate_hash_setup(unit, dw); 386 387 /* Set working data to hash */ 388 dw->lp_cur = dp; 389 390 if ((rv = tr_vlan_xlate_test_init(unit, dp, a)) < 0) { 391 return rv; 392 } else { 393 *p = dp; 394 } 395 396 return 0; 397 } 398 399 /* 400 * Test of VLAN XLATE hashing 401 * 402 * This test tries a number of keys against one of the hashing functions, 403 * checking a software hash against the hardware hash, then searching the 404 * bucket to find the entry after inserting. 405 */ 406 int 407 tr_vlan_xlate_test_hash(int unit, args_t *a, void *p) 408 { 409 tr_hash_testdata_t *ad = p; 410 411 #if defined(BCM_ESW_SUPPORT) 412 uint32 entry[SOC_MAX_MEM_FIELD_WORDS]; 413 #endif 414 int soft_bucket, ix, r, rv = 0; 415 int hash = ad->opt_hash; 416 uint8 key[XGS_HASH_KEY_SIZE]; 417 int iterations, ovid, ivid, num_bits; 418 int vid_inc = ad->opt_vid_inc; 419 int bucket_size; 420 int index; 421 int dual = FALSE; 422 int bank, banks, bank_count = 1; 423 soc_mem_t mem; 424 425 COMPILER_REFERENCE(a); 426 427 if (ad->opt_verbose) { 428 cli_out("Starting VLAN xlate hash test\n"); 429 } 430 431 sal_memset(key, 0, sizeof(key)); 432 mem = ad->mem; 433 434 /* This seems to be a fair "guess". is there a way to find the bucket size used in the HW? */ 435 if (mem != VLAN_XLATEm) { 436 bucket_size = 4; 437 } else { 438 bucket_size = (soc_mem_index_max(unit, VLAN_MACm) < 32767) ? 8 : 16; 439 } 440 441 #ifdef BCM_APACHE_SUPPORT 442 if(SOC_IS_APACHE(unit)) { 443 bucket_size = 8; 444 } 445 #endif 446 447 #if defined(BCM_SABER2_SUPPORT) 448 if(SOC_IS_SABER2(unit)) { 449 /* Even though with the reduced table size saber2 has the same bucket size as KT2 for this table */ 450 bucket_size = 16; 451 } 452 #endif 453 454 iterations = ad->opt_count; 455 ovid = ad->opt_base_ovid; 456 ivid = ad->opt_base_ivid; 457 if (ad->opt_dual_hash != -1) { 458 dual = TRUE; 459 bank_count = 2; 460 } 461 462 for (ix = 0; ix < iterations; ix++) { 463 for (bank = 0; bank < bank_count; bank++) { 464 sal_memset(entry, 0, sizeof (entry)); 465 if (soc_feature(unit, soc_feature_base_valid)) { 466 soc_mem_field32_set(unit, mem, entry, BASE_VALID_0f, 3); 467 soc_mem_field32_set(unit, mem, entry, BASE_VALID_1f, 7); 468 } else { 469 soc_mem_field32_set(unit, mem, entry, VALIDf, 1); 470 } 471 soc_mem_field32_set(unit, mem, entry, KEY_TYPEf, 0); 472 soc_mem_field32_set(unit, mem, entry, OVIDf, ovid); 473 soc_mem_field32_set(unit, mem, entry, IVIDf, ivid); 474 475 #ifdef BCM_TRIDENT3_SUPPORT 476 if (SOC_IS_TRIDENT3X(unit)) { 477 soft_bucket = soc_td3_vlan_xlate_bank_entry_hash(unit, mem, bank, 478 (uint32 *) entry); 479 } else 480 #endif 481 { 482 num_bits = soc_tr_vlan_xlate_base_entry_to_key 483 (unit, (uint32 *) entry, key); 484 soft_bucket = soc_tr_vlan_xlate_hash(unit, hash, num_bits, 485 (uint32 *) entry, key); 486 } 487 banks = 0; 488 if (dual == TRUE) { 489 #ifdef BCM_TRIDENT2_SUPPORT 490 #ifdef BCM_TRIDENT3_SUPPORT 491 if (SOC_IS_TRIDENT3X(unit)) { 492 } else 493 #endif /* BCM_TRIDENT3_SUPPORT */ 494 #ifdef BCM_APACHE_SUPPORT 495 if (SOC_IS_APACHE(unit)) { 496 soft_bucket = soc_ap_vlan_xlate_bank_entry_hash(unit, 497 bank, (uint32 *) entry); 498 } else 499 #endif /* BCM_APACHE_SUPPORT */ 500 #ifdef BCM_TOMAHAWK_SUPPORT 501 if (SOC_IS_TOMAHAWKX(unit)) { 502 soft_bucket = soc_th_vlan_xlate_bank_entry_hash(unit, 503 bank, (uint32 *) entry); 504 } else 505 #endif /* BCM_TOMAHAWK_SUPPORT */ 506 if (soc_feature(unit, soc_feature_extended_hash)) { 507 soft_bucket = soc_td2_vlan_xlate_bank_entry_hash(unit, 508 bank, (uint32 *) entry); 509 } else 510 #endif /* BCM_TRIDENT2_SUPPORT */ 511 { 512 soft_bucket = soc_tr_vlan_xlate_bank_entry_hash 513 (unit, bank, (uint32 *) entry); 514 } 515 banks = (bank == 0) ? 2 : 1; 516 } 517 518 if (ad->opt_verbose) { 519 cli_out("Inserting "); 520 soc_mem_entry_dump(unit, VLAN_XLATEm, &entry, BSL_LSS_CLI); 521 cli_out("\n"); 522 if (dual) { 523 cli_out("into bucket 0x%x (bank %d)\n", 524 soft_bucket, bank); 525 } else { 526 cli_out("into bucket 0x%x\n", soft_bucket); 527 } 528 } 529 530 if ((r = soc_mem_bank_insert(unit, mem, banks, 531 MEM_BLOCK_ALL, entry, NULL)) < 0) { 532 if (r == SOC_E_FULL) { 533 /* Bucket overflow, just pass on */ 534 break; 535 } else { 536 test_error(unit, 537 "Vlan xlate insert failed at bucket %d\n", soft_bucket); 538 rv = -1; 539 goto done; 540 } 541 } 542 543 /* Now we search for the entry */ 544 545 /* Only do a quick check vs. expected bucket here */ 546 if (tr_hash_bucket_search(unit, ad, mem, soft_bucket, 547 bucket_size, VALIDf, entry, dual, bank) < 0) { 548 test_error(unit, 549 "Vlan xlate entry with key " 550 "0x%02x%02x%02x%02x%02x%02x%02x%01x " 551 "not found in predicted bucket %d\n", 552 key[7], key[6], key[5], key[4], 553 key[3], key[2], key[1], (key[0] >> 4) & 0xf, 554 soft_bucket); 555 rv = -1; 556 goto done; 557 } 558 559 /* Search for the entry, should be found */ 560 if (soc_mem_search(unit, mem, MEM_BLOCK_ALL, &index, 561 entry, entry, 0) < 0) { 562 test_error(unit, "Vlan xlate search failed in bucket %d\n", 563 soft_bucket); 564 rv = -1; 565 goto done; 566 } 567 568 /* Insert the entry again, should fail. */ 569 if (soc_mem_bank_insert(unit, mem, banks, 570 MEM_BLOCK_ALL, entry, NULL) != SOC_E_EXISTS) { 571 test_error(unit, 572 "Vlan xlate insert should have failed at bucket %d\n", soft_bucket); 573 rv = -1; 574 goto done; 575 } 576 577 /* Delete the entry */ 578 if (soc_mem_delete(unit, mem, MEM_BLOCK_ALL, entry) < 0) { 579 test_error(unit, "Vlan xlate delete failed at bucket %d\n", 580 soft_bucket); 581 rv = -1; 582 goto done; 583 } 584 585 /* Delete the entry again, should fail.*/ 586 if (soc_mem_delete(unit, mem, 587 MEM_BLOCK_ALL, entry) != SOC_E_NOT_FOUND) { 588 test_error(unit, "Vlan xlate delete should have failed in bucket %d\n", 589 soft_bucket); 590 rv = -1; 591 goto done; 592 } 593 594 /* Search for the entry again, should not be found */ 595 if (soc_mem_search(unit, mem, MEM_BLOCK_ALL, &index, 596 entry, entry, 0) != SOC_E_NOT_FOUND) { 597 test_error(unit, "Vlan xlate search should have failed in bucket %d\n", 598 soft_bucket); 599 rv = -1; 600 goto done; 601 } 602 603 } 604 ovid += vid_inc; 605 if (ovid > TR_VID_MAX) { 606 ovid = 1; 607 } 608 ivid += vid_inc; 609 if (ivid > TR_VID_MAX) { 610 ivid = 1; 611 } 612 } 613 614 done: 615 return rv; 616 } 617 618 /* 619 * Test of Vlan xlate overflow behavior 620 * 621 * This test fills each bucket, then inserts another entry to see 622 * that the last entry fails to insert. 623 */ 624 625 int 626 tr_vlan_xlate_test_ov(int unit, args_t *a, void *p) 627 { 628 tr_hash_testdata_t *ad = p; 629 #if defined(BCM_ESW_SUPPORT) 630 uint32 entry[SOC_MAX_MEM_FIELD_WORDS]; 631 uint32 result[SOC_MAX_MEM_FIELD_WORDS]; 632 /* 20 is good enough for VLAN_XLATE TABLEs */ 633 uint32 entry_tmp[16][20]; 634 #endif 635 int ix, jx, r, idx, rv = 0; 636 int ovid, ivid; 637 int bucket = 0; 638 uint32 hash = ad->opt_hash; 639 int vid_inc = ad->opt_vid_inc; 640 int iter = ad->opt_count; 641 uint8 key[XGS_HASH_KEY_SIZE]; 642 int bucket_size; 643 soc_mem_t mem; 644 645 COMPILER_REFERENCE(a); 646 647 mem = ad->mem; 648 649 /* This seems to be a fair "guess". is there a way to find the bucket size used in the HW? */ 650 if (mem != VLAN_XLATEm) { 651 bucket_size = 4; 652 } else { 653 bucket_size = (soc_mem_index_max(unit, VLAN_MACm) < 32767) ? 8 : 16; 654 } 655 656 #ifdef BCM_APACHE_SUPPORT 657 if(SOC_IS_APACHE(unit)) { 658 bucket_size = 8; 659 } 660 #endif 661 662 #if defined(BCM_SABER2_SUPPORT) 663 if(SOC_IS_SABER2(unit)) { 664 /* Even though with the reduced table size saber2 has the same bucket size as KT2 for this table */ 665 bucket_size = 16; 666 } 667 #endif 668 669 if (hash != FB_HASH_LSB) { 670 if (ad->opt_verbose) { 671 cli_out("Resetting hash selection to LSB\n"); 672 } 673 674 hash = ad->save_hash_control; 675 soc_reg_field_set(unit, VLAN_XLATE_HASH_CONTROLr, &hash, 676 HASH_SELECT_Af, FB_HASH_LSB); 677 soc_reg_field_set(unit, VLAN_XLATE_HASH_CONTROLr, &hash, 678 HASH_SELECT_Bf, FB_HASH_LSB); 679 680 if (WRITE_VLAN_XLATE_HASH_CONTROLr(unit, hash) < 0) { 681 test_error(unit, "Hash select setting failed\n"); 682 goto done; 683 } 684 685 ad->opt_hash = hash = FB_HASH_LSB; 686 } 687 688 if (iter > soc_mem_index_count(unit, mem)) { 689 iter = soc_mem_index_count(unit, mem); 690 } 691 ovid = 0; 692 ivid = ad->opt_base_ivid; 693 694 while (iter--) { 695 for (ix = 0; ix < bucket_size; ix++) { 696 sal_memset(entry_tmp[ix], 0, sizeof(entry_tmp[0])); 697 if (soc_feature(unit, soc_feature_base_valid)) { 698 soc_mem_field32_set(unit, mem, entry_tmp[ix], BASE_VALID_0f, 3); 699 soc_mem_field32_set(unit, mem, entry_tmp[ix], BASE_VALID_1f, 7); 700 } else { 701 soc_mem_field32_set(unit, mem, entry_tmp[ix], VALIDf, 1); 702 } 703 soc_mem_field32_set(unit, mem, entry_tmp[ix], OVIDf, ovid); 704 soc_mem_field32_set(unit, mem, entry_tmp[ix], IVIDf, ivid); 705 soc_mem_field32_set(unit, mem, entry_tmp[ix], KEY_TYPEf, 0); 706 707 if (ix == 0) { 708 int num_bits; 709 num_bits = soc_tr_vlan_xlate_base_entry_to_key 710 (unit, (uint32 *) entry_tmp[ix], key); 711 bucket = soc_tr_vlan_xlate_hash 712 (unit, hash, num_bits, (uint32 *) entry_tmp[ix], key); 713 714 if (ad->opt_verbose) { 715 cli_out("Filling bucket %d\n", bucket); 716 } 717 } 718 719 if ((r = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry_tmp[ix])) < 0) { 720 if (r == SOC_E_FULL) { 721 /* Already full, stop wasting time */ 722 break; 723 } else { 724 test_error(unit, 725 "Vlan xlate insert failed at bucket %d\n", bucket); 726 rv = -1; 727 goto done; 728 } 729 } 730 731 /* key for LSB is the OVID, so we must keep it constant */ 732 ivid += vid_inc; 733 if (ivid > TR_VID_MAX) { 734 ivid = 1; 735 } 736 } 737 738 if (ad->opt_verbose) { 739 cli_out("Inserting %dth entry in bucket %d, should fail\n", 740 (bucket_size + 1), bucket); 741 } 742 743 sal_memset(entry, 0, sizeof(entry)); 744 if (soc_feature(unit, soc_feature_base_valid)) { 745 soc_mem_field32_set(unit, mem, entry, BASE_VALID_0f, 3); 746 soc_mem_field32_set(unit, mem, entry, BASE_VALID_1f, 7); 747 } else { 748 soc_mem_field32_set(unit, mem, entry, VALIDf, 1); 749 } 750 soc_mem_field32_set(unit, mem, entry, OVIDf, ovid); 751 soc_mem_field32_set(unit, mem, entry, IVIDf, ivid); 752 soc_mem_field32_set(unit, mem, entry, KEY_TYPEf, 0); 753 754 if ((r = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry)) < 0) { 755 if (r != SOC_E_FULL) { 756 test_error(unit, 757 "Vlan xlate insert failed\n"); 758 rv = -1; 759 goto done; 760 } 761 } else { 762 test_error(unit, "Vlan xlate insert to full bucket succeeded\n"); 763 rv = -1; 764 goto done; 765 } 766 767 if (ad->opt_verbose) { 768 cli_out("Verifying entries present\n"); 769 } 770 771 /* Verify bucket contains our added entries */ 772 for (jx = 0; jx < ix; jx++) { 773 if (tr_hash_bucket_search(unit, ad, mem, bucket, 774 bucket_size, VALIDf, entry_tmp[jx], 0, 0) < 0) { 775 test_error(unit, "VLAN xlate entry missing at bucket %d\n", bucket); 776 rv = -1; 777 goto done; 778 } 779 if (soc_mem_search(unit, mem, MEM_BLOCK_ANY, &idx, 780 entry_tmp[jx], result, 0) < 0) { 781 test_error(unit, "VLAN xlate entry missing at bucket %d\n", bucket); 782 rv = -1; 783 goto done; 784 } 785 if (bucket != (idx / bucket_size)) { 786 test_error(unit, "VLAN xlate entry inserted into wrong bucket" 787 " Expected %d Actual %d\n", bucket, idx); 788 rv = -1; 789 goto done; 790 } 791 } 792 793 if (ad->opt_verbose) { 794 cli_out("Cleaning bucket %d\n", bucket); 795 } 796 797 /* Remove the entries that we added */ 798 for (jx = 0; jx < ix; jx++) { 799 if (soc_mem_delete(unit, mem, MEM_BLOCK_ALL, entry_tmp[jx]) < 0) { 800 test_error(unit, "Vlan xlate delete failed at bucket %d\n", bucket); 801 rv = -1; 802 goto done; 803 } 804 } 805 806 /* We want the increment to change buckets by one. For VLAN XLATE, 807 * the LSB hash bucket for KEY_TYPE 0 is determined by OVID. 808 */ 809 ovid += 1; 810 if (ovid > TR_VID_MAX) { 811 ovid = 0; 812 } 813 } 814 815 done: 816 817 return rv; 818 } 819 820 /* 821 * Test clean-up routine used for all Vlan xlate tests 822 */ 823 824 int 825 tr_vlan_xlate_test_done(int unit, void *p) 826 { 827 tr_hash_testdata_t *ad = p; 828 soc_mem_t mem; 829 830 if (ad == NULL) { 831 return 0; 832 } 833 834 mem = ad->mem; 835 836 /* Check if empty at the end of the test */ 837 if (ad->opt_reset) { 838 int rv, ix; 839 int index_min = soc_mem_index_min(unit, mem); 840 int index_max = soc_mem_index_max(unit, mem); 841 uint32 *buf = 0; 842 uint32 *ent; 843 uint32 count; 844 845 buf = soc_cm_salloc(unit, 846 SOC_MEM_TABLE_BYTES(unit, mem), 847 "vlan_xlate_test"); 848 if (!buf) { 849 test_error(unit, "Memory allocation failed\n"); 850 return (-1); 851 } 852 853 if ((rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 854 index_min, index_max, buf)) < 0) { 855 test_error(unit, "Memory DMA of VLAN_XLATEm entries failed\n"); 856 return (-1); 857 } 858 859 count = soc_mem_index_count(unit, mem); 860 for (ix = 0; ix < count; ix++) { 861 int vld = 0; 862 ent = soc_mem_table_idx_to_pointer(unit, mem, 863 uint32 *, buf, ix); 864 865 if (soc_feature(unit, soc_feature_base_valid)) { 866 vld = soc_mem_field32_get(unit, mem, ent, BASE_VALID_0f) == 3 && 867 soc_mem_field32_get(unit, mem, ent, BASE_VALID_1f) == 7; 868 } else 869 { 870 vld = soc_mem_field32_get(unit, mem, ent, VALIDf); 871 } 872 873 if (vld) { 874 test_error(unit, "Vlan xlate table not empty after test entry = %d\n", 875 ix); 876 soc_mem_entry_dump(unit, VLAN_XLATEm, ent, BSL_LSS_CLI); 877 return (-1); 878 } 879 } 880 881 soc_cm_sfree(unit, buf); 882 } 883 884 #ifdef BCM_TRIDENT3_SUPPORT 885 if (soc_feature(unit, soc_feature_base_valid)) { 886 if (soc_mem_write(unit, VLAN_XLATE_1_HASH_CONTROLm, MEM_BLOCK_ALL, 887 0, &ad->save_xlate_hash_control) < 0) { 888 test_error(unit, "Hash Control restore failed\n"); 889 } 890 } else 891 #endif /* BCM_TRIDENT3_SUPPORT */ 892 { 893 if (WRITE_VLAN_XLATE_HASH_CONTROLr(unit, ad->save_hash_control) < 0) { 894 test_error(unit, "Hash select restore failed\n"); 895 } 896 } 897 898 return 0; 899 } 900 901 /************************** END OF VLAN XLATE TESTS ************************/ 902 903 /************************ START OF EGR VLAN XLATE TESTS ********************/ 904 /* 905 * Test initialization routine used for Egress Vlan xlate tests 906 */ 907 908 STATIC int 909 tr_egr_vlan_xlate_test_init(int unit, tr_hash_testdata_t *ad, args_t *a) 910 { 911 int rv = -1, dual = 0; 912 parse_table_t pt; 913 uint32 hash_read; 914 #if defined(BCM_TRIDENT3_SUPPORT) 915 l2_entry_hash_control_entry_t xlate_hash_read; 916 #endif /* BCM_TRIDENT3_SUPPORT */ 917 918 parse_table_init(unit, &pt); 919 920 parse_table_add(&pt, "Count", PQ_INT|PQ_DFL, 0, &ad->opt_count, NULL); 921 parse_table_add(&pt, "Verbose", PQ_BOOL|PQ_DFL, 0, &ad->opt_verbose, NULL); 922 parse_table_add(&pt, "Reset", PQ_BOOL|PQ_DFL, 0, &ad->opt_reset, NULL); 923 parse_table_add(&pt, "Hash", PQ_INT|PQ_DFL, 0, &ad->opt_hash, NULL); 924 parse_table_add(&pt, "DualHash", PQ_INT|PQ_DFL, 0, &ad->opt_dual_hash, NULL); 925 parse_table_add(&pt, "DualEnable", PQ_INT|PQ_DFL, 0, &dual, NULL); 926 parse_table_add(&pt, "BaseOVID", PQ_INT|PQ_DFL, 0, &ad->opt_base_ovid, NULL); 927 parse_table_add(&pt, "BaseIVID", PQ_INT|PQ_DFL, 0, &ad->opt_base_ivid, NULL); 928 parse_table_add(&pt, "VidIncrement", PQ_INT|PQ_DFL, 0, 929 &ad->opt_vid_inc, NULL); 930 931 /* Test the obvious parsings before wasting time with malloc */ 932 if (parse_arg_eq(a, &pt) < 0) { 933 test_error(unit, 934 "%s: Error: Invalid option: %s\n", ARG_CMD(a), 935 ARG_CUR(a) ? ARG_CUR(a) : "*"); 936 goto done; 937 } 938 939 if (ad->opt_count < 1) { 940 test_error(unit, "Illegal count %d\n", ad->opt_count); 941 goto done; 942 } 943 944 if (ad->opt_hash >= ad->hash_count) { 945 test_error(unit, "Illegal hash selection %d\n", ad->opt_hash); 946 goto done; 947 } 948 949 if (dual == 1) { 950 if (ad->opt_dual_hash >= ad->hash_count) { 951 test_error(unit, "Illegal dual hash selection %d\n", ad->opt_dual_hash); 952 goto done; 953 } 954 } else { 955 ad->opt_dual_hash = -1; 956 } 957 958 if (ad->opt_base_ovid >= (1 << 12)) { 959 test_error(unit, "Out of range Outer VLAN ID selection %d\n", 960 ad->opt_base_ovid); 961 goto done; 962 } 963 964 if (ad->opt_base_ivid >= (1 << 12)) { 965 test_error(unit, "Out of range Inner VLAN ID selection %d\n", 966 ad->opt_base_ivid); 967 goto done; 968 } 969 970 /* 971 * Re-initialize chip to ensure tables are clear 972 * at start of test. 973 */ 974 975 if (ad->opt_reset) { 976 BCM_IF_ERROR_RETURN(bcm_linkscan_enable_set(unit, 0)); 977 if (soc_reset_init(unit) < 0) { 978 test_error(unit, "SOC initialization failed\n"); 979 goto done; 980 } 981 982 if (soc_misc_init(unit) < 0) { 983 test_error(unit, "MISC initialization failed\n"); 984 goto done; 985 } 986 987 if (soc_mmu_init(unit) < 0) { 988 test_error(unit, "MMU initialization failed\n"); 989 goto done; 990 } 991 992 if (mbcm_init(unit) < 0) { 993 test_error(unit, "BCM initialization failed\n"); 994 goto done; 995 } 996 997 } 998 #ifdef BCM_TRIDENT3_SUPPORT 999 if (soc_feature(unit, soc_feature_base_valid)) { 1000 if (soc_mem_read(unit, EGR_VLAN_XLATE_1_HASH_CONTROLm, MEM_BLOCK_ALL, 1001 0, &xlate_hash_read) < 0) { 1002 test_error(unit, "Hash Control read failed\n"); 1003 goto done; 1004 } 1005 1006 sal_memcpy(&ad->save_xlate_hash_control, &xlate_hash_read, 1007 sizeof(xlate_hash_read)); 1008 /* Set robust hash, test mode settings if need be.., 1009 For now - we are using default setting */ 1010 } else 1011 #endif /* BCM_TRIDENT3_SUPPORT */ 1012 { 1013 if (READ_EGR_VLAN_XLATE_HASH_CONTROLr(unit, &hash_read) < 0) { 1014 test_error(unit, "Hash select read failed\n"); 1015 goto done; 1016 } 1017 1018 ad->save_hash_control = hash_read; 1019 1020 soc_reg_field_set(unit, EGR_VLAN_XLATE_HASH_CONTROLr, &hash_read, 1021 HASH_SELECT_Af, ad->opt_hash); 1022 if (ad->opt_dual_hash != -1) { 1023 soc_reg_field_set(unit, EGR_VLAN_XLATE_HASH_CONTROLr, &hash_read, 1024 HASH_SELECT_Bf, ad->opt_dual_hash); 1025 } else { 1026 soc_reg_field_set(unit, EGR_VLAN_XLATE_HASH_CONTROLr, &hash_read, 1027 HASH_SELECT_Bf, ad->opt_hash); 1028 } 1029 1030 if (WRITE_EGR_VLAN_XLATE_HASH_CONTROLr(unit, hash_read) < 0) { 1031 test_error(unit, "Hash select setting failed\n"); 1032 goto done; 1033 } 1034 } 1035 1036 if ((rv = soc_mem_clear(unit, ad->mem, COPYNO_ALL, TRUE)) < 0) { 1037 goto done; 1038 } 1039 1040 rv = 0; 1041 1042 done: 1043 1044 parse_arg_eq_done(&pt); 1045 return rv; 1046 } 1047 1048 STATIC void 1049 tr_egr_vlan_xlate_hash_setup(int unit, tr_hash_test_t *dw) 1050 { 1051 tr_hash_testdata_t *ad; 1052 soc_mem_t mem = EGR_VLAN_XLATEm; 1053 1054 if (dw->lw_set_up) { 1055 return; 1056 } 1057 1058 dw->lw_set_up = TRUE; 1059 dw->lw_unit = unit; 1060 1061 if (SOC_MEM_IS_VALID(unit, EGR_VLAN_XLATE_1_DOUBLEm)) { 1062 mem = EGR_VLAN_XLATE_1_DOUBLEm; 1063 } 1064 dw->lp_hash.mem = mem; 1065 dw->lp_ov.mem = mem; 1066 1067 /* Hash */ 1068 ad = &dw->lp_hash; 1069 1070 ad->opt_count = soc_mem_index_count(unit, mem); 1071 #ifdef BCM_TRIDENT2_SUPPORT 1072 if (soc_feature(unit, soc_feature_extended_hash)) { 1073 ad->opt_hash = FB_HASH_CRC32_LOWER; 1074 ad->opt_dual_hash = FB_HASH_CRC32_UPPER; 1075 } else 1076 #endif /* BCM_TRIDENT2_SUPPORT */ 1077 { 1078 ad->opt_hash = FB_HASH_CRC16_LOWER; 1079 ad->opt_dual_hash = -1; 1080 } 1081 ad->hash_count = FB_HASH_COUNT; 1082 ad->opt_base_ovid = 0; 1083 ad->opt_base_ivid = 0; 1084 ad->opt_vid_inc = 1; 1085 1086 /* Overflow */ 1087 ad = &dw->lp_ov; 1088 1089 ad->opt_count = 2048; 1090 ad->opt_hash = TR_DEFAULT_HASH; 1091 ad->opt_dual_hash = -1; 1092 ad->hash_count = FB_HASH_COUNT; 1093 ad->opt_base_ovid = 0; 1094 ad->opt_base_ivid = 0; 1095 ad->opt_vid_inc = 1; 1096 } 1097 1098 /* Individual test init wrappers */ 1099 int 1100 tr_egr_vlan_xlate_hash_test_init(int unit, args_t *a, void **p) 1101 { 1102 tr_hash_test_t *dw = &tr_egr_vlan_xlate_work[unit]; 1103 tr_hash_testdata_t *dp = &dw->lp_hash; 1104 int rv; 1105 1106 tr_egr_vlan_xlate_hash_setup(unit, dw); 1107 1108 /* Set working data to hash */ 1109 dw->lp_cur = dp; 1110 1111 if ((rv = tr_egr_vlan_xlate_test_init(unit, dp, a)) < 0) { 1112 return rv; 1113 } else { 1114 *p = dp; 1115 } 1116 1117 return 0; 1118 } 1119 1120 int 1121 tr_egr_vlan_xlate_ov_test_init(int unit, args_t *a, void **p) 1122 { 1123 tr_hash_test_t *dw = &tr_egr_vlan_xlate_work[unit]; 1124 tr_hash_testdata_t *dp = &dw->lp_ov; 1125 int rv; 1126 1127 tr_egr_vlan_xlate_hash_setup(unit, dw); 1128 1129 /* Set working data to hash */ 1130 dw->lp_cur = dp; 1131 1132 if ((rv = tr_egr_vlan_xlate_test_init(unit, dp, a)) < 0) { 1133 return rv; 1134 } else { 1135 *p = dp; 1136 } 1137 1138 return 0; 1139 } 1140 1141 /* 1142 * Test of EGRESS VLAN XLATE hashing 1143 * 1144 * This test tries a number of keys against one of the hashing functions, 1145 * checking a software hash against the hardware hash, then searching the 1146 * bucket to find the entry after inserting. 1147 */ 1148 int 1149 tr_egr_vlan_xlate_test_hash(int unit, args_t *a, void *p) 1150 { 1151 tr_hash_testdata_t *ad = p; 1152 uint32 entry[SOC_MAX_MEM_FIELD_WORDS]; 1153 int soft_bucket, ix, r, rv = 0; 1154 int hash = ad->opt_hash; 1155 uint8 key[XGS_HASH_KEY_SIZE]; 1156 int iterations, ovid, ivid, num_bits; 1157 int vid_inc = ad->opt_vid_inc; 1158 int bucket_size; 1159 int index; 1160 int dual = FALSE; 1161 int bank, banks, bank_count = 1; 1162 soc_mem_t mem = ad->mem; 1163 1164 COMPILER_REFERENCE(a); 1165 1166 if (ad->opt_verbose) { 1167 cli_out("Starting EGR VLAN xlate hash test\n"); 1168 } 1169 1170 sal_memset(key, 0, sizeof(key)); 1171 1172 /* This seems to be a fair "guess". is there a way to find the bucket size used in the HW? */ 1173 bucket_size = (soc_mem_index_max(unit, mem) < 32767) ? 8 : 16; 1174 1175 if (SOC_IS_TRIDENT3X(unit)) { 1176 bucket_size = 4; 1177 } 1178 1179 #ifdef BCM_APACHE_SUPPORT 1180 if(SOC_IS_APACHE(unit)) { 1181 bucket_size = 8; 1182 } 1183 #endif 1184 1185 #if defined(BCM_SABER2_SUPPORT) 1186 if(SOC_IS_SABER2(unit)) { 1187 /* Even though with the reduced table size saber2 has the same bucket size as KT2 for this table */ 1188 bucket_size = 16; 1189 } 1190 #endif 1191 1192 iterations = ad->opt_count; 1193 ovid = ad->opt_base_ovid; 1194 ivid = ad->opt_base_ivid; 1195 if (ad->opt_dual_hash != -1) { 1196 dual = TRUE; 1197 bank_count = 2; 1198 } 1199 1200 1201 for (ix = 0; ix < iterations; ix++) { 1202 for (bank = 0; bank < bank_count; bank++) { 1203 sal_memset(entry, 0, sizeof (entry)); 1204 if (soc_feature(unit, soc_feature_base_valid)) { 1205 soc_mem_field32_set(unit, mem, entry, BASE_VALID_0f, 3); 1206 soc_mem_field32_set(unit, mem, entry, BASE_VALID_1f, 7); 1207 } else { 1208 soc_mem_field32_set(unit, mem, entry, VALIDf, 1); 1209 } 1210 soc_mem_field32_set(unit, mem, entry, OVIDf, ovid); 1211 soc_mem_field32_set(unit, mem, entry, IVIDf, ivid); 1212 1213 #ifdef BCM_TRIDENT3_SUPPORT 1214 if (SOC_IS_TRIDENT3X(unit)) { 1215 soft_bucket = soc_td3_egr_vlan_xlate_bank_entry_hash(unit, mem, bank, 1216 (uint32 *) entry); 1217 if (mem == EGR_VLAN_XLATE_1_DOUBLEm) { 1218 /* Double Wide Entry , extract 10 bits only */ 1219 soft_bucket &= 0x3FF; 1220 } 1221 } else 1222 #endif 1223 { 1224 num_bits = soc_tr_egr_vlan_xlate_base_entry_to_key 1225 (unit, (uint32 *) entry, key); 1226 soft_bucket = soc_tr_egr_vlan_xlate_hash(unit, hash, num_bits, 1227 (uint32 *)entry, key); 1228 } 1229 banks = 0; 1230 if (dual == TRUE) { 1231 #ifdef BCM_TRIDENT2_SUPPORT 1232 #ifdef BCM_TRIDENT3_SUPPORT 1233 if (SOC_IS_TRIDENT3X(unit)) { 1234 /* soft_bucket is already computed on the top */ 1235 } else 1236 #endif /* BCM_TRIDENT3_SUPPORT */ 1237 #ifdef BCM_APACHE_SUPPORT 1238 if (SOC_IS_APACHE(unit)) { 1239 soft_bucket = soc_ap_egr_vlan_xlate_bank_entry_hash(unit, 1240 bank, (uint32 *) entry); 1241 } else 1242 #endif /* BCM_APACHE_SUPPORT */ 1243 #ifdef BCM_TOMAHAWK_SUPPORT 1244 if (SOC_IS_TOMAHAWKX(unit)) { 1245 soft_bucket = soc_th_egr_vlan_xlate_bank_entry_hash(unit, 1246 bank, (uint32 *) entry); 1247 } else 1248 #endif /* BCM_TOMAHAWK_SUPPORT */ 1249 if (soc_feature(unit, soc_feature_extended_hash)) { 1250 soft_bucket = soc_td2_egr_vlan_xlate_bank_entry_hash(unit, 1251 bank, (uint32 *) entry); 1252 } else 1253 #endif /* BCM_TRIDENT2_SUPPORT */ 1254 { 1255 soft_bucket = soc_tr_egr_vlan_xlate_bank_entry_hash 1256 (unit, bank, (uint32 *) entry); 1257 } 1258 banks = (bank == 0) ? 2 : 1; 1259 } 1260 1261 1262 if (ad->opt_verbose) { 1263 cli_out("Inserting "); 1264 soc_mem_entry_dump(unit, mem, &entry, BSL_LSS_CLI); 1265 cli_out("\n"); 1266 if (dual) { 1267 cli_out("into bucket 0x%x (bank %d)\n", 1268 soft_bucket, bank); 1269 } else { 1270 cli_out("into bucket 0x%x\n", soft_bucket); 1271 } 1272 } 1273 1274 if ((r = soc_mem_bank_insert(unit, mem, banks, 1275 MEM_BLOCK_ALL, entry, NULL)) < 0) { 1276 if (r == SOC_E_FULL) { 1277 /* Bucket overflow, just pass on */ 1278 break; 1279 } else { 1280 test_error(unit, 1281 "EGR Vlan xlate insert failed at bucket %d\n", soft_bucket); 1282 rv = -1; 1283 goto done; 1284 } 1285 } 1286 1287 /* Now we search for the entry */ 1288 1289 /* Only do a quick check vs. expected bucket here */ 1290 if (tr_hash_bucket_search(unit, ad, mem, soft_bucket, 1291 bucket_size, VALIDf, entry, dual, bank) < 0) { 1292 test_error(unit, 1293 "EGR Vlan xlate entry with key " 1294 "0x%02x%02x%02x%02x%02x%02x%02x%01x " 1295 "not found in predicted bucket %d\n", 1296 key[7], key[6], key[5], key[4], 1297 key[3], key[2], key[1], (key[0] >> 4) & 0xf, 1298 soft_bucket); 1299 rv = -1; 1300 goto done; 1301 } 1302 1303 /* Search for the entry, should be found */ 1304 if (soc_mem_search(unit, mem, MEM_BLOCK_ALL, &index, 1305 entry, entry, 0) < 0) { 1306 test_error(unit, "EGR Vlan xlate search failed in bucket %d\n", 1307 soft_bucket); 1308 rv = -1; 1309 goto done; 1310 } 1311 1312 /* Insert the entry again, should fail. */ 1313 if (soc_mem_bank_insert(unit, mem, banks, 1314 MEM_BLOCK_ALL, entry, NULL) != SOC_E_EXISTS) { 1315 test_error(unit, 1316 "EGR Vlan xlate insert should have failed at bucket %d\n", 1317 soft_bucket); 1318 rv = -1; 1319 goto done; 1320 } 1321 1322 /* Delete the entry */ 1323 if (soc_mem_delete(unit, mem, MEM_BLOCK_ALL, entry) < 0) { 1324 test_error(unit, "EGR Vlan xlate delete failed at bucket %d\n", 1325 soft_bucket); 1326 rv = -1; 1327 goto done; 1328 } 1329 1330 /* Delete the entry again, should fail.*/ 1331 if (soc_mem_delete(unit, mem, 1332 MEM_BLOCK_ALL, entry) != SOC_E_NOT_FOUND) { 1333 test_error(unit, "EGR Vlan xlate delete should have failed in bucket %d\n", 1334 soft_bucket); 1335 rv = -1; 1336 goto done; 1337 } 1338 1339 /* Search for the entry again, should not be found */ 1340 if (soc_mem_search(unit, mem, MEM_BLOCK_ALL, &index, 1341 entry, entry, 0) != SOC_E_NOT_FOUND) { 1342 test_error(unit, "EGR Vlan xlate search should have failed in bucket %d\n", 1343 soft_bucket); 1344 rv = -1; 1345 goto done; 1346 } 1347 } 1348 ovid += vid_inc; 1349 if (ovid > TR_VID_MAX) { 1350 ovid = 1; 1351 } 1352 ivid += vid_inc; 1353 if (ivid > TR_VID_MAX) { 1354 ivid = 1; 1355 } 1356 } 1357 1358 done: 1359 return rv; 1360 } 1361 1362 /* 1363 * Test of Egress Vlan xlate overflow behavior 1364 * 1365 * This test fills each bucket, then inserts another entry to see 1366 * that the last entry fails to insert. 1367 */ 1368 1369 int 1370 tr_egr_vlan_xlate_test_ov(int unit, args_t *a, void *p) 1371 { 1372 tr_hash_testdata_t *ad = p; 1373 1374 uint32 entry[SOC_MAX_MEM_FIELD_WORDS]; 1375 uint32 result[SOC_MAX_MEM_FIELD_WORDS]; 1376 /* 20 is good enough for EGR_VLAN_XLATE TABLEs */ 1377 uint32 entry_tmp[16][20]; 1378 1379 int ix, jx, r, idx, rv = 0; 1380 int ivid, port_group; 1381 volatile int ovid; 1382 int bucket = 0; 1383 uint32 hash = ad->opt_hash; 1384 volatile int iter = ad->opt_count; 1385 uint8 key[XGS_HASH_KEY_SIZE]; 1386 int bucket_size; 1387 soc_mem_t mem = ad->mem; 1388 1389 COMPILER_REFERENCE(a); 1390 1391 /* This seems to be a fair "guess". is there a way to find the bucket size used in the HW? */ 1392 bucket_size = (soc_mem_index_max(unit, mem) < 32767) ? 8 : 16; 1393 1394 if (SOC_IS_TRIDENT3X(unit)) { 1395 bucket_size = 4; 1396 } 1397 1398 #ifdef BCM_APACHE_SUPPORT 1399 if(SOC_IS_APACHE(unit)) { 1400 bucket_size = 8; 1401 } 1402 #endif 1403 1404 #if defined(BCM_SABER2_SUPPORT) 1405 if(SOC_IS_SABER2(unit)) { 1406 /* Even though with the reduced table size saber2 has the same bucket size as KT2 for this table */ 1407 bucket_size = 16; 1408 } 1409 #endif 1410 1411 if (hash != FB_HASH_LSB) { 1412 if (ad->opt_verbose) { 1413 cli_out("Resetting hash selection to LSB\n"); 1414 } 1415 1416 hash = ad->save_hash_control; 1417 soc_reg_field_set(unit, EGR_VLAN_XLATE_HASH_CONTROLr, &hash, 1418 HASH_SELECT_Af, FB_HASH_LSB); 1419 soc_reg_field_set(unit, EGR_VLAN_XLATE_HASH_CONTROLr, &hash, 1420 HASH_SELECT_Bf, FB_HASH_LSB); 1421 1422 if (WRITE_EGR_VLAN_XLATE_HASH_CONTROLr(unit, hash) < 0) { 1423 test_error(unit, "Hash select setting failed\n"); 1424 goto done; 1425 } 1426 1427 ad->opt_hash = hash = FB_HASH_LSB; 1428 } 1429 1430 if (iter > soc_mem_index_count(unit, mem)) { 1431 iter = soc_mem_index_count(unit, mem); 1432 } 1433 port_group = 0; 1434 ovid = 0; 1435 ivid = 0; 1436 1437 while (iter--) { 1438 for (ix = 0; ix < bucket_size; ix++) { 1439 sal_memset(entry_tmp[ix], 0, sizeof(entry_tmp[0])); 1440 if (soc_feature(unit, soc_feature_base_valid)) { 1441 soc_mem_field32_set(unit, mem, entry_tmp[ix], BASE_VALID_0f, 3); 1442 soc_mem_field32_set(unit, mem, entry_tmp[ix], BASE_VALID_1f, 7); 1443 } else { 1444 soc_mem_field32_set(unit, mem, entry_tmp[ix], VALIDf, 1); 1445 } 1446 soc_mem_field32_set(unit, mem, entry_tmp[ix], OVIDf, ovid); 1447 soc_mem_field32_set(unit, mem, entry_tmp[ix], IVIDf, ivid); 1448 soc_mem_field32_set(unit, mem, entry_tmp[ix], PORT_GROUP_IDf, port_group); 1449 1450 if (ix == 0) { 1451 int num_bits; 1452 num_bits = soc_tr_egr_vlan_xlate_base_entry_to_key 1453 (unit, (uint32 *) entry_tmp[ix], key); 1454 bucket = soc_tr_egr_vlan_xlate_hash(unit, hash, num_bits, 1455 (uint32 *)entry_tmp[ix], 1456 key); 1457 1458 if (ad->opt_verbose) { 1459 cli_out("Filling bucket %d\n", bucket); 1460 } 1461 } 1462 1463 if ((r = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry_tmp[ix])) < 0) { 1464 if (r == SOC_E_FULL) { 1465 /* Already full, stop wasting time */ 1466 break; 1467 } else { 1468 test_error(unit, 1469 "EGR Vlan xlate insert failed at bucket %d\n", bucket); 1470 rv = -1; 1471 goto done; 1472 } 1473 } 1474 1475 /* key for LSB is the OVID , so we must keep it constant */ 1476 ivid += 1; 1477 if (ivid > TR_VID_MAX) { 1478 ivid = 0; 1479 /* coverity[assignment : FALSE] */ 1480 port_group += 1; 1481 if (port_group > 0x3f) { 1482 port_group = 0; 1483 } 1484 } 1485 } 1486 1487 if (ad->opt_verbose) { 1488 cli_out("Inserting %dth entry in bucket %d, should fail\n", 1489 (bucket_size + 1), bucket); 1490 } 1491 1492 sal_memset(entry, 0, sizeof(entry)); 1493 if (soc_feature(unit, soc_feature_base_valid)) { 1494 soc_mem_field32_set(unit, mem, entry, BASE_VALID_0f, 3); 1495 soc_mem_field32_set(unit, mem, entry, BASE_VALID_1f, 7); 1496 } else { 1497 soc_mem_field32_set(unit, mem, entry, VALIDf, 1); 1498 } 1499 soc_mem_field32_set(unit, mem, entry, OVIDf, ovid); 1500 soc_mem_field32_set(unit, mem, entry, IVIDf, ivid); 1501 soc_mem_field32_set(unit, mem, entry, PORT_GROUP_IDf, port_group); 1502 1503 if ((r = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry)) < 0) { 1504 if (r != SOC_E_FULL) { 1505 test_error(unit, 1506 "EGR Vlan xlate insert failed\n"); 1507 rv = -1; 1508 goto done; 1509 } 1510 } else { 1511 test_error(unit, "EGR Vlan xlate insert to full bucket succeeded\n"); 1512 rv = -1; 1513 goto done; 1514 } 1515 1516 if (ad->opt_verbose) { 1517 cli_out("Verifying entries present\n"); 1518 } 1519 1520 /* Verify bucket contains our added entries */ 1521 for (jx = 0; jx < ix; jx++) { 1522 if (tr_hash_bucket_search(unit, ad, mem, bucket, 1523 bucket_size, VALIDf, entry_tmp[jx], 0, 0) < 0) { 1524 test_error(unit, "EGR VLAN xlate entry missing at bucket %d\n", bucket); 1525 rv = -1; 1526 goto done; 1527 } 1528 if (soc_mem_search(unit, mem, MEM_BLOCK_ANY, &idx, 1529 entry_tmp[jx], result, 0) < 0) { 1530 test_error(unit, "EGR VLAN xlate entry missing at bucket %d\n", bucket); 1531 rv = -1; 1532 goto done; 1533 } 1534 if (bucket != (idx / bucket_size)) { 1535 test_error(unit, "EGR VLAN xlate entry inserted into wrong bucket" 1536 " Expected %d Actual %d\n", bucket, idx); 1537 rv = -1; 1538 goto done; 1539 } 1540 } 1541 1542 if (ad->opt_verbose) { 1543 cli_out("Cleaning bucket %d\n", bucket); 1544 } 1545 1546 /* Remove the entries that we added */ 1547 for (jx = 0; jx < ix; jx++) { 1548 if (soc_mem_delete(unit, mem, MEM_BLOCK_ALL, entry_tmp[jx]) < 0) { 1549 test_error(unit, "EGR Vlan xlate delete failed at bucket %d\n", bucket); 1550 rv = -1; 1551 goto done; 1552 } 1553 } 1554 1555 /* We want the increment to change buckets by one. For EGR VLAN XLATE, 1556 * the LSB hash bucket is determined by {ovid}. 1557 */ 1558 ovid += 1; 1559 if (ovid == TR_VID_MAX) { 1560 ovid = 0; 1561 } 1562 } 1563 1564 done: 1565 1566 return rv; 1567 } 1568 1569 /* 1570 * Test clean-up routine used for all EGR Vlan xlate tests 1571 */ 1572 1573 int 1574 tr_egr_vlan_xlate_test_done(int unit, void *p) 1575 { 1576 tr_hash_testdata_t *ad = p; 1577 soc_mem_t mem; 1578 1579 if (ad == NULL) { 1580 return 0; 1581 } 1582 1583 mem = ad->mem; 1584 1585 /* Check if empty at the end of the test */ 1586 if (ad->opt_reset) { 1587 int rv, ix; 1588 int index_min = soc_mem_index_min(unit, mem); 1589 int index_max = soc_mem_index_max(unit, mem); 1590 uint32 *buf = 0; 1591 uint32 *ent; 1592 uint32 count; 1593 1594 buf = soc_cm_salloc(unit, 1595 SOC_MEM_TABLE_BYTES(unit, mem), 1596 "egr_vlan_xlate_test"); 1597 if (!buf) { 1598 test_error(unit, "Memory allocation failed\n"); 1599 return (-1); 1600 } 1601 1602 if ((rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 1603 index_min, index_max, buf)) < 0) { 1604 test_error(unit, "Memory DMA of EGR_VLAN_XLATEm entries failed\n"); 1605 return (-1); 1606 } 1607 1608 count = soc_mem_index_count(unit, mem); 1609 for (ix = 0; ix < count; ix++) { 1610 int vld = 0; 1611 ent = soc_mem_table_idx_to_pointer(unit, mem, 1612 uint32 *, buf, ix); 1613 if (soc_feature(unit, soc_feature_base_valid)) { 1614 vld = soc_mem_field32_get(unit, mem, ent, BASE_VALID_0f) == 3 && 1615 soc_mem_field32_get(unit, mem, ent, BASE_VALID_1f) == 7; 1616 } else 1617 { 1618 vld = soc_mem_field32_get(unit, mem, ent, VALIDf); 1619 } 1620 1621 if (vld) { 1622 test_error(unit, "EGR Vlan xlate table not empty after test entry = %d\n", 1623 ix); 1624 soc_mem_entry_dump(unit, EGR_VLAN_XLATEm, ent, BSL_LSS_CLI); 1625 return (-1); 1626 } 1627 } 1628 1629 soc_cm_sfree(unit, buf); 1630 } 1631 1632 #ifdef BCM_TRIDENT3_SUPPORT 1633 if (soc_feature(unit, soc_feature_base_valid)) { 1634 if (soc_mem_write(unit, EGR_VLAN_XLATE_1_HASH_CONTROLm, MEM_BLOCK_ALL, 1635 0, &ad->save_xlate_hash_control) < 0) { 1636 test_error(unit, "Hash Control restore failed\n"); 1637 } 1638 } else 1639 #endif /* BCM_TRIDENT3_SUPPORT */ 1640 { 1641 if (WRITE_EGR_VLAN_XLATE_HASH_CONTROLr(unit, ad->save_hash_control) < 0) { 1642 test_error(unit, "Hash select restore failed\n"); 1643 } 1644 } 1645 1646 return 0; 1647 } 1648 /************************** END OF EGR VLAN XLATE TESTS ********************/ 1649 1650 /************************** START OF MPLS TESTS ****************************/ 1651 #ifdef BCM_TRIUMPH_SUPPORT 1652 /* 1653 * Test initialization routine used for MPLS tests 1654 */ 1655 1656 STATIC int 1657 tr_mpls_test_init(int unit, tr_hash_testdata_t *ad, args_t *a) 1658 { 1659 int rv = -1, dual = 0; 1660 parse_table_t pt; 1661 uint32 hash_read; 1662 1663 parse_table_init(unit, &pt); 1664 1665 parse_table_add(&pt, "Count", PQ_INT|PQ_DFL, 0, &ad->opt_count, NULL); 1666 parse_table_add(&pt, "Verbose", PQ_BOOL|PQ_DFL, 0, &ad->opt_verbose, NULL); 1667 parse_table_add(&pt, "Reset", PQ_BOOL|PQ_DFL, 0, &ad->opt_reset, NULL); 1668 parse_table_add(&pt, "Hash", PQ_INT|PQ_DFL, 0, &ad->opt_hash, NULL); 1669 parse_table_add(&pt, "DualHash", PQ_INT|PQ_DFL, 0, &ad->opt_dual_hash, NULL); 1670 parse_table_add(&pt, "DualEnable", PQ_INT|PQ_DFL, 0, &dual, NULL); 1671 parse_table_add(&pt, "BaseLabel", PQ_INT|PQ_DFL, 0, &ad->opt_base_label, NULL); 1672 parse_table_add(&pt, "LabelIncrement", PQ_INT|PQ_DFL, 0, 1673 &ad->opt_label_inc, NULL); 1674 1675 /* Test the obvious parsings before wasting time with malloc */ 1676 if (parse_arg_eq(a, &pt) < 0) { 1677 test_error(unit, 1678 "%s: Error: Invalid option: %s\n", ARG_CMD(a), 1679 ARG_CUR(a) ? ARG_CUR(a) : "*"); 1680 goto done; 1681 } 1682 1683 if (ad->opt_count < 1) { 1684 test_error(unit, "Illegal count %d\n", ad->opt_count); 1685 goto done; 1686 } 1687 1688 if (ad->opt_hash >= ad->hash_count) { 1689 test_error(unit, "Illegal hash selection %d\n", ad->opt_hash); 1690 goto done; 1691 } 1692 1693 if (dual == 1) { 1694 if (ad->opt_dual_hash >= ad->hash_count) { 1695 test_error(unit, "Illegal dual hash selection %d\n", ad->opt_dual_hash); 1696 goto done; 1697 } 1698 } else { 1699 ad->opt_dual_hash = -1; 1700 } 1701 1702 if (ad->opt_base_label >= (1 << 20)) { 1703 test_error(unit, "Out of range MPLS label selection %d\n", 1704 ad->opt_base_label); 1705 goto done; 1706 } 1707 1708 /* 1709 * Re-initialize chip to ensure tables are clear 1710 * at start of test. 1711 */ 1712 1713 if (ad->opt_reset) { 1714 BCM_IF_ERROR_RETURN(bcm_linkscan_enable_set(unit, 0)); 1715 if (soc_reset_init(unit) < 0) { 1716 test_error(unit, "SOC initialization failed\n"); 1717 goto done; 1718 } 1719 1720 if (soc_misc_init(unit) < 0) { 1721 test_error(unit, "MISC initialization failed\n"); 1722 goto done; 1723 } 1724 1725 if (soc_mmu_init(unit) < 0) { 1726 test_error(unit, "MMU initialization failed\n"); 1727 goto done; 1728 } 1729 1730 if (mbcm_init(unit) < 0) { 1731 test_error(unit, "BCM initialization failed\n"); 1732 goto done; 1733 } 1734 1735 } 1736 1737 #if defined(BCM_TRIDENT3_SUPPORT) 1738 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1739 sal_memset(ad->td3_hash_tbl_data, 0, sizeof(ad->td3_hash_tbl_data)); 1740 #ifdef BCM_HELIX5_SUPPORT 1741 if (SOC_IS_HELIX5(unit)) { 1742 rv = soc_hx5_mpls_hash_control_set(ad->td3_hash_tbl_data); 1743 } else 1744 #endif 1745 { 1746 rv = soc_td3_mpls_hash_control_set(ad->td3_hash_tbl_data); 1747 } 1748 if (rv < 0) { 1749 test_error(unit, "Hash select read failed\n"); 1750 goto done; 1751 } 1752 } else 1753 #endif 1754 { 1755 if (READ_MPLS_ENTRY_HASH_CONTROLr(unit, &hash_read) < 0) { 1756 test_error(unit, "Hash select read failed\n"); 1757 goto done; 1758 } 1759 1760 ad->save_hash_control = hash_read; 1761 1762 soc_reg_field_set(unit, MPLS_ENTRY_HASH_CONTROLr, &hash_read, 1763 HASH_SELECT_Af, ad->opt_hash); 1764 if (ad->opt_dual_hash != -1) { 1765 soc_reg_field_set(unit, MPLS_ENTRY_HASH_CONTROLr, &hash_read, 1766 HASH_SELECT_Bf, ad->opt_dual_hash); 1767 } else { 1768 soc_reg_field_set(unit, MPLS_ENTRY_HASH_CONTROLr, &hash_read, 1769 HASH_SELECT_Bf, ad->opt_hash); 1770 } 1771 1772 if (WRITE_MPLS_ENTRY_HASH_CONTROLr(unit, hash_read) < 0) { 1773 test_error(unit, "Hash select setting failed\n"); 1774 goto done; 1775 } 1776 } 1777 rv = 0; 1778 1779 done: 1780 1781 parse_arg_eq_done(&pt); 1782 return rv; 1783 } 1784 1785 STATIC void 1786 tr_mpls_hash_setup(int unit, tr_hash_test_t *dw) 1787 { 1788 tr_hash_testdata_t *ad; 1789 1790 if (dw->lw_set_up) { 1791 return; 1792 } 1793 1794 dw->lw_set_up = TRUE; 1795 dw->lw_unit = unit; 1796 1797 /* Hash */ 1798 ad = &dw->lp_hash; 1799 1800 ad->opt_verbose = FALSE; 1801 if (!SOC_MEM_IS_VALID (unit, MPLS_ENTRYm)) 1802 { 1803 ad->opt_count = -1; 1804 return; 1805 } 1806 ad->opt_count = soc_mem_index_count(unit, MPLS_ENTRYm); 1807 #ifdef BCM_TRIDENT2_SUPPORT 1808 if (soc_feature(unit, soc_feature_extended_hash)) { 1809 ad->opt_hash = FB_HASH_CRC32_LOWER; 1810 ad->opt_dual_hash = FB_HASH_CRC32_UPPER; 1811 } else 1812 #endif /* BCM_TRIDENT2_SUPPORT */ 1813 { 1814 ad->opt_hash = FB_HASH_CRC16_LOWER; 1815 ad->opt_dual_hash = -1; 1816 } 1817 ad->hash_count = FB_HASH_COUNT; 1818 ad->opt_base_label = 0; 1819 ad->opt_label_inc = 1; 1820 1821 /* Overflow */ 1822 ad = &dw->lp_ov; 1823 1824 ad->opt_count = 2048; 1825 ad->opt_hash = TR_DEFAULT_HASH; 1826 ad->opt_dual_hash = -1; 1827 ad->hash_count = FB_HASH_COUNT; 1828 ad->opt_base_label = 0; 1829 ad->opt_label_inc = 1; 1830 } 1831 1832 /* Individual test init wrappers */ 1833 int 1834 tr_mpls_hash_test_init(int unit, args_t *a, void **p) 1835 { 1836 tr_hash_test_t *dw = &tr_mpls_work[unit]; 1837 tr_hash_testdata_t *dp = &dw->lp_hash; 1838 int rv; 1839 1840 tr_mpls_hash_setup(unit, dw); 1841 1842 /* Set working data to hash */ 1843 dw->lp_cur = dp; 1844 1845 if ((rv = tr_mpls_test_init(unit, dp, a)) < 0) { 1846 return rv; 1847 } else { 1848 *p = dp; 1849 } 1850 1851 return 0; 1852 } 1853 1854 int 1855 tr_mpls_ov_test_init(int unit, args_t *a, void **p) 1856 { 1857 tr_hash_test_t *dw = &tr_mpls_work[unit]; 1858 tr_hash_testdata_t *dp = &dw->lp_ov; 1859 int rv; 1860 1861 tr_mpls_hash_setup(unit, dw); 1862 1863 /* Set working data to hash */ 1864 dw->lp_cur = dp; 1865 1866 if ((rv = tr_mpls_test_init(unit, dp, a)) < 0) { 1867 return rv; 1868 } else { 1869 *p = dp; 1870 } 1871 1872 return 0; 1873 } 1874 1875 /* 1876 * Test of MPLS XLATE hashing 1877 * 1878 * This test tries a number of keys against one of the hashing functions, 1879 * checking a software hash against the hardware hash, then searching the 1880 * bucket to find the entry after inserting. 1881 */ 1882 int 1883 tr_mpls_test_hash(int unit, args_t *a, void *p) 1884 { 1885 tr_hash_testdata_t *ad = p; 1886 mpls_entry_entry_t entry; 1887 int soft_bucket, ix, r, rv = 0; 1888 int hash = ad->opt_hash; 1889 uint8 key[XGS_HASH_KEY_SIZE]; 1890 int iterations, label, num_bits; 1891 int label_inc = ad->opt_label_inc; 1892 int bucket_size = 8; 1893 int index; 1894 int dual = FALSE; 1895 int bank, bank_count = 1; 1896 1897 COMPILER_REFERENCE(a); 1898 1899 if (ad->opt_verbose) { 1900 cli_out("Starting MPLS hash test\n"); 1901 } 1902 1903 iterations = ad->opt_count; 1904 label = ad->opt_base_label; 1905 if (ad->opt_dual_hash != -1) { 1906 dual = TRUE; 1907 bank_count = 2; 1908 } 1909 1910 for (ix = 0; ix < iterations; ix++) { 1911 for (bank = 0; bank < bank_count; bank++) { 1912 sal_memset(&entry, 0, sizeof (entry)); 1913 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 1914 soc_MPLS_ENTRYm_field32_set(unit, &entry, BASE_VALID_0f, 3); 1915 soc_MPLS_ENTRYm_field32_set(unit, &entry, BASE_VALID_1f, 7); 1916 } else { 1917 soc_MPLS_ENTRYm_field32_set(unit, &entry, VALIDf, 1); 1918 } 1919 soc_MPLS_ENTRYm_field32_set(unit, &entry, MPLS_LABELf, label); 1920 num_bits = soc_tr_mpls_base_entry_to_key 1921 (unit, (uint32 *) &entry, key); 1922 soft_bucket = soc_tr_mpls_hash(unit, hash, num_bits, 1923 (uint32 *) &entry, key); 1924 if (dual == TRUE) { 1925 #ifdef BCM_TRIDENT2_SUPPORT 1926 #ifdef BCM_APACHE_SUPPORT 1927 if (SOC_IS_APACHE(unit)) { 1928 soft_bucket = soc_ap_mpls_bank_entry_hash(unit, bank, 1929 (uint32 *) &entry); 1930 } else 1931 #endif /* BCM_APACHE_SUPPORT */ 1932 #if defined(BCM_TOMAHAWK3_SUPPORT) 1933 if (SOC_IS_TOMAHAWK3(unit) && 1934 soc_feature(unit, soc_feature_base_valid)) { 1935 soft_bucket = 1936 soc_tomahawk3_mpls_bank_entry_hash( 1937 unit, bank, (uint32 *) &entry); 1938 } else 1939 #endif 1940 #if defined(BCM_TRIDENT3_SUPPORT) 1941 if (soc_feature(unit, soc_feature_base_valid)) { 1942 soft_bucket = soc_td3_mpls_bank_entry_hash(unit, MPLS_ENTRYm, bank, 1943 (uint32 *) &entry); 1944 } else 1945 #endif /* BCM_TRIDENT3_SUPPORT */ 1946 #ifdef BCM_TOMAHAWK_SUPPORT 1947 if (SOC_IS_TOMAHAWKX(unit)) { 1948 soft_bucket = soc_th_mpls_bank_entry_hash(unit, bank, 1949 (uint32 *) &entry); 1950 } else 1951 #endif /* BCM_TOMAHAWK_SUPPORT */ 1952 if (soc_feature(unit, soc_feature_extended_hash)) { 1953 soft_bucket = soc_td2_mpls_bank_entry_hash(unit, bank, 1954 (uint32 *) &entry); 1955 } else 1956 #endif /* BCM_TRIDENT2_SUPPORT */ 1957 { 1958 soft_bucket = soc_tr_mpls_bank_entry_hash 1959 (unit, bank, (uint32 *) &entry); 1960 } 1961 } 1962 1963 if (ad->opt_verbose) { 1964 cli_out("Inserting "); 1965 soc_mem_entry_dump(unit, MPLS_ENTRYm, &entry, BSL_LSS_CLI); 1966 cli_out("\n"); 1967 if (dual) { 1968 cli_out("into bucket 0x%x (bank %d)\n", 1969 soft_bucket, bank); 1970 } else { 1971 cli_out("into bucket 0x%x\n", soft_bucket); 1972 } 1973 } 1974 1975 if ((r = soc_mem_bank_insert(unit, MPLS_ENTRYm, bank, 1976 MEM_BLOCK_ALL, &entry, NULL)) < 0) { 1977 if (r == SOC_E_FULL) { 1978 /* Bucket overflow, just pass on */ 1979 break; 1980 } else { 1981 test_error(unit, 1982 "MPLS insert failed at bucket %d\n", soft_bucket); 1983 rv = -1; 1984 goto done; 1985 } 1986 } 1987 1988 /* Now we search for the entry */ 1989 if (!soc_feature(unit, soc_feature_shared_hash_mem)) { 1990 /* Only do a quick check vs. expected bucket here */ 1991 if (tr_hash_bucket_search(unit, ad, MPLS_ENTRYm, soft_bucket, 1992 bucket_size, VALIDf, &entry, dual, bank) < 0) { 1993 test_error(unit, 1994 "MPLS entry with key " 1995 "0x%02x%02x%02x%02x%02x%02x%02x%01x " 1996 "not found in predicted bucket %d\n", 1997 key[7], key[6], key[5], key[4], 1998 key[3], key[2], key[1], (key[0] >> 4) & 0xf, 1999 soft_bucket); 2000 rv = -1; 2001 goto done; 2002 } 2003 } 2004 2005 /* Search for the entry, should be found */ 2006 if (soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &index, 2007 &entry, &entry, 0) < 0) { 2008 test_error(unit, "MPLS search failed in bucket %d\n", 2009 soft_bucket); 2010 rv = -1; 2011 goto done; 2012 } 2013 2014 /* Insert the entry again, should fail. */ 2015 if (soc_mem_bank_insert(unit, MPLS_ENTRYm, bank, 2016 MEM_BLOCK_ALL, &entry, NULL) != SOC_E_EXISTS) { 2017 test_error(unit, 2018 "MPLS insert should have failed at bucket %d\n", soft_bucket); 2019 rv = -1; 2020 goto done; 2021 } 2022 2023 /* Delete the entry */ 2024 if (soc_mem_delete(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &entry) < 0) { 2025 test_error(unit, "MPLS delete failed at bucket %d\n", 2026 soft_bucket); 2027 rv = -1; 2028 goto done; 2029 } 2030 2031 /* Delete the entry again, should fail.*/ 2032 if (soc_mem_delete(unit, MPLS_ENTRYm, 2033 MEM_BLOCK_ALL, &entry) != SOC_E_NOT_FOUND) { 2034 test_error(unit, "MPLS delete should have failed in bucket %d\n", 2035 soft_bucket); 2036 rv = -1; 2037 goto done; 2038 } 2039 2040 /* Search for the entry again, should not be found */ 2041 if (soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &index, 2042 &entry, &entry, 0) != SOC_E_NOT_FOUND) { 2043 test_error(unit, "MPLS search should have failed in bucket %d\n", 2044 soft_bucket); 2045 rv = -1; 2046 goto done; 2047 } 2048 } 2049 label += label_inc; 2050 if (label > TR_LABEL_MAX) { 2051 label = 1; 2052 } 2053 } 2054 2055 done: 2056 return rv; 2057 } 2058 2059 /* 2060 * Test of MPLS overflow behavior 2061 * 2062 * This test fills each bucket, then inserts another entry to see 2063 * that the last entry fails to insert. 2064 */ 2065 2066 int 2067 tr_mpls_test_ov(int unit, args_t *a, void *p) 2068 { 2069 tr_hash_testdata_t *ad = p; 2070 mpls_entry_entry_t entry, result, entry_tmp[8]; 2071 int ix, jx, r, idx, rv = 0; 2072 int port, module, label; 2073 int bucket = 0; 2074 uint32 hash = ad->opt_hash; 2075 int iter = ad->opt_count; 2076 uint8 key[XGS_HASH_KEY_SIZE]; 2077 int bucket_size = 8; 2078 2079 COMPILER_REFERENCE(a); 2080 2081 if (hash != FB_HASH_LSB) { 2082 if (ad->opt_verbose) { 2083 cli_out("Resetting hash selection to LSB\n"); 2084 } 2085 2086 hash = ad->save_hash_control; 2087 soc_reg_field_set(unit, MPLS_ENTRY_HASH_CONTROLr, &hash, 2088 HASH_SELECT_Af, FB_HASH_LSB); 2089 soc_reg_field_set(unit, MPLS_ENTRY_HASH_CONTROLr, &hash, 2090 HASH_SELECT_Bf, FB_HASH_LSB); 2091 2092 if (WRITE_MPLS_ENTRY_HASH_CONTROLr(unit, hash) < 0) { 2093 test_error(unit, "Hash select setting failed\n"); 2094 goto done; 2095 } 2096 2097 ad->opt_hash = hash = FB_HASH_LSB; 2098 } 2099 2100 if (iter > soc_mem_index_count(unit, MPLS_ENTRYm)) { 2101 iter = soc_mem_index_count(unit, MPLS_ENTRYm); 2102 } 2103 port = 0; 2104 module = 0; 2105 label = 0; 2106 2107 while (iter--) { 2108 for (ix = 0; ix < bucket_size; ix++) { 2109 sal_memset(&entry_tmp[ix], 0, sizeof(mpls_entry_entry_t)); 2110 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 2111 soc_MPLS_ENTRYm_field32_set(unit, &(entry_tmp[ix]), BASE_VALID_0f, 3); 2112 soc_MPLS_ENTRYm_field32_set(unit, &(entry_tmp[ix]), BASE_VALID_1f, 7); 2113 } else { 2114 soc_MPLS_ENTRYm_field32_set(unit, &(entry_tmp[ix]), VALIDf, 1); 2115 } 2116 soc_MPLS_ENTRYm_field32_set(unit, &(entry_tmp[ix]), PORT_NUMf, port); 2117 soc_MPLS_ENTRYm_field32_set(unit, &(entry_tmp[ix]), MODULE_IDf, module); 2118 soc_MPLS_ENTRYm_field32_set(unit, &(entry_tmp[ix]), MPLS_LABELf, label); 2119 2120 if (ix == 0) { 2121 int num_bits; 2122 num_bits = soc_tr_mpls_base_entry_to_key 2123 (unit, (uint32 *) &(entry_tmp[ix]), key); 2124 bucket = soc_tr_mpls_hash(unit, hash, num_bits, 2125 (uint32 *) &(entry_tmp[ix]), key); 2126 if (ad->opt_verbose) { 2127 cli_out("Filling bucket %d\n", bucket); 2128 } 2129 } 2130 2131 if ((r = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &entry_tmp[ix])) < 0) { 2132 if (r == SOC_E_FULL) { 2133 /* Already full, stop wasting time */ 2134 break; 2135 } else { 2136 test_error(unit, 2137 "MPLS insert failed at bucket %d\n", bucket); 2138 rv = -1; 2139 goto done; 2140 } 2141 } 2142 2143 /* key for LSB is the label, so we must keep it constant */ 2144 port += 1; 2145 if (port > 0x3f) { 2146 /* coverity[assignment : FALSE] */ 2147 port = 0; 2148 /* coverity[assignment] */ 2149 module += 1; 2150 if (module > 0x7f) { 2151 module = 0; 2152 } 2153 } 2154 } 2155 2156 if (ad->opt_verbose) { 2157 cli_out("Inserting %dth entry in bucket %d, should fail\n", 2158 (bucket_size + 1), bucket); 2159 } 2160 2161 sal_memset(&entry, 0, sizeof(mpls_entry_entry_t)); 2162 if (soc_feature(unit, soc_feature_td3_style_mpls)) { 2163 soc_MPLS_ENTRYm_field32_set(unit, &entry, BASE_VALID_0f, 3); 2164 soc_MPLS_ENTRYm_field32_set(unit, &entry, BASE_VALID_1f, 7); 2165 } else { 2166 soc_MPLS_ENTRYm_field32_set(unit, &entry, VALIDf, 1); 2167 } 2168 soc_MPLS_ENTRYm_field32_set(unit, &entry, PORT_NUMf, port); 2169 soc_MPLS_ENTRYm_field32_set(unit, &entry, MODULE_IDf, module); 2170 soc_MPLS_ENTRYm_field32_set(unit, &entry, MPLS_LABELf, label); 2171 2172 if ((r = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &entry)) < 0) { 2173 if (r != SOC_E_FULL) { 2174 test_error(unit, 2175 "MPLS insert failed\n"); 2176 rv = -1; 2177 goto done; 2178 } 2179 } else { 2180 test_error(unit, "MPLS insert to full bucket succeeded\n"); 2181 rv = -1; 2182 goto done; 2183 } 2184 2185 if (ad->opt_verbose) { 2186 cli_out("Verifying entries present\n"); 2187 } 2188 2189 /* Verify bucket contains our added entries */ 2190 for (jx = 0; jx < ix; jx++) { 2191 if (tr_hash_bucket_search(unit, ad, MPLS_ENTRYm, bucket, 2192 bucket_size, VALIDf, &(entry_tmp[jx]), 0, 0) < 0) { 2193 test_error(unit, "MPLS entry missing at bucket %d\n", bucket); 2194 rv = -1; 2195 goto done; 2196 } 2197 if (soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &idx, 2198 &entry_tmp[jx], &result, 0) < 0) { 2199 test_error(unit, "MPLS entry missing at bucket %d\n", bucket); 2200 rv = -1; 2201 goto done; 2202 } 2203 if (bucket != (idx / bucket_size)) { 2204 test_error(unit, "MPLS entry inserted into wrong bucket" 2205 " Expected %d Actual %d\n", bucket, idx); 2206 rv = -1; 2207 goto done; 2208 } 2209 } 2210 2211 if (ad->opt_verbose) { 2212 cli_out("Cleaning bucket %d\n", bucket); 2213 } 2214 2215 /* Remove the entries that we added */ 2216 for (jx = 0; jx < ix; jx++) { 2217 if (soc_mem_delete(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &(entry_tmp[jx])) < 0) { 2218 test_error(unit, "MPLS delete failed at bucket %d\n", bucket); 2219 rv = -1; 2220 goto done; 2221 } 2222 } 2223 2224 /* We want the increment to change buckets by one. For MPLS_ENTRYm, 2225 * the LSB hash bucket is determined by {label}. 2226 */ 2227 label += 1; 2228 if (label > TR_LABEL_MAX) { 2229 label = 0; 2230 } 2231 } 2232 2233 done: 2234 2235 return rv; 2236 } 2237 2238 /* 2239 * Test clean-up routine used for all MPLS tests 2240 */ 2241 2242 int 2243 tr_mpls_test_done(int unit, void *p) 2244 { 2245 tr_hash_testdata_t *ad = p; 2246 2247 if (ad == NULL) { 2248 return 0; 2249 } 2250 2251 /* Check if empty at the end of the test */ 2252 if (ad->opt_reset) { 2253 int rv, ix; 2254 int index_min = soc_mem_index_min(unit, MPLS_ENTRYm); 2255 int index_max = soc_mem_index_max(unit, MPLS_ENTRYm); 2256 uint32 *buf = 0; 2257 uint32 *ent; 2258 uint32 count; 2259 2260 buf = soc_cm_salloc(unit, 2261 SOC_MEM_TABLE_BYTES(unit, MPLS_ENTRYm), 2262 "mpls_entry_test"); 2263 if (!buf) { 2264 test_error(unit, "Memory allocation failed\n"); 2265 return (-1); 2266 } 2267 2268 if ((rv = soc_mem_read_range(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, 2269 index_min, index_max, buf)) < 0) { 2270 test_error(unit, "Memory DMA of MPLS_ENTRYm entries failed\n"); 2271 return (-1); 2272 } 2273 2274 count = soc_mem_index_count(unit, MPLS_ENTRYm); 2275 for (ix = 0; ix < count; ix++) { 2276 ent = soc_mem_table_idx_to_pointer(unit, MPLS_ENTRYm, 2277 uint32 *, buf, ix); 2278 2279 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 2280 if (soc_feature(unit, soc_feature_base_valid)) { 2281 if ((soc_MPLS_ENTRYm_field32_get(unit, ent, BASE_VALID_0f) == 3) && 2282 (soc_MPLS_ENTRYm_field32_get(unit, ent, BASE_VALID_1f) == 7)) { 2283 test_error(unit, "MPLS_ENTRY table not empty after test entry = %d\n", 2284 ix); 2285 soc_mem_entry_dump(unit, MPLS_ENTRYm, ent, BSL_LSS_CLI); 2286 return (-1); 2287 } 2288 } else 2289 #endif 2290 { 2291 if (soc_MPLS_ENTRYm_field32_get(unit, ent, VALIDf)) { 2292 test_error(unit, "MPLS_ENTRY table not empty after test entry = %d\n", 2293 ix); 2294 soc_mem_entry_dump(unit, MPLS_ENTRYm, ent, BSL_LSS_CLI); 2295 return (-1); 2296 } 2297 } 2298 } 2299 2300 soc_cm_sfree(unit, buf); 2301 } 2302 2303 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 2304 if (soc_feature(unit, soc_feature_base_valid)) { 2305 if (WRITE_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 2306 ad->td3_hash_tbl_data) < 0) { 2307 test_error(unit, "Hash select restore failed\n"); 2308 } 2309 } else 2310 #endif 2311 { 2312 if (WRITE_MPLS_ENTRY_HASH_CONTROLr(unit, ad->save_hash_control) < 0) { 2313 test_error(unit, "Hash select restore failed\n"); 2314 } 2315 } 2316 2317 return 0; 2318 } 2319 #endif /* BCM_TRIUMPH_SUPPORT */ 2320 /************************** END OF MPLS TESTS ******************************/ 2321 #endif /* BCM_TRX_SUPPORT */ 2322