trill.c (199875B)
1 /* 2 * 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 * 8 * ESW Trill API 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <soc/defs.h> 14 #include <sal/core/libc.h> 15 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3) 16 #include <soc/drv.h> 17 #include <soc/scache.h> 18 #include <soc/util.h> 19 #include <soc/hash.h> 20 #include <soc/debug.h> 21 #include <bcm/types.h> 22 #include <bcm/error.h> 23 24 #include <bcm/types.h> 25 #include <bcm/l3.h> 26 #if defined(BCM_TRIUMPH3_SUPPORT) 27 #include <soc/ism_hash.h> 28 #endif /* BCM_TRIUMPH3_SUPPORT */ 29 #if defined(BCM_TRIDENT2_SUPPORT) 30 #include <soc/trident2.h> 31 #endif /* BCM_TRIDENT2_SUPPORT */ 32 #include <bcm/multicast.h> 33 #include <bcm/trill.h> 34 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 35 #include <bcm/trunk.h> 36 #endif 37 38 #include <bcm_int/esw/mbcm.h> 39 #include <bcm_int/api_xlate_port.h> 40 #include <bcm_int/esw_dispatch.h> 41 #include <bcm_int/esw/virtual.h> 42 #include <bcm_int/esw/firebolt.h> 43 #include <bcm_int/esw/trident.h> 44 #include <bcm_int/esw/triumph.h> 45 #include <bcm_int/esw/triumph2.h> 46 #include <bcm_int/esw/triumph3.h> 47 #include <bcm_int/esw/tomahawk.h> 48 #include <bcm_int/esw/trill.h> 49 #include <bcm_int/common/multicast.h> 50 #include <bcm_int/esw/multicast.h> 51 #include <bcm_int/esw/trx.h> 52 53 #ifdef BCM_WARM_BOOT_SUPPORT 54 #include <bcm_int/esw/switch.h> 55 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 56 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_0 57 #endif /* BCM_WARM_BOOT_SUPPORT */ 58 59 _bcm_td_trill_bookkeeping_t *_bcm_td_trill_bk_info[BCM_MAX_NUM_UNITS] = { 0 }; 60 61 #define TRILL_INFO(_unit_) (_bcm_td_trill_bk_info[_unit_]) 62 #define L3_INFO(_unit_) (&_bcm_l3_bk_info[_unit_]) 63 64 #define BCM_TRILL_CHECK_ERROR_RETURN(_op, _u_, _vp) do { \ 65 int _rv = _op; \ 66 if (_rv < 0) { \ 67 (void) _bcm_vp_free(_u_, _bcmVpTypeTrill, 1, _vp); \ 68 return (_rv); \ 69 } \ 70 } while (0) 71 72 73 #define BCM_TRILL_L2MC_CHECK( _u_ , index) \ 74 if ((index < 0) ||\ 75 (index >= soc_mem_index_count(_u_, L2MCm))) { \ 76 return BCM_E_PARAM; \ 77 } \ 78 79 #define BCM_TRILL_L3MC_CHECK( _u_ , index) \ 80 if ((index < 0) ||\ 81 (index >= soc_mem_index_count(_u_, L3_IPMCm))) { \ 82 return BCM_E_PARAM; \ 83 } \ 84 85 typedef uint32 L3_ENTRY_T[SOC_MAX_MEM_FIELD_WORDS]; 86 87 STATIC int _bcm_td_trill_adjacency_set(int unit, int nh_index); 88 STATIC int _bcm_td_trill_adjacency_reset(int unit, int nh_index); 89 90 /* 91 * Function: 92 * _bcm_trill_check_init 93 * Purpose: 94 * Check if Trill is initialized 95 * Parameters: 96 * unit - Device Number 97 * Returns: 98 * BCM_E_XXX 99 */ 100 101 102 STATIC int 103 _bcm_trill_check_init (int unit) 104 { 105 _bcm_td_trill_bookkeeping_t *trill_info; 106 107 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 108 return BCM_E_UNIT; 109 } 110 111 trill_info = TRILL_INFO(unit); 112 113 if ((trill_info == NULL) || (trill_info->initialized == FALSE)) { 114 return BCM_E_INIT; 115 } else { 116 return BCM_E_NONE; 117 } 118 } 119 120 121 122 /* 123 * Function: 124 * bcm_trill_lock 125 * Purpose: 126 * Take the Trill Lock Sempahore 127 * Parameters: 128 * unit - Device Number 129 * Returns: 130 * BCM_E_XXX 131 */ 132 133 134 int 135 bcm_td_trill_lock (int unit) 136 { 137 int rv = BCM_E_NONE; 138 139 rv = _bcm_trill_check_init (unit); 140 141 if ( rv == BCM_E_NONE ) { 142 sal_mutex_take(TRILL_INFO((unit))->trill_mutex, sal_mutex_FOREVER); 143 } 144 return rv; 145 } 146 147 148 149 /* 150 * Function: 151 * bcm_trill_unlock 152 * Purpose: 153 * Release the Trill Lock Semaphore 154 * Parameters: 155 * unit - Device Number 156 * Returns: 157 * BCM_E_XXX 158 */ 159 160 161 void 162 bcm_td_trill_unlock(int unit) 163 { 164 int rv = BCM_E_NONE; 165 166 rv = _bcm_trill_check_init (unit); 167 if ( rv == BCM_E_NONE ) { 168 sal_mutex_give(TRILL_INFO((unit))->trill_mutex); 169 } 170 } 171 172 173 174 /* 175 * Function: 176 * _bcm_td_trill_free_resource 177 * Purpose: 178 * Free all allocated software resources 179 * Parameters: 180 * unit - SOC unit number 181 * Returns: 182 * Nothing 183 */ 184 185 186 STATIC void 187 _bcm_td_trill_free_resource(int unit) 188 { 189 _bcm_td_trill_bookkeeping_t *trill_info; 190 191 trill_info = TRILL_INFO(unit); 192 193 /* If software tables were not allocated we are done. */ 194 if (NULL == TRILL_INFO(unit)) { 195 return; 196 } 197 198 if (trill_info->rBridge) { 199 sal_free(trill_info->rBridge); 200 trill_info->rBridge = NULL; 201 } 202 203 if (trill_info->multicast_count) { 204 sal_free(trill_info->multicast_count); 205 trill_info->multicast_count = NULL; 206 } 207 208 /* Free module data. */ 209 sal_free(TRILL_INFO(unit)); 210 TRILL_INFO(unit) = NULL; 211 } 212 213 /* 214 * Function: 215 * bcm_td_trill_tpid_add 216 * Purpose: 217 * Add Tpid for TRILL 218 * Parameters: 219 * unit - SOC unit number. 220 * port - Trill gport 221 * tpid - Tag protocol ID 222 * Returns: 223 * BCM_E_XXX. 224 */ 225 int 226 bcm_td_trill_tpid_add(int unit, bcm_gport_t port, int tpid_idx) 227 { 228 int rv = BCM_E_NONE; 229 uint32 ena_f; 230 ing_trill_payload_parse_control_entry_t tpid_ent; 231 232 sal_memset(&tpid_ent, 0, sizeof(ing_trill_payload_parse_control_entry_t)); 233 234 BCM_IF_ERROR_RETURN( 235 soc_mem_read(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 236 MEM_BLOCK_ALL, 0, &tpid_ent)); 237 ena_f = soc_ING_TRILL_PAYLOAD_PARSE_CONTROLm_field32_get 238 (unit, &tpid_ent, TPID_ENABLEf); 239 240 if (!(ena_f & (1 << tpid_idx))) { 241 ena_f |= 1 << tpid_idx; 242 soc_ING_TRILL_PAYLOAD_PARSE_CONTROLm_field32_set 243 (unit, &tpid_ent, TPID_ENABLEf, ena_f); 244 BCM_IF_ERROR_RETURN( 245 soc_mem_write(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 246 MEM_BLOCK_ALL, 0, &tpid_ent)); 247 } 248 return rv; 249 } 250 251 252 /* 253 * Function: 254 * bcm_td_trill_tpid_set 255 * Purpose: 256 * Set Tpid for TRILL 257 * Parameters: 258 * unit - SOC unit number. 259 * port - Trill gport 260 * tpid - Tag protocol ID 261 * Returns: 262 * BCM_E_XXX. 263 */ 264 int 265 bcm_td_trill_tpid_set(int unit, bcm_gport_t port, int tpid_idx) 266 { 267 int rv = BCM_E_NONE; 268 uint32 ena_f; 269 ing_trill_payload_parse_control_entry_t tpid_ent; 270 271 sal_memset(&tpid_ent, 0, sizeof(ing_trill_payload_parse_control_entry_t)); 272 273 BCM_IF_ERROR_RETURN( 274 soc_mem_read(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 275 MEM_BLOCK_ALL, 0, &tpid_ent)); 276 ena_f = soc_ING_TRILL_PAYLOAD_PARSE_CONTROLm_field32_get 277 (unit, &tpid_ent, TPID_ENABLEf); 278 279 if (!(ena_f & (1 << tpid_idx))) { 280 ena_f = 1 << tpid_idx; 281 soc_ING_TRILL_PAYLOAD_PARSE_CONTROLm_field32_set 282 (unit, &tpid_ent, TPID_ENABLEf, ena_f); 283 BCM_IF_ERROR_RETURN( 284 soc_mem_write(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 285 MEM_BLOCK_ALL, 0, &tpid_ent)); 286 } 287 return rv; 288 } 289 290 /* 291 * Function: 292 * bcm_td_trill_tpid_get 293 * Purpose: 294 * Get TRILL TPID 295 * Parameters: 296 * unit - SOC unit number 297 * port - Trill gport 298 * tpid - Tag protocol ID 299 * Returns: 300 * BCM_E_XXX. 301 */ 302 int 303 bcm_td_trill_tpid_get(int unit, bcm_gport_t port, int *tpid_index) 304 { 305 int rv = BCM_E_NONE; 306 ing_trill_payload_parse_control_entry_t tpid_ent; 307 308 sal_memset(&tpid_ent, 0, sizeof(ing_trill_payload_parse_control_entry_t)); 309 BCM_IF_ERROR_RETURN( 310 soc_mem_read(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 311 MEM_BLOCK_ALL, 0, &tpid_ent)); 312 313 *tpid_index = soc_ING_TRILL_PAYLOAD_PARSE_CONTROLm_field32_get 314 (unit, &tpid_ent, TPID_ENABLEf); 315 return rv; 316 } 317 318 /* 319 * Function: 320 * bcm_td_trill_tpid_delete 321 * Purpose: 322 * Delete Tpid for TRILL 323 * Parameters: 324 * unit - SOC unit number. 325 * port - Trill gport 326 * tpid - Tag protocol ID 327 * Returns: 328 * BCM_E_XXX. 329 */ 330 int 331 bcm_td_trill_tpid_delete(int unit, bcm_gport_t port, int tpid_idx) 332 { 333 int rv = BCM_E_NONE; 334 uint32 ena_f; 335 ing_trill_payload_parse_control_entry_t tpid_ent; 336 337 sal_memset(&tpid_ent, 0, sizeof(ing_trill_payload_parse_control_entry_t)); 338 339 BCM_IF_ERROR_RETURN( 340 soc_mem_read(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 341 MEM_BLOCK_ALL, 0, &tpid_ent)); 342 ena_f = soc_ING_TRILL_PAYLOAD_PARSE_CONTROLm_field32_get 343 (unit, &tpid_ent, TPID_ENABLEf); 344 345 if (ena_f & (1 << tpid_idx)) { 346 ena_f &= ~(1 << tpid_idx); 347 soc_ING_TRILL_PAYLOAD_PARSE_CONTROLm_field32_set 348 (unit, &tpid_ent, TPID_ENABLEf, ena_f); 349 BCM_IF_ERROR_RETURN( 350 soc_mem_write(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 351 MEM_BLOCK_ALL, 0, &tpid_ent)); 352 } 353 return rv; 354 } 355 356 /* 357 * Function: 358 * bcm_td_trill_ethertype_set 359 * Purpose: 360 * Enable TRILL functionality 361 * Parameters: 362 * unit - SOC unit number. 363 * etherType - Non-zero value: enable TRILL support 364 * Zero vlaue: Disable TRILL support 365 * Returns: 366 * BCM_E_XXX. 367 */ 368 int 369 bcm_td_trill_ethertype_set(int unit, uint16 etherType) 370 { 371 int rv = BCM_E_NONE; 372 ing_trill_parse_control_entry_t ing_ent; 373 egr_trill_parse_control_entry_t egr_ent; 374 ing_trill_payload_parse_control_entry_t tpid_ent; 375 376 sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t)); 377 sal_memset(&egr_ent, 0, sizeof(egr_trill_parse_control_entry_t)); 378 sal_memset(&tpid_ent, 0, sizeof(ing_trill_payload_parse_control_entry_t)); 379 380 if (etherType > 0) { 381 382 if (SOC_MEM_IS_VALID(unit, ING_TRILL_PARSE_CONTROLm)) { 383 soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent, 384 TRILL_ETHERTYPE_ENABLEf, 0x1); 385 soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent, 386 TRILL_ETHERTYPEf, etherType); 387 } 388 389 soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROLm, &egr_ent, 390 TRILL_ETHERTYPE_ENABLEf, 0x1); 391 soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROLm, &egr_ent, 392 TRILL_ETHERTYPEf, etherType); 393 if (SOC_MEM_IS_VALID(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm)) { 394 soc_mem_field32_set(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, &tpid_ent, 395 TPID_ENABLEf, 0x1); 396 } 397 } 398 399 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PARSE_CONTROLm, 400 MEM_BLOCK_ALL, 0, &ing_ent)); 401 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_PARSE_CONTROLm, 402 MEM_BLOCK_ALL, 0, &egr_ent)); 403 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 404 MEM_BLOCK_ALL, 0, &tpid_ent)); 405 return rv; 406 } 407 408 /* 409 * Function: 410 * bcm_td_trill_ethertype_get 411 * Purpose: 412 * Get TRILL EtherType 413 * Parameters: 414 * unit - SOC unit number. 415 * etherType - return value 416 * Returns: 417 * BCM_E_XXX. 418 */ 419 int 420 bcm_td_trill_ethertype_get(int unit, int *etherType) 421 { 422 int rv = BCM_E_NONE; 423 ing_trill_parse_control_entry_t ing_ent; 424 425 sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t)); 426 427 BCM_IF_ERROR_RETURN( 428 soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm, 429 MEM_BLOCK_ALL, 0, &ing_ent)); 430 431 *etherType = soc_mem_field32_get(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent, 432 TRILL_ETHERTYPEf); 433 return rv; 434 } 435 436 /* 437 * Function: 438 * bcm_td_trill_ISIS_ethertype_set 439 * Purpose: 440 * Set TRILL ISIS EtherType 441 * Parameters: 442 * unit - SOC unit number. 443 * etherType - Non-zero value: enable Ethertype 444 * Returns: 445 * BCM_E_XXX. 446 */ 447 int 448 bcm_td_trill_ISIS_ethertype_set(int unit, uint16 etherType) 449 { 450 int rv = BCM_E_NONE; 451 int en = 0; 452 ing_trill_parse_control_entry_t ing_ent; 453 egr_trill_parse_control_entry_t egr_ent; 454 egr_trill_parse_control_2_entry_t egr2_ent; 455 456 if (!soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 457 L2_IS_IS_ETHERTYPE_ENABLEf) || 458 !soc_mem_field_valid(unit, EGR_TRILL_PARSE_CONTROLm, 459 TRILL_L2_IS_IS_ETHERTYPE_ENABLEf) || 460 !soc_mem_field_valid(unit, EGR_TRILL_PARSE_CONTROL_2m, 461 TRILL_L2_IS_IS_ETHERTYPE_ENABLEf)) { 462 return BCM_E_UNAVAIL; 463 } 464 465 BCM_IF_ERROR_RETURN( 466 soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm, 467 MEM_BLOCK_ALL, 0, &ing_ent)); 468 BCM_IF_ERROR_RETURN( 469 soc_mem_read(unit, EGR_TRILL_PARSE_CONTROLm, 470 MEM_BLOCK_ALL, 0, &egr_ent)); 471 BCM_IF_ERROR_RETURN( 472 soc_mem_read(unit, EGR_TRILL_PARSE_CONTROL_2m, 473 MEM_BLOCK_ALL, 0, &egr2_ent)); 474 475 /* enable if ethertype > 0 */ 476 en = (etherType > 0) ? 1 : 0; 477 478 soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent, 479 L2_IS_IS_ETHERTYPE_ENABLEf, en); 480 soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent, 481 L2_IS_IS_ETHERTYPEf, etherType); 482 soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROLm, &egr_ent, 483 TRILL_L2_IS_IS_ETHERTYPE_ENABLEf, en); 484 soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROLm, &egr_ent, 485 TRILL_L2_IS_IS_ETHERTYPEf, etherType); 486 soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROL_2m, &egr2_ent, 487 TRILL_L2_IS_IS_ETHERTYPE_ENABLEf, en); 488 soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROL_2m, &egr2_ent, 489 TRILL_L2_IS_IS_ETHERTYPEf, etherType); 490 491 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PARSE_CONTROLm, 492 MEM_BLOCK_ALL, 0, &ing_ent)); 493 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_PARSE_CONTROLm, 494 MEM_BLOCK_ALL, 0, &egr_ent)); 495 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_PARSE_CONTROL_2m, 496 MEM_BLOCK_ALL, 0, &egr2_ent)); 497 498 return rv; 499 } 500 501 /* 502 * Function: 503 * bcm_td_trill_ISIS_ethertype_get 504 * Purpose: 505 * Get TRILL ISIS EtherType 506 * Parameters: 507 * unit - SOC unit number. 508 * etherType - return value 509 * Returns: 510 * BCM_E_XXX. 511 */ 512 int 513 bcm_td_trill_ISIS_ethertype_get(int unit, int *etherType) 514 { 515 int rv = BCM_E_NONE; 516 ing_trill_parse_control_entry_t ing_ent; 517 518 sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t)); 519 520 BCM_IF_ERROR_RETURN( 521 soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm, 522 MEM_BLOCK_ALL, 0, &ing_ent)); 523 524 if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 525 L2_IS_IS_ETHERTYPEf)) { 526 *etherType = soc_mem_field32_get(unit, ING_TRILL_PARSE_CONTROLm, 527 &ing_ent, L2_IS_IS_ETHERTYPEf); 528 } else { 529 *etherType = 0; 530 rv = BCM_E_UNAVAIL; /* BCM_E_UNAVAIL if the field is not supported */ 531 } 532 533 return rv; 534 } 535 536 537 /* 538 * Function: 539 * _bcm_td_trill_mac_set 540 * Description: 541 * flag = 0: Set the lower 24 bits of MAC address field for TRILL specific MAC 542 * flag = 1: Set the higher 24 bits of MAC address field for TRILL specific MAC 543 * Parameters: 544 * unit - unit number (driver internal). 545 * type - The required switch control type to set upper MAC for 546 * mac - MAC address 547 * Returns: 548 * BCM_E_xxxx 549 */ 550 551 STATIC void 552 _bcm_td_trill_mac_set(int unit, uint32 mac_field, soc_mem_t mem, 553 void *entry, soc_field_t field, sal_mac_addr_t mac, uint8 flag) 554 { 555 soc_mem_mac_addr_get(unit, mem, entry, 556 field, mac); 557 if (!flag) { 558 /* Set the low-order bytes */ 559 mac[3] = (uint8) (mac_field >> 16 & 0xff); 560 mac[4] = (uint8) (mac_field >> 8 & 0xff); 561 mac[5] = (uint8) (mac_field & 0xff); 562 } else { 563 /* Set the High-order bytes */ 564 mac[0] = (uint8) (mac_field >> 16 & 0xff); 565 mac[1] = (uint8) (mac_field >> 8 & 0xff); 566 mac[2] = (uint8) (mac_field & 0xff); 567 } 568 soc_mem_mac_addr_set(unit, mem, entry, 569 field, mac); 570 } 571 572 /* 573 * Function: 574 * bcm_td_trill_mac_set 575 * Description: 576 * flag = 0: Set the lower 24 bits of MAC address field for TRILL specific MAC 577 * flag = 1: Set the higher 24 bits of MAC address field for TRILL specific MAC 578 * Parameters: 579 * unit - unit number (driver internal). 580 * type - The required switch control type to set upper MAC for 581 * mac - MAC address 582 * Returns: 583 * BCM_E_xxxx 584 */ 585 586 int 587 bcm_td_trill_mac_set(int unit, 588 bcm_switch_control_t type, 589 uint32 mac_field, 590 uint8 flag) 591 { 592 ing_trill_parse_control_entry_t ing_ent; 593 egr_trill_parse_control_entry_t egr_ent; 594 egr_trill_parse_control_2_entry_t egr2_ent; 595 ing_trill_payload_parse_control_entry_t ing_payload_ent; 596 bcm_mac_t mac; 597 598 sal_memset(mac, 0, sizeof(bcm_mac_t)); 599 600 BCM_IF_ERROR_RETURN( 601 soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm, 602 MEM_BLOCK_ALL, 0, &ing_ent)); 603 BCM_IF_ERROR_RETURN( 604 soc_mem_read(unit, EGR_TRILL_PARSE_CONTROLm, 605 MEM_BLOCK_ALL, 0, &egr_ent)); 606 BCM_IF_ERROR_RETURN( 607 soc_mem_read(unit, EGR_TRILL_PARSE_CONTROL_2m, 608 MEM_BLOCK_ALL, 0, &egr2_ent)); 609 BCM_IF_ERROR_RETURN( 610 soc_mem_read(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 611 MEM_BLOCK_ALL, 0, &ing_payload_ent)); 612 613 switch (type) { 614 case bcmSwitchTrillISISDestMacOui: 615 case bcmSwitchTrillISISDestMacNonOui: 616 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm, 617 MEM_BLOCK_ALL, 0, &ing_ent)); 618 _bcm_td_trill_mac_set(unit, mac_field, ING_TRILL_PARSE_CONTROLm, 619 &ing_ent, TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESSf, mac, flag); 620 if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 621 TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf)) { 622 soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent, 623 TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf, 0x1); 624 } 625 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PARSE_CONTROLm, 626 MEM_BLOCK_ALL, 0, &ing_ent)); 627 628 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_TRILL_PARSE_CONTROLm, 629 MEM_BLOCK_ALL, 0, &egr_ent)); 630 sal_memset(mac, 0, sizeof(bcm_mac_t)); 631 _bcm_td_trill_mac_set(unit, mac_field, EGR_TRILL_PARSE_CONTROLm, 632 &egr_ent, TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESSf, mac, flag); 633 if (soc_mem_field_valid(unit, EGR_TRILL_PARSE_CONTROLm, 634 TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf)) { 635 soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROLm, &egr_ent, 636 TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf, 0x1); 637 } 638 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_PARSE_CONTROLm, 639 MEM_BLOCK_ALL, 0, &egr_ent)); 640 641 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_TRILL_PARSE_CONTROL_2m, 642 MEM_BLOCK_ALL, 0, &egr2_ent)); 643 sal_memset(mac, 0, sizeof(bcm_mac_t)); 644 _bcm_td_trill_mac_set(unit, mac_field, EGR_TRILL_PARSE_CONTROL_2m, 645 &egr2_ent, TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESSf, mac, flag); 646 if (soc_mem_field_valid(unit, EGR_TRILL_PARSE_CONTROL_2m, 647 TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf)) { 648 soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROL_2m, &egr2_ent, 649 TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf, 0x1); 650 } 651 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_PARSE_CONTROL_2m, 652 MEM_BLOCK_ALL, 0, &egr2_ent)); 653 break; 654 655 case bcmSwitchTrillBroadcastDestMacOui: 656 case bcmSwitchTrillBroadcastDestMacNonOui: 657 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm, 658 MEM_BLOCK_ALL, 0, &ing_ent)); 659 _bcm_td_trill_mac_set(unit, mac_field, ING_TRILL_PARSE_CONTROLm, 660 &ing_ent, TRILL_ALL_RBRIDGES_MAC_ADDRESSf, mac, flag); 661 if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 662 TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf)) { 663 soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent, 664 TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf, 0x1); 665 } 666 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PARSE_CONTROLm, 667 MEM_BLOCK_ALL, 0, &ing_ent)); 668 669 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_TRILL_PARSE_CONTROLm, 670 MEM_BLOCK_ALL, 0, &egr_ent)); 671 sal_memset(mac, 0, sizeof(bcm_mac_t)); 672 _bcm_td_trill_mac_set(unit, mac_field, EGR_TRILL_PARSE_CONTROLm, 673 &egr_ent, TRILL_ALL_RBRIDGES_MAC_ADDRESSf, mac, flag); 674 if (soc_mem_field_valid(unit, EGR_TRILL_PARSE_CONTROLm, 675 TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf)) { 676 soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROLm, &egr_ent, 677 TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf, 0x1); 678 } 679 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_PARSE_CONTROLm, 680 MEM_BLOCK_ALL, 0, &egr_ent)); 681 #ifdef BCM_TOMAHAWK_SUPPORT 682 if (SOC_IS_TOMAHAWKX(unit)) { 683 BCM_IF_ERROR_RETURN(bcm_th_ipmc_trill_mac_update(unit, 684 mac_field, flag)); 685 } else 686 #endif /* BCM_TOMAHAWK_SUPPORT */ 687 #ifdef BCM_TRIUMPH3_SUPPORT 688 if (SOC_IS_TRIUMPH3(unit)) { 689 BCM_IF_ERROR_RETURN(bcm_tr3_ipmc_trill_mac_update(unit, 690 mac_field, flag)); 691 } 692 #endif /* BCM_TRIUMPH3_SUPPORT */ 693 break; 694 695 case bcmSwitchTrillEndStationDestMacOui: 696 case bcmSwitchTrillEndStationDestMacNonOui: 697 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 698 MEM_BLOCK_ALL, 0, &ing_payload_ent)); 699 _bcm_td_trill_mac_set(unit, mac_field, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 700 &ing_payload_ent, TRILL_ALL_ESADI_RBRIDGES_MAC_ADDRESSf, mac, flag); 701 if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 702 TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf)) { 703 soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent, 704 TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf, 0x1); 705 } 706 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 707 MEM_BLOCK_ALL, 0, &ing_payload_ent)); 708 break; 709 710 default: 711 return BCM_E_PARAM; 712 } 713 return BCM_E_NONE; 714 } 715 716 /* 717 * Function: 718 * _bcm_td_trill_mac_get 719 * Description: 720 * flag = 0: Get the lower 24 bits of MAC address field for TRILL specific MAC 721 * flag = 1: Get the higher 24 bits of MAC address field for TRILL specific MAC 722 * Parameters: 723 * unit - unit number (driver internal). 724 * type - The required switch control type to set upper MAC for 725 * mac - MAC address 726 * Returns: 727 * BCM_E_xxxx 728 */ 729 730 STATIC void 731 _bcm_td_trill_mac_get(int unit, soc_mem_t mem, 732 void *entry, soc_field_t field, uint32 *mac_field, uint8 flag) 733 { 734 bcm_mac_t mac; 735 736 soc_mem_mac_addr_get(unit, mem, entry, 737 field, mac); 738 739 if (flag) { 740 /* read the high-order bytes from Memory */ 741 *mac_field = ((mac[0] << 16) | (mac[1] << 8) | (mac[2] << 0)); 742 } else { 743 /* read the low-order bytes from Memory */ 744 *mac_field = ((mac[3] << 16) | (mac[4] << 8) | (mac[5] << 0)); 745 } 746 } 747 748 749 /* 750 * Function: 751 * bcm_td_trill_mac_get 752 * Description: 753 * flag = 0: Get the lower 24 bits of MAC address field for TRILL specific MAC 754 * flag = 1: Get the higher 24 bits of MAC address field for TRILL specific MAC 755 * Parameters: 756 * unit - unit number (driver internal). 757 * type - The required switch control type to set upper MAC for 758 * mac - MAC address 759 * Returns: 760 * BCM_E_xxxx 761 */ 762 763 int 764 bcm_td_trill_mac_get(int unit, 765 bcm_switch_control_t type, 766 uint32 *mac_field, 767 uint8 flag) 768 { 769 ing_trill_parse_control_entry_t ing_ent; 770 egr_trill_parse_control_entry_t egr_ent; 771 egr_trill_parse_control_2_entry_t egr2_ent; 772 ing_trill_payload_parse_control_entry_t ing_payload_ent; 773 774 sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t)); 775 sal_memset(&egr_ent, 0, sizeof(egr_trill_parse_control_entry_t)); 776 sal_memset(&egr2_ent, 0, sizeof(egr_trill_parse_control_2_entry_t)); 777 sal_memset(&ing_payload_ent, 0, sizeof(ing_trill_payload_parse_control_entry_t)); 778 779 switch (type) { 780 case bcmSwitchTrillISISDestMacOui: 781 case bcmSwitchTrillISISDestMacNonOui: 782 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm, 783 MEM_BLOCK_ALL, 0, &ing_ent)); 784 _bcm_td_trill_mac_get(unit, ING_TRILL_PARSE_CONTROLm, 785 &ing_ent, TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESSf, mac_field, flag); 786 787 break; 788 789 case bcmSwitchTrillBroadcastDestMacOui: 790 case bcmSwitchTrillBroadcastDestMacNonOui: 791 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm, 792 MEM_BLOCK_ALL, 0, &ing_ent)); 793 _bcm_td_trill_mac_get(unit, ING_TRILL_PARSE_CONTROLm, 794 &ing_ent, TRILL_ALL_RBRIDGES_MAC_ADDRESSf, mac_field, flag); 795 796 break; 797 798 case bcmSwitchTrillEndStationDestMacOui: 799 case bcmSwitchTrillEndStationDestMacNonOui: 800 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 801 MEM_BLOCK_ALL, 0, &ing_payload_ent)); 802 _bcm_td_trill_mac_get(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 803 &ing_payload_ent, TRILL_ALL_ESADI_RBRIDGES_MAC_ADDRESSf, mac_field, flag); 804 break; 805 806 default: 807 return BCM_E_PARAM; 808 } 809 return BCM_E_NONE; 810 } 811 812 /* 813 * Function: 814 * bcm_td_trill_MinTtl_set 815 * Description: 816 * Set minimum TTL value for Transit and Egress Rbridge 817 * Parameters: 818 * unit - unit number (driver internal). 819 * min_ttl - Minimum TTL value 820 * Returns: 821 * BCM_E_xxxx 822 */ 823 824 int 825 bcm_td_trill_MinTtl_set(int unit, int min_ttl) 826 { 827 int rv = BCM_E_NONE; 828 ing_trill_parse_control_entry_t ing_ent; 829 830 if (!soc_feature(unit, soc_feature_trill_ttl)) { 831 return BCM_E_UNAVAIL; 832 } 833 834 sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t)); 835 836 if (SOC_MEM_IS_VALID(unit, ING_TRILL_PARSE_CONTROLm)) { 837 if ((min_ttl > 0) && (min_ttl < 64)) { 838 BCM_IF_ERROR_RETURN( 839 soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm, 840 MEM_BLOCK_ALL, 0, &ing_ent)); 841 842 if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 843 MIN_INCOMING_HOPCOUNTf)) { 844 soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent, 845 MIN_INCOMING_HOPCOUNTf, min_ttl); 846 } 847 848 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PARSE_CONTROLm, 849 MEM_BLOCK_ALL, 0, &ing_ent)); 850 } 851 } 852 return rv; 853 } 854 855 /* 856 * Function: 857 * bcm_td_trill_MinTtl_get 858 * Description: 859 * Get minimum TTL value for Transit and Egress Rbridge 860 * Parameters: 861 * unit - unit number (driver internal). 862 * min_ttl - Minimum TTL value 863 * Returns: 864 * BCM_E_xxxx 865 */ 866 867 int 868 bcm_td_trill_MinTtl_get(int unit, int *min_ttl) 869 { 870 int rv = BCM_E_NONE; 871 ing_trill_parse_control_entry_t ing_ent; 872 873 if (!soc_feature(unit, soc_feature_trill_ttl)) { 874 return BCM_E_UNAVAIL; 875 } 876 877 sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t)); 878 879 if (SOC_MEM_IS_VALID(unit, ING_TRILL_PARSE_CONTROLm)) { 880 BCM_IF_ERROR_RETURN( 881 soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm, 882 MEM_BLOCK_ALL, 0, &ing_ent)); 883 884 if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 885 MIN_INCOMING_HOPCOUNTf)) { 886 *min_ttl = soc_mem_field32_get(unit, ING_TRILL_PARSE_CONTROLm, 887 &ing_ent, 888 MIN_INCOMING_HOPCOUNTf); 889 } 890 } 891 return rv; 892 } 893 894 /* 895 * Function: 896 * bcm_td_trill_TtlCheckEnable_set 897 * Description: 898 * Set enable for Egress RBridge TTL Check 899 * Parameters: 900 * unit - unit number (driver internal). 901 * enable - TTL Check Enable 902 * Returns: 903 * BCM_E_xxxx 904 */ 905 int 906 bcm_td_trill_TtlCheckEnable_set(int unit, int enable) 907 { 908 int rv = BCM_E_NONE; 909 ing_trill_parse_control_entry_t ing_ent; 910 911 if (!soc_feature(unit, soc_feature_trill_ttl)) { 912 return BCM_E_UNAVAIL; 913 } 914 915 sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t)); 916 917 if (SOC_MEM_IS_VALID(unit, ING_TRILL_PARSE_CONTROLm)) { 918 if ((enable == TRUE) || (enable == FALSE)) { 919 BCM_IF_ERROR_RETURN( 920 soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm, 921 MEM_BLOCK_ALL, 0, &ing_ent)); 922 923 if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 924 EGRESS_RBRIDGE_CHECK_HOPCOUNTf)) { 925 soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent, 926 EGRESS_RBRIDGE_CHECK_HOPCOUNTf, enable); 927 } 928 929 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PARSE_CONTROLm, 930 MEM_BLOCK_ALL, 0, &ing_ent)); 931 } 932 } 933 return rv; 934 935 } 936 937 /* 938 * Function: 939 * bcm_td_trill_TtlCheckEnable_get 940 * Description: 941 * Get enable for Egress RBridge TTL Check 942 * Parameters: 943 * unit - unit number (driver internal). 944 * enable - TTL Check Enable 945 * Returns: 946 * BCM_E_xxxx 947 */ 948 int 949 bcm_td_trill_TtlCheckEnable_get(int unit, int *enable) 950 { 951 int rv = BCM_E_NONE; 952 ing_trill_parse_control_entry_t ing_ent; 953 954 if (!soc_feature(unit, soc_feature_trill_ttl)) { 955 return BCM_E_UNAVAIL; 956 } 957 958 sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t)); 959 960 if (SOC_MEM_IS_VALID(unit, ING_TRILL_PARSE_CONTROLm)) { 961 BCM_IF_ERROR_RETURN( 962 soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm, 963 MEM_BLOCK_ALL, 0, &ing_ent)); 964 965 if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 966 EGRESS_RBRIDGE_CHECK_HOPCOUNTf)) { 967 *enable = soc_mem_field32_get(unit, ING_TRILL_PARSE_CONTROLm, 968 &ing_ent, 969 EGRESS_RBRIDGE_CHECK_HOPCOUNTf); 970 } 971 } 972 return rv; 973 } 974 975 /* 976 * Function: 977 * bcm_td_trill_allocate_bk 978 * Purpose: 979 * Initialize the Trill software module 980 * Parameters: 981 * unit - Device Number 982 * Returns: 983 * BCM_E_XXX 984 */ 985 986 STATIC int 987 bcm_td_trill_allocate_bk(int unit) 988 { 989 /* Allocate/Init unit software tables. */ 990 if (NULL == TRILL_INFO(unit)) { 991 BCM_TD_TRILL_ALLOC(TRILL_INFO(unit), sizeof(_bcm_td_trill_bookkeeping_t), 992 "trill_bk_module_data"); 993 if (NULL == TRILL_INFO(unit)) { 994 return (BCM_E_MEMORY); 995 } else { 996 TRILL_INFO(unit)->initialized = FALSE; 997 } 998 } 999 return BCM_E_NONE; 1000 } 1001 1002 #ifdef BCM_WARM_BOOT_SUPPORT 1003 /* 1004 * Function: 1005 * bcm_td_trill_sync 1006 * Purpose: 1007 * Store the multicast count Trill book keeping structure 1008 * onto persistent memory. 1009 * Parameters: 1010 * unit : (IN) Device Unit Number 1011 * Returns: 1012 * BCM_E_XXX 1013 */ 1014 int 1015 bcm_td_trill_sync(int unit) 1016 { 1017 int rv=BCM_E_NONE, alloc_sz = 0, num_ipmc=0; 1018 uint8 *trill_state; 1019 soc_scache_handle_t scache_handle; 1020 _bcm_td_trill_bookkeeping_t *trill_info; 1021 1022 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 1023 return BCM_E_NONE; 1024 } 1025 trill_info = TRILL_INFO(unit); 1026 num_ipmc = soc_mem_index_count(unit, L3_IPMCm); 1027 1028 alloc_sz = sizeof(_bcm_td_trill_multicast_count_t) * num_ipmc; 1029 1030 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TRILL, 0); 1031 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 1032 alloc_sz, &trill_state, 1033 BCM_WB_DEFAULT_VERSION, NULL); 1034 if (BCM_FAILURE(rv) && (rv != BCM_E_INTERNAL)) { 1035 return rv; 1036 } 1037 1038 sal_memcpy(trill_state, trill_info->multicast_count, alloc_sz); 1039 1040 return rv; 1041 } 1042 1043 /* 1044 * Function: 1045 * _bcm_td_trill_reinit 1046 * Purpose: 1047 * Perform recovery of Trill s/w state during warmboot. 1048 * Parameters: 1049 * unit - Device Number 1050 * Returns: 1051 * BCM_E_XXX 1052 */ 1053 STATIC int 1054 _bcm_td_trill_reinit(int unit) 1055 { 1056 uint8 *trill_state; 1057 int alloc_sz=0, stable_size = 0, num_ipmc=0; 1058 int idx=0, idx_min=0, idx_max=0; 1059 soc_scache_handle_t scache_handle; 1060 _bcm_td_trill_bookkeeping_t *trill_info; 1061 egr_dvp_attribute_entry_t egr_dvp_attribute; 1062 egr_trill_tree_profile_entry_t egr_trill_profile; 1063 1064 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 1065 1066 if ((stable_size != 0) && (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 1067 1068 trill_info = TRILL_INFO(unit); 1069 1070 /* Recover rBridge book keeping info */ 1071 idx_min = soc_mem_index_min(unit, EGR_DVP_ATTRIBUTEm); 1072 idx_max = soc_mem_index_max(unit, EGR_DVP_ATTRIBUTEm); 1073 1074 for (idx = idx_min; idx <= idx_max; idx++) { 1075 SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_DVP_ATTRIBUTEm, 1076 MEM_BLOCK_ANY, idx, &egr_dvp_attribute)); 1077 if (soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, 1078 &egr_dvp_attribute, VP_TYPEf) != 0x1) { 1079 continue; 1080 } 1081 trill_info->rBridge[idx] = soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, 1082 &egr_dvp_attribute, EGRESS_RBRIDGE_NICKNAMEf); 1083 } 1084 1085 /* Recover rootBridge book keeping info */ 1086 idx_min = soc_mem_index_min(unit, EGR_TRILL_TREE_PROFILEm); 1087 idx_max = soc_mem_index_max(unit, EGR_TRILL_TREE_PROFILEm); 1088 1089 for (idx = idx_min; idx <= idx_max; idx++) { 1090 SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_TRILL_TREE_PROFILEm, 1091 MEM_BLOCK_ANY, idx, &egr_trill_profile)); 1092 /* coverity[overrun-local : FALSE] */ 1093 trill_info->rootBridge[idx] = 1094 soc_EGR_TRILL_TREE_PROFILEm_field32_get(unit, 1095 &egr_trill_profile, ROOT_RBRIDGE_NICKNAMEf); 1096 } 1097 1098 /* Recover multicast ref count book keeping info */ 1099 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TRILL, 0); 1100 num_ipmc = soc_mem_index_count(unit, L3_IPMCm); 1101 1102 alloc_sz = sizeof(_bcm_td_trill_multicast_count_t) * num_ipmc; 1103 SOC_IF_ERROR_RETURN 1104 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 1105 alloc_sz, &trill_state, 1106 BCM_WB_DEFAULT_VERSION, NULL)); 1107 1108 sal_memcpy(trill_info->multicast_count, trill_state, alloc_sz); 1109 } 1110 1111 return BCM_E_NONE; 1112 } 1113 #endif /* BCM_WARM_BOOT_SUPPORT */ 1114 1115 /* 1116 * Function: 1117 * bcm_td_trill_init 1118 * Purpose: 1119 * Initialize the Trill software module 1120 * Parameters: 1121 * unit - Device Number 1122 * Returns: 1123 * BCM_E_XXX 1124 */ 1125 1126 1127 int 1128 bcm_td_trill_init(int unit) 1129 { 1130 _bcm_td_trill_bookkeeping_t *trill_info; 1131 int idx=0, num_vp=0, num_ipmc=0; 1132 #ifdef BCM_WARM_BOOT_SUPPORT 1133 uint8 *trill_state = 0; 1134 soc_scache_handle_t scache_handle; 1135 int rv = BCM_E_NONE, alloc_sz = 0; 1136 #endif /* BCM_WARM_BOOT_SUPPORT */ 1137 1138 if (!L3_INFO(unit)->l3_initialized) { 1139 LOG_ERROR(BSL_LS_BCM_TRILL, 1140 (BSL_META_U(unit, 1141 "L3 module must be initialized prior to TRILL_init\n"))); 1142 return BCM_E_CONFIG; 1143 } 1144 1145 /* Allocate BK Info */ 1146 BCM_IF_ERROR_RETURN(bcm_td_trill_allocate_bk(unit)); 1147 trill_info = TRILL_INFO(unit); 1148 1149 /* 1150 * allocate resources 1151 */ 1152 if (trill_info->initialized) { 1153 BCM_IF_ERROR_RETURN(bcm_td_trill_cleanup(unit)); 1154 BCM_IF_ERROR_RETURN(bcm_td_trill_allocate_bk(unit)); 1155 trill_info = TRILL_INFO(unit); 1156 } 1157 1158 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 1159 num_ipmc = soc_mem_index_count(unit, L3_IPMCm); 1160 1161 trill_info->rBridge = 1162 sal_alloc(sizeof(bcm_trill_name_t) * num_vp, "trill rBridge store"); 1163 if (trill_info->rBridge == NULL) { 1164 _bcm_td_trill_free_resource(unit); 1165 return BCM_E_MEMORY; 1166 } 1167 1168 trill_info->multicast_count = 1169 sal_alloc(sizeof(_bcm_td_trill_multicast_count_t) * num_ipmc, "trill multicast store"); 1170 if (trill_info->multicast_count == NULL) { 1171 _bcm_td_trill_free_resource(unit); 1172 return BCM_E_MEMORY; 1173 } 1174 1175 1176 /* Create Trill protection mutex. */ 1177 trill_info->trill_mutex = sal_mutex_create("trill_mutex"); 1178 if (!trill_info->trill_mutex) { 1179 _bcm_td_trill_free_resource(unit); 1180 return BCM_E_MEMORY; 1181 } 1182 1183 for (idx=0; idx < BCM_MAX_NUM_TRILL_TREES; idx++) { 1184 trill_info->rootBridge[idx] = 0; 1185 } 1186 1187 sal_memset(trill_info->rBridge, 0, sizeof(bcm_trill_name_t) * num_vp); 1188 sal_memset(trill_info->multicast_count, 0, sizeof(_bcm_td_trill_multicast_count_t) * num_ipmc); 1189 1190 #ifdef BCM_WARM_BOOT_SUPPORT 1191 if (SOC_WARM_BOOT(unit)) { 1192 if (BCM_FAILURE(_bcm_td_trill_reinit(unit))) { 1193 _bcm_td_trill_free_resource(unit); 1194 } 1195 } else { /* Coldboot */ 1196 alloc_sz = sizeof(_bcm_td_trill_multicast_count_t) * num_ipmc; 1197 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TRILL, 0); 1198 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 1199 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 1200 alloc_sz, &trill_state, 1201 BCM_WB_DEFAULT_VERSION, NULL); 1202 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1203 return rv; 1204 } 1205 } 1206 } 1207 #endif /* BCM_WARM_BOOT_SUPPORT */ 1208 1209 /* Mark the state as initialized */ 1210 trill_info->initialized = TRUE; 1211 1212 return BCM_E_NONE; 1213 } 1214 1215 /* 1216 * Function: 1217 * _bcm_td_trill_hw_clear 1218 * Purpose: 1219 * Perform hw tables clean up for Trill module. 1220 * Parameters: 1221 * unit - Device Number 1222 * Returns: 1223 * BCM_E_XXX 1224 */ 1225 1226 STATIC int 1227 _bcm_td_trill_hw_clear(int unit) 1228 { 1229 int rv = BCM_E_NONE, rv_error = BCM_E_NONE; 1230 bcm_port_t port; 1231 bcm_trill_stat_t stat; 1232 1233 if (!SOC_HW_RESET(unit)) { 1234 PBMP_E_ITER(unit, port) { 1235 if (SOC_IS_STACK_PORT(unit, port)) { 1236 continue; 1237 } 1238 for (stat=bcmTrillInPkts; stat < bcmTrillErrorPkts; stat++) { 1239 rv = bcm_td_trill_stat_clear(unit, port, stat); 1240 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) { 1241 rv_error = rv; 1242 } 1243 } 1244 } 1245 1246 PBMP_HG_ITER(unit, port) { 1247 if (SOC_IS_STACK_PORT(unit, port)) { 1248 continue; 1249 } 1250 for (stat=bcmTrillInPkts; stat < bcmTrillErrorPkts; stat++) { 1251 rv = bcm_td_trill_stat_clear(unit, port, stat); 1252 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) { 1253 rv_error = rv; 1254 } 1255 } 1256 } 1257 } 1258 1259 rv = bcm_td_trill_port_delete_all(unit); 1260 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) { 1261 rv_error = rv; 1262 } 1263 if (!SOC_HW_RESET(unit)) { 1264 rv = bcm_td_trill_multicast_source_delete_all(unit); 1265 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) { 1266 rv_error = rv; 1267 } 1268 } 1269 1270 return rv_error; 1271 } 1272 1273 /* 1274 * Function: 1275 * bcm_td_trill_cleanup 1276 * Purpose: 1277 * DeInit the Trill software module 1278 * Parameters: 1279 * unit - Device Number 1280 * Returns: 1281 * BCM_E_XXX 1282 */ 1283 1284 int 1285 bcm_td_trill_cleanup(int unit) 1286 { 1287 _bcm_td_trill_bookkeeping_t *trill_info; 1288 int rv = BCM_E_UNAVAIL; 1289 1290 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 1291 return BCM_E_UNIT; 1292 } 1293 1294 trill_info = TRILL_INFO(unit); 1295 1296 if (FALSE == trill_info->initialized) { 1297 return (BCM_E_NONE); 1298 } 1299 1300 rv = bcm_td_trill_lock (unit); 1301 if (BCM_FAILURE(rv)) { 1302 return rv; 1303 } 1304 1305 if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 1306 rv = _bcm_td_trill_hw_clear(unit); 1307 } 1308 1309 /* Mark the state as uninitialized */ 1310 trill_info->initialized = FALSE; 1311 1312 sal_mutex_give(trill_info->trill_mutex); 1313 1314 /* Destroy protection mutex. */ 1315 sal_mutex_destroy(trill_info->trill_mutex ); 1316 1317 /* Free software resources */ 1318 (void) _bcm_td_trill_free_resource(unit); 1319 1320 return rv; 1321 } 1322 1323 /* 1324 * Function: 1325 * _bcm_td_trill_tree_profile_set 1326 * Purpose: 1327 * Set TRILL Tree Profile 1328 * Parameters: 1329 * IN : Unit 1330 * IN : trill_name 1331 * IN : hopcount 1332 * OUT: trill_tree_profile_idx 1333 * Returns: 1334 * BCM_E_XXX 1335 */ 1336 1337 int 1338 _bcm_td_trill_tree_profile_set (int unit, bcm_trill_name_t trill_name, int hopcount, uint8 *trill_tree_profile_idx) 1339 { 1340 _bcm_td_trill_bookkeeping_t *trill_info; 1341 egr_trill_tree_profile_entry_t egr_trill_profile; 1342 int rv=BCM_E_UNAVAIL; 1343 uint8 idx=0; 1344 1345 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 1346 return BCM_E_UNIT; 1347 } 1348 1349 if ((hopcount < 0) || (hopcount > 63)) { 1350 return BCM_E_PARAM; 1351 } 1352 1353 trill_info = TRILL_INFO(unit); 1354 1355 /* Check if root already exists */ 1356 for (idx = 0; idx < BCM_MAX_NUM_TRILL_TREES; idx++) { 1357 if (trill_info->rootBridge[idx] == trill_name) { 1358 *trill_tree_profile_idx = idx; 1359 break; 1360 } 1361 } 1362 1363 /* Root does not exist, Check for free entry */ 1364 if (idx == BCM_MAX_NUM_TRILL_TREES) { 1365 for (idx = 0; idx < BCM_MAX_NUM_TRILL_TREES; idx++) { 1366 if (trill_info->rootBridge[idx] == 0) { 1367 *trill_tree_profile_idx = idx; 1368 break; 1369 } 1370 } 1371 } 1372 1373 if (idx == BCM_MAX_NUM_TRILL_TREES) { 1374 return BCM_E_RESOURCE; 1375 } 1376 trill_info->rootBridge[*trill_tree_profile_idx] = trill_name; 1377 1378 sal_memset(&egr_trill_profile, 0, sizeof(egr_trill_tree_profile_entry_t)); 1379 soc_mem_field32_set(unit, EGR_TRILL_TREE_PROFILEm, &egr_trill_profile, 1380 ROOT_RBRIDGE_NICKNAMEf, trill_name); 1381 soc_mem_field32_set(unit, EGR_TRILL_TREE_PROFILEm, &egr_trill_profile, 1382 HOPCOUNTf, hopcount); 1383 rv = soc_mem_write(unit, EGR_TRILL_TREE_PROFILEm, 1384 MEM_BLOCK_ALL, *trill_tree_profile_idx, &egr_trill_profile); 1385 1386 return rv; 1387 } 1388 1389 /* 1390 * Function: 1391 * _bcm_td_trill_tree_profile_reset 1392 * Purpose: 1393 * Reset TRILL Tree Profile 1394 * Parameters: 1395 * IN : Unit 1396 * IN : trill_Rbridge_nickname 1397 * Returns: 1398 * BCM_E_XXX 1399 */ 1400 1401 int 1402 _bcm_td_trill_tree_profile_reset (int unit, bcm_trill_name_t trill_name) 1403 { 1404 _bcm_td_trill_bookkeeping_t *trill_info; 1405 egr_trill_tree_profile_entry_t egr_trill_profile; 1406 uint8 idx=0; 1407 int rv=BCM_E_UNAVAIL; 1408 1409 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 1410 return BCM_E_UNIT; 1411 } 1412 1413 trill_info = TRILL_INFO(unit); 1414 1415 for (idx = 0; idx < BCM_MAX_NUM_TRILL_TREES; idx++) { 1416 if (trill_info->rootBridge[idx] == trill_name) { 1417 trill_info->rootBridge[idx] = 0; 1418 sal_memset(&egr_trill_profile, 0, sizeof(egr_trill_tree_profile_entry_t)); 1419 rv = soc_mem_write(unit, EGR_TRILL_TREE_PROFILEm, 1420 MEM_BLOCK_ALL, 1421 idx, &egr_trill_profile); 1422 return rv; 1423 } 1424 } 1425 return BCM_E_NONE; 1426 } 1427 1428 /* 1429 * Function: 1430 * bcm_td_trill_tree_profile_get 1431 * Purpose: 1432 * Get TRILL Tree Profile index from trill_name 1433 * Parameters: 1434 * IN : Unit 1435 * IN : trill_tree_profile_idx 1436 * Returns: 1437 * BCM_E_XXX 1438 */ 1439 1440 void 1441 bcm_td_trill_tree_profile_get (int unit, bcm_trill_name_t trill_name, uint8 *trill_tree_profile_idx) 1442 { 1443 _bcm_td_trill_bookkeeping_t *trill_info = TRILL_INFO(unit); 1444 uint8 idx=0; 1445 1446 for (idx = 0; idx < BCM_MAX_NUM_TRILL_TREES; idx++) { 1447 if (trill_info->rootBridge[idx] == trill_name) { 1448 *trill_tree_profile_idx = idx; 1449 break; 1450 } 1451 } 1452 if (idx == BCM_MAX_NUM_TRILL_TREES) { 1453 *trill_tree_profile_idx = BCM_MAX_NUM_TRILL_TREES; 1454 } 1455 } 1456 1457 1458 /* 1459 * Function: 1460 * bcm_td_trill_root_name_get 1461 * Purpose: 1462 * Get TRILL Root name from Tree Profile 1463 * Parameters: 1464 * IN : Unit 1465 * IN : trill_tree_profile_idx 1466 * OUT: trill_name 1467 * Returns: 1468 * BCM_E_XXX 1469 */ 1470 1471 void 1472 bcm_td_trill_root_name_get (int unit, uint8 trill_tree_profile_idx, bcm_trill_name_t *trill_name) 1473 { 1474 _bcm_td_trill_bookkeeping_t *trill_info = TRILL_INFO(unit); 1475 1476 *trill_name = trill_info->rootBridge[trill_tree_profile_idx]; 1477 } 1478 1479 /* 1480 * Function: 1481 * _bcm_td_trill_port_resolve 1482 * Purpose: 1483 * Get the modid, port, trunk values for TRILL port 1484 * Parameters: 1485 * IN : Unit 1486 * IN : trill_port_id 1487 * IN : encap_id 1488 * OUT: module_id 1489 * OUT: port 1490 * OUT: trunk_id 1491 * OUT: vp 1492 * Returns: 1493 * BCM_E_XXX 1494 */ 1495 int 1496 _bcm_td_trill_port_resolve(int unit, bcm_gport_t trill_port_id, 1497 bcm_if_t encap_id, bcm_module_t *modid, 1498 bcm_port_t *port, bcm_trunk_t *trunk_id, int *id) 1499 1500 { 1501 int rv = BCM_E_NONE; 1502 int ecmp=0, nh_index=0, nh_ecmp_index=0, vp=0; 1503 ing_l3_next_hop_entry_t ing_nh; 1504 egr_l3_next_hop_entry_t egr_nh; 1505 ing_dvp_table_entry_t dvp; 1506 uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry. */ 1507 int idx=0, max_ent_count=0, base_idx=0; 1508 BCM_IF_ERROR_RETURN(_bcm_trill_check_init (unit)); 1509 1510 if (!BCM_GPORT_IS_TRILL_PORT(trill_port_id)) { 1511 return (BCM_E_BADID); 1512 } 1513 1514 vp = BCM_GPORT_TRILL_PORT_ID_GET(trill_port_id); 1515 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) { 1516 return BCM_E_NOT_FOUND; 1517 } 1518 BCM_IF_ERROR_RETURN( 1519 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 1520 ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf); 1521 if (!ecmp) { 1522 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 1523 NEXT_HOP_INDEXf); 1524 1525 if (nh_index == 0) { /* Local My RBridge */ 1526 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, modid)); 1527 } else if (nh_index > 0) { 1528 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 1529 nh_index, &ing_nh)); 1530 1531 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf) != 0x2) { 1532 /* Entry type is not TRILL DVP */ 1533 return BCM_E_NOT_FOUND; 1534 } 1535 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 1536 *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf); 1537 } else { 1538 /* Only add this to replication set if destination is local */ 1539 *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf); 1540 *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 1541 } 1542 } 1543 } else { 1544 /* Select the desired nhop from ECMP group - pointed by encap_id */ 1545 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf); 1546 1547 BCM_IF_ERROR_RETURN( 1548 _bcm_xgs3_l3_ecmp_grp_info_get(unit, nh_ecmp_index, 1549 &max_ent_count, &base_idx)); 1550 1551 if(encap_id == -1) { 1552 BCM_IF_ERROR_RETURN( 1553 soc_mem_read(unit, L3_ECMPm, MEM_BLOCK_ANY, 1554 base_idx, hw_buf)); 1555 nh_index = soc_mem_field32_get(unit, L3_ECMPm, 1556 hw_buf, NEXT_HOP_INDEXf); 1557 1558 /* Multipath group should have at least one member. 1559 * If not then nh_index points to black hole for which 1560 * index to ING_L3_NEXT_HOPm is not valid. 1561 */ 1562 if ((max_ent_count > 0) && nh_index) { 1563 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 1564 MEM_BLOCK_ANY, nh_index, &egr_nh)); 1565 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 1566 MEM_BLOCK_ANY, nh_index, &ing_nh)); 1567 1568 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, 1569 ENTRY_TYPEf) != 0x2) { 1570 /* Entry type is not TRILL DVP */ 1571 return BCM_E_NOT_FOUND; 1572 } 1573 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 1574 *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf); 1575 } else { 1576 /* Only add this to replication set if destination is local */ 1577 *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf); 1578 *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 1579 } 1580 } 1581 } else { 1582 for (idx = 0; idx < max_ent_count; idx++) { 1583 BCM_IF_ERROR_RETURN( 1584 soc_mem_read(unit, L3_ECMPm, MEM_BLOCK_ANY, 1585 (base_idx+idx), hw_buf)); 1586 nh_index = soc_mem_field32_get(unit, L3_ECMPm, 1587 hw_buf, NEXT_HOP_INDEXf); 1588 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 1589 MEM_BLOCK_ANY, nh_index, &egr_nh)); 1590 if (encap_id == soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 1591 &egr_nh, INTF_NUMf)) { 1592 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 1593 MEM_BLOCK_ANY, nh_index, &ing_nh)); 1594 1595 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, 1596 ENTRY_TYPEf) != 0x2) { 1597 /* Entry type is not TRILL DVP */ 1598 return BCM_E_NOT_FOUND; 1599 } 1600 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 1601 *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf); 1602 } else { 1603 /* Only add this to replication set if destination is local */ 1604 *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf); 1605 *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 1606 } 1607 break; 1608 } 1609 } 1610 } 1611 } 1612 1613 *id = vp; 1614 return rv; 1615 } 1616 1617 /* 1618 * Function: 1619 * _bcm_td_trill_port_cnt_update 1620 * Purpose: 1621 * Update port's VP count. 1622 * Parameters: 1623 * unit - (IN) SOC unit number. 1624 * gport - (IN) GPORT ID. 1625 * vp - (IN) Virtual port number. 1626 * incr - (IN) If TRUE, increment VP count, else decrease VP count. 1627 * Returns: 1628 * BCM_X_XXX 1629 */ 1630 1631 STATIC int 1632 _bcm_td_trill_port_cnt_update(int unit, bcm_gport_t gport, 1633 int vp, int incr_decr_flag) 1634 { 1635 int mod_out=-1, port_out=-1, tgid_out=-1, vp_out=-1; 1636 bcm_port_t local_member_array[SOC_MAX_NUM_PORTS]; 1637 int local_member_count=0; 1638 int idx=-1; 1639 int mod_local=-1; 1640 _bcm_port_info_t *port_info; 1641 uint32 port_flags; 1642 1643 BCM_IF_ERROR_RETURN 1644 (_bcm_esw_gport_resolve(unit, gport, &mod_out, &port_out, &tgid_out, 1645 &vp_out)); 1646 1647 if (vp_out == -1) { 1648 return BCM_E_PARAM; 1649 } 1650 1651 /* Update the physical port's SW state. If associated with a trunk, 1652 * update each local physical port's SW state. 1653 */ 1654 1655 if (BCM_TRUNK_INVALID != tgid_out) { 1656 1657 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid_out, 1658 SOC_MAX_NUM_PORTS, local_member_array, &local_member_count)); 1659 1660 for (idx = 0; idx < local_member_count; idx++) { 1661 _bcm_port_info_access(unit, local_member_array[idx], &port_info); 1662 if (incr_decr_flag) { 1663 port_info->vp_count++; 1664 } else { 1665 port_info->vp_count--; 1666 } 1667 BCM_IF_ERROR_RETURN( 1668 bcm_esw_port_vlan_member_get( 1669 unit, local_member_array[idx], &port_flags)); 1670 BCM_IF_ERROR_RETURN( 1671 bcm_esw_port_vlan_member_set( 1672 unit, local_member_array[idx], port_flags)); 1673 } 1674 } else { 1675 if (-1 == port_out) { 1676 return BCM_E_NONE; 1677 } 1678 1679 BCM_IF_ERROR_RETURN 1680 (_bcm_esw_modid_is_local(unit, mod_out, &mod_local)); 1681 if (mod_local) { 1682 if (soc_feature(unit, soc_feature_sysport_remap)) { 1683 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 1684 } 1685 _bcm_port_info_access(unit, port_out, &port_info); 1686 if (incr_decr_flag) { 1687 port_info->vp_count++; 1688 } else { 1689 port_info->vp_count--; 1690 } 1691 BCM_IF_ERROR_RETURN( 1692 bcm_esw_port_vlan_member_get( 1693 unit, port_out, &port_flags)); 1694 BCM_IF_ERROR_RETURN( 1695 bcm_esw_port_vlan_member_set( 1696 unit, port_out, port_flags)); 1697 } 1698 } 1699 1700 return BCM_E_NONE; 1701 } 1702 1703 1704 /* 1705 * Function: 1706 * _bcm_td_trill_transit_entry_key_set 1707 * Purpose: 1708 * Set TRILL Transit forwarding entry key 1709 * Parameters: 1710 * IN : Unit 1711 * IN : trill_port 1712 * IN : next_hop / ecmp group index 1713 * IN : MPLS entry pointer 1714 * Returns: 1715 * BCM_E_XXX 1716 */ 1717 1718 1719 STATIC void 1720 _bcm_td_trill_transit_entry_key_set(int unit, bcm_trill_port_t *trill_port, 1721 int nh_ecmp_index, mpls_entry_entry_t *tr_ent, int clean_flag) 1722 { 1723 1724 if (clean_flag) { 1725 sal_memset(tr_ent, 0, sizeof(mpls_entry_entry_t)); 1726 } 1727 1728 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1729 KEY_TYPEf, 0x5); 1730 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1731 TRILL__RBRIDGE_NICKNAMEf, trill_port->name); 1732 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1733 TRILL__CLASS_IDf, trill_port->if_class); 1734 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1735 TRILL__DECAP_TRILL_TUNNELf, 0x0); 1736 if (trill_port->flags & _BCM_TRILL_PORT_MULTIPATH) { 1737 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1738 TRILL__ECMPf, 0x1); 1739 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1740 TRILL__ECMP_PTRf, nh_ecmp_index); 1741 } else { 1742 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1743 TRILL__ECMPf, 0x0); 1744 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1745 TRILL__NEXT_HOP_INDEXf, nh_ecmp_index); 1746 } 1747 if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__UCAST_DST_DISCARDf)) { 1748 if ((trill_port->flags & BCM_TRILL_PORT_DROP) || 1749 !(trill_port->flags & BCM_TRILL_PORT_NETWORK)) { 1750 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1751 TRILL__UCAST_DST_DISCARDf, 0x1); 1752 } else if (trill_port->flags & BCM_TRILL_PORT_NETWORK) { 1753 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1754 TRILL__UCAST_DST_DISCARDf, 0x0); 1755 } 1756 } 1757 if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__DST_COPY_TO_CPUf) && 1758 (trill_port->flags & BCM_TRILL_PORT_COPYTOCPU)) { 1759 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1760 TRILL__DST_COPY_TO_CPUf, 0x1); 1761 } 1762 /* Multicast-traffic discard setting */ 1763 if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__MCAST_DST_DISCARDf)) { 1764 if (trill_port->flags & BCM_TRILL_PORT_MULTICAST) { 1765 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1766 TRILL__MCAST_DST_DISCARDf, 0x0); 1767 } else { 1768 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1769 TRILL__MCAST_DST_DISCARDf, 0x1); 1770 } 1771 } 1772 1773 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1774 VALIDf, 0x1); 1775 } 1776 1777 1778 /* 1779 * Function: 1780 * _bcm_td_trill_transit_entry_set 1781 * Purpose: 1782 * Set TRILL Transit forwarding entry 1783 * Parameters: 1784 * IN : Unit 1785 * IN : trill_port 1786 * IN : next_hop / ecmp group index 1787 * Returns: 1788 * BCM_E_XXX 1789 */ 1790 1791 STATIC int 1792 _bcm_td_trill_transit_entry_set(int unit, bcm_trill_port_t *trill_port, 1793 int nh_ecmp_index) 1794 { 1795 int rv = BCM_E_NONE; 1796 int index=0; 1797 mpls_entry_entry_t key_ent; 1798 mpls_entry_entry_t return_ent; 1799 1800 _bcm_td_trill_transit_entry_key_set(unit, trill_port, 1801 nh_ecmp_index, &key_ent, 1); 1802 1803 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 1804 &key_ent, &return_ent, 0); 1805 if (rv == SOC_E_NONE) { 1806 (void) _bcm_td_trill_transit_entry_key_set(unit, trill_port, 1807 nh_ecmp_index, &return_ent, 0); 1808 rv = soc_mem_write(unit, MPLS_ENTRYm, 1809 MEM_BLOCK_ALL, index, 1810 &return_ent); 1811 } else if (rv != SOC_E_NOT_FOUND) { 1812 return rv; 1813 } else { 1814 rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &key_ent); 1815 } 1816 return rv; 1817 } 1818 1819 /* 1820 * Function: 1821 * _bcm_td_trill_transit_entry_reset 1822 * Purpose: 1823 * Reset TRILL Transit forwarding entry 1824 * Parameters: 1825 * IN : Unit 1826 * IN : vp 1827 * IN : next_hop / ecmp group index 1828 * IN : ecmp flag 1829 * Returns: 1830 * BCM_E_XXX 1831 */ 1832 1833 STATIC int 1834 _bcm_td_trill_transit_entry_reset(int unit, int vp, int nh_ecmp_idx, int ecmp) 1835 { 1836 int rv = BCM_E_UNAVAIL; 1837 int index=0; 1838 bcm_trill_name_t rb_name; /* Destination RBridge Nickname. */ 1839 int if_class; /* Interface class ID. */ 1840 mpls_entry_entry_t tr_ent; 1841 egr_dvp_attribute_entry_t egr_dvp_attribute; 1842 source_vp_entry_t svp; 1843 1844 sal_memset(&tr_ent, 0, sizeof(mpls_entry_entry_t)); 1845 1846 BCM_IF_ERROR_RETURN( 1847 soc_mem_read(unit, EGR_DVP_ATTRIBUTEm, 1848 MEM_BLOCK_ALL, vp, &egr_dvp_attribute)); 1849 1850 rb_name = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 1851 EGRESS_RBRIDGE_NICKNAMEf); 1852 1853 BCM_IF_ERROR_RETURN( 1854 soc_mem_read(unit, SOURCE_VPm, 1855 MEM_BLOCK_ALL, vp, &svp)); 1856 1857 if_class = soc_mem_field32_get(unit, SOURCE_VPm, &svp, CLASS_IDf); 1858 1859 1860 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 1861 KEY_TYPEf, 0x5); 1862 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 1863 TRILL__RBRIDGE_NICKNAMEf, rb_name); 1864 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 1865 TRILL__CLASS_IDf, if_class); 1866 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 1867 TRILL__DECAP_TRILL_TUNNELf, 0x0); 1868 if (ecmp) { 1869 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 1870 TRILL__ECMPf, 0x1); 1871 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 1872 TRILL__ECMP_PTRf, nh_ecmp_idx); 1873 } else { 1874 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 1875 TRILL__NEXT_HOP_INDEXf, nh_ecmp_idx); 1876 } 1877 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 1878 VALIDf, 0x1); 1879 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 1880 &tr_ent, &tr_ent, 0); 1881 if (rv < 0) { 1882 return rv; 1883 } 1884 /* Delete the entry from HW */ 1885 rv = soc_mem_delete(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &tr_ent); 1886 return rv; 1887 } 1888 1889 /* 1890 * Function: 1891 * _bcm_td_trill_learn_entry_key_set 1892 * Purpose: 1893 * Set TRILL learn entry key 1894 * Parameters: 1895 * IN : Unit 1896 * IN : trill_port 1897 * IN : VP 1898 * IN : MPLS entry pointer 1899 * Returns: 1900 * BCM_E_XXX 1901 */ 1902 1903 STATIC void 1904 _bcm_td_trill_learn_entry_key_set(int unit, bcm_trill_port_t *trill_port, 1905 int vp, mpls_entry_entry_t *tr_ent, int clean_flag) 1906 { 1907 uint8 trill_tree_id=0; 1908 1909 if (clean_flag) { 1910 sal_memset(tr_ent, 0, sizeof(mpls_entry_entry_t)); 1911 } 1912 1913 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1914 KEY_TYPEf, 0x5); 1915 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1916 TRILL__RBRIDGE_NICKNAMEf, trill_port->name); 1917 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1918 TRILL__CLASS_IDf, trill_port->if_class); 1919 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1920 TRILL__VIRTUAL_PORTf, vp); 1921 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1922 TRILL__PHB_FROM_OUTER_L2_HEADERf, 0x1); 1923 if (trill_port->flags & BCM_TRILL_PORT_MULTICAST) { 1924 (void) bcm_td_trill_tree_profile_get (unit, trill_port->name, &trill_tree_id); 1925 if (trill_tree_id < BCM_MAX_NUM_TRILL_TREES) { 1926 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1927 TRILL__TREE_IDf, trill_tree_id); 1928 } 1929 } 1930 if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__SRC_DISCARDf) && 1931 (trill_port->flags & BCM_TRILL_PORT_DROP)) { 1932 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1933 TRILL__SRC_DISCARDf, 0x1); 1934 } 1935 if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__SRC_COPY_TO_CPUf) && 1936 (trill_port->flags & BCM_TRILL_PORT_COPYTOCPU)) { 1937 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1938 TRILL__SRC_COPY_TO_CPUf, 0x1); 1939 } 1940 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 1941 VALIDf, 0x1); 1942 } 1943 1944 /* 1945 * Function: 1946 * _bcm_td_trill_learn_entry_set 1947 * Purpose: 1948 * Set TRILL Learn Entry 1949 * Parameters: 1950 * IN : Unit 1951 * IN : trill_port 1952 * IN : vp 1953 * Returns: 1954 * BCM_E_XXX 1955 */ 1956 1957 STATIC int 1958 _bcm_td_trill_learn_entry_set(int unit, bcm_trill_port_t *trill_port, int vp) 1959 { 1960 mpls_entry_entry_t key_ent; 1961 mpls_entry_entry_t return_ent; 1962 int rv = BCM_E_UNAVAIL; 1963 int index; 1964 1965 _bcm_td_trill_learn_entry_key_set(unit, trill_port, vp, &key_ent, 1); 1966 1967 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 1968 &key_ent, &return_ent, 0); 1969 1970 if (rv == SOC_E_NONE) { 1971 (void) _bcm_td_trill_learn_entry_key_set(unit, trill_port, vp, &return_ent, 0); 1972 rv = soc_mem_write(unit, MPLS_ENTRYm, 1973 MEM_BLOCK_ALL, index, 1974 &return_ent); 1975 } else if (rv != SOC_E_NOT_FOUND) { 1976 return rv; 1977 } else { 1978 rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &key_ent); 1979 } 1980 1981 return rv; 1982 } 1983 1984 /* 1985 * Function: 1986 * _bcm_td_trill_learn_entry_reset 1987 * Purpose: 1988 * Reset TRILL RPF entry 1989 * Parameters: 1990 * IN : Unit 1991 * IN : vp 1992 * Returns: 1993 * BCM_E_XXX 1994 */ 1995 1996 STATIC int 1997 _bcm_td_trill_learn_entry_reset(int unit, int vp) 1998 { 1999 int rv = BCM_E_UNAVAIL; 2000 int index=0; 2001 bcm_trill_name_t rb_name; /* Destination RBridge Nickname. */ 2002 int if_class; /* Interface class ID. */ 2003 mpls_entry_entry_t tr_ent; 2004 egr_dvp_attribute_entry_t egr_dvp_attribute; 2005 source_vp_entry_t svp; 2006 2007 sal_memset(&tr_ent, 0, sizeof(mpls_entry_entry_t)); 2008 2009 BCM_IF_ERROR_RETURN( 2010 soc_mem_read(unit, EGR_DVP_ATTRIBUTEm, 2011 MEM_BLOCK_ALL, vp, &egr_dvp_attribute)); 2012 2013 rb_name = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 2014 EGRESS_RBRIDGE_NICKNAMEf); 2015 2016 BCM_IF_ERROR_RETURN( 2017 soc_mem_read(unit, SOURCE_VPm, 2018 MEM_BLOCK_ALL, vp, &svp)); 2019 2020 if_class = soc_mem_field32_get(unit, SOURCE_VPm, &svp, CLASS_IDf); 2021 2022 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 2023 KEY_TYPEf, 0x5); 2024 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 2025 TRILL__RBRIDGE_NICKNAMEf, rb_name); 2026 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 2027 TRILL__CLASS_IDf, if_class); 2028 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 2029 TRILL__VIRTUAL_PORTf, vp); 2030 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 2031 TRILL__PHB_FROM_OUTER_L2_HEADERf, 0x1); 2032 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 2033 VALIDf, 0x1); 2034 2035 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 2036 &tr_ent, &tr_ent, 0); 2037 if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) { 2038 return rv; 2039 } 2040 /* Delete the entry from HW */ 2041 rv = soc_mem_delete(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &tr_ent); 2042 2043 if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) { 2044 return rv; 2045 } else { 2046 return BCM_E_NONE; 2047 } 2048 } 2049 2050 2051 /* 2052 * Function: 2053 * _bcm_td_trill_decap_entry_key_set 2054 * Purpose: 2055 * Set TRILL Decap entry key 2056 * Parameters: 2057 * IN : Unit 2058 * IN : trill_port 2059 * IN : VP 2060 * IN : MPLS entry pointer 2061 * Returns: 2062 * BCM_E_XXX 2063 */ 2064 2065 STATIC void 2066 _bcm_td_trill_decap_entry_key_set(int unit, bcm_trill_port_t *trill_port, 2067 mpls_entry_entry_t *tr_ent, int clean_flag) 2068 { 2069 if (clean_flag) { 2070 sal_memset(tr_ent, 0, sizeof(mpls_entry_entry_t)); 2071 } 2072 2073 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 2074 KEY_TYPEf, 0x5); 2075 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 2076 TRILL__RBRIDGE_NICKNAMEf, trill_port->name); 2077 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 2078 TRILL__DECAP_TRILL_TUNNELf, 0x1); 2079 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 2080 TRILL__CLASS_IDf, trill_port->if_class); 2081 if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__UCAST_DST_DISCARDf)) { 2082 if ((trill_port->flags & BCM_TRILL_PORT_DROP) || 2083 !(trill_port->flags & BCM_TRILL_PORT_NETWORK)) { 2084 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 2085 TRILL__UCAST_DST_DISCARDf, 0x1); 2086 } else if (trill_port->flags & BCM_TRILL_PORT_NETWORK) { 2087 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 2088 TRILL__UCAST_DST_DISCARDf, 0x0); 2089 } 2090 } 2091 if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__DST_COPY_TO_CPUf) && 2092 (trill_port->flags & BCM_TRILL_PORT_COPYTOCPU)) { 2093 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 2094 TRILL__DST_COPY_TO_CPUf, 0x1); 2095 } 2096 /* Multicast-traffic discard setting */ 2097 if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__MCAST_DST_DISCARDf)) { 2098 if (trill_port->flags & BCM_TRILL_PORT_MULTICAST) { 2099 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 2100 TRILL__MCAST_DST_DISCARDf, 0x0); 2101 } else { 2102 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 2103 TRILL__MCAST_DST_DISCARDf, 0x1); 2104 } 2105 } 2106 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 2107 VALIDf, 0x1); 2108 } 2109 2110 /* 2111 * Function: 2112 * _bcm_td_trill_decap_entry_set 2113 * Purpose: 2114 * Set TRILL Decap Entry 2115 * Parameters: 2116 * IN : Unit 2117 * IN : trill_port 2118 * Returns: 2119 * BCM_E_XXX 2120 */ 2121 2122 STATIC int 2123 _bcm_td_trill_decap_entry_set(int unit, bcm_trill_port_t *trill_port) 2124 { 2125 mpls_entry_entry_t tr_ent; 2126 int rv = BCM_E_UNAVAIL; 2127 int index=0; 2128 mpls_entry_entry_t return_ent; 2129 2130 _bcm_td_trill_decap_entry_key_set(unit, trill_port, &tr_ent, 1); 2131 2132 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 2133 &tr_ent, &return_ent, 0); 2134 if (rv == SOC_E_NONE) { 2135 (void) _bcm_td_trill_decap_entry_key_set(unit, trill_port, &return_ent, 0); 2136 rv = soc_mem_write(unit, MPLS_ENTRYm, 2137 MEM_BLOCK_ALL, index, 2138 &return_ent); 2139 } else if (rv != SOC_E_NOT_FOUND) { 2140 return rv; 2141 } else { 2142 rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &tr_ent); 2143 } 2144 return rv; 2145 } 2146 2147 /* 2148 * Function: 2149 * _bcm_td_trill_decap_entry_reset 2150 * Purpose: 2151 * Reset TRILL Decap entry 2152 * Parameters: 2153 * IN : Unit 2154 * IN : vp 2155 * Returns: 2156 * BCM_E_XXX 2157 */ 2158 2159 STATIC int 2160 _bcm_td_trill_decap_entry_reset(int unit, int vp) 2161 { 2162 int rv = BCM_E_UNAVAIL; 2163 int index=0; 2164 bcm_trill_name_t rb_name; /* Destination RBridge Nickname. */ 2165 int if_class=0; /* Interface class ID. */ 2166 mpls_entry_entry_t tr_ent; 2167 egr_dvp_attribute_entry_t egr_dvp_attribute; 2168 source_vp_entry_t svp; 2169 2170 sal_memset(&tr_ent, 0, sizeof(mpls_entry_entry_t)); 2171 2172 BCM_IF_ERROR_RETURN( 2173 soc_mem_read(unit, EGR_DVP_ATTRIBUTEm, 2174 MEM_BLOCK_ALL, vp, &egr_dvp_attribute)); 2175 2176 rb_name = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 2177 EGRESS_RBRIDGE_NICKNAMEf); 2178 2179 BCM_IF_ERROR_RETURN( 2180 soc_mem_read(unit, SOURCE_VPm, 2181 MEM_BLOCK_ALL, vp, &svp)); 2182 2183 if_class = soc_mem_field32_get(unit, SOURCE_VPm, &svp, CLASS_IDf); 2184 2185 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 2186 KEY_TYPEf, 0x5); 2187 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 2188 TRILL__RBRIDGE_NICKNAMEf, rb_name); 2189 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 2190 TRILL__CLASS_IDf, if_class); 2191 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 2192 TRILL__DECAP_TRILL_TUNNELf, 0x1); 2193 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 2194 VALIDf, 0x1); 2195 2196 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 2197 &tr_ent, &tr_ent, 0); 2198 if (rv < 0) { 2199 return rv; 2200 } 2201 2202 /* Delete the entry from HW */ 2203 rv = soc_mem_delete(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &tr_ent); 2204 return rv; 2205 2206 } 2207 2208 2209 /* 2210 * Function: 2211 * _bcm_td_trill_ingress_next_hop_set 2212 * Purpose: 2213 * Set ING_L3_NEXT_HOP Entry 2214 * Parameters: 2215 * IN : Unit 2216 * IN : nh_index 2217 * IN : drop 2218 * Returns: 2219 * BCM_E_XXX 2220 */ 2221 2222 STATIC int 2223 _bcm_td_trill_next_hop_set(int unit, int nh_index, uint32 flags) 2224 { 2225 int rv=BCM_E_NONE; 2226 ing_l3_next_hop_entry_t ing_nh; 2227 bcm_port_t port=0; 2228 bcm_module_t modid=0, local_modid=0; 2229 bcm_trunk_t tgid=0; 2230 int num_local_ports=0, idx=0; 2231 int old_nh_index=-1; 2232 bcm_port_t local_ports[SOC_MAX_NUM_PORTS]; 2233 uint32 replace=0; 2234 int gport; 2235 replace = flags & BCM_L3_REPLACE; 2236 2237 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, 2238 MEM_BLOCK_ANY, nh_index, &ing_nh)); 2239 if (soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, Tf)) { 2240 tgid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 2241 &ing_nh, TGIDf); 2242 rv = _bcm_trunk_id_validate(unit, tgid); 2243 if (BCM_FAILURE(rv)) { 2244 return BCM_E_PORT; 2245 } 2246 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid, 2247 SOC_MAX_NUM_PORTS, local_ports, &num_local_ports)); 2248 } else { 2249 modid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 2250 &ing_nh, MODULE_IDf); 2251 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &local_modid)); 2252 if (modid != local_modid) { 2253 /* Ignore EGR_PORT_TO_NHI_MAPPINGs */ 2254 return BCM_E_NONE; 2255 } 2256 port = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 2257 &ing_nh, PORT_NUMf); 2258 local_ports[num_local_ports++] = port; 2259 } 2260 if (!(flags & BCM_L3_IPMC)) { /* Only for Unicast Nexthops */ 2261 for (idx = 0; idx < num_local_ports; idx++) { 2262 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &modid)); 2263 BCM_GPORT_MODPORT_SET(gport, modid, local_ports[idx]); 2264 BCM_IF_ERROR_RETURN( 2265 _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index)); 2266 if (old_nh_index && !replace) { 2267 if (old_nh_index != nh_index) { 2268 /* Limitation: For TD/TR3, 2269 Trill egress port can be configured with one NHI*/ 2270 return BCM_E_RESOURCE; 2271 } 2272 } else { 2273 BCM_IF_ERROR_RETURN( 2274 _bcm_trx_gport_to_nhi_set(unit, gport, nh_index)); 2275 } 2276 } 2277 BCM_IF_ERROR_RETURN( 2278 _bcm_td_trill_adjacency_set(unit, nh_index)); 2279 } 2280 return rv; 2281 } 2282 2283 /* 2284 * Function: 2285 * _bcm_td_trill_ingress_next_hop_reset 2286 * Purpose: 2287 * Reset ING_L3_NEXT_HOP Entry 2288 * Parameters: 2289 * IN : Unit 2290 * IN : nh_index 2291 * IN : drop 2292 * Returns: 2293 * BCM_E_XXX 2294 */ 2295 2296 STATIC int 2297 _bcm_td_trill_next_hop_reset(int unit, int nh_index) 2298 { 2299 int rv=BCM_E_NONE; 2300 ing_l3_next_hop_entry_t ing_nh; 2301 bcm_port_t port=0; 2302 bcm_module_t modid=0, local_modid=0; 2303 bcm_trunk_t tgid=0; 2304 int num_local_ports=0, idx=0; 2305 bcm_port_t local_ports[SOC_MAX_NUM_PORTS]; 2306 int old_nh_index=-1; 2307 int gport; 2308 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, 2309 MEM_BLOCK_ANY, nh_index, &ing_nh)); 2310 if (soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, Tf)) { 2311 tgid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 2312 &ing_nh, TGIDf); 2313 rv = _bcm_trunk_id_validate(unit, tgid); 2314 if (BCM_FAILURE(rv)) { 2315 return BCM_E_PORT; 2316 } 2317 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid, 2318 SOC_MAX_NUM_PORTS, local_ports, &num_local_ports)); 2319 } else { 2320 modid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 2321 &ing_nh, MODULE_IDf); 2322 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &local_modid)); 2323 2324 if (modid != local_modid) { 2325 /* Ignore reset for non local modid */ 2326 return BCM_E_NONE; 2327 } 2328 port = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 2329 &ing_nh, PORT_NUMf); 2330 local_ports[num_local_ports++] = port; 2331 } 2332 2333 for (idx = 0; idx < num_local_ports; idx++) { 2334 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &modid)); 2335 BCM_GPORT_MODPORT_SET(gport, modid, local_ports[idx]); 2336 BCM_IF_ERROR_RETURN( 2337 _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index)); 2338 if (old_nh_index == nh_index) { 2339 BCM_IF_ERROR_RETURN( 2340 _bcm_trx_gport_to_nhi_set(unit, gport, 0)); 2341 } 2342 } 2343 BCM_IF_ERROR_RETURN( 2344 _bcm_td_trill_adjacency_reset(unit, nh_index)); 2345 return rv; 2346 } 2347 2348 /* 2349 * Function: 2350 * bcm_td_trill_egress_set 2351 * Purpose: 2352 * Set TRILL NextHop 2353 * Parameters: 2354 * IN : Unit 2355 * IN : nh_index 2356 * IN : flags 2357 * Returns: 2358 * BCM_E_XXX 2359 */ 2360 2361 int 2362 bcm_td_trill_egress_set(int unit, int nh_index, uint32 flags) 2363 { 2364 ing_l3_next_hop_entry_t ing_nh; 2365 int rv=BCM_E_NONE; 2366 2367 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, 2368 MEM_BLOCK_ANY, nh_index, &ing_nh)); 2369 2370 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 2371 ENTRY_TYPEf, 0x2); /* L2 DVP */ 2372 if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) { 2373 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 2374 &ing_nh, MTU_SIZEf, 0x3fff); 2375 } 2376 #if defined(BCM_TRIUMPH3_SUPPORT) 2377 else if (SOC_IS_TRIUMPH3(unit)) { 2378 /* Set default ING_L3_NEXT_HOP_ATTRIBUTE_1 MTU_SIZE 2379 * Note: Assumption that first entry has MTU size of 0x3fff 2380 */ 2381 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 2382 &ing_nh, DVP_ATTRIBUTE_1_INDEXf, 0); 2383 } 2384 #endif /* BCM_TRIUMPH3_SUPPORT */ 2385 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_L3_NEXT_HOPm, 2386 MEM_BLOCK_ALL, nh_index, &ing_nh)); 2387 2388 rv = _bcm_td_trill_next_hop_set(unit, nh_index, flags); 2389 return rv; 2390 } 2391 2392 /* 2393 * Function: 2394 * bcm_td_trill_egress_reset 2395 * Purpose: 2396 * Reset TRILL NextHop 2397 * Parameters: 2398 * IN : Unit 2399 * IN : nh_index 2400 * IN : flags 2401 * Returns: 2402 * BCM_E_XXX 2403 */ 2404 2405 int 2406 bcm_td_trill_egress_reset(int unit, int nh_index) 2407 { 2408 ing_l3_next_hop_entry_t ing_nh; 2409 int rv=BCM_E_NONE; 2410 2411 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, 2412 MEM_BLOCK_ANY, nh_index, &ing_nh)); 2413 2414 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 2415 ENTRY_TYPEf, 0x0); /* L2 DVP */ 2416 if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) { 2417 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 2418 &ing_nh, MTU_SIZEf, 0x0); 2419 } 2420 #if defined(BCM_TRIUMPH3_SUPPORT) 2421 else if (SOC_IS_TRIUMPH3(unit)) { 2422 /* Set default ING_L3_NEXT_HOP_ATTRIBUTE_1 MTU_SIZE 2423 * Note: Assumption that first entry has MTU size of 0x3fff 2424 */ 2425 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 2426 &ing_nh, DVP_ATTRIBUTE_1_INDEXf, 0); 2427 } 2428 #endif /* BCM_TRIUMPH3_SUPPORT */ 2429 BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_L3_NEXT_HOPm, 2430 MEM_BLOCK_ALL, nh_index, &ing_nh)); 2431 2432 rv = _bcm_td_trill_next_hop_reset(unit, nh_index); 2433 return rv; 2434 } 2435 2436 /* 2437 * Function: 2438 * bcm_td_trill_egress_get 2439 * Purpose: 2440 * Get TRILL Egress NextHop 2441 * Parameters: 2442 * IN : Unit 2443 * IN : nh_index 2444 * Returns: 2445 * BCM_E_XXX 2446 */ 2447 2448 int 2449 bcm_td_trill_egress_get(int unit, bcm_l3_egress_t *egr, int nh_index) 2450 { 2451 int int_l3_flag; 2452 int_l3_flag = BCM_XGS3_L3_ENT_FLAG(BCM_XGS3_L3_TBL_PTR(unit, next_hop), 2453 nh_index); 2454 if (int_l3_flag == _BCM_L3_TRILL_ONLY) { 2455 egr->flags |= BCM_L3_TRILL_ONLY; 2456 } 2457 2458 return BCM_E_NONE; 2459 } 2460 2461 /* 2462 * Function: 2463 * _bcm_td_trill_egress_name_set 2464 * Purpose: 2465 * Set My RBridge Nickname 2466 * Parameters: 2467 * IN : Unit 2468 * IN : trill_name 2469 * Returns: 2470 * BCM_E_XXX 2471 */ 2472 2473 STATIC int 2474 _bcm_td_trill_egress_name_set(int unit, bcm_trill_name_t trill_name) 2475 { 2476 egr_trill_rbridge_nicknames_entry_t egr_name_entry; 2477 int idx=0; 2478 bcm_trill_name_t temp_name; 2479 2480 for(idx=0; idx < 4; idx++) { 2481 BCM_IF_ERROR_RETURN( 2482 soc_mem_read(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, 2483 MEM_BLOCK_ALL, idx, &egr_name_entry)); 2484 2485 temp_name = 2486 soc_mem_field32_get(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, 2487 &egr_name_entry, 2488 RBRIDGE_NICKNAMEf); 2489 /* If name exists, return */ 2490 if (temp_name == trill_name) { 2491 return BCM_E_NONE; 2492 } 2493 2494 if (!temp_name) { 2495 soc_mem_field32_set(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, 2496 &egr_name_entry, 2497 RBRIDGE_NICKNAMEf, trill_name); 2498 2499 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, 2500 MEM_BLOCK_ALL, idx, &egr_name_entry)); 2501 return BCM_E_NONE; 2502 } 2503 } 2504 return BCM_E_FULL; 2505 } 2506 2507 /* 2508 * Function: 2509 * _bcm_td_trill_egress_name_reset 2510 * Purpose: 2511 * Reset My RBridge Nickname 2512 * Parameters: 2513 * IN : Unit 2514 * IN : trill_name 2515 * Returns: 2516 * BCM_E_XXX 2517 */ 2518 2519 STATIC int 2520 _bcm_td_trill_egress_name_reset(int unit, bcm_trill_name_t trill_name) 2521 { 2522 egr_trill_rbridge_nicknames_entry_t egr_name_entry; 2523 int idx=0; 2524 bcm_trill_name_t temp_name; 2525 2526 for(idx=0; idx < 4; idx++) { 2527 BCM_IF_ERROR_RETURN( 2528 soc_mem_read(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, 2529 MEM_BLOCK_ALL, idx, &egr_name_entry)); 2530 temp_name = 2531 soc_mem_field32_get(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, 2532 &egr_name_entry, 2533 RBRIDGE_NICKNAMEf); 2534 if (temp_name == trill_name) { 2535 soc_mem_field32_set(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, 2536 &egr_name_entry, 2537 RBRIDGE_NICKNAMEf, 0x0); 2538 2539 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, 2540 MEM_BLOCK_ALL, idx, &egr_name_entry)); 2541 return BCM_E_NONE; 2542 } 2543 } 2544 return BCM_E_NOT_FOUND; 2545 } 2546 /* 2547 * Purpose: 2548 * Obtain Trill Nickname index from name 2549 * Parameters: 2550 * unit - Device Number 2551 * source_trill_name - (IN) Trill Root_RBridge 2552 */ 2553 2554 int 2555 bcm_td_trill_source_trill_name_idx_get(int unit, 2556 bcm_trill_name_t source_trill_name, 2557 int *trill_name_index) 2558 { 2559 egr_trill_rbridge_nicknames_entry_t egr_name_entry; 2560 int idx=0; 2561 2562 for(idx=0; idx < 4; idx++) { 2563 BCM_IF_ERROR_RETURN( 2564 soc_mem_read(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, 2565 MEM_BLOCK_ALL, idx, &egr_name_entry)); 2566 2567 if ( source_trill_name == soc_mem_field32_get(unit, 2568 EGR_TRILL_RBRIDGE_NICKNAMESm, 2569 &egr_name_entry, 2570 RBRIDGE_NICKNAMEf) ) { 2571 *trill_name_index = idx; 2572 return BCM_E_NONE; 2573 } 2574 } 2575 return BCM_E_NOT_FOUND; 2576 2577 } 2578 2579 /* 2580 * Purpose: 2581 * Obtain Trill Nickname from index 2582 * Parameters: 2583 * unit - Device Number 2584 * source_trill_name - (IN) Trill Root_RBridge 2585 */ 2586 2587 int 2588 bcm_td_trill_source_trill_idx_name_get(int unit, 2589 int trill_name_index, 2590 bcm_trill_name_t *source_trill_name) 2591 { 2592 egr_trill_rbridge_nicknames_entry_t egr_name_entry; 2593 2594 if (SOC_MEM_IS_VALID(unit, EGR_TRILL_RBRIDGE_NICKNAMESm)) { 2595 /* TD3TBD */ 2596 BCM_IF_ERROR_RETURN( 2597 soc_mem_read(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, 2598 MEM_BLOCK_ALL, trill_name_index, &egr_name_entry)); 2599 2600 *source_trill_name = soc_mem_field32_get(unit, 2601 EGR_TRILL_RBRIDGE_NICKNAMESm, 2602 &egr_name_entry, 2603 RBRIDGE_NICKNAMEf); 2604 return BCM_E_NONE; 2605 } else { 2606 return BCM_E_NOT_FOUND; 2607 } 2608 } 2609 2610 2611 /* 2612 * Function: 2613 * _bcm_td_trill_egress_dvp_set 2614 * Purpose: 2615 * Set Egress DVP tables 2616 * Parameters: 2617 * IN : Unit 2618 * IN : vp 2619 * IN : trill_port 2620 * Returns: 2621 * BCM_E_XXX 2622 */ 2623 2624 STATIC int 2625 _bcm_td_trill_egress_dvp_set(int unit, int vp, bcm_trill_port_t *trill_port) 2626 { 2627 int rv=BCM_E_UNAVAIL; 2628 egr_dvp_attribute_entry_t egr_dvp_attribute; 2629 2630 sal_memset(&egr_dvp_attribute, 0, sizeof(egr_dvp_attribute_entry_t)); 2631 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 2632 VP_TYPEf, 0x1); 2633 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 2634 EGRESS_RBRIDGE_NICKNAMEf, trill_port->name); 2635 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 2636 HOPCOUNTf, trill_port->hopcount); 2637 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 2638 MTU_VALUEf, trill_port->mtu); 2639 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, 2640 MTU_ENABLEf, 0x1); 2641 rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTEm, 2642 MEM_BLOCK_ALL, vp, &egr_dvp_attribute); 2643 if (soc_feature(unit,soc_feature_trill_egr_dvp_classid)) { 2644 egr_dvp_attribute_1_entry_t egr_dvp_attribute_1; 2645 sal_memset(&egr_dvp_attribute_1, 0, sizeof(egr_dvp_attribute_1_entry_t)); 2646 soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m, &egr_dvp_attribute_1, 2647 TRILL__CLASS_IDf, trill_port->if_class); 2648 rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTE_1m, 2649 MEM_BLOCK_ALL, vp, &egr_dvp_attribute_1); 2650 } 2651 return rv; 2652 2653 } 2654 2655 /* 2656 * Function: 2657 * _bcm_td_trill_egress_dvp_reset 2658 * Purpose: 2659 * Set Egress DVP tables 2660 * Parameters: 2661 * IN : Unit 2662 * IN : nh_index 2663 * IN : trill_port 2664 * Returns: 2665 * BCM_E_XXX 2666 */ 2667 2668 STATIC int 2669 _bcm_td_trill_egress_dvp_reset(int unit, int vp) 2670 { 2671 int rv=BCM_E_UNAVAIL; 2672 egr_dvp_attribute_entry_t egr_dvp_attribute; 2673 2674 2675 sal_memset(&egr_dvp_attribute, 0, sizeof(egr_dvp_attribute_entry_t)); 2676 rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTEm, 2677 MEM_BLOCK_ALL, vp, &egr_dvp_attribute); 2678 if (soc_feature(unit,soc_feature_trill_egr_dvp_classid)) { 2679 egr_dvp_attribute_1_entry_t egr_dvp_attribute_1; 2680 sal_memset(&egr_dvp_attribute_1, 0, sizeof(egr_dvp_attribute_1_entry_t)); 2681 rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTE_1m, 2682 MEM_BLOCK_ALL, vp, &egr_dvp_attribute_1); 2683 } 2684 return rv; 2685 } 2686 2687 /* 2688 * Purpose: 2689 * Set Egress TRILL Header fields 2690 * Parameters: 2691 * IN : Unit 2692 * IN : trill_name 2693 * Returns: 2694 * BCM_E_XXX 2695 */ 2696 2697 STATIC int 2698 _bcm_td_trill_header_set(int unit, bcm_trill_name_t trill_name) 2699 { 2700 uint32 reg_val=0; 2701 int rv = BCM_E_NONE; 2702 2703 soc_reg_field_set(unit, EGR_TRILL_HEADER_ATTRIBUTESr, 2704 ®_val, RESERVED_FIELDf, 0); 2705 soc_reg_field_set(unit, EGR_TRILL_HEADER_ATTRIBUTESr, 2706 ®_val, VERSIONf, 0); 2707 if (soc_mem_field_valid(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, RBRIDGE_NICKNAMEf)) { 2708 rv = _bcm_td_trill_egress_name_set(unit, trill_name); 2709 } else { 2710 soc_reg_field_set(unit, EGR_TRILL_HEADER_ATTRIBUTESr, 2711 ®_val, RBRIDGE_NICKNAMEf, trill_name); 2712 SOC_IF_ERROR_RETURN( 2713 WRITE_EGR_TRILL_HEADER_ATTRIBUTESr(unit, reg_val)); 2714 } 2715 2716 return rv; 2717 } 2718 2719 /* 2720 * Purpose: 2721 * Reset Egress TRILL Header fields 2722 * Parameters: 2723 * IN : Unit 2724 * IN : trill_name 2725 * Returns: 2726 * BCM_E_XXX 2727 */ 2728 2729 STATIC int 2730 _bcm_td_trill_header_reset(int unit, bcm_trill_name_t trill_name) 2731 { 2732 uint32 reg_val=0; 2733 int rv = BCM_E_NONE; 2734 2735 if (soc_mem_field_valid(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, RBRIDGE_NICKNAMEf)) { 2736 rv = _bcm_td_trill_egress_name_reset(unit, trill_name); 2737 } else { 2738 if (trill_name == soc_reg_field_get(unit, EGR_TRILL_HEADER_ATTRIBUTESr, 2739 reg_val, RBRIDGE_NICKNAMEf)) { 2740 soc_reg_field_set(unit, EGR_TRILL_HEADER_ATTRIBUTESr, 2741 ®_val, RBRIDGE_NICKNAMEf, 0x0); 2742 SOC_IF_ERROR_RETURN( 2743 WRITE_EGR_TRILL_HEADER_ATTRIBUTESr(unit, reg_val)); 2744 2745 } 2746 } 2747 return rv; 2748 } 2749 2750 /* 2751 * Function: 2752 * _bcm_td_trill_adjacency_register_set 2753 * Purpose: 2754 * Set Ingress TRILL Adjacency register 2755 * Parameters: 2756 * IN : Unit 2757 * IN : port 2758 * IN : mac_addr 2759 * IN : vid 2760 * Returns: 2761 * BCM_E_XXX 2762 */ 2763 2764 STATIC int 2765 _bcm_td_trill_adjacency_register_set(int unit, bcm_port_t port, bcm_mac_t dst_mac_addr, bcm_vlan_t vid) 2766 { 2767 uint64 reg_val; 2768 uint64 mac_field; 2769 #if defined(BCM_TOMAHAWK2_SUPPORT) 2770 ing_trill_adjacency_entry_t adjacency_entry; 2771 #endif 2772 COMPILER_64_ZERO(reg_val); 2773 COMPILER_64_ZERO(mac_field); 2774 2775 SAL_MAC_ADDR_TO_UINT64(dst_mac_addr, mac_field); 2776 #if defined(BCM_TOMAHAWK2_SUPPORT) 2777 if (soc_feature(unit, soc_feature_ing_trill_adjacency_is_memory)) { 2778 SOC_IF_ERROR_RETURN(READ_ING_TRILL_ADJACENCYm(unit, MEM_BLOCK_ANY, 2779 port, &adjacency_entry)); 2780 soc_ING_TRILL_ADJACENCYm_field32_set(unit, &adjacency_entry, 2781 VLANf, vid); 2782 soc_mem_mac_addr_set(unit, ING_TRILL_ADJACENCYm, &adjacency_entry, 2783 MAC_ADDRESSf, dst_mac_addr); 2784 SOC_IF_ERROR_RETURN(WRITE_ING_TRILL_ADJACENCYm(unit, MEM_BLOCK_ALL, 2785 port, &adjacency_entry)); 2786 } else 2787 #endif 2788 { 2789 soc_reg64_field32_set(unit, ING_TRILL_ADJACENCYr, ®_val, 2790 VLANf, vid); 2791 soc_reg64_field_set(unit, ING_TRILL_ADJACENCYr, ®_val, 2792 MAC_ADDRESSf, mac_field); 2793 SOC_IF_ERROR_RETURN 2794 (WRITE_ING_TRILL_ADJACENCYr(unit, port, reg_val)); 2795 } 2796 return BCM_E_NONE; 2797 } 2798 2799 /* 2800 * Function: 2801 * _bcm_td_trill_adjacency_register_reset 2802 * Purpose: 2803 * Reset Ingress TRILL Adjacency register 2804 * Parameters: 2805 * IN : Unit 2806 * IN : port 2807 * Returns: 2808 * BCM_E_XXX 2809 */ 2810 2811 STATIC int 2812 _bcm_td_trill_adjacency_register_reset(int unit, bcm_port_t port) 2813 { 2814 uint64 reg_val; 2815 uint64 mac_field; 2816 int id=0; 2817 bcm_mac_t dst_mac_addr; 2818 #if defined(BCM_TOMAHAWK2_SUPPORT) 2819 ing_trill_adjacency_entry_t adjacency_entry; 2820 #endif 2821 COMPILER_64_ZERO(reg_val); 2822 COMPILER_64_ZERO(mac_field); 2823 for (id=0; id<6; id++) { 2824 dst_mac_addr[id] = 0x0; 2825 } 2826 2827 SAL_MAC_ADDR_TO_UINT64(dst_mac_addr, mac_field); 2828 #if defined(BCM_TOMAHAWK2_SUPPORT) 2829 if (soc_feature(unit, soc_feature_ing_trill_adjacency_is_memory)) { 2830 SOC_IF_ERROR_RETURN(READ_ING_TRILL_ADJACENCYm(unit, MEM_BLOCK_ANY, 2831 port, &adjacency_entry)); 2832 soc_ING_TRILL_ADJACENCYm_field32_set(unit, &adjacency_entry, 2833 VLANf, 0x0); 2834 soc_mem_mac_addr_set(unit, ING_TRILL_ADJACENCYm, &adjacency_entry, 2835 MAC_ADDRESSf, dst_mac_addr); 2836 SOC_IF_ERROR_RETURN(WRITE_ING_TRILL_ADJACENCYm(unit, MEM_BLOCK_ALL, 2837 port, &adjacency_entry)); 2838 } else 2839 #endif 2840 { 2841 soc_reg64_field32_set(unit, ING_TRILL_ADJACENCYr, ®_val, 2842 VLANf, 0x0); 2843 soc_reg64_field_set(unit, ING_TRILL_ADJACENCYr, ®_val, 2844 MAC_ADDRESSf, mac_field); 2845 SOC_IF_ERROR_RETURN 2846 (WRITE_ING_TRILL_ADJACENCYr(unit, port, reg_val)); 2847 } 2848 return BCM_E_NONE; 2849 } 2850 2851 /* 2852 * Function: 2853 * _bcm_td_trill_adjacency_set 2854 * Purpose: 2855 * Set TRILL Adjacency 2856 * Parameters: 2857 * IN : Unit 2858 * IN : nh_index 2859 * IN : trill_port 2860 * Returns: 2861 * BCM_E_XXX 2862 */ 2863 2864 STATIC int 2865 _bcm_td_trill_adjacency_set(int unit, int nh_index) 2866 { 2867 int rv=BCM_E_UNAVAIL; 2868 ing_l3_next_hop_entry_t ing_nh; 2869 egr_l3_next_hop_entry_t egr_nh; 2870 egr_l3_intf_entry_t if_entry; 2871 bcm_if_t intf_idx; 2872 bcm_port_t port=0; 2873 bcm_module_t modid=0, local_modid=0; 2874 bcm_mac_t src_mac_addr; 2875 bcm_mac_t dst_mac_addr; 2876 bcm_vlan_t vid=0; 2877 bcm_trunk_t trunk_id=0; 2878 int num_local_ports=0, idx=0; 2879 bcm_port_t local_ports[SOC_MAX_NUM_PORTS]; 2880 uint32 trunk_id_data = 0; 2881 uint32 mod_port_data = 0; 2882 int num_bits_for_port; 2883 2884 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, 2885 MEM_BLOCK_ANY, nh_index, &ing_nh)); 2886 2887 if (soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, Tf)) { 2888 trunk_id = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 2889 &ing_nh, TGIDf); 2890 rv = _bcm_trunk_id_validate(unit, trunk_id); 2891 if (BCM_FAILURE(rv)) { 2892 return BCM_E_PORT; 2893 } 2894 if (soc_mem_field_valid(unit, MY_STATION_TCAMm, SOURCE_FIELDf)) { 2895 trunk_id_data = ((1 << SOC_TRUNK_BIT_POS(unit)) | trunk_id); 2896 } 2897 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, trunk_id, 2898 SOC_MAX_NUM_PORTS, local_ports, &num_local_ports)); 2899 } else { 2900 modid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 2901 &ing_nh, MODULE_IDf); 2902 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &local_modid)); 2903 2904 if (modid != local_modid) { 2905 /* Ignore Adjacency set for non local modid */ 2906 return BCM_E_NONE; 2907 } 2908 port = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 2909 &ing_nh, PORT_NUMf); 2910 local_ports[num_local_ports++] = port; 2911 if (soc_mem_field_valid(unit, MY_STATION_TCAMm, SOURCE_FIELDf)) { 2912 num_bits_for_port = 2913 _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit)); 2914 mod_port_data = (modid << num_bits_for_port) | port; 2915 } 2916 } 2917 2918 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, 2919 MEM_BLOCK_ANY, nh_index, &egr_nh)); 2920 2921 intf_idx = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 2922 &egr_nh, INTF_NUMf); 2923 2924 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_INTFm, 2925 MEM_BLOCK_ANY, intf_idx, &if_entry)); 2926 2927 /* Obtain Source-MAC, Vlan from EGR_L3_INTF */ 2928 soc_mem_mac_addr_get(unit, EGR_L3_INTFm, &if_entry, 2929 MAC_ADDRESSf, src_mac_addr); 2930 vid = soc_mem_field32_get(unit, EGR_L3_INTFm, 2931 &if_entry, VIDf); 2932 2933 /* Obtain vlan and Destination-MAC from EGR_L3_NEXT_HOP */ 2934 soc_mem_mac_addr_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 2935 MAC_ADDRESSf, dst_mac_addr); 2936 /* Trunk supported in MY_STATION_TCAM */ 2937 if (soc_mem_field_valid(unit, MY_STATION_TCAMm, SOURCE_FIELDf)) { 2938 /* Configure MY_STATION entry for trunk */ 2939 if (trunk_id_data) { 2940 BCM_IF_ERROR_RETURN( 2941 bcm_td_metro_myStation_add(unit, src_mac_addr, vid, trunk_id_data, 1)); 2942 for (idx = 0; idx < num_local_ports; idx++) { 2943 /* Configure ING_TRILL_ADJACENCY */ 2944 rv = _bcm_td_trill_adjacency_register_set(unit, local_ports[idx], dst_mac_addr, vid); 2945 } 2946 return rv; 2947 } else if (mod_port_data) { 2948 BCM_IF_ERROR_RETURN( 2949 bcm_td_metro_myStation_add(unit, src_mac_addr, vid, 2950 mod_port_data, 1)); 2951 for (idx = 0; idx < num_local_ports; idx++) { 2952 /* Configure ING_TRILL_ADJACENCY */ 2953 rv = _bcm_td_trill_adjacency_register_set( 2954 unit, local_ports[idx], dst_mac_addr, vid); 2955 } 2956 return rv; 2957 } 2958 } 2959 /* Trunk not supported in MY_STATION_TCAM */ 2960 for (idx = 0; idx < num_local_ports; idx++) { 2961 /* Configure MY_STATION entry */ 2962 BCM_IF_ERROR_RETURN( 2963 bcm_td_metro_myStation_add(unit, src_mac_addr, vid, local_ports[idx], 1)); 2964 2965 /* Configure ING_TRILL_ADJACENCY */ 2966 rv = _bcm_td_trill_adjacency_register_set(unit, local_ports[idx], dst_mac_addr, vid); 2967 } 2968 return rv; 2969 } 2970 2971 /* 2972 * Function: 2973 * _bcm_td_trill_adjacency_reset 2974 * Purpose: 2975 * Reset TRILL Adjacency 2976 * Parameters: 2977 * IN : Unit 2978 * IN : nh_index 2979 * Returns: 2980 * BCM_E_XXX 2981 */ 2982 2983 STATIC int 2984 _bcm_td_trill_adjacency_reset(int unit, int nh_index) 2985 { 2986 int rv=BCM_E_UNAVAIL; 2987 ing_l3_next_hop_entry_t ing_nh; 2988 egr_l3_next_hop_entry_t egr_nh; 2989 egr_l3_intf_entry_t if_entry; 2990 bcm_if_t intf_idx; 2991 bcm_port_t port=0; 2992 bcm_module_t modid=0, local_modid=0; 2993 bcm_mac_t src_mac_addr; 2994 bcm_vlan_t vid=0; 2995 bcm_trunk_t trunk_id=0; 2996 int num_local_ports=0, idx=0; 2997 bcm_port_t local_ports[SOC_MAX_NUM_PORTS]; 2998 uint32 trunk_id_data = 0; 2999 uint32 mod_port_data = 0; 3000 int num_bits_for_port; 3001 3002 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, 3003 MEM_BLOCK_ANY, nh_index, &ing_nh)); 3004 3005 if (soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, Tf)) { 3006 trunk_id = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 3007 &ing_nh, TGIDf); 3008 rv = _bcm_trunk_id_validate(unit, trunk_id); 3009 if (BCM_FAILURE(rv)) { 3010 return BCM_E_PORT; 3011 } 3012 3013 if (soc_mem_field_valid(unit, MY_STATION_TCAMm, SOURCE_FIELDf)) { 3014 trunk_id_data = ((1 << SOC_TRUNK_BIT_POS(unit)) | trunk_id); 3015 } 3016 3017 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, trunk_id, 3018 SOC_MAX_NUM_PORTS, local_ports, &num_local_ports)); 3019 } else { 3020 modid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 3021 &ing_nh, MODULE_IDf); 3022 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &local_modid)); 3023 3024 if (modid != local_modid) { 3025 /* Ignore Adjacency reset for non local modid */ 3026 return BCM_E_NONE; 3027 } 3028 3029 port = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 3030 &ing_nh, PORT_NUMf); 3031 local_ports[num_local_ports++] = port; 3032 if (soc_mem_field_valid(unit, MY_STATION_TCAMm, SOURCE_FIELDf)) { 3033 num_bits_for_port = 3034 _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit)); 3035 mod_port_data = (modid << num_bits_for_port) | port; 3036 } 3037 } 3038 3039 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, 3040 MEM_BLOCK_ANY, nh_index, &egr_nh)); 3041 3042 intf_idx = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 3043 &egr_nh, INTF_NUMf); 3044 3045 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_INTFm, 3046 MEM_BLOCK_ANY, intf_idx, &if_entry)); 3047 3048 /* Obtain Source-MAC from EGR_L3_INTF */ 3049 soc_mem_mac_addr_get(unit, EGR_L3_INTFm, &if_entry, 3050 MAC_ADDRESSf, src_mac_addr); 3051 3052 /* Obtain vlan and Destination-MAC from EGR_L3_NEXT_HOP */ 3053 vid = soc_mem_field32_get(unit, EGR_L3_INTFm, 3054 &if_entry, OVIDf); 3055 /* Trunk supported in MY_STATION_TCAM */ 3056 if (soc_mem_field_valid(unit, MY_STATION_TCAMm, SOURCE_FIELDf)) { 3057 /* Delete MY_STATION entry for trunk */ 3058 if (trunk_id_data) { 3059 rv = bcm_td_metro_myStation_delete(unit, src_mac_addr, vid, trunk_id_data, 1); 3060 if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_FULL)) { 3061 if (rv != BCM_E_NONE) { 3062 return rv; 3063 } 3064 } else { 3065 rv = BCM_E_NONE; 3066 } 3067 for (idx = 0; idx < num_local_ports; idx++) { 3068 /* reset ING_TRILL_ADJACENCY */ 3069 rv = _bcm_td_trill_adjacency_register_reset(unit, local_ports[idx]); 3070 } 3071 return rv; 3072 } else if (mod_port_data) { 3073 rv = bcm_td_metro_myStation_delete(unit, src_mac_addr, vid, 3074 mod_port_data, 1); 3075 if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_FULL)) { 3076 if (rv != BCM_E_NONE) { 3077 return rv; 3078 } 3079 } else { 3080 rv = BCM_E_NONE; 3081 } 3082 for (idx = 0; idx < num_local_ports; idx++) { 3083 /* reset ING_TRILL_ADJACENCY */ 3084 rv = _bcm_td_trill_adjacency_register_reset(unit, 3085 local_ports[idx]); 3086 } 3087 return rv; 3088 } 3089 } 3090 /* Trunk not supported in MY_STATION_TCAM */ 3091 for (idx = 0; idx < num_local_ports; idx++) { 3092 /* Delete MY_STATION entry */ 3093 rv = bcm_td_metro_myStation_delete(unit, src_mac_addr, vid, local_ports[idx], 1); 3094 if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_FULL)) { 3095 if (rv != BCM_E_NONE) { 3096 return rv; 3097 } 3098 } 3099 3100 /* Reset ING_TRILL_ADJACENCY */ 3101 rv = _bcm_td_trill_adjacency_register_reset(unit, local_ports[idx]); 3102 } 3103 return rv; 3104 } 3105 3106 3107 /* 3108 * Function: 3109 * _bcm_td_trill_port_validate 3110 * Purpose: 3111 * Validate Trill Port Parameters 3112 * Parameters: 3113 * IN : trill_port 3114 * Returns: 3115 * BCM_E_XXX 3116 */ 3117 3118 int 3119 _bcm_td_trill_port_validate(bcm_trill_port_t *trill_port) 3120 { 3121 3122 if (!trill_port->name) { 3123 return BCM_E_PARAM; 3124 } 3125 3126 /* Check for unsupported Flag */ 3127 if (trill_port->flags & (~(BCM_TRILL_PORT_WITH_ID | 3128 BCM_TRILL_PORT_DROP | 3129 BCM_TRILL_PORT_COUNTED | 3130 BCM_TRILL_PORT_NETWORK | 3131 BCM_TRILL_PORT_REPLACE | 3132 BCM_TRILL_PORT_MULTICAST | 3133 BCM_TRILL_PORT_LOCAL ))) { 3134 return BCM_E_PARAM; 3135 } 3136 3137 return BCM_E_NONE; 3138 } 3139 3140 /* 3141 * Function: 3142 * _bcm_td_trill_root_rbridge_check 3143 * Purpose: 3144 * Check if Root RBridge already exists 3145 * Parameters: 3146 * IN : unit 3147 * Returns: 3148 * BCM_E_XXX 3149 */ 3150 STATIC int 3151 _bcm_td_trill_root_rbridge_check(int unit, bcm_trill_port_t *trill_port) 3152 { 3153 _bcm_td_trill_bookkeeping_t *trill_info; 3154 int idx=0; 3155 3156 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 3157 return BCM_E_UNIT; 3158 } 3159 3160 trill_info = TRILL_INFO(unit); 3161 3162 for (idx = 0; idx < BCM_MAX_NUM_TRILL_TREES; idx++) { 3163 if (trill_info->rootBridge[idx] == trill_port->name) { 3164 return (BCM_E_EXISTS); 3165 } 3166 } 3167 /* TRILL DVP to Root RBridge do NOT exist */ 3168 return BCM_E_NONE; 3169 } 3170 3171 /* 3172 * Function: 3173 * _bcm_td_trill_root_bridge_set 3174 * Purpose: 3175 * Configure Root RBridge 3176 * Parameters: 3177 * IN : unit 3178 * Returns: 3179 * BCM_E_XXX 3180 */ 3181 3182 STATIC int 3183 _bcm_td_trill_root_bridge_set(int unit, bcm_trill_port_t *trill_port, int vp) 3184 { 3185 _bcm_td_trill_bookkeeping_t *trill_info; 3186 int rv=BCM_E_NONE; 3187 uint8 trill_tree_profile_idx=0; 3188 3189 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 3190 return BCM_E_UNIT; 3191 } 3192 3193 trill_info = TRILL_INFO(unit); 3194 3195 /* Verify whether Root Rbridge already exists? */ 3196 rv = _bcm_td_trill_root_rbridge_check(unit, trill_port); 3197 if (rv == BCM_E_EXISTS) { 3198 if (!(trill_port->flags & BCM_TRILL_PORT_REPLACE)) { 3199 (void) _bcm_vp_free(unit, _bcmVpTypeTrill, 1, vp); 3200 return rv; 3201 } 3202 } 3203 3204 /* Set Tree profile */ 3205 rv = _bcm_td_trill_tree_profile_set (unit, trill_port->name, 3206 trill_port->multicast_hopcount, &trill_tree_profile_idx); 3207 if (rv < 0) { 3208 trill_info->rootBridge[trill_tree_profile_idx] = 0; 3209 (void) _bcm_vp_free(unit, _bcmVpTypeTrill, 1, vp); 3210 return rv; 3211 } 3212 return rv; 3213 } 3214 3215 /* 3216 * Function: 3217 * _bcm_td_trill_root_bridge_clear 3218 * Purpose: 3219 * Configure Root RBridge 3220 * Parameters: 3221 * IN : unit 3222 * Returns: 3223 * BCM_E_XXX 3224 */ 3225 3226 STATIC int 3227 _bcm_td_trill_root_bridge_clear(int unit, bcm_trill_port_t *trill_port) 3228 { 3229 int rv=BCM_E_NONE; 3230 3231 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 3232 return BCM_E_UNIT; 3233 } 3234 3235 /* Verify whether Root Rbridge already exists? */ 3236 rv = _bcm_td_trill_root_rbridge_check(unit, trill_port); 3237 if (rv == BCM_E_EXISTS) { 3238 /* Clear Tree profile */ 3239 rv = _bcm_td_trill_tree_profile_reset (unit, trill_port->name); 3240 } 3241 return rv; 3242 } 3243 3244 /* 3245 * Function: 3246 * _bcm_td_trill_rbridge_name_exists 3247 * Purpose: 3248 * Configure Root RBridge 3249 * Parameters: 3250 * IN : unit 3251 * Returns: 3252 * BCM_E_XXX 3253 */ 3254 3255 STATIC int 3256 _bcm_td_trill_rbridge_name_exists(int unit, bcm_trill_port_t *trill_port) 3257 { 3258 _bcm_td_trill_bookkeeping_t *trill_info; 3259 int idx=0, num_vp=0; 3260 3261 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 3262 return BCM_E_UNIT; 3263 } 3264 3265 trill_info = TRILL_INFO(unit); 3266 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 3267 3268 for (idx = 0; idx < num_vp; idx++) { 3269 if (trill_info->rBridge[idx] == trill_port->name) { 3270 return (BCM_E_EXISTS); 3271 } 3272 } 3273 /* TRILL DVP to given RBridge_name do NOT exist */ 3274 return BCM_E_NONE; 3275 } 3276 3277 /* 3278 * Function: 3279 * bcm_td_multicast_trill_rootname_get 3280 * Purpose: 3281 * Get Root RBridge name 3282 * Parameters: 3283 * IN : unit 3284 * Returns: 3285 * BCM_E_XXX 3286 */ 3287 3288 int 3289 bcm_td_multicast_trill_rootname_get(int unit, bcm_multicast_t group, bcm_trill_name_t *root_name) 3290 { 3291 _bcm_td_trill_bookkeeping_t *trill_info; 3292 int l3mc_index=-1; 3293 uint8 trill_tree_id=0xFF; 3294 int rv = BCM_E_NONE; 3295 3296 trill_info = TRILL_INFO(unit); 3297 3298 l3mc_index = _BCM_MULTICAST_ID_GET(group); 3299 rv = bcm_td_multicast_trill_group_get(unit, l3mc_index, &trill_tree_id); 3300 if (BCM_SUCCESS(rv)) { 3301 *root_name = trill_info->rootBridge[trill_tree_id]; 3302 } 3303 return rv; 3304 } 3305 3306 3307 3308 /* 3309 * Purpose: 3310 * Activate Trunk Port-membership from 3311 * ING_TRILL_ADJACENY, EGR_PORT_TO_NHI_MAPPING 3312 * Parameters: 3313 * unit - (IN) Device Number 3314 * tgid - (IN) Trunk Group ID 3315 * trunk_member_count - (IN) Count of Trunk members to be deleted 3316 * trunk_member_array - (IN) Trunk member ports to be deleted 3317 */ 3318 3319 int 3320 bcm_td_trill_trunk_member_add (int unit, bcm_trunk_t trunk_id, 3321 int trunk_member_count, bcm_port_t *trunk_member_array) 3322 { 3323 int idx=0; 3324 int rv=BCM_E_NONE; 3325 int nh_index=0, old_nh_index=-1; 3326 bcm_l3_egress_t egr; 3327 egr_l3_next_hop_entry_t egr_nh; 3328 egr_l3_intf_entry_t if_entry; 3329 bcm_if_t intf_idx; 3330 bcm_vlan_t vid=0; 3331 bcm_mac_t dst_mac_addr; 3332 int gport = 0; 3333 int modid = 0; 3334 rv = _bcm_trunk_id_validate(unit, trunk_id); 3335 if (BCM_FAILURE(rv)) { 3336 return BCM_E_PORT; 3337 } 3338 3339 /* Obtain nh_index for trunk_id */ 3340 rv = _bcm_xgs3_trunk_nh_store_get(unit, trunk_id, &nh_index); 3341 if (nh_index == 0) { 3342 return rv; 3343 } 3344 bcm_l3_egress_t_init(&egr); 3345 BCM_IF_ERROR_RETURN(bcm_td_trill_egress_get(unit, &egr, nh_index)); 3346 3347 if (egr.flags & BCM_L3_TRILL_ONLY) { 3348 for (idx = 0; idx < trunk_member_count; idx++) { 3349 if (soc_mem_field_valid(unit, MY_STATION_TCAMm, SOURCE_FIELDf)) { 3350 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, 3351 MEM_BLOCK_ANY, nh_index, &egr_nh)); 3352 intf_idx = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 3353 &egr_nh, INTF_NUMf); 3354 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_INTFm, 3355 MEM_BLOCK_ANY, intf_idx, &if_entry)); 3356 /* Obtain Vlan from EGR_L3_INTF */ 3357 vid = soc_mem_field32_get(unit, EGR_L3_INTFm, 3358 &if_entry, VIDf); 3359 /* Obtain Destination-MAC from EGR_L3_NEXT_HOP */ 3360 soc_mem_mac_addr_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 3361 MAC_ADDRESSf, dst_mac_addr); 3362 /* Set ING_TRILL_ADJACENCY */ 3363 BCM_IF_ERROR_RETURN( 3364 _bcm_td_trill_adjacency_register_set(unit, trunk_member_array[idx], 3365 dst_mac_addr, vid)); 3366 } else { 3367 BCM_IF_ERROR_RETURN( 3368 _bcm_td_trill_adjacency_set(unit, nh_index)); 3369 } 3370 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 3371 BCM_GPORT_MODPORT_SET(gport, modid, trunk_member_array[idx]); 3372 BCM_IF_ERROR_RETURN( 3373 _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index)); 3374 if (!old_nh_index) { 3375 BCM_IF_ERROR_RETURN( 3376 _bcm_trx_gport_to_nhi_set(unit, gport, nh_index)); 3377 } 3378 3379 } 3380 } 3381 return rv; 3382 } 3383 3384 3385 /* 3386 * Purpose: 3387 * Clear Trunk Port-membership from 3388 * ING_TRILL_ADJACENY, EGR_PORT_TO_NHI_MAPPING 3389 * Parameters: 3390 * unit - (IN) Device Number 3391 * tgid - (IN) Trunk Group ID 3392 * trunk_member_count - (IN) Count of Trunk members to be deleted 3393 * trunk_member_array - (IN) Trunk member ports to be deleted 3394 */ 3395 3396 int 3397 bcm_td_trill_trunk_member_delete (int unit, bcm_trunk_t trunk_id, 3398 int trunk_member_count, bcm_port_t *trunk_member_array) 3399 { 3400 int idx=0; 3401 int rv=BCM_E_NONE; 3402 int old_nh_index=0; 3403 bcm_mac_t src_mac_addr; 3404 bcm_vlan_t vid=0; 3405 bcm_l3_egress_t egr; 3406 egr_l3_next_hop_entry_t egr_nh; 3407 egr_l3_intf_entry_t if_entry; 3408 bcm_if_t intf_idx; 3409 int nh_index = 0; 3410 int gport = 0; 3411 int modid = 0; 3412 3413 rv = _bcm_trunk_id_validate(unit, trunk_id); 3414 if (BCM_FAILURE(rv)) { 3415 return BCM_E_PORT; 3416 } 3417 3418 /* Obtain nh_index for trunk_id */ 3419 rv = _bcm_xgs3_trunk_nh_store_get(unit, trunk_id, &nh_index); 3420 if (nh_index == 0) { 3421 return rv; 3422 } 3423 bcm_l3_egress_t_init(&egr); 3424 BCM_IF_ERROR_RETURN(bcm_td_trill_egress_get(unit, &egr, nh_index)); 3425 3426 if (egr.flags & BCM_L3_TRILL_ONLY) { 3427 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 3428 for (idx = 0; idx < trunk_member_count; idx++) { 3429 /* Reset ING_TRILL_ADJACENCY */ 3430 rv = _bcm_td_trill_adjacency_register_reset(unit, trunk_member_array[idx]); 3431 if (BCM_FAILURE(rv)) { 3432 return rv; 3433 } 3434 BCM_GPORT_MODPORT_SET(gport, modid, trunk_member_array[idx]); 3435 BCM_IF_ERROR_RETURN( 3436 _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index)); 3437 3438 if (0 != old_nh_index) { 3439 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, 3440 MEM_BLOCK_ANY, old_nh_index, &egr_nh)); 3441 intf_idx = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 3442 &egr_nh, INTF_NUMf); 3443 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_INTFm, 3444 MEM_BLOCK_ANY, intf_idx, &if_entry)); 3445 /* Obtain Source-MAC from EGR_L3_INTF */ 3446 soc_mem_mac_addr_get(unit, EGR_L3_INTFm, &if_entry, 3447 MAC_ADDRESSf, src_mac_addr); 3448 /* Obtain vlan and Destination-MAC from EGR_L3_NEXT_HOP */ 3449 vid = soc_mem_field32_get(unit, EGR_L3_INTFm, 3450 &if_entry, OVIDf); 3451 3452 /* Delete MY_STATION entry */ 3453 rv = bcm_td_metro_myStation_delete(unit, src_mac_addr, vid, trunk_member_array[idx], 1); 3454 if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_FULL)) { 3455 if (rv != BCM_E_NONE) { 3456 return rv; 3457 } 3458 } 3459 3460 rv = _bcm_trx_gport_to_nhi_set(unit, gport, 0); 3461 if (BCM_FAILURE(rv)) { 3462 return rv; 3463 } 3464 } 3465 } 3466 } 3467 return rv; 3468 } 3469 3470 /* 3471 * Purpose: 3472 * Add Trill port to TRILL Cloud 3473 * Parameters: 3474 * unit - (IN) Device Number 3475 * trill_port - (IN/OUT) trill port information (OUT : trill_port_id) 3476 */ 3477 int 3478 bcm_td_trill_port_add(int unit, bcm_trill_port_t *trill_port) 3479 { 3480 _bcm_td_trill_bookkeeping_t *trill_info; 3481 int rv=BCM_E_NONE; 3482 int nh_ecmp_index = -1; 3483 int old_nh_ecmp_index = -1, old_nh_index = -1; 3484 int ref_count = 0; 3485 int vp, num_vp=0; 3486 source_vp_entry_t svp; 3487 ing_dvp_table_entry_t dvp; 3488 uint32 flags=0; 3489 bcm_if_t intf; 3490 int cml_default_enable=0, cml_default_new=0, cml_default_move=0; 3491 _bcm_vp_info_t vp_info; 3492 int bit_num = 0; 3493 int network_group=0; 3494 3495 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 3496 return BCM_E_UNIT; 3497 } 3498 3499 /* Validate paramters */ 3500 if ((trill_port->name < 0) || (trill_port->name > 0xffff) || 3501 (trill_port->mtu < 0) || (trill_port->mtu > 0x3fff) || 3502 (trill_port->hopcount < 0) || (trill_port->hopcount > 0x3f)) { 3503 return BCM_E_PARAM; 3504 } 3505 3506 if (soc_feature(unit, soc_feature_extended_address_class)) { 3507 if ((trill_port->if_class > SOC_EXT_ADDR_CLASS_MAX(unit)) || 3508 (trill_port->if_class < 0)) { 3509 return (BCM_E_PARAM); 3510 } 3511 } else { 3512 bit_num = soc_mem_field_length(unit, MPLS_ENTRYm, TRILL__CLASS_IDf); 3513 if ((trill_port->if_class > (( 1 << bit_num ) - 1)) || 3514 (trill_port->if_class < 0)) { 3515 return BCM_E_PARAM; 3516 } 3517 } 3518 3519 trill_info = TRILL_INFO(unit); 3520 BCM_IF_ERROR_RETURN( 3521 _bcm_td_trill_port_validate(trill_port)); 3522 3523 /* 3524 * Extract next-hop index from egress object OR 3525 * Extract ecmp group index from multipath egress object. */ 3526 3527 if (!(trill_port->flags & BCM_TRILL_PORT_LOCAL)) { 3528 BCM_IF_ERROR_RETURN( 3529 bcm_xgs3_get_nh_from_egress_object(unit, 3530 trill_port->egress_if, &flags, 1, &nh_ecmp_index)); 3531 if (nh_ecmp_index == BCM_XGS3_L3_INVALID_INDEX) { 3532 return BCM_E_PARAM; 3533 } 3534 } 3535 3536 if (flags == BCM_L3_MULTIPATH) { 3537 trill_port->flags |= _BCM_TRILL_PORT_MULTIPATH; 3538 } 3539 3540 _bcm_vp_info_init(&vp_info); 3541 vp_info.vp_type = _bcmVpTypeTrill; 3542 if (trill_port->flags & BCM_TRILL_PORT_NETWORK) { 3543 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT; 3544 } else { 3545 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT); 3546 } 3547 3548 if (trill_port->flags & BCM_TRILL_PORT_REPLACE) { 3549 3550 vp = BCM_GPORT_TRILL_PORT_ID_GET(trill_port->trill_port_id); 3551 if (vp == -1) { 3552 return BCM_E_PARAM; 3553 } 3554 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) { 3555 return BCM_E_NOT_FOUND; 3556 } 3557 if (trill_info->rBridge[vp] != trill_port->name) { 3558 return BCM_E_PARAM; 3559 } 3560 3561 BCM_IF_ERROR_RETURN( 3562 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp)); 3563 BCM_IF_ERROR_RETURN( 3564 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 3565 3566 /* Decrement port's VP count */ 3567 rv = _bcm_td_trill_port_cnt_update(unit, trill_port->trill_port_id, vp, FALSE); 3568 if (rv < 0) { 3569 return rv; 3570 } 3571 3572 /* Get replaced egress NHI/ECMP index */ 3573 if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf)) { 3574 old_nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf); 3575 } else { 3576 old_nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 3577 } 3578 } else if (trill_port->flags & BCM_TRILL_PORT_WITH_ID ) { 3579 3580 if (!BCM_GPORT_IS_TRILL_PORT(trill_port->trill_port_id)) { 3581 return (BCM_E_BADID); 3582 } 3583 3584 /* Check if rbridge_name already exists */ 3585 BCM_IF_ERROR_RETURN(_bcm_td_trill_rbridge_name_exists(unit, trill_port)); 3586 3587 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 3588 vp = BCM_GPORT_TRILL_PORT_ID_GET(trill_port->trill_port_id); 3589 if (vp >= num_vp) { 3590 return (BCM_E_BADID); 3591 } 3592 rv = _bcm_vp_used_get(unit, vp, _bcmVpTypeTrill); 3593 if (rv) { 3594 return (BCM_E_EXISTS); 3595 } 3596 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info)); 3597 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 3598 3599 } else { 3600 3601 /* Check if rbridge_name already exists */ 3602 BCM_IF_ERROR_RETURN(_bcm_td_trill_rbridge_name_exists(unit, trill_port)); 3603 3604 /* allocate a new VP index */ 3605 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 3606 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp); 3607 if (rv < 0) { 3608 return rv; 3609 } 3610 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 3611 3612 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info)); 3613 } 3614 3615 /* Set Virtual Port */ 3616 soc_SOURCE_VPm_field32_set(unit, &svp, CLASS_IDf, 3617 trill_port->if_class); 3618 soc_SOURCE_VPm_field32_set(unit, &svp, 3619 ENTRY_TYPEf, 0x3); /* TRILL VP */ 3620 3621 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 3622 network_group = trill_port->network_group_id; 3623 rv = _bcm_validate_splithorizon_network_group(unit, 3624 trill_port->flags & BCM_TRILL_PORT_NETWORK, 3625 &network_group); 3626 BCM_IF_ERROR_RETURN(rv); 3627 soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf, 3628 network_group); 3629 } else { 3630 soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 0x1); 3631 network_group=_bcmVpIngDvpPortTypeNetwork; 3632 } 3633 3634 /* Set the CML */ 3635 BCM_TRILL_CHECK_ERROR_RETURN( 3636 _bcm_vp_default_cml_mode_get (unit, 3637 &cml_default_enable, &cml_default_new, 3638 &cml_default_move), unit, vp); 3639 3640 if (cml_default_enable) { 3641 /* Set the CML to default values */ 3642 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml_default_new); 3643 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml_default_move); 3644 } else { 3645 /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */ 3646 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, 0x8); 3647 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, 0x8); 3648 } 3649 3650 soc_SOURCE_VPm_field32_set(unit, &svp, TPID_SOURCEf, 0x3); 3651 BCM_TRILL_CHECK_ERROR_RETURN( 3652 WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp), unit, vp); 3653 3654 if (trill_port->flags & BCM_TRILL_PORT_LOCAL) { /* My RBridge */ 3655 intf = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_ecmp_index; 3656 BCM_IF_ERROR_RETURN( 3657 _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigSet, vp, 3658 _bcmVpIngDvpVpTypeTRILL, intf, 3659 network_group)); 3660 3661 BCM_TRILL_CHECK_ERROR_RETURN( 3662 _bcm_td_trill_egress_dvp_set(unit, vp, trill_port), unit, vp); 3663 BCM_TRILL_CHECK_ERROR_RETURN( 3664 _bcm_td_trill_header_set(unit, trill_port->name), unit, vp); 3665 3666 /* ******** TRILL Decap Entry ******************** */ 3667 #if defined(BCM_TRIUMPH3_SUPPORT) 3668 if (SOC_IS_TRIUMPH3(unit)) { 3669 rv = _bcm_tr3_trill_decap_entry_set(unit, trill_port); 3670 } else 3671 #endif /* BCM_TRIUMPH3_SUPPORT */ 3672 { 3673 rv = _bcm_td_trill_decap_entry_set(unit, trill_port); 3674 } 3675 if (rv < 0) { 3676 return rv; 3677 } 3678 trill_info->rBridge[vp] = trill_port->name; 3679 3680 /* Root RBridge case */ 3681 if (trill_port->flags & BCM_TRILL_PORT_MULTICAST) { 3682 /* Add Tree profile */ 3683 rv = _bcm_td_trill_root_bridge_set(unit, trill_port, vp); 3684 } else if (trill_port->flags & BCM_TRILL_PORT_REPLACE) { 3685 /* Update as Regular RBridge - if Root Rbridge already exists */ 3686 rv = _bcm_td_trill_root_bridge_clear(unit, trill_port); 3687 } 3688 if (rv < 0) { 3689 return rv; 3690 } 3691 } else { 3692 3693 /* Root RBridge */ 3694 if (trill_port->flags & BCM_TRILL_PORT_MULTICAST) { 3695 /* Add Tree profile */ 3696 rv = _bcm_td_trill_root_bridge_set(unit, trill_port, vp); 3697 } else if (trill_port->flags & BCM_TRILL_PORT_REPLACE) { 3698 /* Update as Regular RBridge - if Root Rbridge already exists */ 3699 rv = _bcm_td_trill_root_bridge_clear(unit, trill_port); 3700 } 3701 if (rv < 0) { 3702 return rv; 3703 } 3704 /* ******** TRILL Access ECMP/Next-Hop ********** */ 3705 if (trill_port->flags&_BCM_TRILL_PORT_MULTIPATH) { 3706 intf = BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit) + nh_ecmp_index; 3707 } else { 3708 intf = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_ecmp_index; 3709 } 3710 BCM_IF_ERROR_RETURN( 3711 _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigSet, vp, 3712 _bcmVpIngDvpVpTypeTRILL, 3713 intf, network_group)); 3714 3715 3716 BCM_TRILL_CHECK_ERROR_RETURN( 3717 _bcm_td_trill_egress_dvp_set(unit, vp, trill_port), unit, vp); 3718 3719 #if defined(BCM_TRIUMPH3_SUPPORT) 3720 if (SOC_IS_TRIUMPH3(unit)) { 3721 /* ******** TRILL Transit Forwarding Entry ********** */ 3722 BCM_TRILL_CHECK_ERROR_RETURN( 3723 _bcm_tr3_trill_transit_entry_set(unit, trill_port, nh_ecmp_index), unit, vp); 3724 3725 /* ******** TRILL Decap Learn Entry ********** */ 3726 BCM_TRILL_CHECK_ERROR_RETURN( 3727 _bcm_tr3_trill_learn_entry_set(unit, trill_port, vp), unit, vp); 3728 } else 3729 #endif /* BCM_TRIUMPH3_SUPPORT */ 3730 { 3731 /* ******** TRILL Transit Forwarding Entry ********** */ 3732 BCM_TRILL_CHECK_ERROR_RETURN( 3733 _bcm_td_trill_transit_entry_set(unit, trill_port, nh_ecmp_index), unit, vp); 3734 /* ******** TRILL Decap Learn Entry ********** */ 3735 BCM_TRILL_CHECK_ERROR_RETURN( 3736 _bcm_td_trill_learn_entry_set(unit, trill_port, vp), unit, vp); 3737 } 3738 trill_info->rBridge[vp] = trill_port->name; 3739 } 3740 /* Set TRILL port ID */ 3741 BCM_GPORT_TRILL_PORT_ID_SET(trill_port->trill_port_id, vp); 3742 trill_port->encap_id = nh_ecmp_index; 3743 /* Increment new-port's VP count */ 3744 BCM_IF_ERROR_RETURN( 3745 _bcm_td_trill_port_cnt_update(unit, trill_port->trill_port_id, vp, TRUE)); 3746 3747 if (old_nh_ecmp_index != -1) { 3748 BCM_IF_ERROR_RETURN( 3749 bcm_xgs3_get_ref_count_from_nhi( 3750 unit, BCM_L3_MULTIPATH, &ref_count, old_nh_ecmp_index)); 3751 } 3752 if (old_nh_index != -1) { 3753 BCM_IF_ERROR_RETURN( 3754 bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, old_nh_index)); 3755 } 3756 3757 return BCM_E_NONE; 3758 } 3759 3760 /* 3761 * Purpose: 3762 * Get a trill port 3763 * Parameters: 3764 * unit - (IN) Device Number 3765 * trill_port - (IN/OUT) Trill port information (IN : trill_port_id) 3766 */ 3767 3768 int 3769 bcm_td_trill_port_get(int unit, bcm_trill_port_t *trill_port) 3770 { 3771 uint32 vp=0; 3772 egr_dvp_attribute_entry_t egr_dvp_attribute; 3773 source_vp_entry_t svp; 3774 egr_trill_tree_profile_entry_t egr_trill_profile; 3775 ing_dvp_table_entry_t dvp; 3776 int nh_ecmp_index=0; 3777 int ecmp=0; 3778 int network_port=0; 3779 uint8 trill_tree_id=0; 3780 _bcm_vp_info_t vp_info; 3781 3782 vp = BCM_GPORT_TRILL_PORT_ID_GET(trill_port->trill_port_id); 3783 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) { 3784 return BCM_E_NOT_FOUND; 3785 } 3786 3787 /* Initialize the structure */ 3788 bcm_trill_port_t_init(trill_port); 3789 BCM_GPORT_TRILL_PORT_ID_SET(trill_port->trill_port_id, vp); 3790 3791 BCM_IF_ERROR_RETURN( 3792 soc_mem_read(unit, EGR_DVP_ATTRIBUTEm, 3793 MEM_BLOCK_ALL, vp, &egr_dvp_attribute)); 3794 3795 trill_port->name = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 3796 &egr_dvp_attribute, EGRESS_RBRIDGE_NICKNAMEf); 3797 trill_port->mtu = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 3798 &egr_dvp_attribute, MTU_VALUEf); 3799 trill_port->hopcount = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 3800 &egr_dvp_attribute, HOPCOUNTf); 3801 3802 BCM_IF_ERROR_RETURN( 3803 soc_mem_read(unit, SOURCE_VPm, 3804 MEM_BLOCK_ALL, vp, &svp)); 3805 3806 trill_port->if_class = soc_mem_field32_get(unit, SOURCE_VPm, 3807 &svp, CLASS_IDf); 3808 3809 BCM_IF_ERROR_RETURN( 3810 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 3811 ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf); 3812 if (ecmp) { 3813 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf); 3814 trill_port->egress_if = nh_ecmp_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 3815 } else { 3816 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 3817 /* Extract next hop index from unipath egress object. */ 3818 if (nh_ecmp_index) { 3819 trill_port->egress_if = nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 3820 } else { 3821 trill_port->flags |= BCM_TRILL_PORT_LOCAL; 3822 } 3823 } 3824 3825 BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info)); 3826 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { 3827 network_port = TRUE; 3828 } 3829 3830 if (network_port) { 3831 trill_port->flags |= BCM_TRILL_PORT_NETWORK; 3832 } 3833 3834 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) { 3835 trill_port->network_group_id = soc_ING_DVP_TABLEm_field32_get 3836 (unit, &dvp, NETWORK_GROUPf); 3837 } 3838 /* Check Tree-ID */ 3839 (void) bcm_td_trill_tree_profile_get (unit, trill_port->name, &trill_tree_id); 3840 if (trill_tree_id < BCM_MAX_NUM_TRILL_TREES) { 3841 trill_port->flags |= BCM_TRILL_PORT_MULTICAST; 3842 BCM_IF_ERROR_RETURN( 3843 soc_mem_read(unit, EGR_TRILL_TREE_PROFILEm, 3844 MEM_BLOCK_ALL, trill_tree_id, &egr_trill_profile)); 3845 trill_port->multicast_hopcount = soc_mem_field32_get(unit, EGR_TRILL_TREE_PROFILEm, 3846 &egr_trill_profile, HOPCOUNTf); 3847 } 3848 3849 return BCM_E_NONE; 3850 } 3851 3852 /* 3853 * Purpose: 3854 * Get all trill ports from TRILL Cloud 3855 * Parameters: 3856 * unit - (IN) Device Number 3857 * port_max - (IN) Maximum number of Trill ports in array 3858 * port_array - (OUT) Array of Trill ports 3859 * port_count - (OUT) Number of Trill ports returned in array 3860 * 3861 * Returns: 3862 * BCM_E_XXX 3863 * Notes: If port_max == 0 and port_array == NULL, actual number of 3864 * trill ports in the TRILL cloud will be returned. 3865 */ 3866 3867 int 3868 bcm_td_trill_port_get_all(int unit, int port_max, bcm_trill_port_t *port_array, int *port_count ) 3869 { 3870 int rv = BCM_E_NONE; 3871 int vp=0; 3872 uint32 num_vp=0; 3873 ing_dvp_table_entry_t dvp; 3874 3875 /* Input parameters check. */ 3876 if (port_max < 0) { 3877 return BCM_E_PARAM; 3878 } 3879 3880 if ((port_max > 0) && (NULL == port_array)) { 3881 return BCM_E_PARAM; 3882 } 3883 3884 if (NULL == port_count) { 3885 return (BCM_E_PARAM); 3886 } 3887 3888 *port_count = 0; 3889 3890 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 3891 for (vp = 0; vp < num_vp; vp++) { 3892 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) { 3893 continue; 3894 } 3895 if (0 == port_max) { 3896 (*port_count)++; 3897 } else { 3898 if (*port_count == port_max) { 3899 break; 3900 } 3901 BCM_IF_ERROR_RETURN( 3902 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 3903 3904 if (0x1 == soc_ING_DVP_TABLEm_field32_get(unit, &dvp, VP_TYPEf)){ 3905 BCM_GPORT_TRILL_PORT_ID_SET(port_array[*port_count].trill_port_id, vp); 3906 rv = bcm_td_trill_port_get(unit, 3907 &port_array[*port_count]); 3908 if (rv<0) { 3909 return rv; 3910 } 3911 (*port_count)++; 3912 } 3913 } 3914 } 3915 return rv; 3916 } 3917 3918 3919 /* 3920 * Purpose: 3921 * Delete Trill port from TRILL Cloud 3922 * Parameters: 3923 * unit - (IN) Device Number 3924 * trill_port_id - (IN) Trill port ID 3925 */ 3926 int 3927 bcm_td_trill_port_delete(int unit, bcm_gport_t trill_port_id) 3928 { 3929 _bcm_td_trill_bookkeeping_t *trill_info; 3930 int vp=0; 3931 source_vp_entry_t svp; 3932 ing_dvp_table_entry_t dvp; 3933 egr_dvp_attribute_entry_t egr_dvp_attribute; 3934 int rv=BCM_E_NONE; 3935 int nh_ecmp_index=-1; 3936 int ecmp =-1; 3937 bcm_trill_name_t trill_name; 3938 uint32 flags=0; 3939 int ref_count=0; 3940 bcm_trill_port_t trill_port; 3941 3942 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 3943 return BCM_E_UNIT; 3944 } 3945 3946 trill_info = TRILL_INFO(unit); 3947 vp = BCM_GPORT_TRILL_PORT_ID_GET(trill_port_id); 3948 if (vp == -1) { 3949 return BCM_E_PARAM; 3950 } 3951 3952 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) { 3953 return BCM_E_NOT_FOUND; 3954 } 3955 3956 bcm_trill_port_t_init(&trill_port); 3957 trill_port.trill_port_id = trill_port_id; 3958 BCM_IF_ERROR_RETURN( 3959 bcm_td_trill_port_get(unit, &trill_port)); 3960 3961 BCM_IF_ERROR_RETURN( 3962 soc_mem_read(unit, EGR_DVP_ATTRIBUTEm, 3963 MEM_BLOCK_ALL, vp, &egr_dvp_attribute)); 3964 3965 trill_name = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 3966 &egr_dvp_attribute, EGRESS_RBRIDGE_NICKNAMEf); 3967 3968 /* Decrement port's VP count */ 3969 rv = _bcm_td_trill_port_cnt_update(unit, trill_port_id, vp, FALSE); 3970 if (rv < 0) { 3971 return rv; 3972 } 3973 3974 3975 BCM_IF_ERROR_RETURN( 3976 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 3977 ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf); 3978 if (ecmp) { 3979 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf); 3980 flags = BCM_L3_MULTIPATH; 3981 BCM_IF_ERROR_RETURN( 3982 bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index)); 3983 } else { 3984 nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 3985 if(nh_ecmp_index != 0) { 3986 BCM_IF_ERROR_RETURN( 3987 bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index)); 3988 } 3989 } 3990 if (nh_ecmp_index) { 3991 #if defined(BCM_TRIUMPH3_SUPPORT) 3992 if (SOC_IS_TRIUMPH3(unit)) { 3993 BCM_IF_ERROR_RETURN( 3994 _bcm_tr3_trill_transit_entry_reset(unit, vp, nh_ecmp_index, ecmp)); 3995 BCM_IF_ERROR_RETURN( 3996 _bcm_tr3_trill_learn_entry_reset(unit, vp)); 3997 3998 } else 3999 #endif /* BCM_TRIUMPH3_SUPPORT */ 4000 { 4001 BCM_IF_ERROR_RETURN( 4002 _bcm_td_trill_transit_entry_reset(unit, vp, nh_ecmp_index, ecmp)); 4003 BCM_IF_ERROR_RETURN( 4004 _bcm_td_trill_learn_entry_reset(unit, vp)); 4005 } 4006 BCM_IF_ERROR_RETURN( 4007 _bcm_td_trill_egress_dvp_reset(unit, vp)); 4008 } else { 4009 #if defined(BCM_TRIUMPH3_SUPPORT) 4010 if (SOC_IS_TRIUMPH3(unit)) { 4011 BCM_IF_ERROR_RETURN( 4012 _bcm_tr3_trill_decap_entry_reset(unit, vp)); 4013 } else 4014 #endif /* BCM_TRIUMPH3_SUPPORT */ 4015 { 4016 BCM_IF_ERROR_RETURN( 4017 _bcm_td_trill_decap_entry_reset(unit, vp)); 4018 } 4019 BCM_IF_ERROR_RETURN( 4020 _bcm_td_trill_egress_dvp_reset(unit, vp)); 4021 } 4022 /* Clear the SVP and DVP table entries */ 4023 sal_memset(&svp, 0, sizeof(source_vp_entry_t)); 4024 BCM_IF_ERROR_RETURN( 4025 WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp)); 4026 4027 BCM_IF_ERROR_RETURN( 4028 _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigClear, vp, 4029 ING_DVP_CONFIG_INVALID_VP_TYPE, 4030 ING_DVP_CONFIG_INVALID_INTF_ID, 4031 ING_DVP_CONFIG_INVALID_PORT_TYPE)); 4032 4033 if (trill_port.flags & BCM_TRILL_PORT_LOCAL) { 4034 BCM_IF_ERROR_RETURN( 4035 _bcm_td_trill_header_reset(unit, trill_name)); 4036 } 4037 4038 if (trill_port.flags & BCM_TRILL_PORT_MULTICAST) { 4039 BCM_IF_ERROR_RETURN( 4040 _bcm_td_trill_tree_profile_reset (unit, trill_name)); 4041 } 4042 /* Free RBridge */ 4043 trill_info->rBridge[vp] = 0; 4044 4045 /* Free the VP */ 4046 (void) _bcm_vp_free(unit, _bcmVpTypeTrill, 1, vp); 4047 4048 return rv; 4049 } 4050 4051 /* 4052 * Purpose: 4053 * Delete all Trill ports from TRILL Cloud 4054 * Parameters: 4055 * unit - Device Number 4056 */ 4057 4058 int 4059 bcm_td_trill_port_delete_all(int unit) 4060 { 4061 int rv=BCM_E_NONE; 4062 uint32 vp=0, num_vp=0; 4063 ing_dvp_table_entry_t dvp; 4064 bcm_gport_t trill_port_id; 4065 4066 num_vp = soc_mem_index_count(unit, ING_DVP_TABLEm); 4067 for (vp = 0; vp < num_vp; vp++) { 4068 /* Check for validity of the VP */ 4069 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) { 4070 continue; 4071 } 4072 BCM_IF_ERROR_RETURN( 4073 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 4074 if ((soc_ING_DVP_TABLEm_field32_get(unit, &dvp, VP_TYPEf) == 0x1)) { 4075 BCM_GPORT_TRILL_PORT_ID_SET(trill_port_id, vp); 4076 rv = bcm_td_trill_port_delete(unit, trill_port_id); 4077 if (rv < 0) { 4078 return rv; 4079 } 4080 } 4081 } 4082 return rv; 4083 } 4084 4085 /* 4086 * Function: 4087 * _bcm_td_trill_multicast_transit_entry_key_set 4088 * Purpose: 4089 * Set TRILL Multicast entry key 4090 * Parameters: 4091 * IN : Unit 4092 * IN : Trill Root name 4093 * IN : MPLS entry pointer 4094 * Returns: 4095 * BCM_E_XXX 4096 */ 4097 4098 STATIC int 4099 _bcm_td_trill_multicast_transit_entry_key_set (int unit, bcm_trill_name_t root_name, 4100 mpls_entry_entry_t *tr_ent) 4101 { 4102 uint8 trill_tree_id=0; 4103 4104 (void) bcm_td_trill_tree_profile_get (unit, root_name, &trill_tree_id); 4105 if (trill_tree_id == BCM_MAX_NUM_TRILL_TREES) { 4106 return BCM_E_PARAM; 4107 } 4108 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 4109 TRILL__TREE_IDf, trill_tree_id); 4110 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 4111 KEY_TYPEf, 0x5); 4112 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 4113 TRILL__RBRIDGE_NICKNAMEf, root_name); 4114 soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent, 4115 VALIDf, 0x1); 4116 return BCM_E_NONE; 4117 } 4118 4119 /* 4120 * Purpose: 4121 * Set TRILL Multicast entry for Transit operation 4122 * Parameters: 4123 * unit - (IN) Device Number 4124 * root_name - (IN) trill Root_RBridge 4125 * mc_index - (IN) Multicast index 4126 */ 4127 4128 int 4129 bcm_td_trill_multicast_transit_entry_set(int unit, int flags, 4130 bcm_trill_name_t root_name, int mc_index, uint8 trill_tree_id) 4131 { 4132 mpls_entry_entry_t tr_key, tr_entry; 4133 int rv = BCM_E_UNAVAIL; 4134 int entry_index=0; 4135 4136 sal_memset(&tr_key, 0, sizeof(mpls_entry_entry_t)); 4137 sal_memset(&tr_entry, 0, sizeof(mpls_entry_entry_t)); 4138 4139 (void) _bcm_td_trill_multicast_transit_entry_key_set(unit, root_name, &tr_key); 4140 4141 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &entry_index, 4142 &tr_key, &tr_entry, 0); 4143 if (rv == SOC_E_NONE) { 4144 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_entry, 4145 TRILL__L3MC_INDEXf, mc_index); 4146 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_entry, 4147 TRILL__TREE_IDf, (uint32) trill_tree_id); 4148 /* Enable Multicast traffic */ 4149 if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__MCAST_DST_DISCARDf)) { 4150 if (flags & BCM_TRILL_PORT_DROP) { 4151 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_entry, 4152 TRILL__MCAST_DST_DISCARDf, 0x1); 4153 } else { 4154 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_entry, 4155 TRILL__MCAST_DST_DISCARDf, 0x0); 4156 } 4157 } 4158 rv = soc_mem_write(unit, MPLS_ENTRYm, 4159 MEM_BLOCK_ALL, entry_index, &tr_entry); 4160 } else { 4161 /* Root Entry Must be present */ 4162 return rv; 4163 } 4164 return rv; 4165 4166 } 4167 4168 4169 /* 4170 * Purpose: 4171 * Enable TRILL Multicast traffic 4172 * Parameters: 4173 * unit - (IN) Device Number 4174 * root_name - (IN) trill Root_RBridge 4175 */ 4176 4177 int 4178 bcm_td_trill_multicast_enable(int unit, int flags, bcm_trill_name_t root_name) 4179 { 4180 mpls_entry_entry_t tr_key, tr_entry; 4181 int rv = BCM_E_UNAVAIL; 4182 int entry_index=0; 4183 4184 sal_memset(&tr_key, 0, sizeof(mpls_entry_entry_t)); 4185 sal_memset(&tr_entry, 0, sizeof(mpls_entry_entry_t)); 4186 4187 (void) _bcm_td_trill_multicast_transit_entry_key_set(unit, root_name, &tr_key); 4188 4189 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &entry_index, 4190 &tr_key, &tr_entry, 0); 4191 if (rv == SOC_E_NONE) { 4192 /* Enable Multicast traffic */ 4193 if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__MCAST_DST_DISCARDf)) { 4194 if (flags & BCM_TRILL_PORT_DROP) { 4195 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_entry, 4196 TRILL__MCAST_DST_DISCARDf, 0x1); 4197 } else { 4198 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_entry, 4199 TRILL__MCAST_DST_DISCARDf, 0x0); 4200 } 4201 } 4202 rv = soc_mem_write(unit, MPLS_ENTRYm, 4203 MEM_BLOCK_ALL, entry_index, &tr_entry); 4204 } else { 4205 /* Root Entry Must be present */ 4206 return rv; 4207 } 4208 return rv; 4209 } 4210 4211 4212 /* 4213 * Purpose: 4214 * Disable TRILL Multicast traffic 4215 * Parameters: 4216 * unit - (IN) Device Number 4217 * root_name - (IN) trill Root_RBridge 4218 */ 4219 4220 int 4221 bcm_td_trill_multicast_disable(int unit, int flags, bcm_trill_name_t root_name) 4222 { 4223 mpls_entry_entry_t tr_ent; 4224 int rv = BCM_E_UNAVAIL; 4225 int index=0; 4226 4227 sal_memset(&tr_ent, 0, sizeof(mpls_entry_entry_t)); 4228 4229 (void) _bcm_td_trill_multicast_transit_entry_key_set(unit, root_name, &tr_ent); 4230 4231 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 4232 &tr_ent, &tr_ent, 0); 4233 if (rv < 0) { 4234 return rv; 4235 } 4236 4237 /* Disable Multicast Traffic */ 4238 if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__MCAST_DST_DISCARDf)) { 4239 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 4240 TRILL__MCAST_DST_DISCARDf, 0x1); 4241 } 4242 rv = soc_mem_write(unit, MPLS_ENTRYm, 4243 MEM_BLOCK_ALL, index, &tr_ent); 4244 4245 return rv; 4246 } 4247 4248 /* 4249 * Purpose: 4250 * Reset TRILL Multicast entry for Transit operation 4251 * Parameters: 4252 * unit - (IN) Device Number 4253 * root_name - (IN) trill Root_RBridge 4254 * mc_index - (IN) Multicast index 4255 */ 4256 4257 int 4258 bcm_td_trill_multicast_transit_entry_reset(int unit, bcm_trill_name_t root_name) 4259 { 4260 mpls_entry_entry_t tr_ent; 4261 int rv = BCM_E_UNAVAIL; 4262 int index=0; 4263 4264 sal_memset(&tr_ent, 0, sizeof(mpls_entry_entry_t)); 4265 4266 (void) _bcm_td_trill_multicast_transit_entry_key_set(unit, root_name, &tr_ent); 4267 4268 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 4269 &tr_ent, &tr_ent, 0); 4270 if (rv < 0) { 4271 return rv; 4272 } 4273 4274 /* Remove l3mc_index from HW entry */ 4275 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 4276 TRILL__L3MC_INDEXf, 0); 4277 /* Remove Multicast Tree Id */ 4278 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 4279 TRILL__TREE_IDf, (uint32) 0); 4280 /* Disable Multicast Traffic */ 4281 if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__MCAST_DST_DISCARDf)) { 4282 soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent, 4283 TRILL__MCAST_DST_DISCARDf, 0x1); 4284 } 4285 rv = soc_mem_write(unit, MPLS_ENTRYm, 4286 MEM_BLOCK_ALL, index, &tr_ent); 4287 4288 return rv; 4289 } 4290 4291 /* 4292 * Purpose: 4293 * Get TRILL Multicast entry for Transit operation 4294 * Parameters: 4295 * unit - (IN) Device Number 4296 * root_name - (IN) trill Root_RBridge 4297 * group - (OUT) Multicast Group 4298 */ 4299 4300 int 4301 bcm_td_trill_multicast_transit_entry_get(int unit, bcm_trill_name_t root_name, bcm_multicast_t *group) 4302 { 4303 mpls_entry_entry_t tr_ent; 4304 int rv = BCM_E_UNAVAIL; 4305 int index=0; 4306 4307 sal_memset(&tr_ent, 0, sizeof(mpls_entry_entry_t)); 4308 4309 (void) _bcm_td_trill_multicast_transit_entry_key_set(unit, root_name, &tr_ent); 4310 4311 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index, 4312 &tr_ent, &tr_ent, 0); 4313 if (rv < 0) { 4314 return rv; 4315 } 4316 4317 _BCM_MULTICAST_GROUP_SET(*group, 4318 _BCM_MULTICAST_TYPE_TRILL, 4319 soc_mem_field32_get (unit, MPLS_ENTRYm, (uint32 *)&tr_ent, 4320 TRILL__L3MC_INDEXf)); 4321 return rv; 4322 } 4323 4324 /* 4325 * Purpose: 4326 * Reset all TRILL Multicast entries for Transit operation 4327 * Parameters: 4328 * unit - (IN) Device Number 4329 * tree_id - (IN) trill Tree ID 4330 * mc_index - (IN) Multicast index 4331 */ 4332 4333 int 4334 bcm_td_trill_multicast_transit_entry_reset_all (int unit, uint8 tree_id) 4335 { 4336 int idx=0, num_entries=0; 4337 int rv = BCM_E_UNAVAIL; 4338 mpls_entry_entry_t ment; 4339 int name; 4340 4341 _bcm_td_trill_bookkeeping_t *trill_info = TRILL_INFO(unit); 4342 /* Tree ID and Root name is 1:1 mapping. 4343 Match on Rbridge name to match */ 4344 name = trill_info->rootBridge[tree_id]; 4345 4346 num_entries = soc_mem_index_count(unit, MPLS_ENTRYm); 4347 for (idx = 0; idx < num_entries; idx++) { 4348 rv = READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, idx, &ment); 4349 if (rv < 0) { 4350 return rv; 4351 } 4352 if (!soc_MPLS_ENTRYm_field32_get(unit, &ment, VALIDf)) { 4353 continue; 4354 } 4355 if (soc_MPLS_ENTRYm_field32_get(unit, &ment, KEY_TYPEf) != 0x5) { 4356 continue; 4357 } 4358 4359 if ((soc_MPLS_ENTRYm_field32_get(unit, &ment, 4360 TRILL__TREE_IDf) != tree_id) || 4361 (soc_MPLS_ENTRYm_field32_get(unit, &ment, 4362 TRILL__RBRIDGE_NICKNAMEf) != name)) { 4363 continue; 4364 } 4365 4366 /* Entry found, for a given RBridge Name + Tree ID Key 4367 * there can be only one entry. Hence stop when entry found. 4368 */ 4369 break; 4370 } 4371 4372 /* Set L3MC index to 0, reserved entry with BITMAP = 0 */ 4373 soc_MPLS_ENTRYm_field32_set(unit, &ment, TRILL__L3MC_INDEXf, 0); 4374 4375 /* Write to HW */ 4376 BCM_IF_ERROR_RETURN( 4377 soc_mem_write(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, idx, &ment)); 4378 4379 return BCM_E_NONE; 4380 } 4381 4382 /* 4383 * Purpose: 4384 * Add TRILL multicast entry 4385 * root_name = 0: Add Access -> Network entry 4386 * root_name > 0: Add Network -> Access entry 4387 * Parameters: 4388 * unit - Device Number 4389 * flags 4390 * root_name - (IN) trill Root_RBridge 4391 * vid- (IN) Customer VLAN 4392 * c_dmac - (IN) Customer D-MAC 4393 * group - (IN) Multicast Group ID 4394 */ 4395 4396 int 4397 bcm_td_trill_multicast_add( int unit, uint32 flags, 4398 bcm_trill_name_t root_name, 4399 bcm_vlan_t vid, 4400 bcm_mac_t c_dmac, 4401 bcm_multicast_t group) 4402 { 4403 int l3mc_index=0; 4404 int rv = BCM_E_UNAVAIL; 4405 uint8 trill_tree_id=0; 4406 bcm_mac_t mac_zero = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 4407 4408 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 4409 return BCM_E_UNIT; 4410 } 4411 4412 /* Check Vlan range */ 4413 if (vid >= BCM_VLAN_INVALID) { 4414 return BCM_E_PARAM; 4415 } 4416 4417 /* Check DA */ 4418 if (c_dmac == NULL) { 4419 return BCM_E_PARAM; 4420 } 4421 4422 /* Check Tree-ID */ 4423 (void) bcm_td_trill_tree_profile_get (unit, root_name, &trill_tree_id); 4424 if (trill_tree_id >= BCM_MAX_NUM_TRILL_TREES) { 4425 return BCM_E_PARAM; 4426 } 4427 4428 flags |= BCM_TRILL_MULTICAST_STATIC; 4429 4430 if (flags & BCM_TRILL_MULTICAST_ACCESS_TO_NETWORK) { 4431 4432 l3mc_index = _BCM_MULTICAST_ID_GET(group); 4433 BCM_TRILL_L3MC_CHECK (unit, l3mc_index); 4434 if (vid != BCM_VLAN_NONE){ 4435 /* TRILL_Network Domain entry */ 4436 BCM_IF_ERROR_RETURN( 4437 _bcm_esw_trill_multicast_entry_add(unit, flags, 4438 TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS, 4439 vid, c_dmac, trill_tree_id, group)); 4440 4441 /* Access-domain Entry - Update */ 4442 BCM_IF_ERROR_RETURN( 4443 _bcm_esw_trill_multicast_entry_update(unit, TR_L2_HASH_KEY_TYPE_BRIDGE, 4444 vid, c_dmac, trill_tree_id, group)); 4445 } 4446 4447 /* Set EGR_IPMC.trill_tree_id */ 4448 rv = bcm_td_multicast_trill_group_update(unit, l3mc_index, trill_tree_id); 4449 } else { 4450 4451 /* TRILL-Network Domain - Unpruned entry */ 4452 if ((vid == BCM_VLAN_NONE) && (!sal_memcmp(c_dmac, mac_zero, sizeof(bcm_mac_t)))) { 4453 4454 l3mc_index = _BCM_MULTICAST_ID_GET(group); 4455 BCM_TRILL_L3MC_CHECK (unit, l3mc_index); 4456 4457 rv = _bcm_esw_trill_multicast_transit_entry_set(unit, flags, 4458 root_name, l3mc_index, trill_tree_id); 4459 4460 } else if ((!sal_memcmp(c_dmac, mac_zero, sizeof(bcm_mac_t))) && (vid != BCM_VLAN_NONE)) { 4461 4462 l3mc_index = _BCM_MULTICAST_ID_GET(group); 4463 BCM_TRILL_L3MC_CHECK (unit, l3mc_index); 4464 4465 rv = _bcm_esw_trill_multicast_enable(unit, flags, root_name); 4466 BCM_IF_ERROR_RETURN (rv); 4467 4468 /* TRILL-Network Domain - Pruned entry - Short */ 4469 rv = _bcm_esw_trill_multicast_entry_add(unit, flags, 4470 TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT, 4471 vid, c_dmac, trill_tree_id, group); 4472 } else if (vid != BCM_VLAN_NONE) { 4473 4474 l3mc_index = _BCM_MULTICAST_ID_GET(group); 4475 BCM_TRILL_L3MC_CHECK (unit, l3mc_index); 4476 4477 rv = _bcm_esw_trill_multicast_enable(unit, flags, root_name); 4478 BCM_IF_ERROR_RETURN (rv); 4479 4480 /* TRILL-Network Domain - Pruned entry - Long */ 4481 rv = _bcm_esw_trill_multicast_entry_add(unit, flags, 4482 TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG, 4483 vid, c_dmac, trill_tree_id, group); 4484 } 4485 } 4486 return rv; 4487 } 4488 4489 /* 4490 * Purpose: 4491 * Delete TRILL multicast entry 4492 * Parameters: 4493 * unit - Device Number 4494 * flags 4495 * root_name - (IN) trill Root_RBridge 4496 * vid- (IN) Customer VLAN 4497 * c_dmac (IN) Customer D-MAC 4498 * access_domain_group - (IN) Multicast Group ID 4499 * trill_domain_group - (IN) Multicast Group ID 4500 */ 4501 4502 int 4503 bcm_td_trill_multicast_delete(int unit, uint32 flags, 4504 bcm_trill_name_t root_name, 4505 bcm_vlan_t vid, 4506 bcm_mac_t c_dmac) 4507 { 4508 int rv = BCM_E_NONE; 4509 uint8 trill_tree_id=0; 4510 bcm_mac_t mac_zero = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 4511 4512 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 4513 return BCM_E_UNIT; 4514 } 4515 4516 /* Check Vlan range */ 4517 if (vid >= BCM_VLAN_INVALID) { 4518 return BCM_E_PARAM; 4519 } 4520 4521 /* Check DA */ 4522 if (c_dmac == NULL) { 4523 return BCM_E_PARAM; 4524 } 4525 4526 /* Check Tree-ID */ 4527 (void) bcm_td_trill_tree_profile_get (unit, root_name, &trill_tree_id); 4528 if (trill_tree_id >= BCM_MAX_NUM_TRILL_TREES) { 4529 return BCM_E_PARAM; 4530 } 4531 4532 if (flags & BCM_TRILL_MULTICAST_ACCESS_TO_NETWORK) { 4533 4534 if (vid != BCM_VLAN_NONE){ 4535 /* TRILL_Network Domain entry */ 4536 rv = _bcm_esw_trill_multicast_entry_delete(unit, 4537 TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS, 4538 vid, c_dmac, trill_tree_id); 4539 } 4540 } else { 4541 /* TRILL-Network Domain - Unpruned entry */ 4542 if ((vid == BCM_VLAN_NONE) && (!sal_memcmp(c_dmac, mac_zero, sizeof(bcm_mac_t)))) { 4543 rv = _bcm_esw_trill_multicast_transit_entry_reset(unit, 4544 root_name); 4545 } else if ((!sal_memcmp(c_dmac, mac_zero, sizeof(bcm_mac_t))) && (vid != BCM_VLAN_NONE)) { 4546 BCM_IF_ERROR_RETURN (rv); 4547 /* TRILL-Network Domain - Pruned entry - Short */ 4548 rv = _bcm_esw_trill_multicast_entry_delete(unit, 4549 TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT, 4550 vid, c_dmac, trill_tree_id); 4551 } else if (vid != BCM_VLAN_NONE) { 4552 BCM_IF_ERROR_RETURN (rv); 4553 /* TRILL-Network Domain - Pruned entry - Long */ 4554 rv = _bcm_esw_trill_multicast_entry_delete(unit, 4555 TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG, 4556 vid, c_dmac, trill_tree_id); 4557 } 4558 } 4559 return rv; 4560 } 4561 4562 /* 4563 * Purpose: 4564 * Delete all TRILL multicast entries 4565 * Parameters: 4566 * unit - Device Number 4567 */ 4568 4569 int 4570 bcm_td_trill_multicast_delete_all(int unit, bcm_trill_name_t root_name) 4571 { 4572 int rv=BCM_E_UNAVAIL; 4573 uint8 trill_tree_id=0; 4574 4575 (void) bcm_td_trill_tree_profile_get (unit, root_name, &trill_tree_id); 4576 if (trill_tree_id >= BCM_MAX_NUM_TRILL_TREES) { 4577 return BCM_E_PARAM; 4578 } 4579 4580 BCM_IF_ERROR_RETURN( 4581 _bcm_esw_trill_multicast_transit_entry_reset_all (unit, trill_tree_id)); 4582 4583 rv = _bcm_esw_trill_multicast_entry_delete_all(unit, trill_tree_id); 4584 4585 return rv; 4586 } 4587 4588 /* 4589 * Purpose: 4590 * Get TRILL multicast entry 4591 * Parameters: 4592 * unit - Device Number 4593 * trill_mc_entry - Trill Multicast Entry 4594 */ 4595 4596 int 4597 bcm_td_trill_multicast_entry_get( int unit, 4598 bcm_trill_multicast_entry_t *trill_mc_entry) 4599 { 4600 _bcm_td_trill_bookkeeping_t *trill_info; 4601 int rv = BCM_E_NONE; 4602 uint8 trill_tree_id=0; 4603 bcm_mac_t mac_zero = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 4604 int l3mc_index=0; 4605 4606 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 4607 return BCM_E_UNIT; 4608 } 4609 trill_info = TRILL_INFO(unit); 4610 4611 /* Check Vlan range */ 4612 if (trill_mc_entry->c_vlan >= BCM_VLAN_INVALID) { 4613 return BCM_E_PARAM; 4614 } 4615 4616 /* Check DA */ 4617 /* coverity[array_null] */ 4618 if (trill_mc_entry->c_dmac == NULL) { 4619 return BCM_E_PARAM; 4620 } 4621 4622 trill_mc_entry->flags |= BCM_TRILL_MULTICAST_STATIC; 4623 4624 if (trill_mc_entry->flags & BCM_TRILL_MULTICAST_ACCESS_TO_NETWORK) { 4625 4626 if (trill_mc_entry->c_vlan != BCM_VLAN_NONE){ 4627 rv = _bcm_esw_trill_multicast_entry_get(unit, TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS, 4628 trill_mc_entry->c_vlan, trill_mc_entry->c_dmac, 4629 trill_tree_id, &trill_mc_entry->group); 4630 l3mc_index = _BCM_MULTICAST_ID_GET(trill_mc_entry->group); 4631 BCM_TRILL_L3MC_CHECK (unit, l3mc_index); 4632 rv = bcm_td_multicast_trill_group_get(unit, l3mc_index, &trill_tree_id); 4633 trill_mc_entry->root_name = trill_info->rootBridge[trill_tree_id]; 4634 } else if (trill_mc_entry->c_vlan == BCM_VLAN_NONE) { 4635 /* Get EGR_IPMC.trill_tree_id */ 4636 l3mc_index = _BCM_MULTICAST_ID_GET(trill_mc_entry->group); 4637 BCM_TRILL_L3MC_CHECK (unit, l3mc_index); 4638 rv = bcm_td_multicast_trill_group_get(unit, l3mc_index, &trill_tree_id); 4639 trill_mc_entry->root_name = trill_info->rootBridge[trill_tree_id]; 4640 } 4641 } else { 4642 /* Check Tree-ID */ 4643 (void) bcm_td_trill_tree_profile_get (unit, trill_mc_entry->root_name, &trill_tree_id); 4644 if (trill_tree_id >= BCM_MAX_NUM_TRILL_TREES) { 4645 return BCM_E_PARAM; 4646 } 4647 4648 if ((trill_mc_entry->c_vlan == BCM_VLAN_NONE) && 4649 (!sal_memcmp(trill_mc_entry->c_dmac, mac_zero, sizeof(bcm_mac_t)))) { 4650 rv = _bcm_esw_trill_multicast_transit_entry_get(unit, 4651 trill_mc_entry->root_name, &trill_mc_entry->group); 4652 } else if ((!sal_memcmp(trill_mc_entry->c_dmac, mac_zero, sizeof(bcm_mac_t))) && 4653 (trill_mc_entry->c_vlan != BCM_VLAN_NONE)) { 4654 /* TRILL-Network Domain - Unpruned entry */ 4655 rv = _bcm_esw_trill_multicast_entry_get(unit, TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT, 4656 trill_mc_entry->c_vlan, trill_mc_entry->c_dmac, 4657 trill_tree_id, &trill_mc_entry->group); 4658 } else if (trill_mc_entry->c_vlan != BCM_VLAN_NONE) { 4659 /* TRILL-Network Domain - Pruned entry - Long */ 4660 rv = _bcm_esw_trill_multicast_entry_get(unit, TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG, 4661 trill_mc_entry->c_vlan, trill_mc_entry->c_dmac, 4662 trill_tree_id, &trill_mc_entry->group); 4663 } 4664 } 4665 return rv; 4666 } 4667 4668 /* 4669 * Purpose: 4670 * Verify Trill Multicast group 4671 * Parameters: 4672 * unit - (IN) Unit number. 4673 * l3mc_group - (IN) Multicast Group 4674 * Returns: 4675 * BCM_E_XXX 4676 * Notes: 4677 */ 4678 int 4679 bcm_td_trill_multicast_check(int unit, bcm_multicast_t l3mc_group) 4680 { 4681 _bcm_td_trill_bookkeeping_t *trill_info = TRILL_INFO(unit); 4682 int rv=BCM_E_UNAVAIL; 4683 int l3mc_index=0; 4684 4685 if (_BCM_MULTICAST_IS_TRILL(l3mc_group)) { 4686 l3mc_index = _BCM_MULTICAST_ID_GET(l3mc_group); 4687 if (trill_info->multicast_count[l3mc_index].network_port_count) { 4688 BCM_TRILL_L3MC_CHECK (unit, l3mc_index); 4689 return BCM_E_NONE; 4690 } 4691 } 4692 return rv; 4693 } 4694 4695 4696 4697 /* 4698 * Description: 4699 * Traverse TRILL Unpruned Multicast entries 4700 * Parameters: 4701 * unit - device number 4702 * trav_st - Traverse structure with all the data. 4703 * Return: 4704 * BCM_E_XXX 4705 */ 4706 int 4707 bcm_td_trill_unpruned_entry_traverse (int unit, _bcm_td_trill_multicast_entry_traverse_t *trav_st) 4708 { 4709 /* Indexes to iterate over memories, chunks and entries */ 4710 int chnk_idx=0, ent_idx=0, chnk_idx_max=0, mem_idx_max=0; 4711 int buf_size=0, chunksize=0, chnk_end=0; 4712 uint32 *unpruned_trill_tbl_chnk; 4713 mpls_entry_entry_t *ment; 4714 int rv = BCM_E_NONE; 4715 soc_mem_t mem; 4716 int key_type=0; 4717 uint8 tree_id=0xff; 4718 bcm_trill_name_t root_name=0; 4719 bcm_trill_multicast_entry_t trill_mc; 4720 4721 sal_memset (&trill_mc, 0, sizeof (bcm_trill_multicast_entry_t)); 4722 4723 mem = MPLS_ENTRYm; 4724 4725 if (!soc_mem_index_count(unit, mem)) { 4726 return BCM_E_NONE; 4727 } 4728 4729 chunksize = 4096; 4730 4731 buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize; 4732 unpruned_trill_tbl_chnk = soc_cm_salloc(unit, buf_size, "trill multicast unpruned traverse"); 4733 if (NULL == unpruned_trill_tbl_chnk) { 4734 return BCM_E_MEMORY; 4735 } 4736 4737 mem_idx_max = soc_mem_index_max(unit, mem); 4738 for (chnk_idx = soc_mem_index_min(unit, mem); 4739 chnk_idx <= mem_idx_max; chnk_idx += chunksize) { 4740 sal_memset((void *)unpruned_trill_tbl_chnk, 0, buf_size); 4741 4742 chnk_idx_max = 4743 ((chnk_idx + chunksize) < mem_idx_max) ? 4744 (chnk_idx + chunksize - 1) : mem_idx_max; 4745 4746 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 4747 chnk_idx, chnk_idx_max, unpruned_trill_tbl_chnk); 4748 if (SOC_FAILURE(rv)) { 4749 break; 4750 } 4751 chnk_end = (chnk_idx_max - chnk_idx); 4752 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) { 4753 ment = soc_mem_table_idx_to_pointer(unit, mem, mpls_entry_entry_t *, 4754 unpruned_trill_tbl_chnk, ent_idx); 4755 4756 if (!soc_mem_field32_get(unit, mem, ment, VALIDf)) { 4757 continue; 4758 } 4759 4760 /* Match the Key Type to TRILL */ 4761 key_type = soc_mem_field32_get(unit, mem, ment, KEY_TYPEf); 4762 4763 if (key_type != 0x5) { /* RBRIDGE_NICKNAME */ 4764 continue; 4765 } 4766 4767 /* Skip entries that discard multicast destinations */ 4768 if (soc_mem_field_valid(unit, MPLS_ENTRYm, 4769 TRILL__MCAST_DST_DISCARDf)) { 4770 if (soc_mem_field32_get(unit, 4771 mem, ment, TRILL__MCAST_DST_DISCARDf)) { 4772 continue; 4773 } 4774 } 4775 4776 4777 /* Check for Valid Tree_Id */ 4778 tree_id = soc_mem_field32_get(unit, mem, ment, TRILL__TREE_IDf); 4779 if (tree_id >= BCM_MAX_NUM_TRILL_TREES ) { 4780 continue; 4781 } 4782 root_name = soc_mem_field32_get(unit, mem, ment, TRILL__RBRIDGE_NICKNAMEf); 4783 (void) bcm_td_trill_root_name_get (unit, tree_id, &trill_mc.root_name); 4784 if (root_name != trill_mc.root_name) { 4785 continue; 4786 } 4787 4788 _BCM_MULTICAST_GROUP_SET(trill_mc.group, 4789 _BCM_MULTICAST_TYPE_TRILL, 4790 soc_mem_field32_get (unit, mem, ment, 4791 TRILL__L3MC_INDEXf)); 4792 4793 rv = trav_st->user_cb(unit, &trill_mc, trav_st->user_data); 4794 if (BCM_FAILURE(rv)) { 4795 break; 4796 } 4797 } 4798 if (BCM_FAILURE(rv)) { 4799 break; 4800 } 4801 } 4802 soc_cm_sfree(unit, unpruned_trill_tbl_chnk); 4803 return rv; 4804 } 4805 4806 /* 4807 * Description: 4808 * Traverse TRILL Access Default Multicast entries 4809 * Parameters: 4810 * unit - device number 4811 * trav_st - Traverse structure with all the data. 4812 * Return: 4813 * BCM_E_XXX 4814 */ 4815 int 4816 bcm_td_trill_access_default_multicast_entry_traverse (int unit, _bcm_td_trill_multicast_entry_traverse_t *trav_st) 4817 { 4818 /* Indexes to iterate over memories, chunks and entries */ 4819 int chnk_idx=0, ent_idx=0, chnk_idx_max=0, mem_idx_max=0; 4820 int buf_size=0, chunksize=0, chnk_end=0; 4821 uint32 *access_trill_vlan_chnk; 4822 vlan_tab_entry_t *vlant; 4823 int rv = BCM_E_NONE; 4824 soc_mem_t mem; 4825 int bc_f=0, uuc_f=0, umc_f=0; 4826 bcm_trill_multicast_entry_t trill_mc; 4827 4828 sal_memset (&trill_mc, 0, sizeof (bcm_trill_multicast_entry_t)); 4829 4830 mem = VLAN_TABm; 4831 4832 if (!soc_mem_index_count(unit, mem)) { 4833 return BCM_E_NONE; 4834 } 4835 4836 chunksize = 1024; 4837 4838 buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize; 4839 access_trill_vlan_chnk = soc_cm_salloc(unit, buf_size, "trill access default multicast traverse"); 4840 if (NULL == access_trill_vlan_chnk) { 4841 return BCM_E_MEMORY; 4842 } 4843 4844 mem_idx_max = soc_mem_index_max(unit, mem); 4845 for (chnk_idx = soc_mem_index_min(unit, mem); 4846 chnk_idx <= mem_idx_max; chnk_idx += chunksize) { 4847 sal_memset((void *)access_trill_vlan_chnk, 0, buf_size); 4848 4849 chnk_idx_max = 4850 ((chnk_idx + chunksize) < mem_idx_max) ? 4851 (chnk_idx + chunksize - 1) : mem_idx_max; 4852 4853 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 4854 chnk_idx, chnk_idx_max, access_trill_vlan_chnk); 4855 if (SOC_FAILURE(rv)) { 4856 break; 4857 } 4858 chnk_end = (chnk_idx_max - chnk_idx); 4859 for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) { 4860 vlant = soc_mem_table_idx_to_pointer(unit, mem, vlan_tab_entry_t *, 4861 access_trill_vlan_chnk, ent_idx); 4862 4863 if (!soc_mem_field32_get(unit, mem, vlant, VALIDf)) { 4864 continue; 4865 } 4866 4867 if (SOC_MEM_FIELD_VALID(unit, mem, 4868 BC_TRILL_NETWORK_RECEIVERS_PRESENTf)) { 4869 bc_f = soc_mem_field32_get(unit, mem, vlant, 4870 BC_TRILL_NETWORK_RECEIVERS_PRESENTf); 4871 } 4872 if (SOC_MEM_FIELD_VALID(unit, mem, 4873 UMC_TRILL_NETWORK_RECEIVERS_PRESENTf)) { 4874 umc_f = soc_mem_field32_get(unit, VLAN_TABm, vlant, 4875 UMC_TRILL_NETWORK_RECEIVERS_PRESENTf); 4876 } 4877 if (SOC_MEM_FIELD_VALID(unit, mem, 4878 UUC_TRILL_NETWORK_RECEIVERS_PRESENTf)) { 4879 uuc_f = soc_mem_field32_get(unit, mem, vlant, 4880 UUC_TRILL_NETWORK_RECEIVERS_PRESENTf); 4881 } 4882 4883 if ((!bc_f) && (!uuc_f) && (!umc_f) ) { 4884 continue; 4885 } 4886 4887 _BCM_MULTICAST_GROUP_SET(trill_mc.group, 4888 _BCM_MULTICAST_TYPE_TRILL, 4889 soc_mem_field32_get (unit, mem, vlant, 4890 TRILL_DOMAIN_NONUC_REPL_INDEXf)); 4891 4892 trill_mc.flags = BCM_TRILL_MULTICAST_ACCESS_TO_NETWORK; 4893 rv = bcm_td_multicast_trill_rootname_get(unit, trill_mc.group, &trill_mc.root_name); 4894 if (BCM_FAILURE(rv)) { 4895 continue; 4896 } 4897 rv = trav_st->user_cb(unit, &trill_mc, trav_st->user_data); 4898 if (BCM_FAILURE(rv)) { 4899 break; 4900 } 4901 } 4902 if (BCM_FAILURE(rv)) { 4903 break; 4904 } 4905 } 4906 soc_cm_sfree(unit, access_trill_vlan_chnk); 4907 return rv; 4908 4909 } 4910 4911 /* 4912 * Purpose: 4913 * Traverse all valid TRILL Multicast entries and call the 4914 * supplied callback routine. 4915 * Parameters: 4916 * unit - Device Number 4917 * cb - User callback function, called once per Trill Multicast entry. 4918 * user_data - cookie 4919 */ 4920 4921 int 4922 bcm_td_trill_multicast_traverse(int unit, bcm_trill_multicast_entry_traverse_cb cb, 4923 void *user_data) 4924 { 4925 _bcm_td_trill_multicast_entry_traverse_t trav_st; 4926 int rv = BCM_E_NONE; 4927 4928 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 4929 return BCM_E_UNIT; 4930 } 4931 /* If no callback provided, we are done. */ 4932 if (NULL == cb) { 4933 return BCM_E_NONE; 4934 } 4935 4936 sal_memset(&trav_st, 0, sizeof(_bcm_td_trill_multicast_entry_traverse_t)); 4937 4938 trav_st.user_cb = cb; 4939 trav_st.user_data = user_data; 4940 4941 /* Traverse Unpruned Trill Multicast entry */ 4942 rv = _bcm_esw_trill_unpruned_entry_traverse(unit, &trav_st); 4943 if (BCM_SUCCESS(rv)) { 4944 /* Traverse Pruned Trill Network Multicast entry */ 4945 rv = _bcm_esw_trill_network_multicast_entry_traverse(unit, &trav_st); 4946 if (BCM_SUCCESS(rv)) { 4947 /* Traverse Trill Access Multicast entry */ 4948 rv = _bcm_esw_trill_access_multicast_entry_traverse(unit, &trav_st); 4949 if (BCM_SUCCESS(rv)) { 4950 /* Traverse Trill default Multicast entry */ 4951 rv = bcm_td_trill_access_default_multicast_entry_traverse(unit, &trav_st); 4952 } 4953 } 4954 } 4955 return rv; 4956 } 4957 4958 4959 /* 4960 * Purpose: 4961 * Add C-VLAN multicast_idx when enabled for TRILL 4962 * Parameters: 4963 * unit - (IN) Unit number. 4964 * vlan - (IN) C-VLAN 4965 * vtab - (IN/OUT) Vlan Table entry 4966 * Returns: 4967 * BCM_E_XXX 4968 * Notes: 4969 */ 4970 int 4971 bcm_td_trill_vlan_multicast_group_add(int unit, bcm_vlan_t vlan, vlan_tab_entry_t *vtab) 4972 { 4973 bcm_pbmp_t vlan_pbmp, vlan_ubmp, pbmp, l3_pbmp; 4974 soc_field_t group_type[3] = {BC_IDXf, UMC_IDXf, UUC_IDXf}; 4975 int i=0, mc_idx=0; 4976 int rv = BCM_E_NONE; 4977 bcm_multicast_t mc_grp; 4978 4979 /* Enable VP switching on the VLAN */ 4980 if (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) { 4981 if (!soc_mem_field32_get(unit, VLAN_TABm, vtab, 4982 TRILL_ACCESS_RECEIVERS_PRESENTf)) { 4983 soc_mem_field32_set(unit, VLAN_TABm, vtab, 4984 TRILL_ACCESS_RECEIVERS_PRESENTf, 1); 4985 4986 rv = bcm_td_l2_trill_vlan_multicast_entry_modify (unit, vlan, 0x1); 4987 if (rv < 0) { 4988 return rv; 4989 } 4990 4991 if (SHR_BITGET(vlan_info[unit].vp_mode, vlan)) { 4992 return rv; 4993 } 4994 4995 soc_mem_field32_set(unit, VLAN_TABm, vtab, VIRTUAL_PORT_ENf, 1); 4996 4997 /* Also need to copy the physical port members to the L2_BITMAP of 4998 * the IPMC entry for each group once we've gone virtual */ 4999 rv = mbcm_driver[unit]->mbcm_vlan_port_get 5000 (unit, vlan, &vlan_pbmp, &vlan_ubmp, NULL); 5001 5002 if (rv < 0) { 5003 return rv; 5004 } 5005 5006 /* Deal with each group */ 5007 for (i = 0; i < 3; i++) { 5008 BCM_PBMP_CLEAR(l3_pbmp); 5009 mc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, vtab, group_type[i]); 5010 if (BCM_FAILURE(_bcm_tr_multicast_ipmc_group_type_get(unit, 5011 mc_idx, &mc_grp))) { 5012 continue; 5013 } 5014 if ((mc_idx >= 0) && 5015 (mc_idx < soc_mem_index_count(unit, L3_IPMCm))) { 5016 rv = _bcm_esw_multicast_ipmc_read(unit, mc_idx, &pbmp, 5017 &l3_pbmp); 5018 if (rv < 0) { 5019 return rv; 5020 } 5021 rv = _bcm_esw_multicast_ipmc_write(unit, mc_idx, vlan_pbmp, 5022 l3_pbmp, TRUE); 5023 if (rv < 0) { 5024 return rv; 5025 } 5026 } 5027 } 5028 } 5029 } 5030 return rv; 5031 } 5032 5033 /* 5034 * Purpose: 5035 * Delete C-VLAN multicast_idx when enabled for TRILL 5036 * Parameters: 5037 * unit - (IN) Unit number. 5038 * vlan - (IN) C-VLAN 5039 * vtab - (IN/OUT) Vlan Table entry 5040 * Returns: 5041 * BCM_E_XXX 5042 * Notes: 5043 */ 5044 int 5045 bcm_td_trill_vlan_multicast_group_delete(int unit, bcm_vlan_t vlan, vlan_tab_entry_t *vtab) 5046 { 5047 bcm_pbmp_t vlan_pbmp, pbmp, l3_pbmp; 5048 soc_field_t group_type[3] = {BC_IDXf, UMC_IDXf, UUC_IDXf}; 5049 int i=0, mc_idx=0; 5050 int rv = BCM_E_NONE; 5051 bcm_multicast_t mc_grp; 5052 5053 /* Enable VP switching on the VLAN */ 5054 if (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) { 5055 if (soc_mem_field32_get(unit, VLAN_TABm, vtab, 5056 TRILL_ACCESS_RECEIVERS_PRESENTf)) { 5057 soc_mem_field32_set(unit, VLAN_TABm, vtab, 5058 TRILL_ACCESS_RECEIVERS_PRESENTf, 0); 5059 5060 rv = bcm_td_l2_trill_vlan_multicast_entry_modify(unit, vlan, 0x0); 5061 if (rv < 0) { 5062 return rv; 5063 } 5064 5065 if (SHR_BITGET(vlan_info[unit].vp_mode, vlan)) { 5066 return rv; 5067 } 5068 5069 soc_mem_field32_set(unit, VLAN_TABm, vtab, VIRTUAL_PORT_ENf, 0); 5070 5071 /* Deal with each group */ 5072 for (i = 0; i < 3; i++) { 5073 BCM_PBMP_CLEAR(pbmp); 5074 mc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, vtab, group_type[i]); 5075 if (BCM_FAILURE(_bcm_tr_multicast_ipmc_group_type_get(unit, 5076 mc_idx, &mc_grp))) { 5077 continue; 5078 } 5079 5080 if ((mc_idx >= 0) && (mc_idx < soc_mem_index_count(unit, L3_IPMCm))) { 5081 rv = _bcm_esw_multicast_ipmc_read(unit, mc_idx, &vlan_pbmp, 5082 &l3_pbmp); 5083 if (rv < 0) { 5084 return rv; 5085 } 5086 rv = _bcm_esw_multicast_ipmc_write(unit, mc_idx, pbmp, 5087 l3_pbmp, TRUE); 5088 if (rv < 0) { 5089 return rv; 5090 } 5091 } 5092 } 5093 } 5094 } 5095 return rv; 5096 5097 } 5098 /* 5099 * Purpose: 5100 * Add TRILL Gports to L2MC 5101 * Parameters: 5102 * unit - (IN) Unit number. 5103 * port - (IN) Gport. 5104 * mc_index - (IN) Multicast Index 5105 * Returns: 5106 * BCM_E_XXX 5107 * Notes: 5108 */ 5109 int 5110 bcm_td_trill_egress_add(int unit, bcm_multicast_t l3mc_group) 5111 { 5112 _bcm_td_trill_bookkeeping_t *trill_info; 5113 int rv = BCM_E_NONE; 5114 int l3mc_index=0; 5115 5116 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 5117 return BCM_E_UNIT; 5118 } 5119 5120 trill_info = TRILL_INFO(unit); 5121 l3mc_index = _BCM_MULTICAST_ID_GET(l3mc_group); 5122 5123 if (trill_info->multicast_count[l3mc_index].network_port_count == 0) { 5124 trill_info->multicast_count[l3mc_index].l3mc_group = l3mc_group; 5125 trill_info->multicast_count[l3mc_index].network_port_count++; 5126 } else if (trill_info->multicast_count[l3mc_index].network_port_count > 0) { 5127 trill_info->multicast_count[l3mc_index].network_port_count++; 5128 } 5129 return rv; 5130 } 5131 5132 /* 5133 * Purpose: 5134 * Delete TRILL Gports from L2MC 5135 * Parameters: 5136 * unit - (IN) Unit number. 5137 * port - (IN) Gport. 5138 * mc_index - (IN) Multicast Index 5139 * Returns: 5140 * BCM_E_XXX 5141 * Notes: 5142 */ 5143 int 5144 bcm_td_trill_egress_delete(int unit, bcm_multicast_t l3mc_group) 5145 { 5146 _bcm_td_trill_bookkeeping_t *trill_info; 5147 int rv = BCM_E_NONE; 5148 int l3mc_index=0; 5149 5150 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 5151 return BCM_E_UNIT; 5152 } 5153 5154 trill_info = TRILL_INFO(unit); 5155 5156 l3mc_index = _BCM_MULTICAST_ID_GET(l3mc_group); 5157 l3mc_group = trill_info->multicast_count[l3mc_index].l3mc_group; 5158 trill_info->multicast_count[l3mc_index].network_port_count--; 5159 5160 return rv; 5161 } 5162 5163 /* 5164 * Function: 5165 * _bcm_td_trill_multicast_source_entry_key_set 5166 * Purpose: 5167 * Set TRILL Multicast RPF entry key 5168 * Parameters: 5169 * IN : Unit 5170 * IN : root_name 5171 * IN : source_name 5172 * IN : gport to desired-neighbor 5173 * IN : entry pointer 5174 * Returns: 5175 * BCM_E_XXX 5176 */ 5177 5178 STATIC int 5179 _bcm_td_trill_multicast_source_entry_key_set(int unit, 5180 bcm_trill_name_t root_name, bcm_trill_name_t source_name, 5181 bcm_gport_t gport, bcm_if_t encap_intf, L3_ENTRY_T *l3_key) 5182 { 5183 int rv = BCM_E_NONE; 5184 uint8 trill_tree_id=0; 5185 bcm_module_t local_modid=-1; 5186 bcm_port_t local_port=-1; 5187 bcm_trunk_t local_tgid=BCM_TRUNK_INVALID; 5188 int local_id=-1; 5189 soc_mem_t mem; 5190 5191 (void) bcm_td_trill_tree_profile_get (unit, root_name, &trill_tree_id); 5192 if (trill_tree_id >= BCM_MAX_NUM_TRILL_TREES) { 5193 return BCM_E_PARAM; 5194 } 5195 rv = _bcm_esw_gport_resolve(unit, gport, &local_modid, 5196 &local_port, &local_tgid, &local_id); 5197 if (rv < 0) { 5198 return SOC_E_UNAVAIL; 5199 } 5200 5201 #if defined(BCM_TRIUMPH3_SUPPORT) 5202 if (SOC_IS_TRIUMPH3(unit)) { 5203 mem = L3_ENTRY_1m; 5204 soc_mem_field32_set(unit, mem, l3_key, KEY_TYPEf, 5205 SOC_MEM_KEY_L3_ENTRY_1_TRILL_TRILL); 5206 } else 5207 #endif /* BCM_TRIUMPH3_SUPPORT */ 5208 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) 5209 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 5210 mem = L3_ENTRY_IPV4_UNICASTm; 5211 soc_mem_field32_set(unit, mem, l3_key, KEY_TYPEf, 5212 TD2_L3_HASH_KEY_TYPE_TRILL); 5213 } else 5214 #endif /* BCM_TRIDENT2_SUPPORT */ 5215 { 5216 mem = L3_ENTRY_IPV4_UNICASTm; 5217 soc_mem_field32_set(unit, mem, l3_key, KEY_TYPEf, 5218 TR_L3_HASH_KEY_TYPE_TRILL); 5219 5220 } 5221 5222 soc_mem_field32_set(unit, mem, l3_key, 5223 TRILL__INGRESS_RBRIDGE_NICKNAMEf, source_name); 5224 soc_mem_field32_set(unit, mem, l3_key, 5225 TRILL__TREE_IDf, trill_tree_id); 5226 if (BCM_TRUNK_INVALID != local_tgid) { 5227 soc_mem_field32_set(unit, mem, l3_key, 5228 TRILL__EXPECTED_TGIDf, local_tgid); 5229 soc_mem_field32_set(unit, mem, l3_key, 5230 TRILL__EXPECTED_Tf, 0x1); 5231 } else { 5232 soc_mem_field32_set(unit, mem, l3_key, 5233 TRILL__EXPECTED_MODULE_IDf, local_modid); 5234 soc_mem_field32_set(unit, mem, l3_key, 5235 TRILL__EXPECTED_PORT_NUMf, local_port); 5236 } 5237 5238 soc_mem_field32_set(unit, mem, l3_key, VALIDf, 1); 5239 return rv; 5240 } 5241 5242 /* 5243 * Purpose: 5244 * Add TRILL multicast RPF entry 5245 * Parameters: 5246 * unit - Device Number 5247 * root_name - (IN) Trill Root_RBridge 5248 * source_name - (IN) Source Rbridge 5249 * port - (IN) Ingress port 5250 */ 5251 5252 int 5253 bcm_td_trill_multicast_source_add( int unit, 5254 bcm_trill_name_t root_name, 5255 bcm_trill_name_t source_name, 5256 bcm_gport_t gport, 5257 bcm_if_t encap_intf) 5258 { 5259 L3_ENTRY_T l3_key, l3_entry; 5260 int rv = BCM_E_NONE; 5261 int l3_entry_index=0; 5262 soc_mem_t mem; 5263 5264 sal_memset(&l3_key, 0, sizeof(L3_ENTRY_T)); 5265 sal_memset(&l3_entry, 0, sizeof(L3_ENTRY_T)); 5266 5267 if (SOC_IS_TRIUMPH3(unit)) { 5268 mem = L3_ENTRY_1m; 5269 } else { 5270 mem = L3_ENTRY_IPV4_UNICASTm; 5271 } 5272 5273 /* Check for Gport type - Mod Port or TRUNK Port */ 5274 if ( (SOC_GPORT_IS_TRUNK(gport)) || 5275 (SOC_GPORT_IS_LOCAL(gport)) || 5276 (SOC_GPORT_IS_DEVPORT(gport)) || 5277 (SOC_GPORT_IS_MODPORT(gport))) { 5278 BCM_IF_ERROR_RETURN( 5279 _bcm_td_trill_multicast_source_entry_key_set(unit, root_name, 5280 source_name, gport, encap_intf, &l3_key)); 5281 } else { 5282 return BCM_E_PARAM; 5283 } 5284 5285 5286 rv = soc_mem_search(unit, mem, 5287 MEM_BLOCK_ANY, &l3_entry_index, 5288 &l3_key, &l3_entry, 0); 5289 if (rv == SOC_E_NONE) { 5290 rv = soc_mem_write(unit, mem, 5291 MEM_BLOCK_ALL, l3_entry_index, &l3_key); 5292 } else if (rv != SOC_E_NOT_FOUND) { 5293 return rv; 5294 } else { 5295 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, &l3_key); 5296 } 5297 return rv; 5298 } 5299 5300 /* 5301 * Purpose: 5302 * Delete TRILL multicast RPF entry 5303 * Parameters: 5304 * unit - Device Number 5305 * root_name - (IN) Trill Root_RBridge 5306 * source_name - (IN) Source Rbridge 5307 * port - (IN) Ingress port 5308 */ 5309 5310 int 5311 bcm_td_trill_multicast_source_delete( int unit, 5312 bcm_trill_name_t root_name, 5313 bcm_trill_name_t source_name, 5314 bcm_gport_t gport, 5315 bcm_if_t encap_intf) 5316 { 5317 L3_ENTRY_T l3_entry; 5318 int rv = BCM_E_UNAVAIL; 5319 int l3_entry_index=0; 5320 soc_mem_t mem; 5321 5322 if (SOC_IS_TRIUMPH3(unit)) { 5323 mem = L3_ENTRY_1m; 5324 } else { 5325 mem = L3_ENTRY_IPV4_UNICASTm; 5326 } 5327 5328 sal_memset(&l3_entry, 0, sizeof(L3_ENTRY_T)); 5329 if ( (SOC_GPORT_IS_TRUNK(gport)) || 5330 (SOC_GPORT_IS_LOCAL(gport)) || 5331 (SOC_GPORT_IS_DEVPORT(gport)) || 5332 (SOC_GPORT_IS_MODPORT(gport))) { 5333 (void) _bcm_td_trill_multicast_source_entry_key_set(unit, root_name, 5334 source_name, gport, encap_intf, &l3_entry); 5335 } else { 5336 return BCM_E_PARAM; 5337 } 5338 5339 rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l3_entry_index, 5340 &l3_entry, &l3_entry, 0); 5341 if (rv < 0) { 5342 return rv; 5343 } 5344 5345 /* Delete the entry from HW */ 5346 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, &l3_entry); 5347 5348 if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) { 5349 return rv; 5350 } else { 5351 return BCM_E_NONE; 5352 } 5353 } 5354 5355 /* 5356 * Purpose: 5357 * Get TRILL multicast RPF entry 5358 * Parameters: 5359 * unit - Device Number 5360 * root_name - (IN) Trill Root_RBridge 5361 * source_name - (IN) Source Rbridge 5362 * port - (OUT) Ingress port 5363 */ 5364 5365 int 5366 bcm_td_trill_multicast_source_get( int unit, 5367 bcm_trill_name_t root_name, 5368 bcm_trill_name_t source_name, 5369 bcm_gport_t *gport) 5370 { 5371 L3_ENTRY_T l3_key, l3_entry; 5372 int l3_entry_index=0; 5373 uint8 trill_tree_id=0; 5374 bcm_module_t module_id=0, mod_out=0; 5375 bcm_port_t port_num=0, port_out=0; 5376 bcm_trunk_t tgid=0; 5377 soc_mem_t mem; 5378 5379 sal_memset(&l3_key, 0, sizeof(L3_ENTRY_T)); 5380 5381 if (SOC_IS_TRIUMPH3(unit)) { 5382 mem = L3_ENTRY_1m; 5383 } else { 5384 mem = L3_ENTRY_IPV4_UNICASTm; 5385 } 5386 5387 (void) bcm_td_trill_tree_profile_get (unit, root_name, &trill_tree_id); 5388 if (trill_tree_id >= BCM_MAX_NUM_TRILL_TREES) { 5389 return BCM_E_PARAM; 5390 } 5391 5392 soc_mem_field32_set(unit, mem, &l3_key, TRILL__INGRESS_RBRIDGE_NICKNAMEf, source_name); 5393 5394 soc_mem_field32_set(unit, mem, &l3_key, TRILL__TREE_IDf, trill_tree_id); 5395 5396 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) 5397 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 5398 soc_mem_field32_set(unit, mem, &l3_key, KEY_TYPEf, 5399 TD2_L3_HASH_KEY_TYPE_TRILL); 5400 } else 5401 #endif /* BCM_TRIDENT2_SUPPORT */ 5402 { 5403 soc_mem_field32_set(unit, mem, &l3_key, KEY_TYPEf, 5404 TR_L3_HASH_KEY_TYPE_TRILL); 5405 } 5406 5407 BCM_IF_ERROR_RETURN ( 5408 soc_mem_search(unit, mem, MEM_BLOCK_ANY, 5409 &l3_entry_index, &l3_key, &l3_entry, 0)); 5410 5411 if (soc_mem_field32_get(unit, mem, &l3_entry, TRILL__EXPECTED_Tf)) { 5412 tgid = soc_mem_field32_get(unit, mem, 5413 &l3_entry, TRILL__EXPECTED_TGIDf); 5414 SOC_GPORT_TRUNK_SET(*gport, tgid); 5415 } else { 5416 module_id = soc_mem_field32_get(unit, mem, 5417 &l3_entry, TRILL__EXPECTED_MODULE_IDf); 5418 port_num = soc_mem_field32_get(unit, mem, 5419 &l3_entry, TRILL__EXPECTED_PORT_NUMf); 5420 BCM_IF_ERROR_RETURN ( 5421 _bcm_gport_modport_hw2api_map(unit, module_id, 5422 port_num, &mod_out, 5423 &port_out)); 5424 SOC_GPORT_MODPORT_SET(*gport, mod_out, port_out); 5425 } 5426 return BCM_E_NONE; 5427 } 5428 5429 /* Purpose: 5430 * Traverse all valid TRILL Multicast RPF entries and call the 5431 * supplied callback routine. 5432 * Parameters: 5433 * unit - Device Number 5434 * cb - User callback function, called once per Trill Multicast entry. 5435 * user_data - cookie 5436 */ 5437 5438 int 5439 bcm_td_trill_multicast_source_traverse(int unit, bcm_trill_multicast_source_traverse_cb cb, 5440 void *user_data) 5441 { 5442 uint32 *l3_entry_p; 5443 uint8 tree_id=0; 5444 bcm_module_t module_id=0, mod_out=0; 5445 bcm_port_t port_num=0, port_out=0; 5446 bcm_trunk_t tgid=0; 5447 bcm_gport_t gport=0; 5448 soc_mem_t mem; 5449 uint32 trill_key_type=0xff; 5450 bcm_trill_name_t root_name=0; 5451 bcm_trill_name_t source_name=0; 5452 5453 int table_ent_size=0; /* Table entry size. */ 5454 int table_size=0; /* Number of entries in the table. */ 5455 int idx_max=0; /* Maximum iteration index. */ 5456 int idx_min=0; /* Minimum iteration index. */ 5457 int idx=0; /* Iterator index. */ 5458 char *l3_tbl_ptr = NULL; /* Table dma pointer. */ 5459 int rv = BCM_E_NONE; /* Operation return value. */ 5460 _bcm_td_trill_bookkeeping_t *trill_info; 5461 5462 trill_info = TRILL_INFO(unit); 5463 5464 /* If no callback provided, we are done. */ 5465 if (NULL == cb) { 5466 return (BCM_E_NONE); 5467 } 5468 5469 if (SOC_IS_TRIUMPH3(unit)) { 5470 mem = L3_ENTRY_1m; 5471 } else { 5472 mem = L3_ENTRY_IPV4_UNICASTm; 5473 } 5474 5475 /* Get table boundaries. */ 5476 idx_max = soc_mem_index_max(unit, mem); 5477 idx_min = soc_mem_index_min(unit, mem); 5478 5479 /* Get single entry size. */ 5480 table_ent_size = BCM_XGS3_L3_ENT_SZ(unit, v4); 5481 5482 soc_mem_lock(unit, mem); 5483 /* Dma the table - to speed up operation. */ 5484 rv = bcm_xgs3_l3_tbl_dma(unit, mem, table_ent_size, 5485 "trill_rpf_tbl", &l3_tbl_ptr, &table_size); 5486 soc_mem_unlock(unit, mem); 5487 5488 if (BCM_FAILURE(rv)) { 5489 if(l3_tbl_ptr) { 5490 soc_cm_sfree(unit, l3_tbl_ptr); 5491 } 5492 return rv; 5493 } 5494 5495 /* Iterate over all the entries - show matching ones. */ 5496 for (idx = idx_min; idx <= idx_max; idx++) { 5497 l3_entry_p = 5498 soc_mem_table_idx_to_pointer(unit, mem, 5499 uint32 *, 5500 l3_tbl_ptr, idx); 5501 5502 /* Check if this is an TRILL RPF entry */ 5503 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) 5504 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 5505 trill_key_type = TD2_L3_HASH_KEY_TYPE_TRILL; 5506 } else 5507 #endif /* BCM_TRIDENT2_SUPPORT */ 5508 { 5509 trill_key_type = TR_L3_HASH_KEY_TYPE_TRILL; 5510 } 5511 if (soc_mem_field32_get(unit, mem, l3_entry_p, KEY_TYPEf) != trill_key_type) { 5512 continue; 5513 } 5514 5515 tree_id = soc_mem_field32_get(unit, mem, l3_entry_p, TRILL__TREE_IDf); 5516 if (!(tree_id < BCM_MAX_NUM_TRILL_TREES)) { 5517 /* Not a vaild Root tree: entry shouldn't exist */ 5518 continue; 5519 } 5520 5521 root_name = trill_info->rootBridge[tree_id]; 5522 source_name = soc_mem_field32_get(unit, mem, l3_entry_p, 5523 TRILL__INGRESS_RBRIDGE_NICKNAMEf); 5524 5525 if (soc_mem_field32_get(unit, mem, l3_entry_p, TRILL__EXPECTED_Tf)) { 5526 tgid = soc_mem_field32_get(unit, mem, 5527 l3_entry_p, TRILL__EXPECTED_TGIDf); 5528 SOC_GPORT_TRUNK_SET(gport, tgid); 5529 } else { 5530 module_id = soc_mem_field32_get(unit, mem, 5531 l3_entry_p, TRILL__EXPECTED_MODULE_IDf); 5532 port_num = soc_mem_field32_get(unit, mem, 5533 l3_entry_p, TRILL__EXPECTED_PORT_NUMf); 5534 rv = _bcm_gport_modport_hw2api_map(unit, module_id, port_num, &mod_out, 5535 &port_out); 5536 if (BCM_FAILURE(rv)) { 5537 break; 5538 } 5539 SOC_GPORT_MODPORT_SET(gport, mod_out, port_out); 5540 } 5541 5542 rv = (*cb) (unit, root_name, source_name, gport, user_data); 5543 #ifdef BCM_CB_ABORT_ON_ERR 5544 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 5545 break; 5546 } 5547 #endif 5548 } 5549 5550 if(l3_tbl_ptr) { 5551 soc_cm_sfree(unit, l3_tbl_ptr); 5552 } 5553 5554 /* Reset last read status. */ 5555 if (BCM_E_NOT_FOUND == rv) { 5556 rv = BCM_E_NONE; 5557 } 5558 5559 return (rv); 5560 } 5561 5562 /* 5563 * Function: 5564 * bcm_td_trill_multicast_source_delete_all 5565 * Purpose: 5566 * Delete all RFP entries in L3 Table 5567 * Parameters: 5568 * unit - Device Number 5569 * Returns: 5570 * BCM_E_XXX 5571 */ 5572 int 5573 bcm_td_trill_multicast_source_delete_all(int unit) 5574 { 5575 uint32 *l3_entry_p; 5576 soc_mem_t mem; 5577 uint32 trill_key_type=0xff; /* L3 Table KEY_TYPE */ 5578 5579 int table_ent_size=0; /* Table entry size. */ 5580 int table_size=0; /* Number of entries in the table. */ 5581 int idx_max=0; /* Maximum iteration index. */ 5582 int idx_min=0; /* Minimum iteration index. */ 5583 int idx=0; /* Iterator index. */ 5584 char *l3_tbl_ptr = NULL; /* Table dma pointer. */ 5585 int rv = BCM_E_NONE; /* Operation return value. */ 5586 5587 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) 5588 if (SOC_IS_TRIDENT2X(unit)|| SOC_IS_TOMAHAWKX(unit)) { 5589 mem = L3_ENTRY_IPV4_UNICASTm; 5590 trill_key_type = TD2_L3_HASH_KEY_TYPE_TRILL; 5591 } else 5592 #endif /* BCM_TRIDENT2_SUPPORT */ 5593 #if defined(BCM_TRIDENT3_SUPPORT) 5594 if (SOC_IS_TRIDENT3X(unit)) { 5595 mem = L3_ENTRY_ONLY_SINGLEm; 5596 trill_key_type = TD2_L3_HASH_KEY_TYPE_TRILL; 5597 } else 5598 #endif /* BCM_TRIDENT3_SUPPORT */ 5599 #if defined(BCM_TRIUMPH3_SUPPORT) 5600 if (SOC_IS_TRIUMPH3(unit)) { 5601 mem = L3_ENTRY_1m; 5602 trill_key_type = SOC_MEM_KEY_L3_ENTRY_1_TRILL_TRILL; 5603 } else 5604 #endif /* BCM_TRIUMPH3_SUPPORT */ 5605 { 5606 mem = L3_ENTRY_IPV4_UNICASTm; 5607 trill_key_type = TR_L3_HASH_KEY_TYPE_TRILL; 5608 } 5609 5610 /* Get table boundaries. */ 5611 idx_max = soc_mem_index_max(unit, mem); 5612 idx_min = soc_mem_index_min(unit, mem); 5613 5614 /* Get single entry size. */ 5615 table_ent_size = BCM_XGS3_L3_ENT_SZ(unit, v4); 5616 5617 soc_mem_lock(unit, mem); 5618 /* Dma the table - to speed up operation. */ 5619 rv = bcm_xgs3_l3_tbl_dma(unit, mem, table_ent_size, 5620 "trill_rpf_tbl", &l3_tbl_ptr, &table_size); 5621 5622 if (BCM_FAILURE(rv)) { 5623 if(l3_tbl_ptr) { 5624 soc_cm_sfree(unit, l3_tbl_ptr); 5625 } 5626 5627 soc_mem_unlock(unit, mem); 5628 return rv; 5629 } 5630 5631 /* Iterate over all the entries - show matching ones. */ 5632 for (idx = idx_min; idx <= idx_max; idx++) { 5633 l3_entry_p = 5634 soc_mem_table_idx_to_pointer(unit, mem, 5635 uint32 *, 5636 l3_tbl_ptr, idx); 5637 5638 5639 /* Skip entry if its not a Trill RFP entry */ 5640 if (soc_mem_field32_get(unit, mem, l3_entry_p, KEY_TYPEf) != trill_key_type) { 5641 continue; 5642 } 5643 5644 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, l3_entry_p); 5645 if (BCM_FAILURE(rv)) { 5646 break; 5647 } 5648 } 5649 5650 /* Free resources */ 5651 if(l3_tbl_ptr) { 5652 soc_cm_sfree(unit, l3_tbl_ptr); 5653 } 5654 5655 soc_mem_unlock(unit, mem); 5656 return (rv); 5657 } 5658 5659 5660 /* 5661 * Function: 5662 * bcm_tr_trill_stat_get 5663 * Purpose: 5664 * Get TRILL Stats 5665 * Parameters: 5666 * unit - (IN) SOC unit # 5667 * port - (IN) Physical port 5668 * stat - (IN) specify the Stat type 5669 * val - (OUT) 64-bit Stats value 5670 * Returns: 5671 * BCM_E_XXX 5672 */ 5673 5674 int 5675 bcm_td_trill_stat_get(int unit, bcm_port_t port, 5676 bcm_trill_stat_t stat, uint64 *val) 5677 { 5678 int rv=BCM_E_NONE; 5679 uint32 reg_val=0; 5680 uint32 val_low=0; 5681 trill_drop_stats_entry_t drop; 5682 bcm_port_t local_port=-1; 5683 int local_id=-1; 5684 5685 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 5686 return BCM_E_UNIT; 5687 } 5688 5689 if (BCM_GPORT_IS_SET(port)) { 5690 if ( (SOC_GPORT_IS_LOCAL(port)) || 5691 (SOC_GPORT_IS_DEVPORT(port)) || 5692 (SOC_GPORT_IS_MODPORT(port))) { 5693 BCM_IF_ERROR_RETURN 5694 (bcm_esw_port_local_get(unit, port, &local_port)); 5695 } else if (SOC_GPORT_IS_TRILL_PORT(port)) { 5696 /* Flex stats not supported for TRILL port */ 5697 return BCM_E_UNAVAIL; 5698 } else { 5699 return BCM_E_PARAM; 5700 } 5701 } else if (SOC_GPORT_INVALID == port) { 5702 local_id = 0; 5703 } else { 5704 local_port = port; 5705 } 5706 5707 COMPILER_64_ZERO(*val); 5708 5709 switch (stat) { 5710 5711 case bcmTrillInPkts: 5712 if (local_port != -1) { 5713 if (SOC_REG_IS_VALID(unit, ING_TRILL_RX_PKTSr)) { 5714 SOC_IF_ERROR_RETURN 5715 (READ_ING_TRILL_RX_PKTSr(unit, local_port, ®_val)); 5716 val_low = 5717 soc_reg_field_get(unit, ING_TRILL_RX_PKTSr, 5718 reg_val, COUNTf); 5719 COMPILER_64_SET(*val, 0, val_low); 5720 } else { 5721 uint64 rval64; 5722 5723 SOC_IF_ERROR_RETURN 5724 (READ_ING_TRILL_RX_PKTS_64r(unit, local_port, &rval64)); 5725 *val = soc_reg64_field_get(unit, ING_TRILL_RX_PKTS_64r, 5726 rval64, COUNTf); 5727 } 5728 } else { 5729 return BCM_E_UNAVAIL; 5730 } 5731 break; 5732 5733 case bcmTrillOutPkts: 5734 if (local_port != -1) { 5735 if (SOC_REG_IS_VALID(unit, EGR_TRILL_TX_PKTSr)) { 5736 SOC_IF_ERROR_RETURN 5737 (READ_EGR_TRILL_TX_PKTSr(unit, local_port, ®_val)); 5738 val_low = 5739 soc_reg_field_get(unit, EGR_TRILL_TX_PKTSr, 5740 reg_val, COUNTf); 5741 COMPILER_64_SET(*val, 0, val_low); 5742 } else { 5743 uint64 rval64; 5744 5745 SOC_IF_ERROR_RETURN 5746 (READ_EGR_TRILL_TX_PKTS_64r(unit, local_port, &rval64)); 5747 *val = soc_reg64_field_get(unit, EGR_TRILL_TX_PKTS_64r, 5748 rval64, COUNTf); 5749 } 5750 } else { 5751 return BCM_E_UNAVAIL; 5752 } 5753 break; 5754 5755 case bcmTrillErrorPkts: 5756 if (local_id == 0) { 5757 BCM_IF_ERROR_RETURN( 5758 soc_mem_read(unit, TRILL_DROP_STATSm, 5759 MEM_BLOCK_ALL, local_id, &drop)); 5760 soc_mem_field64_get(unit, TRILL_DROP_STATSm, 5761 &drop, TRILL_ERROR_DROPSf, val); 5762 } else { 5763 return BCM_E_UNAVAIL; 5764 } 5765 break; 5766 5767 case bcmTrillNameMissPkts: 5768 if (local_id == 0) { 5769 BCM_IF_ERROR_RETURN( 5770 soc_mem_read(unit, TRILL_DROP_STATSm, 5771 MEM_BLOCK_ALL, local_id, &drop)); 5772 soc_mem_field64_get(unit, TRILL_DROP_STATSm, &drop, 5773 TRILL_RBRIDGE_LOOKUP_MISS_DROPSf, val); 5774 } else { 5775 return BCM_E_UNAVAIL; 5776 } 5777 break; 5778 5779 case bcmTrillRpfFailPkts: 5780 if (local_id == 0) { 5781 BCM_IF_ERROR_RETURN( 5782 soc_mem_read(unit, TRILL_DROP_STATSm, 5783 MEM_BLOCK_ALL, local_id, &drop)); 5784 soc_mem_field64_get(unit, TRILL_DROP_STATSm, &drop, 5785 TRILL_RPF_CHECK_FAIL_DROPSf, val); 5786 } else { 5787 return BCM_E_UNAVAIL; 5788 } 5789 break; 5790 5791 case bcmTrillTtlFailPkts: 5792 if (local_id == 0) { 5793 BCM_IF_ERROR_RETURN( 5794 soc_mem_read(unit, TRILL_DROP_STATSm, 5795 MEM_BLOCK_ALL, local_id, &drop)); 5796 soc_mem_field64_get(unit, TRILL_DROP_STATSm, &drop, 5797 TRILL_HOPCOUNT_CHECK_FAIL_DROPSf, val); 5798 } else { 5799 return BCM_E_UNAVAIL; 5800 } 5801 break; 5802 5803 default: 5804 break; 5805 5806 } 5807 5808 return rv; 5809 } 5810 5811 int 5812 bcm_td_trill_stat_get32(int unit, bcm_port_t port, 5813 bcm_trill_stat_t stat, uint32 *val) 5814 { 5815 int rv=BCM_E_NONE; 5816 uint64 val64; 5817 5818 rv = bcm_td_trill_stat_get(unit, port, stat, &val64); 5819 if (rv == BCM_E_NONE) { 5820 *val = COMPILER_64_LO(val64); 5821 } 5822 return rv; 5823 } 5824 5825 /* 5826 * Function: 5827 * bcm_td_trill_stat_clear 5828 * Purpose: 5829 * Clear TRILL Stats 5830 * Parameters: 5831 * unit - (IN) SOC unit # 5832 * port - (IN) Physcial port 5833 * stat - (IN) specify the Stat type 5834 * Returns: 5835 * BCM_E_XXX 5836 */ 5837 5838 int 5839 bcm_td_trill_stat_clear(int unit, bcm_port_t port, 5840 bcm_trill_stat_t stat) 5841 { 5842 int rv=BCM_E_NONE; 5843 uint32 reg_val=0; 5844 trill_drop_stats_entry_t drop; 5845 bcm_port_t local_port=-1; 5846 int local_id=-1; 5847 5848 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 5849 return BCM_E_UNIT; 5850 } 5851 5852 if (BCM_GPORT_IS_SET(port)) { 5853 if ( (SOC_GPORT_IS_LOCAL(port)) || 5854 (SOC_GPORT_IS_DEVPORT(port)) || 5855 (SOC_GPORT_IS_MODPORT(port))) { 5856 BCM_IF_ERROR_RETURN 5857 (bcm_esw_port_local_get(unit, port, &local_port)); 5858 } else if (SOC_GPORT_IS_TRILL_PORT(port)) { 5859 /* Flex stats not supported for TRILL port */ 5860 return BCM_E_UNAVAIL; 5861 } else { 5862 return BCM_E_PARAM; 5863 } 5864 } else if (SOC_GPORT_INVALID == port) { 5865 local_id = 0; 5866 5867 /* Global stats , initialize and read entry */ 5868 sal_memset(&drop, 0, sizeof(trill_drop_stats_entry_t)); 5869 BCM_IF_ERROR_RETURN( 5870 soc_mem_read(unit, TRILL_DROP_STATSm, MEM_BLOCK_ALL, 5871 0, &drop)); 5872 } else { 5873 local_port = port; 5874 } 5875 5876 switch (stat) { 5877 5878 case bcmTrillInPkts: 5879 5880 if (local_port != -1) { 5881 if (SOC_REG_IS_VALID(unit, ING_TRILL_RX_PKTSr)) { 5882 soc_reg_field_set(unit, ING_TRILL_RX_PKTSr, 5883 ®_val, COUNTf, 0); 5884 SOC_IF_ERROR_RETURN 5885 (WRITE_ING_TRILL_RX_PKTSr(unit, local_port, reg_val)); 5886 } else { 5887 uint64 cntval; 5888 uint64 rval64; /* Current 64 bit register data. */ 5889 5890 COMPILER_64_ZERO(cntval); 5891 COMPILER_64_ZERO(rval64); 5892 5893 soc_reg64_field_set(unit, ING_TRILL_RX_PKTS_64r, 5894 &rval64, COUNTf, cntval); 5895 SOC_IF_ERROR_RETURN 5896 (WRITE_ING_TRILL_RX_PKTS_64r(unit, local_port, rval64)); 5897 } 5898 } else { 5899 return BCM_E_UNAVAIL; 5900 } 5901 break; 5902 5903 case bcmTrillOutPkts: 5904 5905 if (local_port != -1) { 5906 if (SOC_REG_IS_VALID(unit, EGR_TRILL_TX_PKTSr)) { 5907 soc_reg_field_set(unit, EGR_TRILL_TX_PKTSr, 5908 ®_val, COUNTf, 0); 5909 SOC_IF_ERROR_RETURN 5910 (WRITE_EGR_TRILL_TX_PKTSr(unit, local_port, reg_val)); 5911 } else { 5912 uint64 cntval; 5913 uint64 rval64; /* Current 64 bit register data. */ 5914 5915 COMPILER_64_ZERO(cntval); 5916 COMPILER_64_ZERO(rval64); 5917 5918 soc_reg64_field_set(unit, EGR_TRILL_TX_PKTS_64r, 5919 &rval64, COUNTf, cntval); 5920 SOC_IF_ERROR_RETURN 5921 (WRITE_EGR_TRILL_TX_PKTS_64r(unit, local_port, rval64)); 5922 } 5923 } else { 5924 return BCM_E_UNAVAIL; 5925 } 5926 break; 5927 5928 case bcmTrillErrorPkts: 5929 5930 if (local_id == 0) { 5931 uint64 mem_val; 5932 COMPILER_64_ZERO(mem_val); 5933 soc_mem_field64_set(unit, TRILL_DROP_STATSm, &drop, 5934 TRILL_ERROR_DROPSf, mem_val); 5935 5936 BCM_IF_ERROR_RETURN 5937 (soc_mem_write(unit, TRILL_DROP_STATSm, 5938 MEM_BLOCK_ALL, local_id, &drop)); 5939 } else { 5940 return BCM_E_UNAVAIL; 5941 } 5942 break; 5943 5944 case bcmTrillNameMissPkts: 5945 5946 if (local_id == 0) { 5947 uint64 mem_val; 5948 COMPILER_64_ZERO(mem_val); 5949 soc_mem_field64_set(unit, TRILL_DROP_STATSm, &drop, 5950 TRILL_RBRIDGE_LOOKUP_MISS_DROPSf, mem_val); 5951 BCM_IF_ERROR_RETURN 5952 (soc_mem_write(unit, TRILL_DROP_STATSm, 5953 MEM_BLOCK_ALL, local_id, &drop)); 5954 } else { 5955 return BCM_E_UNAVAIL; 5956 } 5957 break; 5958 5959 case bcmTrillRpfFailPkts: 5960 5961 if (local_id == 0) { 5962 uint64 mem_val; 5963 COMPILER_64_ZERO(mem_val); 5964 soc_mem_field64_set(unit, TRILL_DROP_STATSm, &drop, 5965 TRILL_RPF_CHECK_FAIL_DROPSf, mem_val); 5966 BCM_IF_ERROR_RETURN 5967 (soc_mem_write(unit, TRILL_DROP_STATSm, 5968 MEM_BLOCK_ALL, local_id, &drop)); 5969 } else { 5970 return BCM_E_UNAVAIL; 5971 } 5972 break; 5973 5974 case bcmTrillTtlFailPkts: 5975 5976 if (local_id == 0) { 5977 uint64 mem_val; 5978 COMPILER_64_ZERO(mem_val); 5979 soc_mem_field64_set(unit, TRILL_DROP_STATSm, &drop, 5980 TRILL_HOPCOUNT_CHECK_FAIL_DROPSf, mem_val); 5981 BCM_IF_ERROR_RETURN 5982 (soc_mem_write(unit, TRILL_DROP_STATSm, 5983 MEM_BLOCK_ALL, local_id, &drop)); 5984 } else { 5985 return BCM_E_UNAVAIL; 5986 } 5987 break; 5988 5989 default: 5990 break; 5991 5992 } 5993 5994 return rv; 5995 } 5996 5997 #ifndef BCM_SW_STATE_DUMP_DISABLE 5998 /* 5999 * Function: 6000 * _bcm_td_trill_sw_dump 6001 * Purpose: 6002 * Displays Trill State information maintained by software. 6003 * Parameters: 6004 * unit - Device unit number 6005 * Returns: 6006 * None 6007 */ 6008 void 6009 _bcm_td_trill_sw_dump(int unit) 6010 { 6011 int idx=0, num_vp=0, num_ipmc=0; 6012 _bcm_td_trill_bookkeeping_t *trill_info = TRILL_INFO(unit); 6013 6014 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 6015 num_ipmc = soc_mem_index_count(unit, L3_IPMCm); 6016 6017 LOG_CLI((BSL_META_U(unit, 6018 "\nRoot Bridges:\n"))); 6019 for (idx = 0; idx < BCM_MAX_NUM_TRILL_TREES; idx++) { 6020 LOG_CLI((BSL_META_U(unit, 6021 "%d "), trill_info->rootBridge[idx])); 6022 } 6023 6024 LOG_CLI((BSL_META_U(unit, 6025 "\n\nrBridges:\n"))); 6026 for (idx = 0; idx < num_vp; idx++) { 6027 if (trill_info->rBridge[idx] != 0) { 6028 LOG_CLI((BSL_META_U(unit, 6029 "Index:%d rBridge nickname:%d\n"), idx, 6030 trill_info->rBridge[idx])); 6031 } 6032 } 6033 6034 LOG_CLI((BSL_META_U(unit, 6035 "\n\nMulticast use count:\n"))); 6036 for (idx = 0; idx < num_ipmc; idx++) { 6037 if (trill_info->multicast_count[idx].network_port_count != 0) { 6038 LOG_CLI((BSL_META_U(unit, 6039 " Multicast group %d use count:%d\n"), 6040 trill_info->multicast_count[idx].l3mc_group, 6041 trill_info->multicast_count[idx].network_port_count)); 6042 } 6043 } 6044 6045 return; 6046 } 6047 6048 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 6049 6050 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */ 6051