multicast.c (42301B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: multicast.c 8 * Purpose: Manages multicast functions 9 */ 10 11 #include <soc/defs.h> 12 #include <sal/core/libc.h> 13 14 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 15 16 #include <soc/drv.h> 17 #include <soc/scache.h> 18 #include <soc/util.h> 19 #include <soc/debug.h> 20 #include <soc/triumph.h> 21 22 #include <bcm/error.h> 23 24 #include <bcm_int/esw/mbcm.h> 25 #include <bcm_int/esw/l3.h> 26 #include <bcm_int/esw/firebolt.h> 27 #include <bcm_int/esw/triumph.h> 28 #ifdef BCM_TRIUMPH2_SUPPORT 29 #include <bcm_int/esw/triumph2.h> 30 #endif 31 #include <bcm_int/esw/virtual.h> 32 #include <bcm_int/esw/xgs3.h> 33 #include <bcm_int/common/multicast.h> 34 #include <bcm_int/esw/multicast.h> 35 #include <bcm_int/esw/trx.h> 36 #include <bcm_int/esw/ipmc.h> 37 #include <bcm_int/esw/virtual.h> 38 #include <bcm_int/esw/switch.h> 39 #include <bcm_int/esw/stack.h> 40 #include <bcm_int/api_xlate_port.h> 41 #include <bcm_int/esw_dispatch.h> 42 #ifdef BCM_TRIDENT_SUPPORT 43 #include <bcm_int/esw/trill.h> 44 #include <bcm_int/esw/trident.h> 45 #endif /* BCM_TRIDENT_SUPPORT */ 46 #ifdef BCM_TRIDENT2_SUPPORT 47 #include <bcm_int/esw/trident2.h> 48 #endif /* BCM_TRIDENT2_SUPPORT */ 49 #include <bcm_int/esw/failover.h> 50 #include <bcm_int/esw/mpls.h> 51 52 uint8 *_multicast_ipmc_group_types[BCM_MAX_NUM_UNITS]; 53 uint8 *bcmi_multicast_multi_group_count[BCM_MAX_NUM_UNITS]; 54 55 /* 56 * Function: 57 * bcmi_multicast_multi_count_set 58 * Purpose: 59 * Record count for Multicast objects at this id. 60 * Parameters: 61 * unit - (IN) StrataSwitch unit number. 62 * group - (IN) multicast group number 63 * count - (OUT) no of elements 64 * Returns: 65 * BCM_E_XXX 66 */ 67 int 68 bcmi_multicast_multi_count_set(int unit, bcm_multicast_t group, 69 int count) 70 { 71 uint32 ipmc_id = _BCM_MULTICAST_ID_GET(group); 72 73 if (bcmi_multicast_multi_group_count[unit] == NULL) { 74 return BCM_E_INIT; 75 } 76 77 bcmi_multicast_multi_group_count[unit][ipmc_id] = count; 78 79 return BCM_E_NONE; 80 } 81 82 /* 83 * Function: 84 * bcmi_multicast_multi_count_get 85 * Purpose: 86 * Retrieve count for Multicast objects at this id. 87 * Parameters: 88 * unit - (IN) StrataSwitch unit number. 89 * group - (IN) multicast group number 90 * count - (OUT) no of elements 91 * Returns: 92 * BCM_E_XXX 93 */ 94 int 95 bcmi_multicast_multi_count_get(int unit, bcm_multicast_t group, 96 int *count) 97 { 98 uint32 ipmc_id = _BCM_MULTICAST_ID_GET(group); 99 100 if (bcmi_multicast_multi_group_count[unit] == NULL) { 101 return BCM_E_INIT; 102 } 103 104 *count = bcmi_multicast_multi_group_count[unit][ipmc_id]; 105 return BCM_E_NONE; 106 } 107 108 109 int 110 _bcm_tr_multicast_ipmc_group_type_set(int unit, bcm_multicast_t group) 111 { 112 uint8 group_type = _BCM_MULTICAST_TYPE_GET(group); 113 uint32 ipmc_id = _BCM_MULTICAST_ID_GET(group); 114 115 /* Don't check if MULTICAST_GROUP_IS_SET because we also want to 116 * be able to clear a group. */ 117 118 if ((_BCM_MULTICAST_TYPE_L2 != group_type)) { 119 if ((ipmc_id < soc_mem_index_min(unit, L3_IPMCm)) || 120 (ipmc_id > soc_mem_index_max(unit, L3_IPMCm))) { 121 return BCM_E_PARAM; 122 } 123 124 /* It's an IPMC type group */ 125 _multicast_ipmc_group_types[unit][ipmc_id] = group_type; 126 127 #ifdef BCM_WARM_BOOT_SUPPORT 128 SOC_CONTROL_LOCK(unit); 129 SOC_CONTROL(unit)->scache_dirty = 1; 130 SOC_CONTROL_UNLOCK(unit); 131 #endif 132 } 133 134 return BCM_E_NONE; 135 } 136 137 int 138 _bcm_tr_multicast_ipmc_group_type_get(int unit, uint32 ipmc_id, 139 bcm_multicast_t *group) 140 { 141 if (SOC_IS_XGS3_FABRIC(unit)) { 142 /* _multicast_ipmc_group_types not initialized for fabric chips. */ 143 *group = 0; 144 return BCM_E_NOT_FOUND; 145 } 146 147 if (ipmc_id >= soc_mem_index_count(unit, L3_IPMCm)) { 148 *group = 0; 149 return BCM_E_NOT_FOUND; 150 } 151 152 if ((NULL != _multicast_ipmc_group_types[unit]) && /* Verify init */ 153 (0 != _multicast_ipmc_group_types[unit][ipmc_id])) { 154 _BCM_MULTICAST_GROUP_SET(*group, 155 _multicast_ipmc_group_types[unit][ipmc_id], 156 ipmc_id); 157 return BCM_E_NONE; 158 } else { 159 *group = 0; 160 return BCM_E_NOT_FOUND; 161 } 162 } 163 164 #ifdef BCM_WARM_BOOT_SUPPORT 165 166 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 167 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 168 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_1 169 170 /* 171 * Function: 172 * _bcm_trx_multicast_sync 173 * Purpose: 174 * Record Multicast module persisitent info for Level 2 Warm Boot 175 * Parameters: 176 * unit - StrataSwitch unit number. 177 * Returns: 178 * BCM_E_XXX 179 */ 180 int 181 _bcm_trx_multicast_sync(int unit) 182 { 183 int ipmc_mem_size, alloc_size=0; 184 soc_scache_handle_t scache_handle; 185 uint8 *multicast_scache; 186 187 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 188 return BCM_E_NONE; 189 } 190 ipmc_mem_size = soc_mem_index_count(unit, L3_IPMCm); 191 alloc_size = ipmc_mem_size * sizeof(uint8); 192 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 193 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1) { 194 alloc_size += ipmc_mem_size * sizeof(uint8); 195 } 196 } 197 198 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MULTICAST, 0); 199 BCM_IF_ERROR_RETURN 200 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 201 alloc_size, 202 &multicast_scache, 203 BCM_WB_DEFAULT_VERSION, NULL)); 204 /* reset alloc size */ 205 alloc_size = ipmc_mem_size * sizeof(uint8); 206 if (_multicast_ipmc_group_types[unit] != NULL) { 207 sal_memcpy(multicast_scache, _multicast_ipmc_group_types[unit], 208 alloc_size); 209 multicast_scache += alloc_size; 210 } 211 212 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 213 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1) { 214 sal_memcpy(multicast_scache, bcmi_multicast_multi_group_count[unit], 215 alloc_size); 216 multicast_scache += alloc_size; 217 } 218 } 219 220 return BCM_E_NONE; 221 } 222 223 typedef struct _bcm_esw_multicast_cb_info_s { 224 uint32 flags; 225 SHR_BITDCL *ipmc_groups_bits; 226 int stale_scache; 227 } _bcm_multicast_cb_info_t; 228 229 /* 230 * Function: 231 * _bcm_trx_multicast_reinit_group 232 * Purpose: 233 * Parse multicast group type and reinitialize the internal structure. 234 * Parameters: 235 * unit - (IN) Device Number 236 * group - (IN) Multicast group ID 237 * mc_cb_info - (IN) data structure pointer passed via the traverse 238 * Returns: 239 * BCM_E_XXX 240 */ 241 STATIC int 242 _bcm_trx_multicast_reinit_group(int unit, bcm_multicast_t group, 243 _bcm_multicast_cb_info_t *mc_cb_info) 244 { 245 int rv, mc_index; 246 uint32 group_flags; 247 uint8 group_type; 248 bcm_multicast_t scache_group; 249 250 mc_index = _BCM_MULTICAST_ID_GET(group); 251 252 if (SHR_BITGET(mc_cb_info->ipmc_groups_bits, mc_index)) { 253 /* Already did this group index, skip */ 254 return BCM_E_NONE; 255 } 256 257 group_type = _BCM_MULTICAST_TYPE_GET(group); 258 259 if (_BCM_MULTICAST_TYPE_L2 == group_type) { 260 /* This shouldn't happen */ 261 return BCM_E_INTERNAL; 262 } 263 264 rv = _bcm_tr_multicast_ipmc_group_type_get(unit, mc_index, 265 &scache_group); 266 267 if (BCM_E_NOT_FOUND == rv) { 268 /* Normal operation at UNCACHED Warm Boot */ 269 } else if (BCM_FAILURE(rv)) { 270 return rv; 271 } else if (scache_group != group) { 272 if (FALSE == mc_cb_info->stale_scache) { 273 if (_BCM_MULTICAST_TYPE_L3 != group_type) { 274 /* We have Level 2 info which tells us it isn't, 275 * L3 type, so go with the saved info. */ 276 } else { 277 /* Stale scache for Warm Boot */ 278 /* We haven't yet complained about the stale scache */ 279 SOC_IF_ERROR_RETURN 280 (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR, 281 SOC_STABLE_STALE, 282 SOC_STABLE_MULTICAST, 0)); 283 mc_cb_info->stale_scache = TRUE; 284 } 285 } /* Else, record this as L3 type */ 286 } else { 287 /* Synchronized scache from Warm Boot Level 2. Nothing to do */ 288 return BCM_E_NONE; 289 } 290 291 group_flags = _bcm_esw_multicast_group_type_to_flags(group_type); 292 /* We record the used group ID's to determine 293 * which ones are pure L3. */ 294 SHR_BITSET(mc_cb_info->ipmc_groups_bits, mc_index); 295 296 if (mc_cb_info->flags & group_flags) { 297 BCM_IF_ERROR_RETURN 298 (_bcm_tr_multicast_ipmc_group_type_set(unit, group)); 299 } else { 300 /* We shouldn't have this type of group for this device! */ 301 return BCM_E_INTERNAL; 302 } 303 304 return BCM_E_NONE; 305 } 306 307 /* 308 * Function: 309 * _bcm_trx_multicast_l2_traverse 310 * Purpose: 311 * Callback for L2 traverse to parse multicast groups. 312 * Parameters: 313 * unit - (IN) Device Number 314 * info - (IN) L2 addr data structure, including multicast group 315 * user_data - (IN) data structure pointer passed via the traverse 316 * Returns: 317 * BCM_E_XXX 318 */ 319 STATIC int 320 _bcm_trx_multicast_l2_traverse(int unit, bcm_l2_addr_t *info, 321 void *user_data) 322 { 323 _bcm_multicast_cb_info_t *mc_cb_info = 324 (_bcm_multicast_cb_info_t *)user_data; 325 326 if (!_BCM_MULTICAST_IS_SET(info->l2mc_group)) { 327 /* Not interested */ 328 return BCM_E_NONE; 329 } 330 331 return _bcm_trx_multicast_reinit_group(unit, info->l2mc_group, 332 mc_cb_info); 333 } 334 335 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 336 /* 337 * Function: 338 * _bcm_trx_multicast_vlan_traverse 339 * Purpose: 340 * Iterate over VLANs and check for multicast groups. 341 * Parameters: 342 * unit - (IN) Device Number 343 * mc_cb_info - (IN) data structure pointer passed via the traverse 344 * Returns: 345 * BCM_E_XXX 346 */ 347 STATIC int 348 _bcm_trx_multicast_vlan_traverse(int unit, 349 _bcm_multicast_cb_info_t *mc_cb_info) 350 { 351 bcm_vlan_t vlan; 352 int rv; 353 bcm_vlan_control_vlan_t control; 354 355 for (vlan = BCM_VLAN_MIN; vlan < BCM_VLAN_COUNT; vlan++) { 356 rv = bcm_esw_vlan_control_vlan_get(unit, vlan, &control); 357 if (BCM_E_PARAM == rv) { 358 /* VLAN isn't created, skip onward */ 359 continue; 360 } else if (BCM_FAILURE(rv)) { 361 return rv; 362 } else { 363 /* Found a VLAN, check it's parameters */ 364 if (_BCM_MULTICAST_IS_SET(control.broadcast_group)) { 365 BCM_IF_ERROR_RETURN 366 (_bcm_trx_multicast_reinit_group(unit, 367 control.broadcast_group, mc_cb_info)); 368 } 369 if (_BCM_MULTICAST_IS_SET(control.unknown_multicast_group)) { 370 BCM_IF_ERROR_RETURN 371 (_bcm_trx_multicast_reinit_group(unit, 372 control.unknown_multicast_group, mc_cb_info)); 373 } 374 if (_BCM_MULTICAST_IS_SET(control.unknown_unicast_group)) { 375 BCM_IF_ERROR_RETURN 376 (_bcm_trx_multicast_reinit_group(unit, 377 control.unknown_unicast_group, mc_cb_info)); 378 } 379 } 380 } 381 382 return BCM_E_NONE; 383 } 384 #endif 385 386 /* 387 * Function: 388 * _bcm_trx_multicast_vfi_traverse 389 * Purpose: 390 * Iterate over VFIs and check for multicast groups. 391 * Parameters: 392 * unit - (IN) Device Number 393 * mc_cb_info - (IN) data structure pointer passed via the traverse 394 * Returns: 395 * BCM_E_XXX 396 */ 397 STATIC int 398 _bcm_trx_multicast_vfi_traverse(int unit, 399 _bcm_multicast_cb_info_t *mc_cb_info) 400 { 401 int vfi, num_vfi; 402 int mc_index; 403 uint32 multicast_type; 404 bcm_multicast_t group; 405 int rv = BCM_E_NONE; 406 char *vfi_tbl_ptr = NULL; /* Table dma pointer. */ 407 void *vfi_entry_ptr = NULL; /* VFI Profile entry buffer pointer.*/ 408 vfi_entry_t vfi_entry; 409 410 if (!SOC_MEM_IS_VALID(unit,VFIm)) { 411 /* if (SOC_IS_HURRICANE(unit)) */ 412 return BCM_E_NONE; 413 } 414 415 num_vfi = soc_mem_index_count(unit, VFIm); 416 rv = bcm_xgs3_l3_tbl_dma(unit, VFIm, 417 sizeof(vfi_entry_t), 418 "vfi", &vfi_tbl_ptr, NULL); 419 if (BCM_FAILURE(rv)) { 420 vfi_tbl_ptr = NULL; 421 } 422 for (vfi = 0; vfi < num_vfi; vfi++) { 423 if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) { 424 multicast_type = _BCM_MULTICAST_TYPE_VPLS; 425 #ifdef BCM_TRIUMPH2_SUPPORT 426 } else if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) { 427 multicast_type = _BCM_MULTICAST_TYPE_MIM; 428 #endif 429 } else { 430 /* Not a VFI we're interested in */ 431 continue; 432 } 433 if (vfi_tbl_ptr == NULL) { 434 vfi_entry_ptr = (vfi_entry_t *)&vfi_entry; 435 sal_memcpy(vfi_entry_ptr, soc_mem_entry_null(unit, VFIm), 436 soc_mem_entry_words(unit, VFIm) * 4); 437 BCM_IF_ERROR_RETURN( 438 READ_VFIm(unit, MEM_BLOCK_ALL, vfi, vfi_entry_ptr)); 439 } else { 440 vfi_entry_ptr = 441 soc_mem_table_idx_to_pointer(unit, VFIm, uint32 *, 442 vfi_tbl_ptr, vfi); 443 /* coverity[var_deref_model : FALSE] */ 444 } 445 #ifdef BCM_TRIUMPH2_SUPPORT 446 if (soc_feature(unit, soc_feature_mpls_enhanced)) { 447 mc_index = soc_VFIm_field32_get(unit, vfi_entry_ptr, BC_INDEXf); 448 _BCM_MULTICAST_GROUP_SET(group, multicast_type, mc_index); 449 rv = _bcm_trx_multicast_reinit_group(unit, group, mc_cb_info); 450 if (BCM_FAILURE(rv)) { 451 goto cleanup; 452 } 453 mc_index = soc_VFIm_field32_get(unit, vfi_entry_ptr, UUC_INDEXf); 454 _BCM_MULTICAST_GROUP_SET(group, multicast_type, mc_index); 455 rv = _bcm_trx_multicast_reinit_group(unit, group, mc_cb_info); 456 if (BCM_FAILURE(rv)) { 457 goto cleanup; 458 } 459 mc_index = soc_VFIm_field32_get(unit, vfi_entry_ptr, UMC_INDEXf); 460 _BCM_MULTICAST_GROUP_SET(group, multicast_type, mc_index); 461 rv = _bcm_trx_multicast_reinit_group(unit, group, mc_cb_info); 462 if (BCM_FAILURE(rv)) { 463 goto cleanup; 464 } 465 } else 466 #endif 467 { 468 mc_index = soc_VFIm_field32_get(unit, vfi_entry_ptr, L3MC_INDEXf); 469 _BCM_MULTICAST_GROUP_SET(group, multicast_type, mc_index); 470 rv = _bcm_trx_multicast_reinit_group(unit, group, mc_cb_info); 471 if (BCM_FAILURE(rv)) { 472 goto cleanup; 473 } 474 } 475 } 476 cleanup: 477 if (vfi_tbl_ptr) { 478 soc_cm_sfree(unit, vfi_tbl_ptr); 479 } 480 return rv; 481 } 482 483 /* 484 * Function: 485 * _bcm_trx_multicast_reinit 486 * Purpose: 487 * Recover Multicast module state for Warm Boot 488 * Parameters: 489 * unit - StrataSwitch unit number. 490 * Returns: 491 * BCM_E_XXX 492 */ 493 STATIC int 494 _bcm_trx_multicast_reinit(int unit) 495 { 496 int mem_size=0, mc_index, is_set, rv = BCM_E_NONE; 497 int alloc_size = 0; 498 soc_scache_handle_t scache_handle; 499 bcm_multicast_t group, scache_group; 500 SHR_BITDCL *ipmc_groups_bits = NULL; 501 uint8 *multicast_scache; 502 _bcm_multicast_cb_info_t mc_cb_info; 503 int num_ipmc_groups; 504 505 /* L3 IPMC info may use scache info */ 506 mem_size = soc_mem_index_count(unit, L3_IPMCm); 507 508 num_ipmc_groups = mem_size; 509 #if defined(BCM_TRIUMPH3_SUPPORT) 510 if (soc_feature(unit, soc_feature_static_repl_head_alloc)) { 511 soc_info_t *si; 512 int member_count; 513 int port, phy_port, mmu_port; 514 /* Each replication group is statically allocated a region 515 * in REPL_HEAD table. The size of the region depends on the 516 * maximum number of valid ports. Thus, the max number of 517 * replication groups is limited to number of REPL_HEAD entries 518 * divided by the max number of valid ports. 519 */ 520 si = &SOC_INFO(unit); 521 member_count = 0; 522 PBMP_ITER(SOC_CONTROL(unit)->repl_eligible_pbmp, port) { 523 phy_port = si->port_l2p_mapping[port]; 524 mmu_port = si->port_p2m_mapping[phy_port]; 525 if ((mmu_port == 57) || (mmu_port == 59) || (mmu_port == 62)) { 526 /* No replication on MMU ports 57, 59, and 62 */ 527 continue; 528 } 529 member_count++; 530 } 531 if (member_count > 0) { 532 num_ipmc_groups = soc_mem_index_count(unit, MMU_REPL_HEAD_TBLm) / 533 member_count; 534 if (num_ipmc_groups > mem_size) { 535 num_ipmc_groups = mem_size; 536 } 537 } 538 } 539 #endif /* BCM_TRIUMPH3_SUPPORT */ 540 541 alloc_size = mem_size * sizeof(uint8); 542 543 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 544 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1) { 545 alloc_size += mem_size * sizeof(uint8); 546 } 547 } 548 549 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MULTICAST, 0); 550 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 551 alloc_size, &multicast_scache, 552 BCM_WB_DEFAULT_VERSION, NULL); 553 554 if (BCM_E_NOT_FOUND == rv) { 555 multicast_scache = NULL; 556 } else if (BCM_FAILURE(rv)) { 557 return rv; 558 } else { 559 alloc_size = mem_size * sizeof(uint8); 560 sal_memcpy(_multicast_ipmc_group_types[unit], multicast_scache, 561 alloc_size); 562 multicast_scache += alloc_size; 563 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 564 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1) { 565 sal_memcpy(bcmi_multicast_multi_group_count[unit], 566 multicast_scache, alloc_size); 567 multicast_scache += alloc_size; 568 } 569 } 570 571 for (mc_index = 0; mc_index < num_ipmc_groups; mc_index++) { 572 rv = _bcm_tr_multicast_ipmc_group_type_get( 573 unit, mc_index, &scache_group); 574 if (BCM_FAILURE(rv)) { 575 if (rv == BCM_E_NOT_FOUND) { 576 continue; 577 } 578 bcm_fb_ipmc_repl_detach(unit); 579 return rv; 580 } 581 582 rv = bcm_xgs3_ipmc_id_is_set(unit, mc_index, &is_set); 583 if (BCM_SUCCESS(rv)) { 584 if (_BCM_MULTICAST_IS_L3(scache_group) && (!is_set)) { 585 /* This is an L3 group that was created but 586 * not installed, so there is no HW sign of it. 587 * We need to mark it recovered in the IPMC area. 588 */ 589 rv = bcm_xgs3_ipmc_id_alloc(unit, mc_index); 590 if (BCM_FAILURE(rv)) { 591 bcm_fb_ipmc_repl_detach(unit); 592 return rv; 593 } 594 } 595 } 596 } 597 598 return BCM_E_NONE; 599 } 600 601 /* Traversing multiple next hop types, set up IPMC repl logging */ 602 alloc_size = SHR_BITALLOCSIZE(mem_size); 603 ipmc_groups_bits = sal_alloc(alloc_size, "IPMC groups referenced"); 604 if (ipmc_groups_bits == NULL) { 605 bcm_fb_ipmc_repl_detach(unit); 606 return BCM_E_MEMORY; 607 } 608 sal_memset(ipmc_groups_bits, 0, alloc_size); 609 610 /* Store info for callback functions */ 611 mc_cb_info.ipmc_groups_bits = ipmc_groups_bits; 612 mc_cb_info.stale_scache = FALSE; 613 614 mc_cb_info.flags = BCM_MULTICAST_TYPE_L3; 615 616 if (soc_feature(unit, soc_feature_mpls)) { 617 mc_cb_info.flags |= BCM_MULTICAST_TYPE_VPLS; 618 } 619 if (soc_feature(unit, soc_feature_subport)) { 620 mc_cb_info.flags |= BCM_MULTICAST_TYPE_SUBPORT; 621 } 622 if (soc_feature(unit, soc_feature_mim)) { 623 mc_cb_info.flags |= BCM_MULTICAST_TYPE_MIM; 624 } 625 if (soc_feature(unit, soc_feature_wlan)) { 626 mc_cb_info.flags |= BCM_MULTICAST_TYPE_WLAN; 627 } 628 if (soc_feature(unit, soc_feature_vlan_vp)) { 629 mc_cb_info.flags |= BCM_MULTICAST_TYPE_VLAN; 630 } 631 if (soc_feature(unit, soc_feature_trill)) { 632 mc_cb_info.flags |= BCM_MULTICAST_TYPE_TRILL; 633 } 634 if (soc_feature(unit, soc_feature_niv)) { 635 mc_cb_info.flags |= BCM_MULTICAST_TYPE_NIV; 636 } 637 if (soc_feature(unit, soc_feature_mpls)) { 638 mc_cb_info.flags |= BCM_MULTICAST_TYPE_EGRESS_OBJECT; 639 } 640 if (soc_feature(unit, soc_feature_port_extension)) { 641 mc_cb_info.flags |= BCM_MULTICAST_TYPE_EXTENDER; 642 } 643 644 /* Traverse L2 table for multicast groups */ 645 rv = bcm_esw_l2_traverse(unit, &_bcm_trx_multicast_l2_traverse, 646 &mc_cb_info); 647 648 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 649 /* Traverse VLAN MC groups */ 650 if (BCM_SUCCESS(rv) && (soc_feature(unit, soc_feature_wlan) || 651 soc_feature(unit, soc_feature_vlan_vp) || 652 soc_feature(unit, soc_feature_trill) || 653 soc_feature(unit, soc_feature_niv) || 654 soc_feature(unit, soc_feature_port_extension))) { 655 rv = _bcm_trx_multicast_vlan_traverse(unit, &mc_cb_info); 656 } 657 #endif 658 659 /* Traverse VFI groups */ 660 if (BCM_SUCCESS(rv)) { 661 if (soc_feature(unit, soc_feature_virtual_switching)) { 662 rv = _bcm_trx_multicast_vfi_traverse(unit, &mc_cb_info); 663 } 664 } 665 666 if (BCM_SUCCESS(rv)) { 667 for (mc_index = 0; mc_index < num_ipmc_groups; mc_index++) { 668 if (SHR_BITGET(ipmc_groups_bits, mc_index)) { 669 /* Already did this group index, skip */ 670 continue; 671 } 672 673 rv = bcm_xgs3_ipmc_id_is_set(unit, mc_index, &is_set); 674 if ((BCM_E_INIT == rv) || (BCM_E_UNAVAIL == rv)) { 675 676 rv = BCM_E_NONE; 677 break; 678 } else if (BCM_FAILURE(rv)) { 679 break; 680 } else if (is_set) { 681 /* coverity[dead_error_condition] */ 682 if (NULL != multicast_scache) { 683 /* If scache was used, check for staleness */ 684 rv = _bcm_tr_multicast_ipmc_group_type_get(unit, 685 mc_index, &scache_group); 686 687 if (BCM_E_NOT_FOUND == rv) { 688 #ifdef BCM_KATANA_SUPPORT 689 if (SOC_IS_KATANAX(unit) && 690 ((mc_index == 0) || (mc_index == 1))) { 691 continue; 692 } 693 #endif /* BCM_KATANA_SUPPORT */ 694 #ifdef BCM_XGS3_SWITCH_SUPPORT 695 if (SOC_IS_XGS3_SWITCH(unit) && 696 !(SOC_IS_KATANAX(unit)) && mc_index == 0) { 697 continue; 698 } 699 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 700 701 /* We expect a group from the HW state, but 702 * it isn't in the scache info */ 703 if (FALSE == mc_cb_info.stale_scache) { 704 /* We have yet to complain about stale scache */ 705 rv = soc_event_generate(unit, 706 BCM_SWITCH_EVENT_STABLE_ERROR, 707 SOC_STABLE_STALE, 708 SOC_STABLE_MULTICAST, 0); 709 if (BCM_FAILURE(rv)) { 710 break; 711 } 712 mc_cb_info.stale_scache = TRUE; 713 } 714 } else if (BCM_FAILURE(rv)) { 715 return rv; 716 } /* Keep the cached group info and continue */ 717 } else { 718 /* Best guess is that this is an L3 group */ 719 _BCM_MULTICAST_GROUP_SET(group, 720 _BCM_MULTICAST_TYPE_L3, 721 mc_index); 722 rv = _bcm_trx_multicast_reinit_group(unit, group, 723 &mc_cb_info); 724 if (BCM_FAILURE(rv)) { 725 break; 726 } 727 } 728 } else if (NULL != multicast_scache) { 729 /* If scache was used, check for staleness */ 730 rv = _bcm_tr_multicast_ipmc_group_type_get(unit, mc_index, 731 &scache_group); 732 733 if (BCM_E_NOT_FOUND == rv) { 734 /* In sync */ 735 rv = BCM_E_NONE; 736 } else if (BCM_FAILURE(rv)) { 737 return rv; 738 } else if (0 != scache_group) { 739 if (!_BCM_MULTICAST_IS_L3(scache_group)) { 740 /* We expect a group from the scache info, but 741 * it wasn't recovered from HW. */ 742 if (FALSE == mc_cb_info.stale_scache) { 743 /* We have yet to complain about stale scache */ 744 rv = soc_event_generate(unit, 745 BCM_SWITCH_EVENT_STABLE_ERROR, 746 SOC_STABLE_STALE, 747 SOC_STABLE_MULTICAST, 0); 748 if (BCM_FAILURE(rv)) { 749 break; 750 } 751 mc_cb_info.stale_scache = TRUE; 752 } 753 } else { 754 /* This is an L3 group that was created but 755 * not installed, so there is no HW sign of it. 756 * We need to mark it recovered in the IPMC area. 757 */ 758 rv = bcm_xgs3_ipmc_id_alloc(unit, mc_index); 759 if (BCM_FAILURE(rv)) { 760 break; 761 } 762 } 763 } 764 } 765 } 766 } 767 768 sal_free(ipmc_groups_bits); 769 770 return rv; 771 } 772 #endif /* BCM_WARM_BOOT_SUPPORT */ 773 774 /* 775 * Function: 776 * bcm_trx_multicast_init 777 * Purpose: 778 * Initialize the multicast module. 779 * Parameters: 780 * unit - (IN) Unit number. 781 * Returns: 782 * BCM_E_xxx 783 * Notes: 784 */ 785 int 786 bcm_trx_multicast_init(int unit) 787 { 788 int ipmc_mem_size=0, alloc_size=0; 789 #ifdef BCM_WARM_BOOT_SUPPORT 790 int rv = BCM_E_NONE; 791 soc_scache_handle_t scache_handle; 792 uint8 *multicast_scache; 793 #endif /* BCM_WARM_BOOT_SUPPORT */ 794 795 ipmc_mem_size = soc_mem_index_count(unit, L3_IPMCm); 796 alloc_size = ipmc_mem_size * sizeof(uint8); 797 798 #ifdef BCM_WARM_BOOT_SUPPORT 799 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 800 if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1) { 801 alloc_size += ipmc_mem_size * sizeof(uint8); 802 } 803 } 804 805 806 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 807 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MULTICAST, 0); 808 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 809 (0 == SOC_WARM_BOOT(unit)), 810 alloc_size, 811 &multicast_scache, 812 BCM_WB_DEFAULT_VERSION, NULL); 813 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 814 return rv; 815 } 816 } /* Else, not enough memory, don't allocate scache */ 817 #endif /* BCM_WARM_BOOT_SUPPORT */ 818 819 /* change alloc size for individual memebers in scache */ 820 alloc_size = ipmc_mem_size * sizeof(uint8); 821 822 if (NULL == _multicast_ipmc_group_types[unit]) { 823 _multicast_ipmc_group_types[unit] = 824 sal_alloc(alloc_size, "multicast_group_types"); 825 if (NULL == _multicast_ipmc_group_types[unit]) { 826 return BCM_E_MEMORY; 827 } 828 } 829 sal_memset(_multicast_ipmc_group_types[unit], 0, alloc_size); 830 831 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 832 if (NULL == bcmi_multicast_multi_group_count[unit]) { 833 bcmi_multicast_multi_group_count[unit] = 834 sal_alloc(alloc_size, "multicast_group_count"); 835 if (NULL == bcmi_multicast_multi_group_count[unit]) { 836 return BCM_E_MEMORY; 837 } 838 } 839 sal_memset(bcmi_multicast_multi_group_count[unit], 0, alloc_size); 840 } 841 842 843 #ifdef BCM_TRIDENT2_SUPPORT 844 if (soc_feature(unit, soc_feature_virtual_port_routing)) { 845 BCM_IF_ERROR_RETURN(bcm_td2_multicast_l3_vp_init(unit)); 846 } 847 #endif /* BCM_TRIDENT2_SUPPORT */ 848 849 #ifdef BCM_WARM_BOOT_SUPPORT 850 if (SOC_WARM_BOOT(unit)) { 851 return (_bcm_trx_multicast_reinit(unit)); 852 } 853 #endif /* BCM_WARM_BOOT_SUPPORT */ 854 855 return BCM_E_NONE; 856 } 857 858 /* 859 * Function: 860 * bcm_trx_multicast_detach 861 * Purpose: 862 * Shut down (uninitialize) the multicast module. 863 * Parameters: 864 * unit - (IN) Unit number. 865 * Returns: 866 * BCM_E_xxx 867 * Notes: 868 */ 869 int 870 bcm_trx_multicast_detach(int unit) 871 { 872 873 #ifdef BCM_WARM_BOOT_SUPPORT 874 int autosync; 875 BCM_IF_ERROR_RETURN( 876 bcm_esw_switch_control_get(unit, bcmSwitchControlAutoSync, &autosync)); 877 if (autosync) { 878 BCM_IF_ERROR_RETURN(_bcm_trx_multicast_sync(unit)); 879 } 880 #endif /* BCM_WARM_BOOT_SUPPORT */ 881 #ifdef BCM_TRIDENT2_SUPPORT 882 if (soc_feature(unit, soc_feature_virtual_port_routing)) { 883 BCM_IF_ERROR_RETURN(bcm_td2_multicast_l3_vp_detach(unit)); 884 } 885 #endif /* BCM_TRIDENT2_SUPPORT */ 886 887 if (NULL != _multicast_ipmc_group_types[unit]) { 888 sal_free(_multicast_ipmc_group_types[unit]); 889 _multicast_ipmc_group_types[unit] = NULL; 890 } 891 892 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 893 if (NULL != bcmi_multicast_multi_group_count[unit]) { 894 sal_free(bcmi_multicast_multi_group_count[unit]); 895 bcmi_multicast_multi_group_count[unit] = NULL; 896 } 897 } 898 899 return BCM_E_NONE; 900 } 901 902 /* 903 * Function: 904 * bcm_multicast_vpls_encap_get 905 * Purpose: 906 * Get the Encap ID for a MPLS port. 907 * Parameters: 908 * unit - (IN) Unit number. 909 * group - (IN) Multicast group ID. 910 * port - (IN) Physical port. 911 * mpls_port_id - (IN) MPLS port ID. 912 * encap_id - (OUT) Encap ID. 913 * Returns: 914 * BCM_E_XXX 915 * Notes: 916 */ 917 int 918 bcm_tr_multicast_vpls_encap_get(int unit, bcm_multicast_t group, 919 bcm_gport_t port, 920 bcm_gport_t mpls_port_id, bcm_if_t *encap_id) 921 { 922 #if defined(BCM_MPLS_SUPPORT) 923 uint32 vp; 924 ing_dvp_table_entry_t dvp; 925 int vpless_failover_port = FALSE; 926 int rv = BCM_E_NONE; 927 928 if (!BCM_GPORT_IS_MPLS_PORT(mpls_port_id)) { 929 return BCM_E_PARAM; 930 } 931 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(mpls_port_id)) { 932 vpless_failover_port = TRUE; 933 mpls_port_id = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(mpls_port_id); 934 } 935 936 vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port_id); 937 if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) { 938 return BCM_E_PARAM; 939 } 940 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 941 return BCM_E_PARAM; 942 } 943 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 944 945 /* Next-hop index is used for multicast replication */ 946 *encap_id = (bcm_if_t) soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 947 if (vpless_failover_port == TRUE) { 948 int failover_nh_index=0; 949 int failover_id =0; 950 int failover_mc_group=0; 951 952 rv = _bcm_esw_failover_prot_nhi_get (unit, *encap_id, 953 &failover_id, &failover_nh_index, &failover_mc_group); 954 if (BCM_SUCCESS(rv)) { 955 if (failover_nh_index) { 956 *encap_id = failover_nh_index; 957 } 958 /*For 1+1 protection NHI use failover multicast group index*/ 959 if(failover_mc_group > 0){ 960 rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit,vp, 961 *encap_id, &failover_nh_index); 962 if (BCM_SUCCESS(rv)) { 963 *encap_id = failover_nh_index; 964 } 965 } 966 } else if (rv == BCM_E_UNAVAIL) { 967 if (soc_feature(unit, soc_feature_mpls_software_failover)) { 968 rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit,vp, 969 *encap_id, &failover_nh_index); 970 if (BCM_SUCCESS(rv)) { 971 *encap_id = failover_nh_index; 972 } 973 } 974 } 975 } 976 return rv; 977 #else 978 return BCM_E_UNAVAIL; 979 #endif 980 } 981 982 /* 983 * Function: 984 * bcm_multicast_subport_encap_get 985 * Purpose: 986 * Get the Encap ID for a subport. 987 * Parameters: 988 * unit - (IN) Unit number. 989 * group - (IN) Multicast group ID. 990 * port - (IN) Physical port. 991 * subport - (IN) Subport ID. 992 * encap_id - (OUT) Encap ID. 993 * Returns: 994 * BCM_E_XXX 995 * Notes: 996 */ 997 int 998 bcm_tr_multicast_subport_encap_get(int unit, bcm_multicast_t group, 999 bcm_gport_t port, 1000 bcm_gport_t subport, bcm_if_t *encap_id) 1001 { 1002 int vp, l3_idx,rv; 1003 ing_dvp_table_entry_t dvp; 1004 egr_l3_intf_entry_t l3_intf; 1005 1006 if (!BCM_GPORT_IS_SUBPORT_PORT(subport)) { 1007 return BCM_E_PARAM; 1008 } 1009 1010 l3_idx = BCM_GPORT_SUBPORT_PORT_GET(subport) & 0xfff; 1011 if (l3_idx >= BCM_XGS3_L3_IF_TBL_SIZE(unit)) { 1012 return (BCM_E_PARAM); 1013 } 1014 1015 rv = soc_mem_read(unit, EGR_L3_INTFm, MEM_BLOCK_ALL, l3_idx, &l3_intf); 1016 BCM_IF_ERROR_RETURN(rv); 1017 1018 vp = soc_mem_field32_get(unit, EGR_L3_INTFm, &l3_intf, IVIDf); 1019 if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) { 1020 return BCM_E_PARAM; 1021 } 1022 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeSubport)) { 1023 return BCM_E_PARAM; 1024 } 1025 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 1026 1027 /* Next-hop index is used for multicast replication */ 1028 *encap_id = (bcm_if_t) soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 1029 if (!SOC_IS_ENDURO(unit)) { 1030 *encap_id += BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 1031 } 1032 return BCM_E_NONE; 1033 1034 } 1035 1036 1037 /* 1038 * Function: 1039 * bcm_trx_multicast_group_traverse 1040 * Purpose: 1041 * Iterate over the defined multicast groups of the type 1042 * specified in 'flags'. If all types are desired, use 1043 * MULTICAST_TYPE_MASK. 1044 * Parameters: 1045 * unit - (IN) Unit number. 1046 * trav_fn - (IN) Callback function. 1047 * flags - (IN) BCM_MULTICAST_* 1048 * user_data - (IN) User data to be passed to callback function. 1049 * Returns: 1050 * BCM_E_XXX 1051 */ 1052 int 1053 bcm_trx_multicast_group_traverse(int unit, 1054 bcm_multicast_group_traverse_cb_t trav_fn, 1055 uint32 flags, void *user_data) 1056 { 1057 int l2mc_size, l3mc_size, mc_index, is_set, rv = BCM_E_NONE; 1058 uint32 group_flags, flags_mask; 1059 bcm_multicast_t group; 1060 1061 flags_mask = BCM_MULTICAST_TYPE_L2 | BCM_MULTICAST_TYPE_L3; 1062 1063 if (soc_feature(unit, soc_feature_mpls)) { 1064 flags_mask |= BCM_MULTICAST_TYPE_VPLS; 1065 } 1066 if (soc_feature(unit, soc_feature_subport)) { 1067 flags_mask |= BCM_MULTICAST_TYPE_SUBPORT; 1068 } 1069 if (soc_feature(unit, soc_feature_mim)) { 1070 flags_mask |= BCM_MULTICAST_TYPE_MIM; 1071 } 1072 if (soc_feature(unit, soc_feature_wlan)) { 1073 flags_mask |= BCM_MULTICAST_TYPE_WLAN; 1074 } 1075 if (soc_feature(unit, soc_feature_vlan_vp)) { 1076 flags_mask |= BCM_MULTICAST_TYPE_VLAN; 1077 } 1078 if (soc_feature(unit, soc_feature_trill)) { 1079 flags_mask |= BCM_MULTICAST_TYPE_TRILL; 1080 } 1081 if (soc_feature(unit, soc_feature_niv)) { 1082 flags_mask |= BCM_MULTICAST_TYPE_NIV; 1083 } 1084 if (soc_feature(unit, soc_feature_mpls)) { 1085 flags_mask |= BCM_MULTICAST_TYPE_EGRESS_OBJECT; 1086 } 1087 if (soc_feature(unit, soc_feature_port_extension)) { 1088 flags_mask |= BCM_MULTICAST_TYPE_EXTENDER; 1089 } 1090 if (soc_feature(unit, soc_feature_vxlan)) { 1091 flags_mask |= BCM_MULTICAST_TYPE_VXLAN; 1092 } 1093 if (soc_feature(unit, soc_feature_l2gre)) { 1094 flags_mask |= BCM_MULTICAST_TYPE_L2GRE; 1095 } 1096 1097 if (0 == (flags & flags_mask)) { 1098 /* No recognized multicast types to traverse */ 1099 return BCM_E_PARAM; 1100 } 1101 1102 flags &= flags_mask; 1103 1104 /* Replace the L2 MC logic */ 1105 if (flags & BCM_MULTICAST_TYPE_L2) { 1106 BCM_IF_ERROR_RETURN(_bcm_xgs3_l2mc_size_get(unit, &l2mc_size)); 1107 group_flags = BCM_MULTICAST_TYPE_L2 | BCM_MULTICAST_WITH_ID; 1108 1109 for (mc_index = 0; mc_index < l2mc_size; mc_index++) { 1110 rv = _bcm_xgs3_l2mc_index_is_set(unit, mc_index, &is_set); 1111 if (BCM_FAILURE(rv)) { 1112 return rv; 1113 } else if (is_set) { 1114 _BCM_MULTICAST_GROUP_SET(group, _BCM_MULTICAST_TYPE_L2, 1115 mc_index); 1116 BCM_IF_ERROR_RETURN 1117 ((*trav_fn)(unit, group, group_flags, user_data)); 1118 } 1119 } 1120 } 1121 1122 if (flags & ~(BCM_MULTICAST_TYPE_L2)) { 1123 l3mc_size = soc_mem_index_count(unit, L3_IPMCm); 1124 for (mc_index = 0; mc_index < l3mc_size; mc_index++) { 1125 rv = _bcm_tr_multicast_ipmc_group_type_get(unit, mc_index, 1126 &group); 1127 1128 if (BCM_E_NOT_FOUND == rv) { 1129 continue; 1130 } else if (BCM_FAILURE(rv)) { 1131 return rv; 1132 } else { 1133 group_flags = 1134 _bcm_esw_multicast_group_type_to_flags( 1135 _BCM_MULTICAST_TYPE_GET(group)) | 1136 BCM_MULTICAST_WITH_ID; 1137 1138 if (group_flags & flags) { 1139 BCM_IF_ERROR_RETURN 1140 ((*trav_fn)(unit, group, group_flags, user_data)); 1141 } 1142 } 1143 } 1144 } 1145 1146 return BCM_E_NONE; 1147 } 1148 1149 /* 1150 * Function: 1151 * bcm_trx_multicast_group_get 1152 * Purpose: 1153 * Retrieve the flags for a multicast group, if it exists. 1154 * Parameters: 1155 * unit - (IN) Device Number 1156 * group - (IN) Group ID 1157 * flags - (OUT) BCM_MULTICAST_* 1158 * Returns: 1159 * BCM_E_XXX 1160 */ 1161 int 1162 bcm_trx_multicast_group_get(int unit, bcm_multicast_t group, uint32 *flags) 1163 { 1164 int rv = BCM_E_NONE, mc_index, is_set = FALSE; 1165 bcm_multicast_t get_group; 1166 1167 mc_index = _BCM_MULTICAST_ID_GET(group); 1168 if (_BCM_MULTICAST_IS_L2(group)) { 1169 BCM_IF_ERROR_RETURN 1170 (_bcm_xgs3_l2mc_index_is_set(unit, mc_index, &is_set)); 1171 if (is_set) { 1172 *flags |= BCM_MULTICAST_TYPE_L2 | BCM_MULTICAST_WITH_ID; 1173 } else { 1174 *flags = 0; 1175 return BCM_E_NOT_FOUND; 1176 } 1177 } else { 1178 if (!_BCM_MULTICAST_IS_L3(group) && 1179 !_BCM_MULTICAST_IS_VPLS(group) && 1180 !_BCM_MULTICAST_IS_MIM(group) && 1181 !_BCM_MULTICAST_IS_SUBPORT(group) && 1182 !_BCM_MULTICAST_IS_WLAN(group) && 1183 !_BCM_MULTICAST_IS_VLAN(group) && 1184 !_BCM_MULTICAST_IS_TRILL(group) && 1185 !_BCM_MULTICAST_IS_NIV(group) && 1186 !_BCM_MULTICAST_IS_L2GRE(group) && 1187 !_BCM_MULTICAST_IS_VXLAN(group) && 1188 !_BCM_MULTICAST_IS_FLOW(group) && 1189 !_BCM_MULTICAST_IS_EGRESS_OBJECT(group) && 1190 !_BCM_MULTICAST_IS_EXTENDER(group)) { 1191 return BCM_E_PARAM; 1192 } 1193 1194 if (_BCM_MULTICAST_IS_VPLS(group) && 1195 !soc_feature(unit, soc_feature_mpls)) { 1196 return BCM_E_UNAVAIL; 1197 } 1198 if (_BCM_MULTICAST_IS_SUBPORT(group) && 1199 !soc_feature(unit, soc_feature_subport)) { 1200 return BCM_E_UNAVAIL; 1201 } 1202 if (_BCM_MULTICAST_IS_MIM(group) && 1203 !soc_feature(unit, soc_feature_mim)) { 1204 return BCM_E_UNAVAIL; 1205 } 1206 if (_BCM_MULTICAST_IS_WLAN(group) && 1207 !soc_feature(unit, soc_feature_wlan)) { 1208 return BCM_E_UNAVAIL; 1209 } 1210 if (_BCM_MULTICAST_IS_VLAN(group) && 1211 !soc_feature(unit, soc_feature_vlan_vp)) { 1212 return BCM_E_UNAVAIL; 1213 } 1214 if (_BCM_MULTICAST_IS_TRILL(group) && 1215 !soc_feature(unit, soc_feature_trill)) { 1216 return BCM_E_UNAVAIL; 1217 } 1218 if (_BCM_MULTICAST_IS_NIV(group) && 1219 !soc_feature(unit, soc_feature_niv)) { 1220 return BCM_E_UNAVAIL; 1221 } 1222 if (_BCM_MULTICAST_IS_EGRESS_OBJECT(group) && 1223 !soc_feature(unit, soc_feature_mpls)) { 1224 return BCM_E_UNAVAIL; 1225 } 1226 if (_BCM_MULTICAST_IS_L2GRE(group) && 1227 !soc_feature(unit, soc_feature_l2gre)) { 1228 return BCM_E_UNAVAIL; 1229 } 1230 if (_BCM_MULTICAST_IS_VXLAN(group) && 1231 !soc_feature(unit, soc_feature_vxlan)) { 1232 return BCM_E_UNAVAIL; 1233 } 1234 if (_BCM_MULTICAST_IS_FLOW(group) && 1235 !soc_feature(unit, soc_feature_flex_flow)) { 1236 return BCM_E_UNAVAIL; 1237 } 1238 if (_BCM_MULTICAST_IS_EXTENDER(group) && 1239 !soc_feature(unit, soc_feature_port_extension)) { 1240 return BCM_E_UNAVAIL; 1241 } 1242 1243 rv = _bcm_tr_multicast_ipmc_group_type_get(unit, mc_index, 1244 &get_group); 1245 1246 if (BCM_E_NOT_FOUND == rv) { 1247 *flags = 0; 1248 } else if (BCM_FAILURE(rv)) { 1249 return rv; 1250 } else if (get_group != group) { 1251 /* IPMC index is allocated, but not to the same group type */ 1252 *flags = 0; 1253 return BCM_E_NOT_FOUND; 1254 } else { 1255 *flags = 1256 _bcm_esw_multicast_group_type_to_flags( 1257 _BCM_MULTICAST_TYPE_GET(group)) | 1258 BCM_MULTICAST_WITH_ID; 1259 } 1260 } 1261 1262 return rv; 1263 } 1264 1265 #else /* INCLUDE_L3 && BCM_TRX_SUPPORT */ 1266 int bcm_esw_triumph_multicast_not_empty; 1267 #endif /* INCLUDE_L3 && BCM_TRX_SUPPORT */