multicast.c (312269B)
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 #include <shared/bsl.h> 11 12 #include <sal/core/libc.h> 13 #include <sal/core/time.h> 14 #include <soc/defs.h> 15 #include <soc/drv.h> 16 #include <soc/scache.h> 17 #include <soc/util.h> 18 #if defined(BCM_BRADLEY_SUPPORT) 19 #include <soc/bradley.h> 20 #endif /* BCM_BRADLEY_SUPPORT */ 21 #include <bcm/l2.h> 22 #include <bcm/port.h> 23 #include <bcm/error.h> 24 #include <bcm/multicast.h> 25 26 #include <bcm_int/esw/mbcm.h> 27 #include <bcm_int/esw/firebolt.h> 28 #include <bcm_int/common/multicast.h> 29 #include <bcm_int/esw/multicast.h> 30 #include <bcm_int/esw/ipmc.h> 31 #include <bcm_int/esw/switch.h> 32 #if defined(BCM_TRX_SUPPORT) 33 #include <bcm_int/esw/triumph.h> 34 #include <bcm_int/esw/trx.h> 35 #endif /* BCM_TRX_SUPPORT */ 36 #if defined(BCM_TRIUMPH2_SUPPORT) 37 #include <bcm_int/esw/triumph2.h> 38 #endif /* BCM_TRIUMPH2_SUPPORT */ 39 #if defined(BCM_TRIDENT_SUPPORT) 40 #include <bcm_int/esw/trident.h> 41 #endif /* BCM_TRIDENT_SUPPORT */ 42 #if defined(BCM_KATANA_SUPPORT) 43 #include <bcm_int/esw/katana.h> 44 #include <soc/katana2.h> 45 #endif /* BCM_KATANA_SUPPORT */ 46 #if defined(BCM_TRIDENT2_SUPPORT) 47 #include <bcm_int/esw/trident2.h> 48 #endif /* BCM_TRIDENT2_SUPPORT */ 49 #if defined(BCM_HGPROXY_COE_SUPPORT) 50 #include <bcm_int/esw/xgs5.h> 51 #include <bcm_int/esw/subport.h> 52 #endif /* BCM_HGPROXY_COE_SUPPORT */ 53 #if defined(BCM_KATANA2_SUPPORT) 54 #include <bcm_int/esw/katana2.h> 55 #include <bcm_int/esw/subport.h> 56 #endif /* BCM_KATANA2_SUPPORT */ 57 #if defined(BCM_TOMAHAWK_SUPPORT) 58 #include <bcm_int/esw/tomahawk.h> 59 #endif /* BCM_TOMAHAWK_SUPPORT */ 60 #if defined(BCM_TOMAHAWK3_SUPPORT) 61 #include <bcm_int/esw/tomahawk3.h> 62 #include <soc/flexport/tomahawk3_mmu_flexport.h> 63 #endif /* BCM_TOMAHAWK3_SUPPORT */ 64 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 65 #include <bcm_int/esw/trident2plus.h> 66 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 67 #if defined(BCM_GREYHOUND2_SUPPORT) 68 #include <bcm_int/esw/greyhound2.h> 69 #endif /* BCM_GREYHOUND2_SUPPORT */ 70 #ifdef BCM_TRIDENT3_SUPPORT 71 #include <soc/esw/cancun.h> 72 #include <soc/esw/cancun_enums.h> 73 #endif /* BCM_TRIDENT3_SUPPORT */ 74 75 #include <bcm_int/esw_dispatch.h> 76 #include <bcm_int/esw/virtual.h> 77 #include <bcm_int/esw/xgs3.h> 78 #include <bcm_int/esw/stack.h> 79 #include <bcm_int/esw/trunk.h> 80 #include <bcm_int/api_xlate_port.h> 81 #include <bcm_int/esw/triumph3.h> 82 #include<bcm_int/esw/saber2.h> 83 84 #define _BCM_MULTICAST_MTU_TABLE_OFFSET(unit) \ 85 ((SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) || \ 86 SOC_IS_METROLITE(unit) || SOC_IS_GREYHOUND2(unit)) ? 512 : \ 87 SOC_IS_TRIDENT2PLUS(unit) ? 12288 : SOC_IS_MONTEREY(unit) ? 2048 : \ 88 (SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit)) ? 16384 : \ 89 SOC_IS_APACHE(unit) ? 12288 : 8192) 90 #define _BCM_TR3_MULTICAST_MTU_TABLE_OFFSET(unit) (SOC_IS_HELIX4(unit) ? 12288 : 16384) 91 92 #ifdef BCM_WARM_BOOT_SUPPORT 93 static int multicast_mode_set[BCM_MAX_NUM_UNITS]; 94 #endif /* BCM_WARM_BOOT_SUPPORT */ 95 96 #define _BCM_MULTICAST_L2_OR_FABRIC(_unit_, _group_) \ 97 (_BCM_MULTICAST_IS_L2(_group_) || SOC_IS_XGS3_FABRIC(_unit_)) 98 99 #ifdef BCM_XGS3_FABRIC_SUPPORT 100 typedef struct _bcm_fabric_multicast_info_s { 101 int mcast_size; 102 int ipmc_size; 103 uint32 *mcast_used; 104 } _bcm_fabric_multicast_info_t; 105 106 static _bcm_fabric_multicast_info_t _bcm_fabric_mc_info[BCM_MAX_NUM_UNITS]; 107 uint8 *_fabric_multicast_ipmc_group_types[BCM_MAX_NUM_UNITS]; 108 109 STATIC int 110 _bcm_esw_multicast_egress_get(int unit, bcm_multicast_t group, int port_max, 111 bcm_gport_t *port_array, 112 bcm_if_t *encap_id_array, 113 int *port_count); 114 STATIC int 115 _bcm_esw_multicast_egress_set(int unit, bcm_multicast_t group, int port_count, 116 bcm_gport_t *port_array, bcm_if_t *encap_id_array); 117 118 #ifdef BCM_WARM_BOOT_SUPPORT 119 /* Warm boot scache version to store 120 * _fabric_multicast_ipmc_group_types array information. 121 */ 122 #define BCM_FABRIC_IPMC_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 123 #define BCM_FABRIC_IPMC_WB_DEFAULT_VERSION BCM_FABRIC_IPMC_WB_VERSION_1_0 124 #endif 125 126 #define BCM_FABRIC_MCAST_BASE(unit) (0) 127 #define BCM_FABRIC_MCAST_MAX(unit) (_bcm_fabric_mc_info[unit].mcast_size - 1) 128 #define BCM_FABRIC_IPMC_BASE(unit) (_bcm_fabric_mc_info[unit].mcast_size) 129 #define BCM_FABRIC_IPMC_MAX(unit) \ 130 (_bcm_fabric_mc_info[unit].mcast_size + \ 131 _bcm_fabric_mc_info[unit].ipmc_size - 1) 132 #define BCM_FABRIC_MC_USED_BITMAP(unit) \ 133 (_bcm_fabric_mc_info[unit].mcast_used) 134 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 135 136 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_SCORPION_SUPPORT) 137 /* Cache of MTU profile size regs */ 138 STATIC soc_profile_reg_t *_bcm_mtu_profile[BCM_MAX_NUM_UNITS]; 139 #endif 140 141 142 #if defined(BCM_KATANA_SUPPORT) 143 STATIC int 144 _bcm_esw_multicast_egress_subscriber_delete_all(int unit, bcm_multicast_t group); 145 extern int _bcm_kt_hw_to_sw_queue(int unit, int *queue_array, bcm_port_t *port); 146 #endif 147 STATIC int multicast_initialized[BCM_MAX_NUM_UNITS]; 148 #define MULTICAST_INIT_CHECK(unit) \ 149 if (!multicast_initialized[unit]) { \ 150 return BCM_E_INIT; \ 151 } 152 153 int 154 _bcm_esw_multicast_flags_to_group_type(uint32 flags) 155 { 156 int group_type = 0; 157 158 if (flags & BCM_MULTICAST_TYPE_L2) { 159 group_type = _BCM_MULTICAST_TYPE_L2; 160 } else if (flags & BCM_MULTICAST_TYPE_L3){ 161 group_type = _BCM_MULTICAST_TYPE_L3; 162 } else if (flags & BCM_MULTICAST_TYPE_VPLS){ 163 group_type = _BCM_MULTICAST_TYPE_VPLS; 164 } else if (flags & BCM_MULTICAST_TYPE_SUBPORT){ 165 group_type = _BCM_MULTICAST_TYPE_SUBPORT; 166 } else if (flags & BCM_MULTICAST_TYPE_MIM){ 167 group_type = _BCM_MULTICAST_TYPE_MIM; 168 } else if (flags & BCM_MULTICAST_TYPE_WLAN){ 169 group_type = _BCM_MULTICAST_TYPE_WLAN; 170 } else if (flags & BCM_MULTICAST_TYPE_VLAN) { 171 group_type = _BCM_MULTICAST_TYPE_VLAN; 172 } else if (flags & BCM_MULTICAST_TYPE_TRILL) { 173 group_type = _BCM_MULTICAST_TYPE_TRILL; 174 } else if (flags & BCM_MULTICAST_TYPE_NIV) { 175 group_type = _BCM_MULTICAST_TYPE_NIV; 176 } else if (flags & BCM_MULTICAST_TYPE_EGRESS_OBJECT) { 177 group_type = _BCM_MULTICAST_TYPE_EGRESS_OBJECT; 178 } else if (flags & BCM_MULTICAST_TYPE_L2GRE) { 179 group_type = _BCM_MULTICAST_TYPE_L2GRE; 180 } else if (flags & BCM_MULTICAST_TYPE_VXLAN) { 181 group_type = _BCM_MULTICAST_TYPE_VXLAN; 182 } else if (flags & BCM_MULTICAST_TYPE_FLOW) { 183 group_type = _BCM_MULTICAST_TYPE_FLOW; 184 } else if (flags & BCM_MULTICAST_TYPE_EXTENDER) { 185 group_type = _BCM_MULTICAST_TYPE_EXTENDER; 186 }/* Else default to 0 above */ 187 188 return group_type; 189 } 190 191 uint32 192 _bcm_esw_multicast_group_type_to_flags(int group_type) 193 { 194 uint32 flags = 0; 195 196 switch (group_type) { 197 case _BCM_MULTICAST_TYPE_L2: 198 flags = BCM_MULTICAST_TYPE_L2; 199 break; 200 case _BCM_MULTICAST_TYPE_L3: 201 flags = BCM_MULTICAST_TYPE_L3; 202 break; 203 case _BCM_MULTICAST_TYPE_VPLS: 204 flags = BCM_MULTICAST_TYPE_VPLS; 205 break; 206 case _BCM_MULTICAST_TYPE_SUBPORT: 207 flags = BCM_MULTICAST_TYPE_SUBPORT; 208 break; 209 case _BCM_MULTICAST_TYPE_MIM: 210 flags = BCM_MULTICAST_TYPE_MIM; 211 break; 212 case _BCM_MULTICAST_TYPE_WLAN: 213 flags = BCM_MULTICAST_TYPE_WLAN; 214 break; 215 case _BCM_MULTICAST_TYPE_VLAN: 216 flags = BCM_MULTICAST_TYPE_VLAN; 217 break; 218 case _BCM_MULTICAST_TYPE_TRILL: 219 flags = BCM_MULTICAST_TYPE_TRILL; 220 break; 221 case _BCM_MULTICAST_TYPE_NIV: 222 flags = BCM_MULTICAST_TYPE_NIV; 223 break; 224 case _BCM_MULTICAST_TYPE_EGRESS_OBJECT: 225 flags = BCM_MULTICAST_TYPE_EGRESS_OBJECT; 226 break; 227 case _BCM_MULTICAST_TYPE_L2GRE: 228 flags = BCM_MULTICAST_TYPE_L2GRE; 229 break; 230 case _BCM_MULTICAST_TYPE_VXLAN: 231 flags = BCM_MULTICAST_TYPE_VXLAN; 232 break; 233 case _BCM_MULTICAST_TYPE_FLOW: 234 flags = BCM_MULTICAST_TYPE_FLOW; 235 break; 236 case _BCM_MULTICAST_TYPE_EXTENDER: 237 flags = BCM_MULTICAST_TYPE_EXTENDER; 238 break; 239 240 default: 241 /* flags defaults to 0 above */ 242 break; 243 } 244 245 return flags; 246 } 247 248 #ifdef BCM_XGS3_FABRIC_SUPPORT 249 /* 250 * Function: 251 * _bcm_esw_fabric_multicast_param_check 252 * Purpose: 253 * Validate fabric multicast parameters and adjust HW index. 254 * Parameters: 255 * unit - (IN) Device Number 256 * group - (IN) Multicast group ID. 257 * mc_id - (IN/OUT) multicast index. 258 * Returns: 259 * BCM_E_XXX 260 */ 261 STATIC int 262 _bcm_esw_fabric_multicast_param_check(int unit, bcm_multicast_t group, 263 int *mc_index) 264 { 265 if (_BCM_MULTICAST_IS_L2(group)) { 266 /* L2 multicast groups start at index 1 */ 267 if ((*mc_index < BCM_FABRIC_MCAST_BASE(unit)) || 268 (*mc_index > BCM_FABRIC_MCAST_MAX(unit))) { 269 return BCM_E_PARAM; 270 } 271 } else if (_BCM_MULTICAST_IS_SET(group)) { 272 /* Non-L2 groups are offset */ 273 *mc_index += BCM_FABRIC_IPMC_BASE(unit); 274 if ((*mc_index < BCM_FABRIC_IPMC_BASE(unit)) || 275 (*mc_index > BCM_FABRIC_IPMC_MAX(unit))) { 276 return BCM_E_PARAM; 277 } 278 } else { 279 return BCM_E_PARAM; 280 } 281 if (!SHR_BITGET(BCM_FABRIC_MC_USED_BITMAP(unit), *mc_index)) { 282 return BCM_E_NOT_FOUND; 283 } 284 return BCM_E_NONE; 285 } 286 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 287 288 /* 289 * Function: 290 * _bcm_esw_multicast_ipmc_read 291 * Purpose: 292 * Read L3 multicast distribuition ports. 293 * Parameters: 294 * unit - (IN) Device Number 295 * ipmc_id - (IN) IPMC index. 296 * l2_pbmp - (IN) L2 distribution ports. 297 * l3_pbmp - (IN) L3 distribuition port. 298 * Returns: 299 * BCM_E_XXX 300 */ 301 int 302 _bcm_esw_multicast_ipmc_read(int unit, int ipmc_id, bcm_pbmp_t *l2_pbmp, 303 bcm_pbmp_t *l3_pbmp) 304 { 305 uint32 entry[SOC_MAX_MEM_FIELD_WORDS]; /* hw entry bufffer. */ 306 307 /* Input parameters check. */ 308 if ((NULL == l2_pbmp) || (NULL == l3_pbmp)) { 309 return (BCM_E_PARAM); 310 } 311 312 /* Table index sanity check. */ 313 if ((ipmc_id < soc_mem_index_min(unit, L3_IPMCm)) || 314 (ipmc_id > soc_mem_index_max(unit, L3_IPMCm))) { 315 return BCM_E_PARAM; 316 } 317 318 /* Read L3 ipmc table. */ 319 BCM_IF_ERROR_RETURN(soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, 320 ipmc_id, entry)); 321 322 /* If entry is invalid - clear L2 & L3 bitmaps. */ 323 if (soc_mem_field32_get(unit, L3_IPMCm, entry, VALIDf) == 0) { 324 BCM_PBMP_CLEAR(*l2_pbmp); 325 BCM_PBMP_CLEAR(*l3_pbmp); 326 return (BCM_E_NONE); 327 } 328 /* Extract L2 & L3 bitmaps. */ 329 soc_mem_pbmp_field_get(unit, L3_IPMCm, entry, L2_BITMAPf, l2_pbmp); 330 soc_mem_pbmp_field_get(unit, L3_IPMCm, entry, L3_BITMAPf, l3_pbmp); 331 332 return (BCM_E_NONE); 333 } 334 335 /* 336 * Function: 337 * _bcm_esw_multicast_ipmc_write 338 * Purpose: 339 * Write L3 multicast distribuition ports. 340 * Parameters: 341 * unit - (IN) Device Number 342 * ipmc_id - (IN) IPMC index. 343 * l2_pbmp - (IN) L2 distribution ports. 344 * l3_pbmp - (IN) L3 distribuition port. 345 * valid - (IN) Distribuition is valid bit. 346 * Returns: 347 * BCM_E_XXX 348 */ 349 int 350 _bcm_esw_multicast_ipmc_write(int unit, int ipmc_id, bcm_pbmp_t l2_pbmp, 351 bcm_pbmp_t l3_pbmp, int valid) 352 { 353 uint32 entry[SOC_MAX_MEM_FIELD_WORDS]; /* hw entry bufffer. */ 354 int rv; 355 #if defined(BCM_KATANA_SUPPORT) 356 int remap_id = 0; 357 #endif 358 359 sal_memset(&entry, 0, sizeof(ipmc_entry_t)); 360 361 /* Currently there is no need to invalidate distribution. */ 362 if (0 == valid) { 363 BCM_PBMP_CLEAR(l2_pbmp); 364 BCM_PBMP_CLEAR(l3_pbmp); 365 } 366 367 /* Table index sanity check. */ 368 if ((ipmc_id < soc_mem_index_min(unit, L3_IPMCm)) || 369 (ipmc_id > soc_mem_index_max(unit, L3_IPMCm))) { 370 return BCM_E_PARAM; 371 } 372 373 /* Read / Modify / Write section. */ 374 soc_mem_lock(unit, L3_IPMCm); 375 rv = soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, ipmc_id, entry); 376 if (BCM_SUCCESS(rv)) { 377 #if defined(BCM_KATANA_SUPPORT) 378 if (SOC_IS_KATANAX(unit)) { 379 remap_id = soc_mem_field32_get(unit, L3_IPMCm, entry, 380 MMU_MC_REDIRECTION_PTRf); 381 if (soc_mem_field32_get(unit, L3_IPMCm, entry, VALIDf) == 0 || !valid) { 382 /* Invalid entry, flush */ 383 sal_memset(&entry, 0, sizeof(ipmc_entry_t)); 384 if (remap_id) { 385 soc_mem_field32_set(unit, L3_IPMCm, entry, 386 MMU_MC_REDIRECTION_PTRf, remap_id); 387 } 388 } 389 soc_mem_field32_set(unit, L3_IPMCm, entry, VALIDf, valid); 390 if ((0 == soc_mem_field32_get(unit, L3_IPMCm, entry, 391 MMU_MC_REDIRECTION_PTRf))) { 392 soc_mem_field32_set(unit, L3_IPMCm, entry, 393 MMU_MC_REDIRECTION_PTRf, ipmc_id); 394 } 395 } else 396 #endif 397 { 398 if (soc_mem_field32_get(unit, L3_IPMCm, entry, VALIDf) == 0 || !valid) { 399 /* Invalid entry, flush */ 400 sal_memset(&entry, 0, sizeof(ipmc_entry_t)); 401 } 402 soc_mem_field32_set(unit, L3_IPMCm, entry, VALIDf, valid); 403 } 404 } 405 406 soc_mem_pbmp_field_set(unit, L3_IPMCm, entry, L2_BITMAPf, &l2_pbmp); 407 soc_mem_pbmp_field_set(unit, L3_IPMCm, entry, L3_BITMAPf, &l3_pbmp); 408 409 #if defined(BCM_TRIDENT3_SUPPORT) 410 if (SOC_MEM_FIELD_VALID(unit, L3_IPMCm, L2_L3f) && 411 BCM_PBMP_NOT_NULL(l3_pbmp)) { 412 uint32 cancun_ver; 413 414 BCM_IF_ERROR_RETURN(soc_cancun_version_get(unit, &cancun_ver)); 415 416 if (cancun_ver < SOC_CANCUN_VERSION_DEF_5_3_2) { 417 soc_mem_field32_set(unit, L3_IPMCm, entry, L2_L3f, 1); 418 } 419 } 420 #endif 421 422 rv = soc_mem_write(unit, L3_IPMCm, MEM_BLOCK_ALL, ipmc_id, &entry); 423 424 soc_mem_unlock(unit, L3_IPMCm); 425 426 #if defined(BCM_BRADLEY_SUPPORT) 427 if (BCM_SUCCESS(rv) && (SOC_IS_HBX(unit) || SOC_IS_TD_TT(unit)) && 428 !(soc_feature(unit, soc_feature_l2mc_table_no_shared_ipmc))) { 429 /* On these devices, the Higig packets use the L2MC table with 430 * IPMC offset to get the L2 bitmap. */ 431 int mc_base, mc_size, mc_index; 432 l2mc_entry_t l2mc; 433 434 SOC_IF_ERROR_RETURN 435 (soc_hbx_ipmc_size_get(unit, &mc_base, &mc_size)); 436 /* coverity[check_after_sink] */ 437 if (ipmc_id < 0 || ipmc_id > mc_size) { 438 return BCM_E_PARAM; 439 } 440 mc_index = ipmc_id + mc_base; 441 442 soc_mem_lock(unit, L2MCm); 443 if (!valid) { 444 rv = WRITE_L2MCm(unit, MEM_BLOCK_ALL, mc_index, 445 soc_mem_entry_null(unit, L2MCm)); 446 } else { 447 rv = READ_L2MCm(unit, MEM_BLOCK_ANY, mc_index, &l2mc); 448 if (rv >= 0) { 449 soc_mem_pbmp_field_set(unit, L2MCm, &l2mc, 450 PORT_BITMAPf, &l2_pbmp); 451 soc_mem_field32_set(unit, L2MCm, &l2mc, VALIDf, 1); 452 rv = WRITE_L2MCm(unit, MEM_BLOCK_ALL, mc_index, &l2mc); 453 } 454 } 455 soc_mem_unlock(unit, L2MCm); 456 } 457 #endif /* BCM_BRADLEY_SUPPORT */ 458 459 return rv; 460 } 461 462 /* 463 * Function: 464 * _bcm_esw_ipmc_egress_intf_add 465 * Purpose: 466 * Helper function to add ipmc egress interface on different devices. 467 * Parameters: 468 * unit - (IN) Device Number 469 * ipmc_id - (IN) ipmc id 470 * port - (IN) Port number 471 * nh_index - (IN) Next Hop index 472 * is_l3 - (IN) Indicates if multicast group type is IPMC. 473 * Returns: 474 * BCM_E_XXX 475 */ 476 int 477 _bcm_esw_ipmc_egress_intf_add(int unit, int ipmc_id, bcm_port_t port, 478 int nh_index, int is_l3) 479 { 480 #if defined (INCLUDE_L3) 481 #if defined(BCM_TOMAHAWK3_SUPPORT) 482 if (SOC_IS_TOMAHAWK3(unit)) { 483 uint16 dev_id; 484 uint8 rev_id; 485 int local_port, intf_max, port_intf_count; 486 int rv = BCM_E_NONE; 487 int alloc_size; 488 bcm_if_t *port_intf_array = NULL; 489 bcm_pbmp_t l2_pbmp, l3_pbmp, pbmp_all; 490 soc_info_t *si = &SOC_INFO(unit); 491 uint32 itm_map = si->itm_map; 492 int itm; 493 bcm_pbmp_t link_bmap; 494 uint32 entry[SOC_MAX_MEM_FIELD_WORDS]; 495 496 soc_cm_get_id(unit, &dev_id, &rev_id); 497 if (rev_id != BCM56980_A0_REV_ID && dev_id != BCM56983_DEVICE_ID) { 498 intf_max = TH3_IPMC_MAX_INTF_COUNT; 499 500 /*Allocate intf array for intfs*/ 501 alloc_size = intf_max * sizeof(bcm_if_t); 502 port_intf_array = sal_alloc(alloc_size, "IPMC group, port intfs array"); 503 if (port_intf_array == NULL) { 504 return BCM_E_MEMORY; 505 } 506 BCM_PBMP_CLEAR(pbmp_all); 507 BCM_PBMP_ASSIGN(pbmp_all, PBMP_ALL(unit)); 508 PBMP_ITER(pbmp_all, local_port) { 509 if (!IS_LB_PORT(unit, local_port)) { 510 port_intf_count = 0; 511 /* retrieve the interface id array for the {group, port} */ 512 rv = bcm_esw_ipmc_egress_intf_get(unit, ipmc_id, local_port, 513 intf_max, port_intf_array, &port_intf_count); 514 if (rv != BCM_E_NONE) { 515 sal_free(port_intf_array); 516 return rv; 517 } 518 if ((local_port == port) && (port_intf_count < intf_max)) { 519 /* Current port is the port for new encap id addition */ 520 /* Current interface list doesnt have all the interface 521 * ids */ 522 port_intf_array[port_intf_count] = nh_index; 523 port_intf_count++; 524 } 525 /* Add the new port, intf list to group 0*/ 526 if (port_intf_count > 0) { 527 rv = _bcm_esw_ipmc_egress_intf_set(unit, 0, local_port, 528 port_intf_count, port_intf_array, 1, FALSE); 529 if (rv != BCM_E_NONE) { 530 sal_free(port_intf_array); 531 return rv; 532 } 533 } 534 } 535 } 536 /* Free memory for interface array as it is not needed further*/ 537 sal_free(port_intf_array); 538 /* Add port 158 to IP's EPC_LINK_BMAP */ 539 soc_mem_lock(unit, EPC_LINK_BMAPm); 540 rv = soc_mem_read(unit, EPC_LINK_BMAPm, MEM_BLOCK_ANY, 0, entry); 541 if (rv != BCM_E_NONE) { 542 soc_mem_unlock(unit, EPC_LINK_BMAPm); 543 return rv; 544 } 545 soc_mem_pbmp_field_get(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf, 546 &link_bmap); 547 BCM_PBMP_PORT_ADD(link_bmap, 158); 548 soc_mem_pbmp_field_set(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf, 549 &link_bmap); 550 rv = soc_mem_write(unit, EPC_LINK_BMAPm, MEM_BLOCK_ALL, 0, &entry); 551 soc_mem_unlock(unit, EPC_LINK_BMAPm); 552 if (rv != BCM_E_NONE) { 553 return rv; 554 } 555 556 /* Add port 158 to IP's ING_DEST_PORT_ENABLE */ 557 soc_mem_lock(unit, ING_DEST_PORT_ENABLEm); 558 rv = soc_mem_read(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ANY, 559 0, entry); 560 if (rv != BCM_E_NONE) { 561 soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm); 562 return rv; 563 } 564 soc_mem_pbmp_field_get(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf, 565 &link_bmap); 566 BCM_PBMP_PORT_ADD(link_bmap, 158); 567 soc_mem_pbmp_field_set(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf, 568 &link_bmap); 569 rv = soc_mem_write(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ALL, 0, 570 &entry); 571 soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm); 572 if (rv != BCM_E_NONE) { 573 return rv; 574 } 575 /* Add port 158 to the IPMC_L3_BITMAP */ 576 soc_mem_lock(unit, L3_IPMCm); 577 rv = _bcm_esw_multicast_ipmc_read(unit, ipmc_id, &l2_pbmp, &l3_pbmp); 578 if (rv != BCM_E_NONE) { 579 return rv; 580 } 581 BCM_PBMP_PORT_ADD(l3_pbmp, 158); 582 rv = _bcm_esw_multicast_ipmc_write(unit, ipmc_id, l2_pbmp, 583 l3_pbmp, TRUE); 584 soc_mem_unlock(unit, L3_IPMCm); 585 586 if (rv != BCM_E_NONE) { 587 return rv; 588 } 589 if (!SAL_BOOT_SIMULATION) { 590 /* mmu rqe Flush*/ 591 for (itm = 0; itm < NUM_ITM(unit); itm++) { 592 if (itm_map & (1 << itm)) { 593 /* Issue RQE flush twice per each ITM*/ 594 rv = soc_tomahawk3_mmu_rqe_port_flush(unit, itm, 1); 595 if (rv != BCM_E_NONE) { 596 return rv; 597 } 598 rv = soc_tomahawk3_mmu_rqe_port_flush(unit, itm, 2); 599 if (rv != BCM_E_NONE) { 600 return rv; 601 } 602 } 603 } 604 } 605 /* Update the repl group to add new repl_id to the port*/ 606 BCM_IF_ERROR_RETURN(_bcm_th_ipmc_egress_intf_add(unit, ipmc_id, port, 607 nh_index, is_l3)); 608 609 /* Remove port 158 from the IPMC_L3_BITMAP */ 610 soc_mem_lock(unit, L3_IPMCm); 611 rv = _bcm_esw_multicast_ipmc_read(unit, ipmc_id, &l2_pbmp, &l3_pbmp); 612 if (rv != BCM_E_NONE) { 613 soc_mem_unlock(unit, L3_IPMCm); 614 return rv; 615 } 616 BCM_PBMP_PORT_REMOVE(l3_pbmp, 158); 617 rv = _bcm_esw_multicast_ipmc_write(unit, ipmc_id, l2_pbmp, 618 l3_pbmp, TRUE); 619 soc_mem_unlock(unit, L3_IPMCm); 620 if (rv != BCM_E_NONE) { 621 return rv; 622 } 623 624 /* Remove port 158 from IP's EPC_LINK_BMAP */ 625 soc_mem_lock(unit, EPC_LINK_BMAPm); 626 rv = soc_mem_read(unit, EPC_LINK_BMAPm, MEM_BLOCK_ANY, 0, entry); 627 if (rv != BCM_E_NONE) { 628 soc_mem_unlock(unit, EPC_LINK_BMAPm); 629 return rv; 630 } 631 soc_mem_pbmp_field_get(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf, 632 &link_bmap); 633 BCM_PBMP_PORT_REMOVE(link_bmap, 158); 634 soc_mem_pbmp_field_set(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf, 635 &link_bmap); 636 rv = soc_mem_write(unit, EPC_LINK_BMAPm, MEM_BLOCK_ALL, 0, 637 &entry); 638 soc_mem_unlock(unit, EPC_LINK_BMAPm); 639 if (rv != BCM_E_NONE) { 640 return rv; 641 } 642 643 /* Remove port 158 from IP's ING_DEST_PORT_ENABLE */ 644 soc_mem_lock(unit, ING_DEST_PORT_ENABLEm); 645 rv = soc_mem_read(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ANY, 646 0, entry); 647 if (rv != BCM_E_NONE) { 648 soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm); 649 return rv; 650 } 651 soc_mem_pbmp_field_get(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf, 652 &link_bmap); 653 BCM_PBMP_PORT_REMOVE(link_bmap, 158); 654 soc_mem_pbmp_field_set(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf, 655 &link_bmap); 656 rv = soc_mem_write(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ALL, 0, 657 &entry); 658 soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm); 659 if (rv != BCM_E_NONE) { 660 return rv; 661 } 662 663 664 if (!SAL_BOOT_SIMULATION) { 665 /* mmu rqe Flush*/ 666 for (itm = 0; itm < NUM_ITM(unit); itm++) { 667 if (itm_map & (1 << itm)) { 668 /* Issue RQE flush twice per each ITM*/ 669 rv = soc_tomahawk3_mmu_rqe_port_flush(unit, itm, 1); 670 if (rv != BCM_E_NONE) { 671 return rv; 672 } 673 rv = soc_tomahawk3_mmu_rqe_port_flush(unit, itm, 2); 674 if (rv != BCM_E_NONE) { 675 return rv; 676 } 677 } 678 } 679 } 680 681 /* reset programming in repl group 0*/ 682 PBMP_ITER(pbmp_all, local_port) { 683 if (!IS_LB_PORT(unit, local_port)) { 684 rv = _bcm_esw_ipmc_egress_intf_set(unit, 0, local_port, 0, 685 NULL, 1, FALSE); 686 if (rv != BCM_E_NONE) { 687 return rv; 688 } 689 } 690 } 691 692 return rv; 693 694 } else { 695 return _bcm_th_ipmc_egress_intf_add(unit, ipmc_id, port, nh_index, 696 is_l3); 697 } 698 } 699 #endif /* BCM_TOMAHAWK3_SUPPORT*/ 700 #if defined(BCM_TOMAHAWK_SUPPORT) 701 if ((SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) && 702 !(SOC_IS_TOMAHAWK3(unit))) { 703 return _bcm_th_ipmc_egress_intf_add(unit, ipmc_id, port, nh_index, 704 is_l3); 705 } 706 #endif /* BCM_TOMAHAWK_SUPPORT */ 707 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 708 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit) || 709 SOC_IS_KATANA2(unit)) { 710 return _bcm_tr3_ipmc_egress_intf_add(unit, ipmc_id, port, nh_index, 711 is_l3); 712 } 713 #endif /* BCM_TRIUMPH3_SUPPORT */ 714 #if defined(BCM_TRIUMPH2_SUPPORT) 715 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_VALKYRIE2(unit) || 716 SOC_IS_APOLLO(unit) || SOC_IS_TD_TT(unit) || 717 SOC_IS_KATANA(unit)) { 718 return _bcm_tr2_ipmc_egress_intf_add(unit, ipmc_id, port, nh_index); 719 } 720 #endif 721 #if defined(BCM_FIREBOLT_SUPPORT) 722 return _bcm_fb_ipmc_egress_intf_add(unit, ipmc_id, port, nh_index, is_l3); 723 #endif /* BCM_FIREBOLT_SUPPORT */ 724 #endif /* INCLUDE_L3 */ 725 return BCM_E_UNAVAIL; 726 } 727 728 729 /* 730 * Function: 731 * _bcm_esw_ipmc_egress_intf_delete 732 * Purpose: 733 * Helper function to delete ipmc egress interface on different devices. 734 * Parameters: 735 * unit - (IN) Device Number 736 * ipmc_id - (IN) ipmc id 737 * port - (IN) Port number 738 * if_max - (IN) Maximal interface 739 * nh_index - (IN) Next Hop index 740 * is_l3 - (IN) Indicates if multicast group type is IPMC. 741 * Returns: 742 * BCM_E_XXX 743 */ 744 int _bcm_esw_ipmc_egress_intf_delete(int unit, int ipmc_id, 745 bcm_port_t port, int if_max, 746 int nh_index, int is_l3) 747 { 748 #if defined (INCLUDE_L3) 749 #if defined(BCM_TOMAHAWK3_SUPPORT) 750 if (SOC_IS_TOMAHAWK3(unit)) { 751 uint16 dev_id; 752 uint8 rev_id; 753 int local_port, intf_max, port_intf_count; 754 int rv = BCM_E_NONE; 755 int alloc_size; 756 bcm_if_t *port_intf_array = NULL; 757 bcm_pbmp_t l2_pbmp, l3_pbmp, pbmp_all; 758 soc_info_t *si = &SOC_INFO(unit); 759 uint32 itm_map = si->itm_map; 760 int itm, intf_loop, intf_del_idx = -1; 761 bcm_pbmp_t link_bmap; 762 uint32 entry[SOC_MAX_MEM_FIELD_WORDS]; 763 764 soc_cm_get_id(unit, &dev_id, &rev_id); 765 if (rev_id != BCM56980_A0_REV_ID) { 766 intf_max = TH3_IPMC_MAX_INTF_COUNT; 767 768 /*Allocate intf array for intfs*/ 769 alloc_size = intf_max * sizeof(bcm_if_t); 770 port_intf_array = sal_alloc(alloc_size, "IPMC group, port intfs array"); 771 if (port_intf_array == NULL) { 772 return BCM_E_MEMORY; 773 } 774 BCM_PBMP_CLEAR(pbmp_all); 775 BCM_PBMP_ASSIGN(pbmp_all, PBMP_ALL(unit)); 776 PBMP_ITER(pbmp_all, local_port) { 777 if (!IS_LB_PORT(unit, local_port)) { 778 port_intf_count = 0; 779 /* retrieve the interface id array for the {group, port} */ 780 rv = bcm_esw_ipmc_egress_intf_get(unit, ipmc_id, local_port, 781 intf_max, port_intf_array, &port_intf_count); 782 if (rv != BCM_E_NONE) { 783 sal_free(port_intf_array); 784 return rv; 785 } 786 if (local_port == port) { 787 /* Current port is the port for new encap id removal */ 788 for (intf_loop = 0; intf_loop < port_intf_count; 789 intf_loop++) { 790 if (port_intf_array[intf_loop] == nh_index) { 791 intf_del_idx = intf_loop; 792 break; 793 } 794 } 795 if (intf_del_idx != -1) { 796 for (intf_loop = intf_del_idx; 797 intf_loop < port_intf_count; 798 intf_loop++) { 799 port_intf_array[intf_loop] = 800 port_intf_array[(intf_loop + 1)]; 801 } 802 port_intf_count--; 803 } 804 } 805 if (port_intf_count > 0) { 806 rv = _bcm_esw_ipmc_egress_intf_set(unit, 0, local_port, 807 port_intf_count, port_intf_array, 1, FALSE); 808 if (rv != BCM_E_NONE) { 809 sal_free(port_intf_array); 810 return rv; 811 } 812 } 813 } 814 } 815 /*Free memory reserved for interafce array*/ 816 sal_free(port_intf_array); 817 /* Add port 158 to IP's EPC_LINK_BMAP */ 818 soc_mem_lock(unit, EPC_LINK_BMAPm); 819 rv = soc_mem_read(unit, EPC_LINK_BMAPm, MEM_BLOCK_ANY, 0, entry); 820 if (rv != BCM_E_NONE) { 821 soc_mem_unlock(unit, EPC_LINK_BMAPm); 822 return rv; 823 } 824 soc_mem_pbmp_field_get(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf, 825 &link_bmap); 826 BCM_PBMP_PORT_ADD(link_bmap, 158); 827 soc_mem_pbmp_field_set(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf, 828 &link_bmap); 829 rv = soc_mem_write(unit, EPC_LINK_BMAPm, MEM_BLOCK_ALL, 0, &entry); 830 soc_mem_unlock(unit, EPC_LINK_BMAPm); 831 if (rv != BCM_E_NONE) { 832 return rv; 833 } 834 835 /* Add port 158 to IP's ING_DEST_PORT_ENABLE */ 836 soc_mem_lock(unit, ING_DEST_PORT_ENABLEm); 837 rv = soc_mem_read(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ANY, 838 0, entry); 839 if (rv != BCM_E_NONE) { 840 soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm); 841 return rv; 842 } 843 soc_mem_pbmp_field_get(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf, 844 &link_bmap); 845 BCM_PBMP_PORT_ADD(link_bmap, 158); 846 soc_mem_pbmp_field_set(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf, 847 &link_bmap); 848 rv = soc_mem_write(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ALL, 0, 849 &entry); 850 soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm); 851 if (rv != BCM_E_NONE) { 852 return rv; 853 } 854 /* Add port 158 to the IPMC_L3_BITMAP */ 855 soc_mem_lock(unit, L3_IPMCm); 856 rv = _bcm_esw_multicast_ipmc_read(unit, ipmc_id, &l2_pbmp, &l3_pbmp); 857 if (rv != BCM_E_NONE) { 858 soc_mem_unlock(unit, L3_IPMCm); 859 return rv; 860 } 861 BCM_PBMP_PORT_ADD(l3_pbmp, 158); 862 rv = _bcm_esw_multicast_ipmc_write(unit, ipmc_id, l2_pbmp, 863 l3_pbmp, TRUE); 864 soc_mem_unlock(unit, L3_IPMCm); 865 866 if (rv != BCM_E_NONE) { 867 return rv; 868 } 869 if (!SAL_BOOT_SIMULATION) { 870 /* mmu rqe Flush*/ 871 for (itm = 0; itm < NUM_ITM(unit); itm++) { 872 if (itm_map & (1 << itm)) { 873 /* Issue RQE flush twice per each ITM*/ 874 rv = soc_tomahawk3_mmu_rqe_port_flush(unit, itm, 1); 875 if (rv != BCM_E_NONE) { 876 return rv; 877 } 878 rv = soc_tomahawk3_mmu_rqe_port_flush(unit, itm, 2); 879 if (rv != BCM_E_NONE) { 880 return rv; 881 } 882 } 883 } 884 } 885 /* Update the repl group to add new repl_id to the port*/ 886 BCM_IF_ERROR_RETURN(_bcm_th_ipmc_egress_intf_delete(unit, ipmc_id, 887 port, intf_max, nh_index, is_l3)); 888 889 /* Remove port 158 from the IPMC_L3_BITMAP */ 890 soc_mem_lock(unit, L3_IPMCm); 891 rv = _bcm_esw_multicast_ipmc_read(unit, ipmc_id, &l2_pbmp, &l3_pbmp); 892 if (rv != BCM_E_NONE) { 893 soc_mem_unlock(unit, L3_IPMCm); 894 return rv; 895 } 896 BCM_PBMP_PORT_REMOVE(l3_pbmp, 158); 897 rv = _bcm_esw_multicast_ipmc_write(unit, ipmc_id, l2_pbmp, 898 l3_pbmp, TRUE); 899 soc_mem_unlock(unit, L3_IPMCm); 900 if (rv != BCM_E_NONE) { 901 return rv; 902 } 903 /* Remove port 158 from IP's EPC_LINK_BMAP */ 904 soc_mem_lock(unit, EPC_LINK_BMAPm); 905 rv = soc_mem_read(unit, EPC_LINK_BMAPm, MEM_BLOCK_ANY, 0, entry); 906 if (rv != BCM_E_NONE) { 907 soc_mem_unlock(unit, EPC_LINK_BMAPm); 908 return rv; 909 } 910 soc_mem_pbmp_field_get(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf, 911 &link_bmap); 912 BCM_PBMP_PORT_REMOVE(link_bmap, 158); 913 soc_mem_pbmp_field_set(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf, 914 &link_bmap); 915 rv = soc_mem_write(unit, EPC_LINK_BMAPm, MEM_BLOCK_ALL, 0, 916 &entry); 917 soc_mem_unlock(unit, EPC_LINK_BMAPm); 918 if (rv != BCM_E_NONE) { 919 return rv; 920 } 921 922 /* Remove port 158 from IP's ING_DEST_PORT_ENABLE */ 923 soc_mem_lock(unit, ING_DEST_PORT_ENABLEm); 924 rv = soc_mem_read(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ANY, 925 0, entry); 926 if (rv != BCM_E_NONE) { 927 soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm); 928 return rv; 929 } 930 soc_mem_pbmp_field_get(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf, 931 &link_bmap); 932 BCM_PBMP_PORT_REMOVE(link_bmap, 158); 933 soc_mem_pbmp_field_set(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf, 934 &link_bmap); 935 rv = soc_mem_write(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ALL, 0, 936 &entry); 937 soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm); 938 if (rv != BCM_E_NONE) { 939 return rv; 940 } 941 942 if (!SAL_BOOT_SIMULATION) { 943 /* mmu rqe Flush*/ 944 for (itm = 0; itm < NUM_ITM(unit); itm++) { 945 if (itm_map & (1 << itm)) { 946 /* Issue RQE flush twice per each ITM*/ 947 rv = soc_tomahawk3_mmu_rqe_port_flush(unit, itm, 1); 948 if (rv != BCM_E_NONE) { 949 return rv; 950 } 951 rv = soc_tomahawk3_mmu_rqe_port_flush(unit, itm, 2); 952 if (rv != BCM_E_NONE) { 953 return rv; 954 } 955 } 956 } 957 } 958 /* reset programming in repl group 0*/ 959 PBMP_ITER(pbmp_all, local_port) { 960 if (!IS_LB_PORT(unit, local_port)) { 961 rv = _bcm_esw_ipmc_egress_intf_set(unit, 0, local_port, 0, 962 NULL, 1, FALSE); 963 if (rv != BCM_E_NONE) { 964 return rv; 965 } 966 } 967 } 968 969 return rv; 970 971 } else { 972 return _bcm_th_ipmc_egress_intf_delete(unit, ipmc_id, port, 973 if_max, nh_index, is_l3); 974 } 975 } 976 #endif /* BCM_TOMAHAWK3_SUPPORT*/ 977 978 #if defined(BCM_TOMAHAWK_SUPPORT) 979 if ((SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) && 980 (!SOC_IS_TOMAHAWK3(unit))) { 981 return _bcm_th_ipmc_egress_intf_delete(unit, ipmc_id, port, 982 if_max, nh_index, is_l3); 983 } 984 #endif /* BCM_TOMAHAWK_SUPPORT */ 985 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 986 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit) || 987 SOC_IS_KATANA2(unit)) { 988 return _bcm_tr3_ipmc_egress_intf_delete(unit, ipmc_id, port, 989 if_max, nh_index, is_l3); 990 } 991 #endif /* BCM_TRIUMPH3_SUPPORT */ 992 #if defined(BCM_TRIUMPH2_SUPPORT) 993 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_VALKYRIE2(unit) || 994 SOC_IS_APOLLO(unit) || SOC_IS_TD_TT(unit) || SOC_IS_KATANA(unit)) { 995 return _bcm_tr2_ipmc_egress_intf_delete(unit, ipmc_id, port, 996 if_max, nh_index); 997 } 998 #endif 999 #if defined(BCM_FIREBOLT_SUPPORT) 1000 return _bcm_fb_ipmc_egress_intf_delete(unit, ipmc_id, port, 1001 if_max, nh_index, is_l3); 1002 #endif /* BCM_FIREBOLT_SUPPORT */ 1003 #endif /* INCLUDE_L3 */ 1004 return BCM_E_UNAVAIL; 1005 } 1006 1007 #ifdef BCM_WARM_BOOT_SUPPORT 1008 #ifdef BCM_XGS3_FABRIC_SUPPORT 1009 /* 1010 * Function: 1011 * _bcm_fabric_multicast_sync 1012 * Purpose: 1013 * Record Fabric's Multicast module persistent info for Level 2 Warm Boot 1014 * Parameters: 1015 * unit - Device number. 1016 * Returns: 1017 * BCM_E_XXX 1018 */ 1019 int 1020 _bcm_fabric_multicast_sync(int unit) 1021 { 1022 int ipmc_mem_size = 0, ipmc_base, alloc_size; 1023 soc_scache_handle_t scache_handle; 1024 uint8 *multicast_scache; 1025 1026 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 1027 return BCM_E_NONE; 1028 } 1029 1030 SOC_IF_ERROR_RETURN 1031 (soc_hbx_ipmc_size_get(unit, &ipmc_base, &ipmc_mem_size)); 1032 1033 alloc_size = ipmc_mem_size * sizeof(uint8); 1034 1035 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MULTICAST, 0); 1036 BCM_IF_ERROR_RETURN 1037 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 1038 0, 1039 &multicast_scache, 1040 BCM_FABRIC_IPMC_WB_DEFAULT_VERSION, NULL)); 1041 1042 if (_fabric_multicast_ipmc_group_types[unit] != NULL) { 1043 sal_memcpy(multicast_scache, _fabric_multicast_ipmc_group_types[unit], 1044 alloc_size); 1045 } 1046 1047 return BCM_E_NONE; 1048 } 1049 #endif 1050 /* 1051 * Function: 1052 * _bcm_esw_multicast_sync 1053 * Purpose: 1054 * Record Multicast module persisitent info for Level 2 Warm Boot 1055 * Parameters: 1056 * unit - StrataSwitch unit number. 1057 * Returns: 1058 * BCM_E_XXX 1059 */ 1060 int 1061 _bcm_esw_multicast_sync(int unit) 1062 { 1063 #ifdef BCM_XGS3_FABRIC_SUPPORT 1064 if(SOC_IS_XGS3_FABRIC(unit)){ 1065 return _bcm_fabric_multicast_sync(unit); 1066 } 1067 #endif 1068 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 1069 if (SOC_IS_TRX(unit) && !SOC_IS_XGS3_FABRIC(unit)) { 1070 return _bcm_trx_multicast_sync(unit); 1071 } 1072 #endif /* BCM_TRX_SUPPORT && INCLUDE_L3 */ 1073 return BCM_E_NONE; 1074 } 1075 #endif /* BCM_WARM_BOOT_SUPPORT */ 1076 1077 1078 #if defined(BCM_XGS3_SWITCH_SUPPORT) 1079 1080 /* 1081 * Function: 1082 * _bcm_esw_multicast_l2_add 1083 * Purpose: 1084 * Helper function to add a port to L2 multicast group 1085 * Parameters: 1086 * unit - (IN) Device Number 1087 * group - (IN) Multicast group ID 1088 * port - (IN) GPORT Identifier 1089 * encap_id - (IN) Encap ID. 1090 * Returns: 1091 * BCM_E_XXX 1092 */ 1093 STATIC int 1094 _bcm_esw_multicast_l2_add(int unit, bcm_multicast_t group, 1095 bcm_port_t port, bcm_if_t encap_id) 1096 { 1097 l2mc_entry_t l2mc_entry; 1098 bcm_pbmp_t l2_pbmp; 1099 int mc_index, gport_id, modid_local, idx, trunk_local_ports = 0; 1100 bcm_module_t mod_out; 1101 bcm_port_t port_out; 1102 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) 1103 bcm_port_t local_trunk_member_ports[SOC_MAX_NUM_PP_PORTS] = {0}; 1104 int max_num_ports = SOC_MAX_NUM_PP_PORTS; 1105 #else 1106 bcm_port_t local_trunk_member_ports[SOC_MAX_NUM_PORTS] = {0}; 1107 int max_num_ports = SOC_MAX_NUM_PORTS; 1108 #endif 1109 bcm_trunk_t trunk_id; 1110 #if defined(BCM_KATANA2_SUPPORT) 1111 int is_local_subport = FALSE, pp_port; 1112 #endif 1113 1114 modid_local = 0; 1115 1116 mc_index = _BCM_MULTICAST_ID_GET(group); 1117 1118 /* Table index sanity check. */ 1119 #ifdef BCM_XGS3_FABRIC_SUPPORT 1120 if (SOC_IS_XGS3_FABRIC(unit)) { 1121 BCM_IF_ERROR_RETURN 1122 (_bcm_esw_fabric_multicast_param_check(unit, group, &mc_index)); 1123 } else 1124 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 1125 if ((mc_index < 0) || 1126 (mc_index >= soc_mem_index_count(unit, L2MCm))) { 1127 return BCM_E_PARAM; 1128 } 1129 1130 BCM_IF_ERROR_RETURN 1131 (_bcm_esw_gport_resolve(unit, port, &mod_out, &port_out, 1132 &trunk_id, &gport_id)); 1133 1134 #if defined(BCM_KATANA2_SUPPORT) 1135 if (soc_feature(unit, soc_feature_linkphy_coe) || 1136 soc_feature(unit, soc_feature_subtag_coe)) { 1137 if (BCM_GPORT_IS_SET(port) && 1138 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port)) { 1139 if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_out) == BCM_E_NONE) { 1140 pp_port = BCM_GPORT_SUBPORT_PORT_GET(port); 1141 if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, pp_port)) { 1142 is_local_subport = TRUE; 1143 } 1144 } 1145 if (is_local_subport == FALSE) { 1146 return BCM_E_PORT; 1147 } 1148 } 1149 } 1150 if (is_local_subport) { 1151 port_out = pp_port; 1152 } else 1153 #endif 1154 1155 if (BCM_TRUNK_INVALID != trunk_id) { 1156 BCM_IF_ERROR_RETURN( 1157 _bcm_esw_trunk_local_members_get(unit, trunk_id, 1158 max_num_ports, 1159 local_trunk_member_ports, 1160 &trunk_local_ports)); 1161 /* Convertion of system ports to physical ports done in */ 1162 /* _bcm_esw_multicast_trunk_members_setup */ 1163 } else { 1164 BCM_IF_ERROR_RETURN( 1165 _bcm_esw_modid_is_local(unit, mod_out, &modid_local)); 1166 if (TRUE != modid_local) { 1167 /* Only add this to replication set if destination is local */ 1168 return BCM_E_PORT; 1169 } 1170 /* Convert system port to physical port */ 1171 if (soc_feature(unit, soc_feature_sysport_remap)) { 1172 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 1173 } 1174 } 1175 1176 /* Add the port to the L2MC port bitmap */ 1177 BCM_IF_ERROR_RETURN 1178 (soc_mem_read(unit, L2MCm, MEM_BLOCK_ANY, mc_index, &l2mc_entry)); 1179 1180 soc_mem_pbmp_field_get(unit, L2MCm, &l2mc_entry, PORT_BITMAPf, 1181 &l2_pbmp); 1182 1183 if (BCM_TRUNK_INVALID != trunk_id) { 1184 for (idx = 0; idx < trunk_local_ports; idx++) { 1185 BCM_PBMP_PORT_ADD(l2_pbmp, local_trunk_member_ports[idx]); 1186 } 1187 } else { 1188 BCM_PBMP_PORT_ADD(l2_pbmp, port_out); 1189 } 1190 soc_mem_pbmp_field_set(unit, L2MCm, &l2mc_entry, PORT_BITMAPf, &l2_pbmp); 1191 1192 return soc_mem_write(unit, L2MCm, MEM_BLOCK_ALL, mc_index, &l2mc_entry); 1193 } 1194 1195 /* 1196 * Function: 1197 * _bcm_esw_multicast_l2_delete 1198 * Purpose: 1199 * Helper function to delete a port from L2 multicast group 1200 * Parameters: 1201 * unit - (IN) Device Number 1202 * group - (IN) Multicast group ID 1203 * port - (IN) GPORT Identifier 1204 * encap_id - (IN) Encap ID. 1205 * Returns: 1206 * BCM_E_XXX 1207 */ 1208 STATIC int 1209 _bcm_esw_multicast_l2_delete(int unit, bcm_multicast_t group, 1210 bcm_port_t port, bcm_if_t encap_id) 1211 { 1212 l2mc_entry_t l2mc_entry; 1213 bcm_pbmp_t l2_pbmp; 1214 int mc_index, gport_id, modid_local, idx, trunk_local_ports = 0; 1215 bcm_module_t mod_out; 1216 bcm_port_t port_out; 1217 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) 1218 bcm_port_t local_trunk_member_ports[SOC_MAX_NUM_PP_PORTS] = {0}; 1219 int max_num_ports = SOC_MAX_NUM_PP_PORTS; 1220 #else 1221 bcm_port_t local_trunk_member_ports[SOC_MAX_NUM_PORTS] = {0}; 1222 int max_num_ports = SOC_MAX_NUM_PORTS; 1223 #endif 1224 bcm_trunk_t trunk_id; 1225 #if defined(BCM_KATANA2_SUPPORT) 1226 int is_local_subport = FALSE, pp_port; 1227 #endif 1228 1229 modid_local = 0; 1230 mc_index = _BCM_MULTICAST_ID_GET(group); 1231 1232 #ifdef BCM_XGS3_FABRIC_SUPPORT 1233 if (SOC_IS_XGS3_FABRIC(unit)) { 1234 BCM_IF_ERROR_RETURN 1235 (_bcm_esw_fabric_multicast_param_check(unit, group, &mc_index)); 1236 } else 1237 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 1238 if ((mc_index < 0) || 1239 (mc_index >= soc_mem_index_count(unit, L2MCm))) { 1240 return BCM_E_PARAM; 1241 } 1242 1243 BCM_IF_ERROR_RETURN 1244 (_bcm_esw_gport_resolve(unit, port, &mod_out, &port_out, 1245 &trunk_id, &gport_id)); 1246 1247 #if defined(BCM_KATANA2_SUPPORT) 1248 if (soc_feature(unit, soc_feature_linkphy_coe) || 1249 soc_feature(unit, soc_feature_subtag_coe)) { 1250 if (BCM_GPORT_IS_SET(port) && 1251 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port)) { 1252 if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_out) == BCM_E_NONE) { 1253 pp_port = BCM_GPORT_SUBPORT_PORT_GET(port); 1254 if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, pp_port)) { 1255 is_local_subport = TRUE; 1256 } 1257 } 1258 if (is_local_subport == FALSE) { 1259 return BCM_E_PORT; 1260 } 1261 } 1262 } 1263 if (is_local_subport) { 1264 port_out = pp_port; 1265 } else 1266 #endif 1267 1268 if (BCM_TRUNK_INVALID != trunk_id) { 1269 BCM_IF_ERROR_RETURN( 1270 _bcm_esw_trunk_local_members_get(unit, trunk_id, 1271 max_num_ports, 1272 local_trunk_member_ports, 1273 &trunk_local_ports)); 1274 /* Convertion of system ports to physical ports done in */ 1275 /* _bcm_esw_trunk_local_members_get */ 1276 } else { 1277 BCM_IF_ERROR_RETURN( 1278 _bcm_esw_modid_is_local(unit, mod_out, &modid_local)); 1279 if (TRUE != modid_local) { 1280 /* Only add this to replication set if destination is local */ 1281 return BCM_E_PORT; 1282 } 1283 /* Convert system port to physical port */ 1284 if (soc_feature(unit, soc_feature_sysport_remap)) { 1285 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 1286 } 1287 } 1288 1289 /* Delete the port from the L2MC port bitmap */ 1290 BCM_IF_ERROR_RETURN 1291 (soc_mem_read(unit, L2MCm, MEM_BLOCK_ANY, mc_index, &l2mc_entry)); 1292 1293 soc_mem_pbmp_field_get(unit, L2MCm, &l2mc_entry, PORT_BITMAPf, 1294 &l2_pbmp); 1295 1296 1297 if (BCM_TRUNK_INVALID != trunk_id) { 1298 for (idx = 0; idx < trunk_local_ports; idx++) { 1299 BCM_PBMP_PORT_REMOVE(l2_pbmp, local_trunk_member_ports[idx]); 1300 } 1301 } else { 1302 BCM_PBMP_PORT_REMOVE(l2_pbmp, port_out); 1303 } 1304 soc_mem_pbmp_field_set(unit, L2MCm, &l2mc_entry, PORT_BITMAPf, &l2_pbmp); 1305 1306 return soc_mem_write(unit, L2MCm, MEM_BLOCK_ALL, mc_index, &l2mc_entry); 1307 } 1308 1309 #if (defined(BCM_TRX_SUPPORT) || defined(BCM_XGS3_SWITCH_SUPPORT)) && defined(INCLUDE_L3) 1310 /* 1311 * Function: 1312 * _bcm_esw_multicast_l2_get 1313 * Purpose: 1314 * Helper function to get ports that are part of L2 multicast 1315 * Parameters: 1316 * unit - (IN) Device Number 1317 * mc_index - (IN) Multicast index 1318 * port_max - (IN) Number of entries in "port_array" 1319 * port_array - (OUT) List of ports 1320 * encap_id_array - (OUT) List of encap identifiers 1321 * port_count - (OUT) Actual number of ports returned 1322 * Returns: 1323 * BCM_E_XXX 1324 * Notes: 1325 * If the input parameter port_max = 0, return in the output parameter 1326 * port_count the total number of ports/encapsulation IDs in the 1327 * specified multicast group's replication list. 1328 */ 1329 1330 STATIC int 1331 _bcm_esw_multicast_l2_get(int unit, bcm_multicast_t group, int port_max, 1332 bcm_gport_t *port_array, bcm_if_t *encap_id_array, 1333 int *port_count) 1334 { 1335 int mc_index, i, rv; 1336 l2mc_entry_t l2mc_entry; 1337 bcm_pbmp_t l2_pbmp; 1338 bcm_port_t port_iter; 1339 1340 i = 0; 1341 rv = BCM_E_NONE; 1342 1343 mc_index = _BCM_MULTICAST_ID_GET(group); 1344 1345 #ifdef BCM_XGS3_FABRIC_SUPPORT 1346 if (SOC_IS_XGS3_FABRIC(unit)) { 1347 BCM_IF_ERROR_RETURN 1348 (_bcm_esw_fabric_multicast_param_check(unit, group, &mc_index)); 1349 } else 1350 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 1351 if ((mc_index < 0) || 1352 (mc_index >= soc_mem_index_count(unit, L2MCm))) { 1353 return BCM_E_PARAM; 1354 } 1355 1356 soc_mem_lock(unit, L2MCm); 1357 rv = soc_mem_read(unit, L2MCm, MEM_BLOCK_ANY, mc_index, &l2mc_entry); 1358 soc_mem_unlock(unit, L2MCm); 1359 BCM_IF_ERROR_RETURN(rv); 1360 1361 soc_mem_pbmp_field_get(unit, L2MCm, &l2mc_entry, PORT_BITMAPf, &l2_pbmp); 1362 PBMP_ITER(l2_pbmp, port_iter) { 1363 if ((port_max > 0) && (i >= port_max)) { 1364 break; 1365 } 1366 if (NULL != port_array) { 1367 #if defined(BCM_KATANA2_SUPPORT) 1368 /* For KT2, pp_port >=42 are used for LinkPHY/SubportPktTag subport. 1369 * Get the subport info associated with the pp_port and form the subport_gport 1370 * subport gport should be returned in the port_array for pp_port >=42*/ 1371 1372 if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, port_iter)) { 1373 _BCM_KT2_SUBPORT_PORT_ID_SET(port_array[i], port_iter); 1374 if (BCM_PBMP_MEMBER( 1375 SOC_INFO(unit).linkphy_pp_port_pbm, port_iter)) { 1376 _BCM_KT2_SUBPORT_PORT_TYPE_SET(port_array[i], 1377 _BCM_KT2_SUBPORT_TYPE_LINKPHY); 1378 } else if (BCM_PBMP_MEMBER( 1379 SOC_INFO(unit).subtag_pp_port_pbm, port_iter)) { 1380 _BCM_KT2_SUBPORT_PORT_TYPE_SET(port_array[i], 1381 _BCM_KT2_SUBPORT_TYPE_SUBTAG); 1382 } else { 1383 return BCM_E_PORT; 1384 } 1385 } else 1386 #endif /* BCM_KATANA2_SUPPORT */ 1387 { 1388 BCM_IF_ERROR_RETURN 1389 (bcm_esw_port_gport_get(unit, port_iter, (port_array + i))); 1390 } 1391 } 1392 1393 if (NULL != encap_id_array) { 1394 encap_id_array[i] = BCM_IF_INVALID; 1395 } 1396 i++; 1397 } 1398 *port_count = i; 1399 return BCM_E_NONE; 1400 } 1401 #endif /* #if (defined(BCM_TRX_SUPPORT) || defined(BCM_XGS3_SWITCH_SUPPORT)) && defined(INCLUDE_L3) */ 1402 1403 /* 1404 * Function: 1405 * _bcm_esw_multicast_l2_create 1406 * Purpose: 1407 * Helper function to allocate a multicast group index for l2 1408 * Parameters: 1409 * unit - (IN) Device Number 1410 * flags - (IN) BCM_MULTICAST_* 1411 * group - (OUT) Group ID 1412 * Returns: 1413 * BCM_E_XXX 1414 */ 1415 STATIC int 1416 _bcm_esw_multicast_l2_create(int unit, uint32 flags, bcm_multicast_t *group) 1417 { 1418 int mc_index; 1419 int is_set = FALSE; 1420 l2mc_entry_t l2mc_entry; 1421 1422 if (flags & BCM_MULTICAST_WITH_ID) { 1423 if (_BCM_MULTICAST_IS_SET(*group) && !_BCM_MULTICAST_IS_L2(*group)) { 1424 /* Group ID doesn't match creation flag type */ 1425 return BCM_E_PARAM; 1426 } 1427 mc_index = _BCM_MULTICAST_ID_GET(*group); 1428 if ((mc_index < 0) || 1429 (mc_index >= soc_mem_index_count(unit, L2MCm))) { 1430 return BCM_E_PARAM; 1431 } 1432 1433 BCM_IF_ERROR_RETURN(_bcm_xgs3_l2mc_index_is_set(unit, mc_index, &is_set)); 1434 if (is_set) { 1435 return BCM_E_EXISTS; 1436 } 1437 1438 BCM_IF_ERROR_RETURN(_bcm_xgs3_l2mc_id_alloc(unit, mc_index)); 1439 } else { 1440 BCM_IF_ERROR_RETURN(_bcm_xgs3_l2mc_free_index(unit, &mc_index)); 1441 } 1442 sal_memset(&l2mc_entry, 0, sizeof(l2mc_entry)); 1443 soc_mem_field32_set(unit, L2MCm, &l2mc_entry, VALIDf, 1); 1444 BCM_IF_ERROR_RETURN( 1445 soc_mem_write(unit, L2MCm, MEM_BLOCK_ALL, mc_index, &l2mc_entry)); 1446 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_L2, mc_index); 1447 1448 return BCM_E_NONE; 1449 } 1450 1451 /* 1452 * Function: 1453 * _bcm_esw_multicast_l2_destroy 1454 * Purpose: 1455 * Helper function to destroy L2 multicast 1456 * Parameters: 1457 * unit - (IN) Device Number 1458 * group - (IN) Multicast group to destroy 1459 * Returns: 1460 * BCM_E_XXX 1461 */ 1462 1463 STATIC int 1464 _bcm_esw_multicast_l2_destroy(int unit, bcm_multicast_t group) 1465 { 1466 int mc_index; 1467 #if defined(BCM_TSN_SR_SUPPORT) 1468 int l2mc_index; 1469 bcm_port_t l2mc_port; 1470 sr_port_table_entry_t sr_port_entry; 1471 sr_lport_tab_entry_t sr_lport_entry; 1472 #endif /* BCM_TSN_SR_SUPPORT */ 1473 mc_index = _BCM_MULTICAST_ID_GET(group); 1474 1475 if ((mc_index < 0) || 1476 (mc_index >= soc_mem_index_count(unit, L2MCm))) { 1477 return BCM_E_PARAM; 1478 } 1479 1480 /* Clear the HW entry */ 1481 BCM_IF_ERROR_RETURN( 1482 soc_mem_write(unit, L2MCm, MEM_BLOCK_ALL, 1483 mc_index, soc_mem_entry_null(unit, L2MCm))); 1484 1485 #if defined(BCM_TSN_SR_SUPPORT) 1486 /* Clear L2MC for related SR ports if mc_index matches */ 1487 if (soc_feature(unit, soc_feature_tsn_sr)) { 1488 int sr_lport_idx; 1489 bcm_module_t my_modid = -1; 1490 int src_trk_idx = 0; /* Source Trunk table index.*/ 1491 uint32 mem_entry[SOC_MAX_MEM_WORDS]; 1492 1493 BCM_IF_ERROR_RETURN( 1494 bcm_esw_stk_my_modid_get(unit, &my_modid)); 1495 1496 BCM_PBMP_ITER(PBMP_ALL(unit), l2mc_port) { 1497 BCM_IF_ERROR_RETURN( 1498 soc_mem_read(unit, SR_PORT_TABLEm, MEM_BLOCK_ANY, 1499 l2mc_port, &sr_port_entry)); 1500 l2mc_index = soc_mem_field32_get(unit, SR_PORT_TABLEm, 1501 &sr_port_entry, L2MCf); 1502 if (l2mc_index == mc_index) { 1503 soc_mem_field32_set(unit, SR_PORT_TABLEm, &sr_port_entry, 1504 L2MCf, 0x0); 1505 BCM_IF_ERROR_RETURN( 1506 soc_mem_write(unit, SR_PORT_TABLEm, MEM_BLOCK_ALL, 1507 l2mc_port, &sr_port_entry)); 1508 } 1509 1510 BCM_IF_ERROR_RETURN( 1511 _bcm_esw_src_mod_port_table_index_get(unit, my_modid, 1512 l2mc_port, &src_trk_idx)); 1513 BCM_IF_ERROR_RETURN( 1514 soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY, 1515 src_trk_idx, mem_entry)); 1516 1517 sr_lport_idx = soc_mem_field32_get(unit, SOURCE_TRUNK_MAP_TABLEm, 1518 mem_entry, LPORT_PROFILE_IDXf); 1519 1520 BCM_IF_ERROR_RETURN( 1521 soc_mem_read(unit, SR_LPORT_TABm, MEM_BLOCK_ANY, 1522 sr_lport_idx, &sr_lport_entry)); 1523 l2mc_index = soc_mem_field32_get(unit, SR_LPORT_TABm, 1524 &sr_lport_entry, L2MCf); 1525 if (l2mc_index == mc_index) { 1526 soc_mem_field32_set(unit, SR_LPORT_TABm, &sr_lport_entry, 1527 L2MCf, 0x0); 1528 BCM_IF_ERROR_RETURN( 1529 soc_mem_write(unit, SR_LPORT_TABm, MEM_BLOCK_ALL, 1530 sr_lport_idx, &sr_lport_entry)); 1531 } 1532 } 1533 } 1534 #endif /* BCM_TSN_SR_SUPPORT */ 1535 1536 /* Free the L2MC index */ 1537 return _bcm_xgs3_l2mc_id_free(unit, mc_index); 1538 } 1539 1540 #if defined (INCLUDE_L3) 1541 1542 /* 1543 * Function: 1544 * _bcm_esw_multicast_egress_mapped_trunk_member_find 1545 * Purpose: 1546 * Find the trunk member the encap id resides on. 1547 * Parameters: 1548 * unit - (IN) Device Number 1549 * group - (IN) Multicast group ID 1550 * port - (IN) GPORT ID 1551 * encap_id - (IN) Encap identifiers 1552 * trunk_member - (OUT) Trunk member the encap id resides on 1553 * Returns: 1554 * BCM_E_XXX 1555 */ 1556 STATIC int 1557 _bcm_esw_multicast_egress_mapped_trunk_member_find(int unit, 1558 bcm_multicast_t group, bcm_gport_t port, bcm_if_t encap_id, 1559 bcm_gport_t *trunk_member) 1560 { 1561 int rv = BCM_E_NONE; 1562 bcm_trunk_t trunk_id; 1563 bcm_trunk_info_t tinfo; 1564 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) 1565 bcm_port_t local_trunk_port_array[SOC_MAX_NUM_PP_PORTS]; 1566 int max_num_ports = SOC_MAX_NUM_PP_PORTS; 1567 #else 1568 bcm_port_t local_trunk_port_array[SOC_MAX_NUM_PORTS]; 1569 int max_num_ports = SOC_MAX_NUM_PORTS; 1570 #endif 1571 int num_local_trunk_ports; 1572 int port_count; 1573 bcm_gport_t *port_array; 1574 bcm_if_t *encap_id_array; 1575 int match; 1576 int i, j; 1577 bcm_port_t local_port; 1578 int mc_index; 1579 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 1580 int is_local_subport = FALSE; 1581 #endif 1582 if (NULL == trunk_member) { 1583 return BCM_E_PARAM; 1584 } 1585 1586 *trunk_member = port; 1587 1588 if (0 == _BCM_MULTICAST_IS_L3(group)) { 1589 /* Software trunk resolution is available only for IPMC groups */ 1590 return BCM_E_NONE; 1591 } 1592 mc_index = _BCM_MULTICAST_ID_GET(group); 1593 if ((mc_index < 0) || (mc_index >= soc_mem_index_count(unit, L3_IPMCm))) { 1594 return BCM_E_PARAM; 1595 } 1596 1597 if (!BCM_GPORT_IS_TRUNK(port)) { 1598 return BCM_E_NONE; 1599 } 1600 1601 if (BCM_IF_INVALID == encap_id) { 1602 return BCM_E_NONE; 1603 } 1604 1605 /* Get trunk property and local member ports */ 1606 trunk_id = BCM_GPORT_TRUNK_GET(port); 1607 BCM_IF_ERROR_RETURN 1608 (bcm_esw_trunk_get(unit, trunk_id, &tinfo, 0, NULL, NULL)); 1609 if (!(tinfo.flags & BCM_TRUNK_FLAG_IPMC_CLEAVE)) { 1610 return BCM_E_NONE; 1611 } 1612 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, trunk_id, 1613 max_num_ports, local_trunk_port_array, 1614 &num_local_trunk_ports)); 1615 1616 /* Get all ports and encap_ids of the multicast group */ 1617 BCM_IF_ERROR_RETURN(bcm_esw_multicast_egress_get(unit, group, 0, 1618 NULL, NULL, &port_count)); 1619 if (0 == port_count) { 1620 return BCM_E_NOT_FOUND; 1621 } 1622 port_array = sal_alloc(sizeof(bcm_gport_t) * port_count, "port_array"); 1623 if (NULL == port_array) { 1624 return BCM_E_MEMORY; 1625 } 1626 encap_id_array = sal_alloc(sizeof(bcm_if_t) * port_count, "encap_id_array"); 1627 if (NULL == encap_id_array) { 1628 sal_free(port_array); 1629 return BCM_E_MEMORY; 1630 } 1631 rv = bcm_esw_multicast_egress_get(unit, group, port_count, 1632 port_array, encap_id_array, &port_count); 1633 if (BCM_FAILURE(rv)) { 1634 sal_free(port_array); 1635 sal_free(encap_id_array); 1636 return rv; 1637 } 1638 1639 /* Search for the trunk member the encap id resides on */ 1640 match = FALSE; 1641 for (i = 0; i < port_count; i++) { 1642 if (encap_id == encap_id_array[i]) { 1643 1644 #if defined(BCM_HGPROXY_COE_SUPPORT) 1645 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 1646 BCM_GPORT_IS_SET(port_array[i]) && 1647 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 1648 is_local_subport = TRUE; 1649 _bcmi_coe_subport_physical_port_get(unit, port_array[i], 1650 &local_port); 1651 } else 1652 #endif 1653 1654 #if defined(BCM_KATANA2_SUPPORT) 1655 if (soc_feature(unit, soc_feature_linkphy_coe) || 1656 soc_feature(unit, soc_feature_subtag_coe)) { 1657 if (BCM_GPORT_IS_SET(port_array[i]) && 1658 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, 1659 port_array[i])) { 1660 is_local_subport = TRUE; 1661 local_port = _BCM_KT2_SUBPORT_PORT_ID_GET(port_array[i]); 1662 } 1663 } 1664 #endif 1665 1666 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 1667 if (is_local_subport) { 1668 /* Local subport assigned above */ 1669 } else 1670 #endif 1671 { 1672 rv = bcm_esw_port_local_get(unit, port_array[i], &local_port); 1673 if (BCM_FAILURE(rv)) { 1674 sal_free(port_array); 1675 sal_free(encap_id_array); 1676 return rv; 1677 } 1678 } 1679 for (j = 0; j < num_local_trunk_ports; j++) { 1680 if (local_trunk_port_array[j] == local_port) { 1681 match = TRUE; 1682 break; 1683 } 1684 } 1685 if (match) { 1686 break; 1687 } 1688 } 1689 } 1690 1691 if (match) { 1692 *trunk_member = port_array[i]; 1693 } else { 1694 rv = BCM_E_NOT_FOUND; 1695 } 1696 1697 sal_free(port_array); 1698 sal_free(encap_id_array); 1699 return rv; 1700 } 1701 1702 /* 1703 * Function: 1704 * _bcm_esw_multicast_egress_encap_id_to_trunk_member_map 1705 * Purpose: 1706 * Maps encap id to a trunk group member. This is performed 1707 * if (1) the given group is an IPMC group, (2) the port in port_array is 1708 * a trunk gport, and (3) IPMC trunk resolution is disabled for that trunk 1709 * group in hardware by setting the BCM_TRUNK_FLAG_IPMC_CLEAVE flag in 1710 * bcm_trunk_info_t. The hash fields used for trunk group member 1711 * selection are specified by ipmc_psc field in bcm_trunk_info_t. 1712 * The valid values for ipmc_psc are BCM_TRUNK_PSC_IPSA, IPDA, EGRESS_VID, 1713 * and RANDOM. 1714 * Parameters: 1715 * unit - (IN) Device Number 1716 * group - (IN) Multicast group ID 1717 * port_count - (IN) Number of ports in replication list 1718 * port_array - (IN) List of GPORT Identifiers 1719 * encap_id_array - (IN) List of encap identifiers 1720 * mapped_port_array - (OUT) List of mapped GPORT identifiers 1721 * Returns: 1722 * BCM_E_XXX 1723 */ 1724 STATIC int 1725 _bcm_esw_multicast_egress_encap_id_to_trunk_member_map(int unit, 1726 bcm_multicast_t group, int port_count, 1727 bcm_gport_t *port_array, bcm_if_t *encap_id_array, 1728 bcm_gport_t *mapped_port_array) 1729 { 1730 int rv = BCM_E_NONE; 1731 bcm_ipmc_addr_t ipmc_data; 1732 uint8 *hash_key = NULL; 1733 uint8 *hash_key_ptr = NULL; 1734 int hash_key_size, max_hash_key_size; 1735 int i, j; 1736 bcm_trunk_t trunk_id; 1737 bcm_trunk_info_t tinfo; 1738 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) 1739 bcm_port_t local_trunk_port_array[SOC_MAX_NUM_PP_PORTS]; 1740 int max_num_ports = SOC_MAX_NUM_PP_PORTS; 1741 #else 1742 bcm_port_t local_trunk_port_array[SOC_MAX_NUM_PORTS]; 1743 int max_num_ports = SOC_MAX_NUM_PORTS; 1744 #endif 1745 int num_local_trunk_ports; 1746 bcm_l3_intf_t l3_intf; 1747 uint32 hash; 1748 bcm_port_t mapped_port; 1749 int mc_index; 1750 int random_num; 1751 int optimize_for_space; 1752 bcm_if_t *temp_encap_array = NULL; 1753 int *sublist_id_array = NULL; 1754 int temp_encap_count; 1755 int sublist_max, sublist_count = 0; 1756 int first_free_sublist_id, next_free_sublist_id; 1757 int selected_sublist_id; 1758 int sublist0_trunk_member_index; 1759 int trunk_member_index; 1760 int temp_encap_index; 1761 1762 if (port_count < 0) { 1763 return BCM_E_PARAM; 1764 } 1765 1766 if (0 == port_count) { 1767 /* Nothing to do */ 1768 return BCM_E_NONE; 1769 } 1770 1771 if (NULL == port_array) { 1772 return BCM_E_PARAM; 1773 } 1774 1775 /* Copy port_array to mapped_port_array */ 1776 sal_memcpy(mapped_port_array, port_array, 1777 sizeof(bcm_gport_t) * port_count); 1778 1779 if (0 == _BCM_MULTICAST_IS_L3(group)) { 1780 /* Software trunk resolution is available only for IPMC groups */ 1781 return BCM_E_NONE; 1782 } 1783 mc_index = _BCM_MULTICAST_ID_GET(group); 1784 if ((mc_index < 0) || (mc_index >= soc_mem_index_count(unit, L3_IPMCm))) { 1785 return BCM_E_PARAM; 1786 } 1787 1788 if (NULL == encap_id_array) { 1789 /* For IPMC groups, encap_id_array should not be NULL */ 1790 return BCM_E_PARAM; 1791 } 1792 1793 /* Allocate hash key. The hash key contains at most two IPv6 address, 1794 * a VLAN ID, and a random integer. 1795 */ 1796 max_hash_key_size = 2 * sizeof(bcm_ip6_t) + sizeof(bcm_vlan_t) + 1797 sizeof(int); 1798 hash_key = sal_alloc(max_hash_key_size, "hash key"); 1799 if (NULL == hash_key) { 1800 return BCM_E_MEMORY; 1801 } 1802 sal_memset(hash_key, 0, max_hash_key_size); 1803 1804 /* Iterate through mapped_port_array */ 1805 for (i = 0; i < port_count; i++) { 1806 if (!BCM_GPORT_IS_TRUNK(mapped_port_array[i])) { 1807 continue; 1808 } 1809 1810 if (BCM_IF_INVALID == encap_id_array[i]) { 1811 continue; 1812 } 1813 1814 trunk_id = BCM_GPORT_TRUNK_GET(mapped_port_array[i]); 1815 rv = bcm_esw_trunk_get(unit, trunk_id, &tinfo, 0, NULL, NULL); 1816 if (BCM_FAILURE(rv)) { 1817 goto done; 1818 } 1819 if (!(tinfo.flags & BCM_TRUNK_FLAG_IPMC_CLEAVE)) { 1820 /* IPMC trunk resolution is enabled in hardware, 1821 * do not perform software trunk resolution. 1822 */ 1823 continue; 1824 } 1825 1826 /* Get local members of the trunk group */ 1827 rv = _bcm_esw_trunk_local_members_get(unit, trunk_id, 1828 max_num_ports, local_trunk_port_array, 1829 &num_local_trunk_ports); 1830 if (BCM_FAILURE(rv)) { 1831 goto done; 1832 } 1833 1834 /* Compute hash */ 1835 1836 sal_memset(hash_key, 0, max_hash_key_size); 1837 hash_key_ptr = hash_key; 1838 1839 if ((tinfo.ipmc_psc & BCM_TRUNK_PSC_IPSA) || 1840 (tinfo.ipmc_psc & BCM_TRUNK_PSC_IPDA)) { 1841 bcm_ipmc_addr_t_init(&ipmc_data); 1842 rv = bcm_esw_ipmc_get_by_index(unit, _BCM_MULTICAST_ID_GET(group), 1843 &ipmc_data); 1844 if (BCM_FAILURE(rv)) { 1845 goto done; 1846 } 1847 if (ipmc_data.flags & BCM_IPMC_IP6) { 1848 if (tinfo.ipmc_psc & BCM_TRUNK_PSC_IPSA) { 1849 sal_memcpy(hash_key_ptr, &ipmc_data.s_ip6_addr, 1850 sizeof(ipmc_data.s_ip6_addr)); 1851 hash_key_ptr += sizeof(ipmc_data.s_ip6_addr); 1852 } 1853 if (tinfo.ipmc_psc & BCM_TRUNK_PSC_IPDA) { 1854 sal_memcpy(hash_key_ptr, &ipmc_data.mc_ip6_addr, 1855 sizeof(ipmc_data.mc_ip6_addr)); 1856 hash_key_ptr += sizeof(ipmc_data.mc_ip6_addr); 1857 } 1858 } else { 1859 if (tinfo.ipmc_psc & BCM_TRUNK_PSC_IPSA) { 1860 sal_memcpy(hash_key_ptr, &ipmc_data.s_ip_addr, 1861 sizeof(ipmc_data.s_ip_addr)); 1862 hash_key_ptr += sizeof(ipmc_data.s_ip_addr); 1863 } 1864 if (tinfo.ipmc_psc & BCM_TRUNK_PSC_IPDA) { 1865 sal_memcpy(hash_key_ptr, &ipmc_data.mc_ip_addr, 1866 sizeof(ipmc_data.mc_ip_addr)); 1867 hash_key_ptr += sizeof(ipmc_data.mc_ip_addr); 1868 } 1869 } 1870 } 1871 1872 if (tinfo.ipmc_psc & BCM_TRUNK_PSC_EGRESS_VID) { 1873 if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, encap_id_array[i])) { 1874 bcm_l3_intf_t_init(&l3_intf); 1875 l3_intf.l3a_intf_id = encap_id_array[i]; 1876 rv = bcm_esw_l3_intf_get(unit, &l3_intf); 1877 if (BCM_FAILURE(rv)) { 1878 goto done; 1879 } 1880 sal_memcpy(hash_key_ptr, &l3_intf.l3a_vid, 1881 sizeof(bcm_vlan_t)); 1882 hash_key_ptr += sizeof(bcm_vlan_t); 1883 } 1884 } 1885 1886 if (tinfo.ipmc_psc & BCM_TRUNK_PSC_RANDOM) { 1887 random_num = sal_time_usecs(); 1888 sal_memcpy(hash_key_ptr, &random_num, sizeof(int)); 1889 hash_key_ptr += sizeof(int); 1890 } 1891 1892 hash_key_size = hash_key_ptr - hash_key; 1893 if (hash_key_size > 0) { 1894 hash = _shr_crc32(0, hash_key, hash_key_size); 1895 } else { 1896 hash = 0; 1897 } 1898 1899 optimize_for_space = FALSE; 1900 #if defined(BCM_TRIUMPH2_SUPPORT) 1901 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 1902 SOC_IS_VALKYRIE2(unit) || SOC_IS_TRIDENT(unit) || 1903 SOC_IS_KATANA(unit)) { 1904 int available_percent, threshold; 1905 1906 rv = bcm_esw_switch_control_get(unit, 1907 bcmSwitchIpmcReplicationAvailabilityThreshold, &threshold); 1908 if (BCM_FAILURE(rv)) { 1909 goto done; 1910 } 1911 if (threshold > 0) { 1912 rv = bcm_tr2_ipmc_repl_availability_get(unit, &available_percent); 1913 if (BCM_FAILURE(rv)) { 1914 goto done; 1915 } 1916 if (available_percent < threshold) { 1917 /* IPMC replication table available space has fallen below the 1918 * configured threshold. Conservation of IPMC replication table 1919 * space now takes precedence over hashing when assigning encap 1920 * ids to trunk members. 1921 */ 1922 optimize_for_space = TRUE; 1923 } 1924 } 1925 } 1926 #endif /* BCM_TRIUMPH2_SUPPORT */ 1927 1928 if (!optimize_for_space) { 1929 mapped_port = local_trunk_port_array[hash % num_local_trunk_ports]; 1930 rv = bcm_esw_port_gport_get(unit, mapped_port, 1931 &mapped_port_array[i]); 1932 if (BCM_FAILURE(rv)) { 1933 goto done; 1934 } 1935 continue; 1936 } 1937 1938 /* Assign encap ids to trunk members with conservation of IPMC 1939 * replication table space as highest priority. 1940 * First, gather all encap ids with the same trunk ID as the 1941 * current trunk group. 1942 */ 1943 1944 if (NULL == temp_encap_array) { 1945 temp_encap_array = sal_alloc(sizeof(bcm_if_t) * port_count, 1946 "temp encap array"); 1947 if (NULL == temp_encap_array) { 1948 rv = BCM_E_MEMORY; 1949 goto done; 1950 } 1951 } 1952 sal_memset(temp_encap_array, 0, sizeof(bcm_if_t) * port_count); 1953 1954 if (NULL == sublist_id_array) { 1955 sublist_id_array = sal_alloc(sizeof(int) * port_count, 1956 "sublist id array"); 1957 if (NULL == sublist_id_array) { 1958 rv = BCM_E_MEMORY; 1959 goto done; 1960 } 1961 } 1962 sal_memset(sublist_id_array, 0, sizeof(int) * port_count); 1963 1964 temp_encap_count = 0; 1965 for (j = i; j < port_count; j++) { 1966 if (!BCM_GPORT_IS_TRUNK(mapped_port_array[j])) { 1967 continue; 1968 } 1969 if (BCM_IF_INVALID == encap_id_array[j]) { 1970 continue; 1971 } 1972 if (BCM_GPORT_TRUNK_GET(mapped_port_array[j]) != trunk_id) { 1973 continue; 1974 } 1975 temp_encap_array[temp_encap_count++] = encap_id_array[j]; 1976 } 1977 1978 /* Split the current trunk group's list of encap ids into sublists, 1979 * such that the sublists match existing replication lists, 1980 * enabling sharing of IPMC replication table entries. 1981 * It's not necessary to generate more sublists than there are 1982 * trunk members, since mapping multiple sublists to a trunk member 1983 * would effectively join those sublists. 1984 */ 1985 1986 sublist_max = num_local_trunk_ports; 1987 for (j = 0; j < temp_encap_count; j++) { 1988 /* Initialize each encap id's sublist id to be 1989 * the invalid value of sublist_max. 1990 */ 1991 sublist_id_array[j] = sublist_max; 1992 } 1993 1994 #if defined(BCM_TRIUMPH2_SUPPORT) 1995 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 1996 SOC_IS_VALKYRIE2(unit) || SOC_IS_TRIDENT(unit) || 1997 SOC_IS_KATANA(unit)) { 1998 1999 rv = bcm_tr2_ipmc_repl_list_split(unit, temp_encap_count, 2000 temp_encap_array, sublist_id_array, 2001 sublist_max, &sublist_count); 2002 if (BCM_FAILURE(rv)) { 2003 goto done; 2004 } 2005 } 2006 #endif /* BCM_TRIUMPH2_SUPPORT */ 2007 2008 /* If the number of sublists used, given by sublist_count, 2009 * is less than the max number of sublists allowed, 2010 * given by sublist_max, the encap ids that are not yet 2011 * a member of any sublist are assigned to the remaining 2012 * free sublists. 2013 * If there are no free sublist left, the encap ids that are 2014 * not yet a member of any sublist are assigned to an 2015 * existing sublist selected by hash. 2016 */ 2017 if (sublist_count < sublist_max) { 2018 first_free_sublist_id = sublist_count; 2019 next_free_sublist_id = first_free_sublist_id; 2020 for (j = 0; j < temp_encap_count; j++) { 2021 if (sublist_id_array[j] == sublist_max) { 2022 sublist_id_array[j] = next_free_sublist_id; 2023 if ((next_free_sublist_id + 1) == sublist_max) { 2024 /* wrap around to the first free sublist id */ 2025 next_free_sublist_id = first_free_sublist_id; 2026 } else { 2027 next_free_sublist_id++; 2028 } 2029 } 2030 } 2031 } else if (sublist_count == sublist_max) { 2032 selected_sublist_id = hash % sublist_max; 2033 for (j = 0; j < temp_encap_count; j++) { 2034 if (sublist_id_array[j] == sublist_max) { 2035 sublist_id_array[j] = selected_sublist_id; 2036 } 2037 } 2038 } else { 2039 /* sublist_count should never be greater than sublist_max */ 2040 rv = BCM_E_INTERNAL; 2041 goto done; 2042 } 2043 2044 /* The sublists will be assigned to trunk members in a round-robin 2045 * fashion, with the starting trunk member selected by hash. 2046 * Sublist 0 will be assigned to a local trunk member selected 2047 * by hashing. Then sublist 1 will be assigned to the 2048 * next trunk member in local_trunk_port_array, and so on. 2049 */ 2050 sublist0_trunk_member_index = hash % num_local_trunk_ports; 2051 temp_encap_index = 0; 2052 for (j = i; j < port_count; j++) { 2053 if (!BCM_GPORT_IS_TRUNK(mapped_port_array[j])) { 2054 continue; 2055 } 2056 if (BCM_IF_INVALID == encap_id_array[j]) { 2057 continue; 2058 } 2059 if (BCM_GPORT_TRUNK_GET(mapped_port_array[j]) != trunk_id) { 2060 continue; 2061 } 2062 if (temp_encap_array[temp_encap_index] != encap_id_array[j]) { 2063 /* They should always match */ 2064 rv = BCM_E_INTERNAL; 2065 goto done; 2066 } 2067 2068 trunk_member_index = (sublist0_trunk_member_index + 2069 sublist_id_array[temp_encap_index]) % num_local_trunk_ports; 2070 2071 mapped_port = local_trunk_port_array[trunk_member_index]; 2072 rv = bcm_esw_port_gport_get(unit, mapped_port, 2073 &mapped_port_array[j]); 2074 if (BCM_FAILURE(rv)) { 2075 goto done; 2076 } 2077 temp_encap_index++; 2078 } 2079 } 2080 2081 done: 2082 if (hash_key) { 2083 sal_free(hash_key); 2084 } 2085 if (temp_encap_array) { 2086 sal_free(temp_encap_array); 2087 } 2088 if (sublist_id_array) { 2089 sal_free(sublist_id_array); 2090 } 2091 2092 return rv; 2093 } 2094 2095 /* 2096 * Function: 2097 * _bcm_esw_multicast_l3_group_check 2098 * Purpose: 2099 * Helper function to validate L3 or Virtual multicast group 2100 * Parameters: 2101 * unit - (IN) Device Number 2102 * group - (IN) Multicast group ID 2103 * is_l3 - (OUT) L3 Group identifier for Firebolt 2104 * Returns: 2105 * BCM_E_XXX 2106 */ 2107 STATIC int 2108 _bcm_esw_multicast_l3_group_check(int unit, bcm_multicast_t group, int *is_l3) 2109 { 2110 if (_BCM_MULTICAST_IS_L3(group) 2111 || _BCM_MULTICAST_IS_TRILL(group) 2112 || _BCM_MULTICAST_IS_FLOW(group) 2113 || _BCM_MULTICAST_IS_VXLAN(group)) { 2114 if (NULL != is_l3) { /* If caller cares about this information */ 2115 *is_l3 = 1; 2116 } 2117 } else if (!SOC_IS_TRX(unit)) { 2118 /* Pre TX devices don't support Virutal multicast groups */ 2119 return (BCM_E_PARAM); 2120 } else if (!_BCM_MULTICAST_IS_VPLS(group) && 2121 !_BCM_MULTICAST_IS_MIM(group) && 2122 !_BCM_MULTICAST_IS_WLAN(group) && 2123 !_BCM_MULTICAST_IS_VLAN(group) && 2124 !_BCM_MULTICAST_IS_NIV(group) && 2125 !_BCM_MULTICAST_IS_L2GRE(group) && 2126 !_BCM_MULTICAST_IS_SUBPORT(group) && 2127 !_BCM_MULTICAST_IS_EGRESS_OBJECT(group) && 2128 !_BCM_MULTICAST_IS_EXTENDER(group)) { 2129 return (BCM_E_PARAM); 2130 } 2131 2132 return (BCM_E_NONE); 2133 } 2134 2135 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) 2136 typedef struct _bcm_trunk_first_member_s { 2137 int trunk_id; 2138 int pipe_id; 2139 int first_member; 2140 } _bcm_trunk_first_member_t; 2141 2142 2143 /* 2144 * Function: 2145 * _bcm_esw_ipmc_egress_intf_destroy_in_trunk_repl_mode 2146 * Purpose: 2147 * Destory ipmc egress intf of given ports which are represented by e_pbmp. 2148 * Parameters: 2149 * unit - (IN) Device Number 2150 * mc_index - (IN) Multicast group ID. 2151 * e_pbmp - (IN) Port bitmap 2152 * is_l3 - (IN) Indicates if multicast group type is IPMC. 2153 * Returns: 2154 * BCM_E_XXX 2155 */ 2156 STATIC int 2157 _bcm_esw_ipmc_egress_intf_destroy_in_trunk_repl_mode(int unit, 2158 int mc_index, bcm_pbmp_t e_pbmp, int is_l3) 2159 { 2160 bcm_trunk_t tgid; 2161 _bcm_trunk_first_member_t *first_member_array; 2162 bcm_port_t first_member, port_iter; 2163 int count, i, is_first_member, pipe; 2164 int rv; 2165 2166 first_member_array = 2167 sal_alloc(sizeof(_bcm_trunk_first_member_t) * SOC_MAX_NUM_PORTS, 2168 "first_member_array pointers"); 2169 if (NULL == first_member_array) { 2170 return BCM_E_MEMORY; 2171 } 2172 2173 for (i = 0; i < SOC_MAX_NUM_PORTS; i++) { 2174 first_member_array[i].trunk_id = BCM_TRUNK_INVALID; 2175 first_member_array[i].first_member = -1; 2176 first_member_array[i].pipe_id = -1; 2177 } 2178 2179 count = 0; 2180 BCM_PBMP_ITER(e_pbmp, port_iter) { 2181 rv = _bcm_esw_ipmc_port_trunkid_get(unit, port_iter, &tgid); 2182 if (BCM_FAILURE(rv)) { 2183 sal_free(first_member_array); 2184 return rv; 2185 } 2186 if (tgid != BCM_TRUNK_INVALID) { 2187 is_first_member = TRUE; 2188 first_member = -1; 2189 pipe = SOC_INFO(unit).port_pipe[port_iter]; 2190 for (i = 0; i < count; i++) { 2191 if ((first_member_array[i].trunk_id == tgid) && 2192 (first_member_array[i].pipe_id == pipe)) { 2193 is_first_member = FALSE; 2194 first_member = first_member_array[i].first_member; 2195 break; 2196 } 2197 } 2198 if (i == count) { 2199 first_member_array[count].trunk_id = tgid; 2200 first_member_array[count].pipe_id = pipe; 2201 first_member_array[count].first_member = port_iter; 2202 is_first_member = TRUE; 2203 count++; 2204 } 2205 2206 if (is_first_member) { 2207 rv = _bcm_esw_ipmc_egress_intf_set_for_trunk_first_member( 2208 unit, mc_index, port_iter, 0, NULL, 2209 is_l3, FALSE, tgid); 2210 } else { 2211 rv = _bcm_esw_ipmc_egress_intf_set_for_same_pipe_member( 2212 unit, mc_index, port_iter, 2213 first_member, BCM_TRUNK_INVALID); 2214 } 2215 } else { 2216 rv = _bcm_esw_ipmc_egress_intf_set_for_trunk_first_member( 2217 unit, mc_index, port_iter,0, NULL, 2218 is_l3, FALSE, BCM_TRUNK_INVALID); 2219 } 2220 2221 if (BCM_FAILURE(rv)) { 2222 sal_free(first_member_array); 2223 return rv; 2224 } 2225 } 2226 2227 sal_free(first_member_array); 2228 2229 return BCM_E_NONE; 2230 } 2231 #endif 2232 2233 #ifdef BCM_TRIDENT2_SUPPORT 2234 static int 2235 _bcm_esw_multicast_l3_mpls_nh_check(int unit, int nh, int* is_l3_mpls) 2236 { 2237 int rv = 0; 2238 int entry_type = 0; 2239 soc_field_t entry_type_field = 0; 2240 egr_l3_next_hop_entry_t egr_entry; 2241 *is_l3_mpls = 0; 2242 2243 if (SOC_IS_TRIDENT3X(unit)) { 2244 entry_type_field = DATA_TYPEf; 2245 } else { 2246 entry_type_field = ENTRY_TYPEf; 2247 } 2248 2249 if (SOC_MEM_IS_VALID(unit, EGR_L3_NEXT_HOPm)) { 2250 if (!BCM_XGS3_L3_ENT_REF_CNT(BCM_XGS3_L3_TBL_PTR(unit, next_hop), nh)) { 2251 return BCM_E_NOT_FOUND; 2252 } 2253 2254 sal_memset(&egr_entry, 0, sizeof(egr_l3_next_hop_entry_t)); 2255 rv = BCM_XGS3_MEM_READ(unit, EGR_L3_NEXT_HOPm, nh, &egr_entry); 2256 if (rv != BCM_E_NONE) { 2257 return rv; 2258 } 2259 2260 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, entry_type_field)) { 2261 entry_type = soc_mem_field32_get( 2262 unit, EGR_L3_NEXT_HOPm, &egr_entry, entry_type_field); 2263 if (entry_type == 1) { 2264 *is_l3_mpls = 1; 2265 } 2266 } 2267 } 2268 2269 return BCM_E_NONE; 2270 } 2271 #endif 2272 2273 2274 /* 2275 * Function: 2276 * _bcm_esw_multicast_l3_add 2277 * Purpose: 2278 * Helper function to add a port to L3 or Virtual multicast group 2279 * Parameters: 2280 * unit - (IN) Device Number 2281 * group - (IN) Multicast group ID 2282 * port - (IN) GPORT Identifier 2283 * encap_id - (IN) Encap ID. 2284 * Returns: 2285 * BCM_E_XXX 2286 */ 2287 STATIC int 2288 _bcm_esw_multicast_l3_add(int unit, bcm_multicast_t group, 2289 bcm_gport_t port, bcm_if_t encap_id) 2290 2291 { 2292 int mc_index, is_l3, gport_id, idx, idx_max, trunk_local_ports = 0; 2293 bcm_module_t mod_out; 2294 bcm_port_t port_out, port_gport; 2295 bcm_trunk_t trunk_id; 2296 int modid_local, rv = BCM_E_NONE; 2297 int is_subport_trunk = FALSE; 2298 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) 2299 bcm_port_t local_trunk_member_ports[SOC_MAX_NUM_PP_PORTS] = {0}; 2300 int max_num_ports = SOC_MAX_NUM_PP_PORTS; 2301 #else 2302 bcm_port_t local_trunk_member_ports[SOC_MAX_NUM_PORTS] = {0}; 2303 int max_num_ports = SOC_MAX_NUM_PORTS; 2304 #endif 2305 bcm_pbmp_t l2_pbmp, l3_pbmp, old_pbmp, *new_pbmp; 2306 int if_max = BCM_MULTICAST_PORT_MAX; 2307 2308 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 2309 int is_local_subport = FALSE; 2310 #endif 2311 #if defined(BCM_HGPROXY_COE_SUPPORT) 2312 bcm_trunk_t subport_trunk_id; 2313 bcm_trunk_member_t *trunk_member = NULL; 2314 bcm_port_t local_port; 2315 int member_count; 2316 int is_local; 2317 #endif 2318 2319 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 2320 /* Size of "L3 Next hop table is limited to 2K on dagger(Enduro variant). 2321 * On Ranger+ max replication interface is limited by 2322 * number of EGR_L3_Intfm. 2323 */ 2324 2325 int nexthop_count = 0, egr_intf_count = 0; 2326 if (SOC_IS_ENDURO(unit) || SOC_IS_TRIUMPH3(unit)) { 2327 nexthop_count = soc_mem_index_count(unit, ING_L3_NEXT_HOPm); 2328 egr_intf_count = soc_mem_index_count(unit, EGR_L3_INTFm); 2329 if_max = (nexthop_count < egr_intf_count)? 2330 ((if_max < nexthop_count)? if_max : nexthop_count): 2331 ((if_max < egr_intf_count)? if_max : egr_intf_count); 2332 } 2333 #endif /* BCM_ENDURO_SUPPORT || BCM_TRIUMPH3_SUPPORT */ 2334 2335 #if defined(BCM_HURRICANE_SUPPROT) || defined(BCM_HURRICANE2_SUPPORT) || \ 2336 defined(BCM_GREYHOUND_SUPPORT) 2337 if (SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) || \ 2338 SOC_IS_GREYHOUND2(unit)) { 2339 /* Assign proper if_max for HURRICANEx and GH since if_max is 4096 2340 * by default. */ 2341 if_max = soc_mem_index_count(unit, EGR_L3_INTFm); 2342 } 2343 #endif /* BCM_HURRICANE_SUPPORT || BCM_HURRICANE2_SUPPORT */ 2344 2345 #ifdef BCM_TRIDENT2_SUPPORT 2346 if (SOC_IS_TD2_TT2(unit)) { 2347 /* To assign proper if_max to avoid getting unexpected parameter 2348 * validation error since if_max is 4096 by default. 2349 */ 2350 if_max = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 2351 } 2352 #endif 2353 2354 is_l3 = 0; /* Needed to support Firebolt style of L3 Multicast */ 2355 trunk_local_ports = 0; 2356 modid_local = FALSE; 2357 2358 mc_index = _BCM_MULTICAST_ID_GET(group); 2359 2360 if ((mc_index < 0) || 2361 (mc_index >= soc_mem_index_count(unit, L3_IPMCm))) { 2362 return BCM_E_PARAM; 2363 } 2364 2365 BCM_IF_ERROR_RETURN(_bcm_esw_multicast_l3_group_check(unit, group, &is_l3)); 2366 2367 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3) 2368 if (soc_feature(unit, soc_feature_trill)) { 2369 if (_BCM_MULTICAST_IS_TRILL(group)) { 2370 BCM_IF_ERROR_RETURN 2371 (bcm_td_trill_egress_add(unit, group)); 2372 } 2373 } 2374 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */ 2375 2376 BCM_IF_ERROR_RETURN( 2377 _bcm_esw_gport_resolve(unit, port, &mod_out, &port_out, 2378 &trunk_id, &gport_id)); 2379 2380 /* In case of extended queuing on KTX, trunk_id gets updated with 2381 * extended queue value. So set it to invalid value. 2382 */ 2383 #ifdef BCM_KATANA_SUPPORT 2384 if (soc_feature(unit, soc_feature_extended_queueing)) { 2385 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) || 2386 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port)) || 2387 (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(port))) { 2388 trunk_id = BCM_TRUNK_INVALID; 2389 } 2390 } 2391 #endif 2392 2393 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 2394 BCM_IF_ERROR_RETURN( 2395 _bcm_esw_port_is_local_subport( 2396 unit, port, mod_out, port_out, &is_local_subport, &port_out)); 2397 2398 if (is_local_subport) { 2399 /* Local subport assigned above */ 2400 } else 2401 #endif 2402 2403 if (BCM_TRUNK_INVALID != trunk_id) { 2404 BCM_IF_ERROR_RETURN( 2405 /* system ports to physical ports conversion done in 2406 * _bcm_esw_trunk_local_members_get 2407 */ 2408 _bcm_esw_trunk_local_members_get(unit, trunk_id, 2409 max_num_ports, 2410 local_trunk_member_ports, 2411 &trunk_local_ports)); 2412 } 2413 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) 2414 else if ((BCM_MC_PER_TRUNK_REPL_MODE(unit)) && 2415 (encap_id == BCM_ENCAP_TRUNK_MEMBER)) { 2416 BCM_IF_ERROR_RETURN( 2417 _bcm_esw_ipmc_egress_intf_add_trunk_member( 2418 unit, mc_index, port_out)); 2419 } 2420 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT2PLUS_SUPPORT */ 2421 else { 2422 BCM_IF_ERROR_RETURN 2423 (_bcm_esw_modid_is_local(unit, mod_out, &modid_local)); 2424 if (TRUE != modid_local) { 2425 /* Only add this to replication set if destination is local */ 2426 return BCM_E_PORT; 2427 } 2428 2429 /* Convert system port to physical port */ 2430 if (soc_feature(unit, soc_feature_sysport_remap)) { 2431 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 2432 } 2433 } 2434 2435 #ifdef BCM_TRIUMPH3_SUPPORT 2436 if (SOC_IS_TRIUMPH3(unit)) { 2437 int use_axp_port = 0; 2438 bcm_l3_egress_t l3_egr; 2439 2440 if (_BCM_MULTICAST_IS_WLAN(group)) { 2441 /* Triumph3 requires WLAN replications to be configured on 2442 * AXP port. 2443 */ 2444 use_axp_port = 1; 2445 } else if (_BCM_MULTICAST_IS_L3(group)) { 2446 /* Triumph3 requires IPMC replications destined for WLAN 2447 * virtual ports to be configured on AXP port. 2448 */ 2449 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, encap_id)) { 2450 2451 bcm_l3_egress_t_init(&l3_egr); 2452 rv = bcm_esw_l3_egress_get(unit, encap_id, &l3_egr); 2453 if (BCM_SUCCESS(rv)) { 2454 if (BCM_GPORT_IS_WLAN_PORT(l3_egr.port)) { 2455 use_axp_port = 1; 2456 } 2457 } 2458 } 2459 } 2460 2461 if (use_axp_port) { 2462 trunk_id = BCM_TRUNK_INVALID; 2463 port_out = AXP_PORT(unit, SOC_AXP_NLF_WLAN_ENCAP); 2464 } 2465 } 2466 #endif /* BCM_TRIUMPH3_SUPPORT */ 2467 #if defined(INCLUDE_XFLOW_MACSEC) 2468 if (soc_feature(unit, soc_feature_xflow_macsec)) { 2469 bcm_l3_egress_t l3_egr; 2470 if (_BCM_MULTICAST_IS_L3(group)) { 2471 bcm_l3_egress_t_init(&l3_egr); 2472 rv = bcm_esw_l3_egress_get(unit, encap_id, &l3_egr); 2473 if (BCM_SUCCESS(rv)) { 2474 if ((l3_egr.flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_ENCRYPT) || 2475 (l3_egr.flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_DECRYPT)) { 2476 /* Macsec IPMC requires macsec port (port 66) in 2477 * IPMC tables. 2478 */ 2479 port_out = 66; 2480 } 2481 } 2482 } 2483 } 2484 #endif 2485 2486 if (BCM_IF_INVALID != encap_id) { 2487 2488 #ifdef BCM_TRIDENT2_SUPPORT 2489 /* if this is a overlay NH enap id, then it 2490 * is part of RioT flow. 2491 * As part of that flow or L2 tunnel encap flow, 2492 * the outer VPLS header will 2493 * be added by underlay NH. No need to add anything from 2494 * egress nh. so clear l3_payload field. 2495 */ 2496 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, encap_id)) { 2497 int is_l3_mpls = 0; 2498 int nh = encap_id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 2499 2500 if (_BCM_MULTICAST_IS_L3(group) || 2501 _BCM_MULTICAST_IS_EGRESS_OBJECT(group)) { 2502 BCM_IF_ERROR_RETURN( 2503 _bcm_esw_multicast_l3_mpls_nh_check(unit, nh, &is_l3_mpls)); 2504 } 2505 2506 if (!is_l3_mpls) { 2507 int local_mc_idx = 0; 2508 egr_ipmc_entry_t egr_ipmc_entry; 2509 local_mc_idx = _BCM_MULTICAST_ID_GET(mc_index); 2510 2511 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_IPMCm, MEM_BLOCK_ANY, 2512 local_mc_idx, &egr_ipmc_entry)); 2513 soc_mem_field32_set(unit, EGR_IPMCm, &egr_ipmc_entry, 2514 L3_PAYLOADf, 0); 2515 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_IPMCm, 2516 MEM_BLOCK_ALL, local_mc_idx, &egr_ipmc_entry)); 2517 } 2518 } 2519 #endif 2520 2521 /* Add all local ports in trunk to the multicast egress interface */ 2522 if (BCM_TRUNK_INVALID != trunk_id) { 2523 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) 2524 if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) { 2525 BCM_IF_ERROR_RETURN( 2526 _bcm_esw_ipmc_egress_intf_add_for_trunk( 2527 unit, mc_index, trunk_id, encap_id, is_l3)); 2528 } else 2529 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT2PLUS_SUPPORT */ 2530 { 2531 idx_max = trunk_local_ports; 2532 for (idx = 0; idx < idx_max; idx++) { 2533 rv = _bcm_esw_ipmc_egress_intf_add(unit, mc_index, 2534 local_trunk_member_ports[idx], 2535 encap_id, is_l3); 2536 if (BCM_FAILURE(rv)) { 2537 while (idx--) { 2538 /* Error code ignored because we already in error */ 2539 (void) _bcm_esw_ipmc_egress_intf_delete(unit,mc_index, 2540 local_trunk_member_ports[idx], 2541 if_max, encap_id, is_l3); 2542 } 2543 return rv; 2544 } 2545 } 2546 } 2547 } else { 2548 /* Add the required port to the multicast egress interface */ 2549 port_gport = port_out; 2550 #if defined(BCM_HGPROXY_COE_SUPPORT) 2551 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 2552 BCM_GPORT_IS_SET(port) && 2553 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 2554 port_gport = port; 2555 } 2556 #endif 2557 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) 2558 if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) { 2559 BCM_IF_ERROR_RETURN( 2560 _bcm_esw_ipmc_egress_intf_add_in_per_trunk_mode( 2561 unit, mc_index, port_gport, encap_id, is_l3)); 2562 } else 2563 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT2PLUS_SUPPORT */ 2564 { 2565 BCM_IF_ERROR_RETURN( 2566 _bcm_esw_ipmc_egress_intf_add(unit, mc_index, port_gport, 2567 encap_id, is_l3)); 2568 } 2569 } 2570 new_pbmp = &l3_pbmp; 2571 } else { 2572 /* Updating the L2 bitmap */ 2573 new_pbmp = &l2_pbmp; 2574 } 2575 2576 /* Add port to the IPMC_L3_BITMAP or L2_BITMAP as decided above */ 2577 rv = _bcm_esw_multicast_ipmc_read(unit, mc_index, &l2_pbmp, &l3_pbmp); 2578 2579 if (BCM_SUCCESS(rv)) { 2580 BCM_PBMP_ASSIGN(old_pbmp, *new_pbmp); 2581 if (BCM_TRUNK_INVALID != trunk_id) { 2582 for (idx = 0; idx < trunk_local_ports; idx++) { 2583 BCM_PBMP_PORT_ADD(*new_pbmp, local_trunk_member_ports[idx]); 2584 } 2585 } else { 2586 BCM_PBMP_PORT_ADD(*new_pbmp, port_out); 2587 } 2588 #if defined (BCM_HGPROXY_COE_SUPPORT) 2589 /* 2590 * If bcm_vlan_control_vlan_set is called before this API, L2_BITMAP 2591 * may be intialized with the port bitmap including subtending ports. 2592 * The subtending ports need to be deleted from the L2_BITMAP here. 2593 */ 2594 if (is_local_subport) { 2595 rv = bcm_esw_trunk_find(unit, 0, port, &subport_trunk_id); 2596 if (BCM_SUCCESS(rv)) { 2597 trunk_member = sal_alloc(sizeof(bcm_trunk_member_t) * 2598 SOC_MAX_NUM_PORTS, "trunk member"); 2599 if (NULL == trunk_member) { 2600 return BCM_E_MEMORY; 2601 } 2602 rv = bcm_esw_trunk_get(unit, subport_trunk_id, 2603 NULL, SOC_MAX_NUM_PORTS, 2604 trunk_member, &member_count); 2605 if (BCM_FAILURE(rv)) { 2606 sal_free(trunk_member); 2607 return rv; 2608 } 2609 2610 for (idx = 0; idx < member_count; idx++) { 2611 rv = _bcm_esw_modid_is_local(unit, 2612 _BCM_SUBPORT_COE_PORT_ID_MOD_GET( 2613 trunk_member[idx].gport), 2614 &is_local); 2615 if (BCM_FAILURE(rv)) { 2616 sal_free(trunk_member); 2617 return rv; 2618 } 2619 if (!is_local) { 2620 continue; 2621 } 2622 rv = bcm_esw_port_local_get(unit, 2623 trunk_member[idx].gport, 2624 &local_port); 2625 if (BCM_FAILURE(rv)) { 2626 sal_free(trunk_member); 2627 return rv; 2628 } 2629 BCM_PBMP_PORT_REMOVE(l2_pbmp, local_port); 2630 } 2631 is_subport_trunk = TRUE; 2632 if (NULL != trunk_member) { 2633 sal_free(trunk_member); 2634 } 2635 } else { 2636 rv = BCM_E_NONE; 2637 is_subport_trunk = FALSE; 2638 } 2639 } 2640 #endif 2641 if (BCM_PBMP_NEQ(old_pbmp, *new_pbmp) || 2642 is_subport_trunk) { 2643 rv = _bcm_esw_multicast_ipmc_write(unit, mc_index, l2_pbmp, 2644 l3_pbmp, TRUE); 2645 } 2646 } 2647 if (BCM_FAILURE(rv) && (encap_id != BCM_IF_INVALID)) { 2648 if (BCM_TRUNK_INVALID != trunk_id) { 2649 #if defined (BCM_TOMAHAWK_SUPPORT) || defined (BCM_TRIDENT2PLUS_SUPPORT) 2650 if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) { 2651 BCM_IF_ERROR_RETURN( 2652 _bcm_esw_ipmc_egress_intf_del_for_trunk( 2653 unit, mc_index, trunk_id, if_max, encap_id, is_l3)); 2654 } else 2655 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT2PLUS_SUPPORT */ 2656 { 2657 idx_max = trunk_local_ports; 2658 for (idx = 0; idx < idx_max; idx++) { 2659 (void) _bcm_esw_ipmc_egress_intf_delete(unit, 2660 mc_index, local_trunk_member_ports[idx], 2661 if_max, encap_id, is_l3); 2662 } 2663 } 2664 } else { 2665 #if defined (BCM_TOMAHAWK_SUPPORT) || defined (BCM_TRIDENT2PLUS_SUPPORT) 2666 if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) { 2667 BCM_IF_ERROR_RETURN( 2668 _bcm_esw_ipmc_egress_intf_del_in_per_trunk_mode( 2669 unit, mc_index, port_out, if_max, encap_id, is_l3)); 2670 } else 2671 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT2PLUS_SUPPORT */ 2672 { 2673 (void) _bcm_esw_ipmc_egress_intf_delete(unit, mc_index, port_out, 2674 if_max, encap_id, is_l3); 2675 } 2676 } 2677 } 2678 2679 return rv; 2680 } 2681 2682 /* 2683 * Function: 2684 * _bcm_esw_multicast_l3_delete 2685 * Purpose: 2686 * Helper function to delete a port from L3 or Virtual multicast group 2687 * Parameters: 2688 * unit - (IN) Device Number 2689 * group - (IN) Multicast group ID 2690 * port - (IN) GPORT Identifier 2691 * encap_id - (IN) Encap ID. 2692 * Returns: 2693 * BCM_E_XXX 2694 */ 2695 STATIC int 2696 _bcm_esw_multicast_l3_delete(int unit, bcm_multicast_t group, 2697 bcm_gport_t port, bcm_if_t encap_id) 2698 2699 { 2700 int mc_index, is_l3, gport_id, i, idx, idx_max, trunk_local_ports = 0; 2701 bcm_module_t mod_out; 2702 bcm_port_t port_out; 2703 bcm_trunk_t trunk_id; 2704 int modid_local, local_count, port_count, rv = BCM_E_NONE; 2705 bcm_port_t temp_port = BCM_GPORT_INVALID; 2706 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) 2707 bcm_port_t local_trunk_member_ports[SOC_MAX_NUM_PP_PORTS] = {0}; 2708 int max_num_ports = SOC_MAX_NUM_PP_PORTS; 2709 #else 2710 bcm_port_t local_trunk_member_ports[SOC_MAX_NUM_PORTS] = {0}; 2711 int max_num_ports = SOC_MAX_NUM_PORTS; 2712 #endif 2713 bcm_pbmp_t l2_pbmp, l3_pbmp, old_pbmp; 2714 bcm_gport_t *port_array; 2715 bcm_if_t *encap_array; 2716 int if_max = BCM_MULTICAST_PORT_MAX; 2717 2718 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 2719 int is_local_subport = FALSE; 2720 #endif 2721 2722 #if defined(BCM_ENDURO_SUPPORT) 2723 /* Size of "L3 Next hop table is limited to 2K on dagger(Enduro variant). 2724 * On Ranger+ max replication interface is limited by 2725 * number of EGR_L3_Intfm. 2726 */ 2727 2728 int nexthop_count = 0, egr_intf_count = 0; 2729 if ((SOC_IS_ENDURO(unit) || (SOC_IS_METROLITE(unit)))) { 2730 nexthop_count = soc_mem_index_count(unit, ING_L3_NEXT_HOPm); 2731 egr_intf_count = soc_mem_index_count(unit, EGR_L3_INTFm); 2732 if_max = (nexthop_count < egr_intf_count)? 2733 ((if_max < nexthop_count)? if_max : nexthop_count): 2734 ((if_max < egr_intf_count)? if_max : egr_intf_count); 2735 } 2736 #endif /* BCM_ENDURO_SUPPORT || BCM_TRIUMPH3_SUPPORT */ 2737 2738 #if defined(BCM_TRIUMPH3_SUPPORT) 2739 if (SOC_IS_TRIUMPH3(unit)) { 2740 if_max = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 2741 } 2742 #endif 2743 2744 #if defined(BCM_HURRICANE_SUPPROT) || defined(BCM_HURRICANE2_SUPPORT) 2745 if (SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit)) { 2746 /* To assign proper if_max to avoid getting unexpected parameter 2747 * validation error since if_max is 4096 by default. 2748 */ 2749 if_max = soc_mem_index_count(unit, EGR_L3_INTFm); 2750 } 2751 #endif /* BCM_HURRICANE_SUPPORT || BCM_HURRICANE2_SUPPORT */ 2752 #ifdef BCM_GREYHOUND_SUPPORT 2753 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) { 2754 /* To assign proper if_max to avoid delete operation got unexpect 2755 * parameter validation error due to if_max is default at 4096. 2756 * 2757 * GH has egress logic changed for IPMC replication to reach 2758 * EGR_L3_NEXT_HOPm before EGR_L3_INTFm. But the maximum replication 2759 * still limited by EGR_L3_INTFm. 2760 */ 2761 if_max = soc_mem_index_count(unit, EGR_L3_INTFm); 2762 } 2763 #endif /* BCM_GREYHOUND_SUPPORT */ 2764 2765 #ifdef BCM_TRIDENT2_SUPPORT 2766 #ifdef BCM_TOMAHAWK3_SUPPORT 2767 if (SOC_IS_TOMAHAWK3(unit)) { 2768 if_max = TH3_IPMC_MAX_INTF_COUNT; 2769 } else 2770 #endif 2771 if (SOC_IS_TD2_TT2(unit)) { 2772 /* To assign proper if_max to avoid getting unexpected parameter 2773 * validation error since if_max is 4096 by default. 2774 */ 2775 if_max = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 2776 } 2777 #endif 2778 2779 is_l3 = 0; /* Needed to support Firebolt style of L3 Multicast */ 2780 trunk_local_ports = 0; 2781 modid_local = FALSE; 2782 port_count = local_count = 0; 2783 2784 mc_index = _BCM_MULTICAST_ID_GET(group); 2785 2786 if ((mc_index < 0) || 2787 (mc_index >= soc_mem_index_count(unit, L3_IPMCm))) { 2788 return BCM_E_PARAM; 2789 } 2790 2791 BCM_IF_ERROR_RETURN(_bcm_esw_multicast_l3_group_check(unit, group, &is_l3)); 2792 2793 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3) 2794 if (soc_feature(unit, soc_feature_trill)) { 2795 if (_BCM_MULTICAST_IS_TRILL(group)) { 2796 BCM_IF_ERROR_RETURN 2797 (bcm_td_trill_egress_delete(unit, group)); 2798 } 2799 } 2800 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */ 2801 2802 BCM_IF_ERROR_RETURN( 2803 _bcm_esw_gport_resolve(unit, port, &mod_out, &port_out, 2804 &trunk_id, &gport_id)); 2805 2806 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 2807 BCM_IF_ERROR_RETURN( 2808 _bcm_esw_port_is_local_subport( 2809 unit, port, mod_out, port_out, &is_local_subport, &port_out)); 2810 2811 if (is_local_subport) { 2812 /* Local subport assigned above */ 2813 } else 2814 #endif 2815 2816 if (BCM_TRUNK_INVALID != trunk_id) { 2817 BCM_IF_ERROR_RETURN( 2818 _bcm_esw_trunk_local_members_get(unit, trunk_id, 2819 max_num_ports, 2820 local_trunk_member_ports, 2821 &trunk_local_ports)); 2822 /* Convertion of system ports to physical ports done in */ 2823 /* _bcm_esw_trunk_local_members_get */ 2824 } 2825 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) 2826 else if ((BCM_MC_PER_TRUNK_REPL_MODE(unit)) && 2827 (encap_id == BCM_ENCAP_TRUNK_MEMBER)) { 2828 BCM_IF_ERROR_RETURN( 2829 _bcm_esw_ipmc_egress_intf_del_trunk_member( 2830 unit, mc_index, port_out)); 2831 } 2832 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT2PLUS_SUPPORT */ 2833 else { 2834 BCM_IF_ERROR_RETURN 2835 (_bcm_esw_modid_is_local(unit, mod_out, &modid_local)); 2836 if (TRUE != modid_local) { 2837 /* Only add this to replication set if destination is local */ 2838 return BCM_E_PORT; 2839 } 2840 2841 /* Convert system port to physical port */ 2842 if (soc_feature(unit, soc_feature_sysport_remap)) { 2843 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 2844 } 2845 } 2846 2847 #ifdef BCM_TRIUMPH3_SUPPORT 2848 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_KATANA2(unit)) { 2849 if (_BCM_MULTICAST_IS_WLAN(group)) { 2850 trunk_id = BCM_TRUNK_INVALID; 2851 port_out = AXP_PORT(unit, SOC_AXP_NLF_WLAN_ENCAP); 2852 } 2853 } 2854 #endif /* BCM_TRIUMPH3_SUPPORT */ 2855 2856 if (encap_id == BCM_IF_INVALID) { 2857 /* Remove L2 port */ 2858 2859 soc_mem_lock(unit, L3_IPMCm); 2860 /* Delete the port from the IPMC L2_BITMAP */ 2861 rv = _bcm_esw_multicast_ipmc_read(unit, mc_index, 2862 &l2_pbmp, &l3_pbmp); 2863 if (BCM_SUCCESS(rv)) { 2864 BCM_PBMP_ASSIGN(old_pbmp, l2_pbmp); 2865 if (BCM_TRUNK_INVALID != trunk_id) { 2866 for (idx = 0; idx < trunk_local_ports; idx++) { 2867 BCM_PBMP_PORT_REMOVE(l2_pbmp, 2868 local_trunk_member_ports[idx]); 2869 } 2870 } else { 2871 BCM_PBMP_PORT_REMOVE(l2_pbmp, port_out); 2872 } 2873 2874 if (BCM_PBMP_NEQ(old_pbmp, l2_pbmp)) { 2875 rv = _bcm_esw_multicast_ipmc_write(unit, mc_index, 2876 l2_pbmp, l3_pbmp, TRUE); 2877 } else if (BCM_TRUNK_INVALID == trunk_id) { 2878 /* trying to remove members of an empty trunk is acceptable */ 2879 rv = BCM_E_NOT_FOUND; 2880 } 2881 } 2882 soc_mem_unlock(unit, L3_IPMCm); 2883 return rv; 2884 } 2885 2886 /* 2887 * Walk through the list of egress interfaces for this group. 2888 * Check if the interface getting deleted is the ONLY 2889 * instance of the local port in the replication list. 2890 * If so, we can delete the port from the IPMC L3_BITMAP. 2891 */ 2892 port_array = sal_alloc(if_max * sizeof(bcm_gport_t), 2893 "mcast port array"); 2894 if (port_array == NULL) { 2895 return BCM_E_MEMORY; 2896 } 2897 encap_array = sal_alloc(if_max * sizeof(bcm_if_t), 2898 "mcast encap array"); 2899 if (encap_array == NULL) { 2900 sal_free (port_array); 2901 return BCM_E_MEMORY; 2902 } 2903 2904 rv = bcm_esw_multicast_egress_get(unit, group, if_max, 2905 port_array, encap_array, &port_count); 2906 if (BCM_FAILURE(rv)) { 2907 sal_free (port_array); 2908 sal_free (encap_array); 2909 return (rv); 2910 } 2911 2912 for (i = 0; i < port_count ; i++) { 2913 if (encap_id == encap_array[i]) { 2914 /* Skip the one we're about to delete */ 2915 continue; 2916 } 2917 2918 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 2919 is_local_subport = FALSE; 2920 #endif 2921 2922 #if defined(BCM_HGPROXY_COE_SUPPORT) 2923 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 2924 BCM_GPORT_IS_SET(port_array[i]) && 2925 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port_array[i])) { 2926 is_local_subport = TRUE; 2927 2928 rv = _bcmi_coe_subport_physical_port_get(unit, 2929 port_array[i], 2930 &temp_port); 2931 if (BCM_FAILURE(rv)) { 2932 sal_free (port_array); 2933 sal_free (encap_array); 2934 return (rv); 2935 } 2936 } else 2937 #endif 2938 #if defined(BCM_KATANA2_SUPPORT) 2939 if (soc_feature(unit, soc_feature_linkphy_coe) || 2940 soc_feature(unit, soc_feature_subtag_coe)) { 2941 if (BCM_GPORT_IS_SET(port_array[i]) && 2942 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, 2943 port_array[i])) { 2944 is_local_subport = TRUE; 2945 temp_port = _BCM_KT2_SUBPORT_PORT_ID_GET(port_array[i]); 2946 } 2947 } 2948 #endif 2949 2950 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 2951 if (is_local_subport) { 2952 /* Local subport assigned above */ 2953 } else 2954 #endif 2955 { 2956 (void) bcm_esw_port_local_get(unit, port_array[i], &temp_port); 2957 } 2958 2959 if (temp_port == port_out) { 2960 local_count = 1; 2961 break; 2962 } else { 2963 for (idx = 0; idx < trunk_local_ports; idx++) { 2964 if (temp_port == local_trunk_member_ports[idx]) { 2965 local_count = 1; 2966 break; 2967 } 2968 } 2969 if (local_count) { 2970 break; 2971 } 2972 } 2973 } 2974 sal_free(port_array); 2975 sal_free(encap_array); 2976 2977 if (!local_count) { 2978 soc_mem_lock(unit, L3_IPMCm); 2979 rv = _bcm_esw_multicast_ipmc_read(unit, mc_index, 2980 &l2_pbmp, &l3_pbmp); 2981 if (BCM_SUCCESS(rv)) { 2982 if (BCM_TRUNK_INVALID != trunk_id) { 2983 for (idx = 0; idx < trunk_local_ports; idx++) { 2984 BCM_PBMP_PORT_REMOVE(l3_pbmp, 2985 local_trunk_member_ports[idx]); 2986 } 2987 } else { 2988 BCM_PBMP_PORT_REMOVE(l3_pbmp, port_out); 2989 } 2990 rv = _bcm_esw_multicast_ipmc_write(unit, mc_index, l2_pbmp, 2991 l3_pbmp, TRUE); 2992 } 2993 soc_mem_unlock(unit, L3_IPMCm); 2994 BCM_IF_ERROR_RETURN(rv); 2995 } 2996 2997 if (BCM_TRUNK_INVALID != trunk_id) { 2998 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) 2999 if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) { 3000 BCM_IF_ERROR_RETURN( 3001 _bcm_esw_ipmc_egress_intf_del_for_trunk( 3002 unit, mc_index, trunk_id, if_max, encap_id, is_l3)); 3003 } else 3004 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT2PLUS_SUPPORT */ 3005 { 3006 idx_max = trunk_local_ports; 3007 for (idx = 0; idx < idx_max; idx++) { 3008 rv = _bcm_esw_ipmc_egress_intf_delete(unit, mc_index, 3009 local_trunk_member_ports[idx], if_max, 3010 encap_id, is_l3); 3011 if (rv < 0) { 3012 while (idx--) { 3013 (void) _bcm_esw_ipmc_egress_intf_add(unit, mc_index, 3014 local_trunk_member_ports[idx], encap_id, is_l3); 3015 } 3016 return rv; 3017 } 3018 } 3019 } 3020 } else { 3021 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) 3022 if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) { 3023 BCM_IF_ERROR_RETURN( 3024 _bcm_esw_ipmc_egress_intf_del_in_per_trunk_mode( 3025 unit, mc_index, port_out, if_max, encap_id, is_l3)); 3026 } else 3027 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT2PLUS_SUPPORT */ 3028 { 3029 rv = _bcm_esw_ipmc_egress_intf_delete(unit, mc_index, port_out, 3030 if_max, encap_id, is_l3); 3031 } 3032 } 3033 3034 return rv; 3035 } 3036 3037 3038 /* 3039 * Function: 3040 * _bcm_esw_multicast_l3_get 3041 * Purpose: 3042 * Helper function to get ports that are part of L3 or Virtual multicast 3043 * Parameters: 3044 * unit - (IN) Device Number 3045 * mc_index - (IN) Multicast index 3046 * port_max - (IN) Number of entries in "port_array" 3047 * port_array - (OUT) List of ports 3048 * encap_id_array - (OUT) List of encap identifiers 3049 * port_count - (OUT) Actual number of ports returned 3050 * Returns: 3051 * BCM_E_XXX 3052 * Notes: 3053 * If the input parameter port_max = 0, return in the output parameter 3054 * port_count the total number of ports/encapsulation IDs in the 3055 * specified multicast group's replication list. 3056 */ 3057 3058 STATIC int 3059 _bcm_esw_multicast_l3_get(int unit, bcm_multicast_t group, int port_max, 3060 bcm_gport_t *port_array, bcm_if_t *encap_id_array, 3061 int *port_count) 3062 { 3063 int mc_index, i, count, rv; 3064 bcm_pbmp_t ether_higig_pbmp, l2_pbmp, l3_pbmp; 3065 bcm_port_t port_iter; 3066 bcm_if_t *local_id_array; 3067 #if defined(BCM_KATANA2_SUPPORT) 3068 int is_local_subport = FALSE; 3069 #endif 3070 3071 i= 0; 3072 rv = BCM_E_NONE; 3073 local_id_array = NULL; 3074 3075 mc_index = _BCM_MULTICAST_ID_GET(group); 3076 if ((mc_index < 0) || 3077 (mc_index >= soc_mem_index_count(unit, L3_IPMCm))) { 3078 return BCM_E_PARAM; 3079 } 3080 3081 BCM_IF_ERROR_RETURN(_bcm_esw_multicast_l3_group_check(unit, group, NULL)); 3082 3083 if (port_max > 0) { 3084 local_id_array = sal_alloc(sizeof(bcm_if_t) * port_max, 3085 "local array of interfaces"); 3086 if (NULL == local_id_array) { 3087 return BCM_E_MEMORY; 3088 } 3089 sal_memset(local_id_array, 0x00, sizeof(bcm_if_t) * port_max); 3090 } 3091 3092 /* Collect list of GPORTs for each front-panel and Higig port. */ 3093 *port_count = 0; 3094 BCM_PBMP_ASSIGN(ether_higig_pbmp, PBMP_E_ALL(unit)); 3095 BCM_PBMP_OR(ether_higig_pbmp, PBMP_HG_ALL(unit)); 3096 3097 /* CPU ports are valid for replication on TD2 */ 3098 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 3099 BCM_PBMP_OR(ether_higig_pbmp, PBMP_CMIC(unit)); 3100 } 3101 if (soc_feature(unit, soc_feature_axp)) { 3102 if (_BCM_MULTICAST_IS_WLAN(group)) { 3103 BCM_PBMP_PORT_SET(ether_higig_pbmp, 3104 AXP_PORT(unit, SOC_AXP_NLF_WLAN_ENCAP)); 3105 } 3106 } 3107 #if defined(BCM_KATANA2_SUPPORT) 3108 if (soc_feature(unit, soc_feature_subtag_coe) || 3109 soc_feature(unit, soc_feature_linkphy_coe)) { 3110 _bcm_kt2_subport_pbmp_update(unit, ðer_higig_pbmp); 3111 } 3112 #endif 3113 BCM_PBMP_ITER(ether_higig_pbmp, port_iter) { 3114 if (port_max > 0) { 3115 rv = bcm_esw_ipmc_egress_intf_get(unit, mc_index, port_iter, 3116 port_max - *port_count, 3117 local_id_array, 3118 &count); 3119 } else { 3120 rv = bcm_esw_ipmc_egress_intf_get(unit, mc_index, port_iter, 3121 0, 3122 NULL, 3123 &count); 3124 } 3125 if (BCM_FAILURE(rv)) { 3126 sal_free((void *)local_id_array); 3127 return rv; 3128 } 3129 #if defined(BCM_KATANA2_SUPPORT) 3130 /* For KT2, pp_port >=42 are used for LinkPHY/SubportPktTag subport. 3131 * Get the subport info associated with the pp_port and 3132 * form the subport_gport. 3133 */ 3134 is_local_subport = FALSE; 3135 if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, port_iter)) { 3136 is_local_subport = TRUE; 3137 } 3138 #endif 3139 3140 for (i = 0; i < count; i++) { 3141 /* Copy data to provided arrays */ 3142 if ((NULL != encap_id_array) && (NULL != local_id_array)) { 3143 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) { 3144 /* Translate the HW index to encap_id */ 3145 encap_id_array[*port_count + i] = local_id_array[i] + 3146 BCM_XGS3_EGRESS_IDX_MIN(unit); 3147 } else { 3148 encap_id_array[*port_count + i] = local_id_array[i]; 3149 } 3150 } 3151 if (NULL != port_array) { 3152 /* Convert to GPORT values */ 3153 #if defined(BCM_KATANA2_SUPPORT) 3154 if (is_local_subport) { 3155 3156 _BCM_KT2_SUBPORT_PORT_ID_SET(port_array[*port_count + i], 3157 port_iter); 3158 if (BCM_PBMP_MEMBER( 3159 SOC_INFO(unit).linkphy_pp_port_pbm, port_iter)) { 3160 _BCM_KT2_SUBPORT_PORT_TYPE_SET( 3161 port_array[*port_count + i], 3162 _BCM_KT2_SUBPORT_TYPE_LINKPHY); 3163 } else if (BCM_PBMP_MEMBER( 3164 SOC_INFO(unit).subtag_pp_port_pbm, port_iter)) { 3165 _BCM_KT2_SUBPORT_PORT_TYPE_SET( 3166 port_array[*port_count + i], 3167 _BCM_KT2_SUBPORT_TYPE_SUBTAG); 3168 } else { 3169 sal_free((void *)local_id_array); 3170 return BCM_E_PORT; 3171 } 3172 } else 3173 #endif /* BCM_KATANA2_SUPPORT */ 3174 { 3175 rv = bcm_esw_port_gport_get(unit, port_iter, 3176 &(port_array[(*port_count + i)])); 3177 if (BCM_FAILURE(rv)) { 3178 sal_free((void *)local_id_array); 3179 return rv; 3180 } 3181 } 3182 } 3183 } 3184 *port_count += count; 3185 if ((port_max > 0) && (*port_count == port_max)) { 3186 break; 3187 } 3188 } 3189 3190 /* Check for L2 ports */ 3191 rv =_bcm_esw_multicast_ipmc_read(unit, mc_index, &l2_pbmp, &l3_pbmp); 3192 if (BCM_FAILURE(rv)) { 3193 sal_free((void *)local_id_array); 3194 return rv; 3195 } 3196 3197 BCM_PBMP_ITER(l2_pbmp, port_iter) { 3198 if ((port_max > 0) && (*port_count == port_max)) { 3199 break; 3200 } 3201 if (NULL != port_array) { 3202 #if defined(BCM_KATANA2_SUPPORT) 3203 /* For KT2, pp_port >=42 are used for LinkPHY/SubportPktTag subport. 3204 * Get the subport info associated with the pp_port and 3205 * form the subport_gport. 3206 */ 3207 is_local_subport = FALSE; 3208 if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, port_iter)) { 3209 is_local_subport = TRUE; 3210 } 3211 if (is_local_subport) { 3212 _BCM_KT2_SUBPORT_PORT_ID_SET(port_array[*port_count], 3213 port_iter); 3214 if (BCM_PBMP_MEMBER( 3215 SOC_INFO(unit).linkphy_pp_port_pbm, port_iter)) { 3216 _BCM_KT2_SUBPORT_PORT_TYPE_SET(port_array[*port_count], 3217 _BCM_KT2_SUBPORT_TYPE_LINKPHY); 3218 } else if (BCM_PBMP_MEMBER( 3219 SOC_INFO(unit).subtag_pp_port_pbm, port_iter)) { 3220 _BCM_KT2_SUBPORT_PORT_TYPE_SET(port_array[*port_count], 3221 _BCM_KT2_SUBPORT_TYPE_SUBTAG); 3222 } else { 3223 sal_free((void *)local_id_array); 3224 return BCM_E_PORT; 3225 } 3226 3227 } else 3228 #endif /* BCM_KATANA2_SUPPORT */ 3229 { 3230 rv = bcm_esw_port_gport_get(unit, port_iter, 3231 &(port_array[*port_count])); 3232 3233 if (BCM_FAILURE(rv)) { 3234 sal_free((void *)local_id_array); 3235 return rv; 3236 } 3237 } 3238 } 3239 if (NULL != encap_id_array) { 3240 encap_id_array[*port_count] = BCM_IF_INVALID; 3241 } 3242 *port_count += 1; 3243 } 3244 3245 if (local_id_array) { 3246 sal_free((void *)local_id_array); 3247 } 3248 return rv; 3249 } 3250 3251 /* 3252 * Function: 3253 * _bcm_esw_multicast_l3_create 3254 * Purpose: 3255 * Helper function to allocate a multicast group index for L3 or Virtual 3256 * Parameters: 3257 * unit - (IN) Device Number 3258 * flags - (IN) BCM_MULTICAST_* 3259 * group - (OUT) Group ID 3260 * Returns: 3261 * BCM_E_XXX 3262 */ 3263 STATIC int 3264 _bcm_esw_multicast_l3_create(int unit, uint32 flags, bcm_multicast_t *group) 3265 { 3266 int mc_index, rv; 3267 int is_set = FALSE; 3268 egr_ipmc_entry_t egr_ipmc; 3269 bcm_pbmp_t active, l2_pbmp, l3_pbmp; 3270 uint32 type; 3271 uint32 entry[SOC_MAX_MEM_FIELD_WORDS]; /* hw entry bufffer. */ 3272 3273 /* Check if IPMC module is initialized */ 3274 IPMC_INIT(unit); 3275 3276 rv = BCM_E_NONE; 3277 type = flags & BCM_MULTICAST_TYPE_MASK; 3278 3279 if (flags & BCM_MULTICAST_WITH_ID) { 3280 mc_index = _BCM_MULTICAST_ID_GET(*group); 3281 if ((mc_index < 0) || 3282 (mc_index >= soc_mem_index_count(unit, L3_IPMCm))) { 3283 return BCM_E_PARAM; 3284 } 3285 rv = bcm_xgs3_ipmc_id_is_set(unit, mc_index, &is_set); 3286 if (BCM_SUCCESS(rv)) { 3287 if (is_set) { 3288 return BCM_E_EXISTS; 3289 } 3290 } else { 3291 return rv; 3292 } 3293 rv = bcm_xgs3_ipmc_id_alloc(unit, mc_index); 3294 if (BCM_FAILURE(rv)) { 3295 return rv; 3296 } 3297 } else { 3298 /* Allocate an IPMC index */ 3299 BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_create(unit, &mc_index)); 3300 } 3301 3302 /*Per IPMC Group Attributes */ 3303 sal_memset(&egr_ipmc, 0, sizeof(egr_ipmc)); 3304 3305 /* For L3 IPMC case , L3_PAYLOAD must be set to 1 */ 3306 if (soc_feature(unit, soc_feature_egr_ipmc_mem_field_l3_payload_valid) && 3307 (type == BCM_MULTICAST_TYPE_L3)) { 3308 uint32 val=1; 3309 soc_EGR_IPMCm_field_set(unit, &egr_ipmc, L3_PAYLOADf, &val); 3310 } 3311 3312 if ((type & _BCM_VIRTUAL_TYPES_MASK) && 3313 (type != BCM_MULTICAST_TYPE_WLAN)) { 3314 if (soc_mem_field_valid(unit, EGR_IPMCm, REPLICATION_TYPEf)) { 3315 soc_EGR_IPMCm_field32_set(unit, &egr_ipmc, 3316 REPLICATION_TYPEf, 0x1); 3317 /* Next-hop indexes from MMU */ 3318 } 3319 if (soc_mem_field_valid(unit, EGR_IPMCm, DONT_PRUNE_VLANf)) { 3320 soc_EGR_IPMCm_field32_set(unit, &egr_ipmc, DONT_PRUNE_VLANf, 1); 3321 } 3322 } 3323 3324 /* Commit the values to HW */ 3325 if (SOC_MEM_IS_VALID(unit, EGR_IPMCm)) { 3326 rv = WRITE_EGR_IPMCm(unit, MEM_BLOCK_ALL, mc_index, &egr_ipmc); 3327 if (BCM_FAILURE(rv)) { 3328 (void) bcm_xgs3_ipmc_id_free(unit, mc_index); 3329 return rv; 3330 } 3331 } 3332 3333 /* Add stack ports to L2 PBMP */ 3334 BCM_PBMP_CLEAR(l2_pbmp); 3335 BCM_PBMP_CLEAR(l3_pbmp); 3336 SOC_PBMP_STACK_ACTIVE_GET(unit, active); 3337 BCM_PBMP_OR(l2_pbmp, active); 3338 BCM_PBMP_REMOVE(l2_pbmp, SOC_PBMP_STACK_INACTIVE(unit)); 3339 3340 rv = _bcm_esw_multicast_ipmc_write(unit, mc_index, l2_pbmp, 3341 l3_pbmp, TRUE); 3342 if (BCM_FAILURE(rv)) { 3343 sal_memset(&egr_ipmc, 0, sizeof(egr_ipmc)); 3344 if (SOC_MEM_IS_VALID(unit, EGR_IPMCm)) { 3345 (void) WRITE_EGR_IPMCm(unit, MEM_BLOCK_ALL, mc_index, 3346 &egr_ipmc); 3347 (void) bcm_xgs3_ipmc_id_free(unit, mc_index); 3348 return rv; 3349 } 3350 } 3351 3352 if (type == BCM_MULTICAST_TYPE_L3) { 3353 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_L3, 3354 mc_index); 3355 } else if (type == BCM_MULTICAST_TYPE_VPLS) { 3356 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_VPLS, 3357 mc_index); 3358 } else if (type == BCM_MULTICAST_TYPE_MIM) { 3359 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_MIM, 3360 mc_index); 3361 } else if (type == BCM_MULTICAST_TYPE_WLAN) { 3362 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_WLAN, 3363 mc_index); 3364 } else if (type == BCM_MULTICAST_TYPE_SUBPORT) { 3365 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_SUBPORT, 3366 mc_index); 3367 }else if (type == BCM_MULTICAST_TYPE_TRILL) { 3368 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_TRILL, 3369 mc_index); 3370 } else if (type == BCM_MULTICAST_TYPE_VLAN) { 3371 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_VLAN, 3372 mc_index); 3373 } else if (type == BCM_MULTICAST_TYPE_NIV) { 3374 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_NIV, 3375 mc_index); 3376 } else if (type == BCM_MULTICAST_TYPE_EGRESS_OBJECT) { 3377 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_EGRESS_OBJECT, 3378 mc_index); 3379 } else if (type == BCM_MULTICAST_TYPE_L2GRE) { 3380 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_L2GRE, 3381 mc_index); 3382 } else if (type == BCM_MULTICAST_TYPE_VXLAN) { 3383 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_VXLAN, 3384 mc_index); 3385 } else if (type == BCM_MULTICAST_TYPE_FLOW) { 3386 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_FLOW, 3387 mc_index); 3388 } else if (type == BCM_MULTICAST_TYPE_EXTENDER) { 3389 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_EXTENDER, 3390 mc_index); 3391 } 3392 3393 if (soc_feature(unit, soc_feature_trill)) { 3394 if (type == BCM_MULTICAST_TYPE_TRILL) { 3395 if (SOC_MEM_FIELD_VALID(unit, L3_IPMCm, REMOVE_SGLP_FROM_L3_BITMAPf)) { 3396 rv = soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, mc_index, entry); 3397 if (BCM_SUCCESS(rv)) { 3398 soc_mem_field32_set(unit, L3_IPMCm, entry, 3399 REMOVE_SGLP_FROM_L3_BITMAPf, 0x1); 3400 rv = soc_mem_write(unit, L3_IPMCm, MEM_BLOCK_ALL, mc_index, &entry); 3401 } 3402 } 3403 } 3404 } 3405 3406 if (BCM_SUCCESS(rv) && SOC_IS_TRX(unit)) { 3407 /* Record IPMC types for reference */ 3408 rv = _bcm_tr_multicast_ipmc_group_type_set(unit, *group); 3409 } 3410 3411 return rv; 3412 } 3413 3414 3415 /* 3416 * Function: 3417 * _bcm_esw_multicast_l3_destroy 3418 * Purpose: 3419 * Helper function to destroy L3 and Virtual multicast 3420 * Parameters: 3421 * unit - (IN) Device Number 3422 * group - (IN) Multicast group to destroy 3423 * Returns: 3424 * BCM_E_XXX 3425 */ 3426 3427 STATIC int 3428 _bcm_esw_multicast_l3_destroy(int unit, bcm_multicast_t group) 3429 { 3430 int is_l3, mc_index; 3431 bcm_port_t port_iter; 3432 bcm_pbmp_t ether_higig_pbmp, l2_pbmp, l3_pbmp; 3433 egr_ipmc_entry_t egr_ipmc; 3434 3435 3436 /* Check if IPMC module is initialized */ 3437 IPMC_INIT(unit); 3438 3439 is_l3 = 0; 3440 3441 BCM_IF_ERROR_RETURN(_bcm_esw_multicast_l3_group_check(unit, group, &is_l3)); 3442 3443 mc_index = _BCM_MULTICAST_ID_GET(group); 3444 if ((mc_index < 0) || (mc_index >= soc_mem_index_count(unit, L3_IPMCm))) { 3445 return BCM_E_PARAM; 3446 } 3447 3448 /* Decrement ref count by calling 'free' */ 3449 BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_free(unit, mc_index)); 3450 3451 if (IPMC_USED_ISSET(unit, mc_index)) { 3452 /* Group is in use, correct the ref count 3453 * decremented by above 'free' and return error. */ 3454 IPMC_USED_SET(unit, mc_index) \ 3455 return BCM_E_BUSY; 3456 } else { /* Ref count is zero. Group is not being used. */ 3457 /* Clear the replication set */ 3458 BCM_IF_ERROR_RETURN( 3459 _bcm_esw_multicast_ipmc_read(unit, mc_index, &l2_pbmp, &l3_pbmp)); 3460 if(is_l3) { 3461 BCM_PBMP_ASSIGN(ether_higig_pbmp, l3_pbmp); 3462 } else { 3463 BCM_PBMP_ASSIGN(ether_higig_pbmp, l2_pbmp); 3464 } 3465 BCM_PBMP_OR(ether_higig_pbmp, PBMP_HG_ALL(unit)); 3466 /* CPU ports are valid for replication on TD2 */ 3467 if (SOC_IS_TRIDENT2X(unit)) { 3468 BCM_PBMP_OR(ether_higig_pbmp, PBMP_CMIC(unit)); 3469 } 3470 if (soc_feature(unit, soc_feature_axp)) { 3471 if (_BCM_MULTICAST_IS_WLAN(group)) { 3472 BCM_PBMP_PORT_SET(ether_higig_pbmp, 3473 AXP_PORT(unit, SOC_AXP_NLF_WLAN_ENCAP)); 3474 } 3475 } 3476 #if defined(BCM_KATANA2_SUPPORT) 3477 if (soc_feature(unit, soc_feature_subtag_coe) || 3478 soc_feature(unit, soc_feature_linkphy_coe)) { 3479 _bcm_kt2_subport_pbmp_update(unit, ðer_higig_pbmp); 3480 } 3481 #endif 3482 3483 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) 3484 if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) { 3485 BCM_IF_ERROR_RETURN( 3486 _bcm_esw_ipmc_egress_intf_destroy_in_trunk_repl_mode( 3487 unit, mc_index, ether_higig_pbmp, is_l3)); 3488 } else 3489 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT2PLUS_SUPPORT */ 3490 { 3491 BCM_PBMP_ITER(ether_higig_pbmp, port_iter) { 3492 BCM_IF_ERROR_RETURN( 3493 _bcm_esw_ipmc_egress_intf_set(unit, mc_index, port_iter, 0, 3494 NULL, is_l3, FALSE)); 3495 } 3496 } 3497 3498 /* Clear the IPMC related tables */ 3499 BCM_PBMP_CLEAR(l2_pbmp); 3500 BCM_PBMP_CLEAR(l3_pbmp); 3501 3502 BCM_IF_ERROR_RETURN( 3503 _bcm_esw_multicast_ipmc_write(unit, mc_index, l2_pbmp, l3_pbmp, FALSE)); 3504 3505 if (SOC_MEM_IS_VALID(unit, EGR_IPMCm)) { 3506 sal_memset(&egr_ipmc, 0, sizeof(egr_ipmc)); 3507 BCM_IF_ERROR_RETURN 3508 (WRITE_EGR_IPMCm(unit, MEM_BLOCK_ALL, mc_index, &egr_ipmc)); 3509 } 3510 3511 /* Free IPMC type record */ 3512 if (SOC_IS_TRX(unit)) { 3513 BCM_IF_ERROR_RETURN( 3514 _bcm_tr_multicast_ipmc_group_type_set(unit, mc_index)); 3515 } 3516 } 3517 3518 return BCM_E_NONE; 3519 } 3520 #endif /* INCLUDE_L3 */ 3521 3522 /* 3523 * Function: 3524 * _bcm_esw_multicast_type_validate 3525 * Purpose: 3526 * Helper function to validate multicast type support 3527 * Parameters: 3528 * unit - (IN) Device Number 3529 * type - (IN) BCM_MULTICAST_TYPE_* 3530 * Returns: 3531 * BCM_E_XXX 3532 */ 3533 STATIC int 3534 _bcm_esw_multicast_type_validate(int unit, uint32 type) 3535 { 3536 int rv; 3537 3538 /* Only single multicast type is allowed per API call */ 3539 /* therefore number of bits on indicating Multicast type must equal to 1 */ 3540 if (1 != _shr_popcount(type)) { 3541 return BCM_E_PARAM; 3542 } 3543 3544 rv = BCM_E_PARAM; /* return error by default */ 3545 3546 switch (type) { 3547 case BCM_MULTICAST_TYPE_L2: 3548 rv = BCM_E_NONE; 3549 break; 3550 case BCM_MULTICAST_TYPE_L3: 3551 if (soc_feature(unit, soc_feature_ip_mcast_repl)) { 3552 rv = BCM_E_NONE; 3553 }else { 3554 rv = BCM_E_UNAVAIL; 3555 } 3556 break; 3557 case BCM_MULTICAST_TYPE_VPLS: 3558 if (soc_feature(unit, soc_feature_mpls)) { 3559 rv = BCM_E_NONE; 3560 } else { 3561 rv = BCM_E_UNAVAIL; 3562 } 3563 break; 3564 case BCM_MULTICAST_TYPE_SUBPORT: 3565 if (soc_feature(unit, soc_feature_subport)) { 3566 rv = BCM_E_NONE; 3567 } 3568 break; 3569 case BCM_MULTICAST_TYPE_MIM: 3570 if (soc_feature(unit, soc_feature_mim)) { 3571 rv = BCM_E_NONE; 3572 } 3573 break; 3574 case BCM_MULTICAST_TYPE_WLAN: 3575 if (soc_feature(unit, soc_feature_wlan)) { 3576 rv = BCM_E_NONE; 3577 } 3578 break; 3579 case BCM_MULTICAST_TYPE_VLAN: 3580 if (soc_feature(unit, soc_feature_vlan_vp)) { 3581 rv = BCM_E_NONE; 3582 } 3583 break; 3584 case BCM_MULTICAST_TYPE_TRILL: 3585 if (soc_feature(unit, soc_feature_trill)) { 3586 rv = BCM_E_NONE; 3587 } 3588 break; 3589 case BCM_MULTICAST_TYPE_NIV: 3590 if (soc_feature(unit, soc_feature_niv)) { 3591 rv = BCM_E_NONE; 3592 } 3593 break; 3594 case BCM_MULTICAST_TYPE_EGRESS_OBJECT: 3595 if (soc_feature(unit, soc_feature_mpls)) { 3596 rv = BCM_E_NONE; 3597 } 3598 break; 3599 case BCM_MULTICAST_TYPE_L2GRE: 3600 if (soc_feature(unit, soc_feature_l2gre)) { 3601 rv = BCM_E_NONE; 3602 } else { 3603 rv = BCM_E_UNAVAIL; 3604 } 3605 break; 3606 case BCM_MULTICAST_TYPE_VXLAN: 3607 if (soc_feature(unit, soc_feature_vxlan) || 3608 soc_feature(unit, soc_feature_vxlan_lite)) { 3609 rv = BCM_E_NONE; 3610 } else { 3611 rv = BCM_E_UNAVAIL; 3612 } 3613 break; 3614 case BCM_MULTICAST_TYPE_FLOW: 3615 if (soc_feature(unit, soc_feature_flex_flow)) { 3616 rv = BCM_E_NONE; 3617 } else { 3618 rv = BCM_E_UNAVAIL; 3619 } 3620 break; 3621 case BCM_MULTICAST_TYPE_EXTENDER: 3622 if (soc_feature(unit, soc_feature_port_extension)) { 3623 rv = BCM_E_NONE; 3624 } 3625 break; 3626 3627 default: 3628 rv = BCM_E_PARAM; 3629 } 3630 3631 return rv; 3632 } 3633 3634 /* 3635 * Function: 3636 * _bcm_multicast_create 3637 * Purpose: 3638 * Helper function to allocate a multicast group index 3639 * Parameters: 3640 * unit - (IN) Device Number 3641 * flags - (IN) BCM_MULTICAST_* 3642 * group - (OUT) Group ID 3643 * Returns: 3644 * BCM_E_XXX 3645 */ 3646 STATIC int 3647 _bcm_esw_multicast_create(int unit, uint32 flags, bcm_multicast_t *group) 3648 { 3649 uint32 type; 3650 3651 type = flags & BCM_MULTICAST_TYPE_MASK; 3652 3653 BCM_IF_ERROR_RETURN( 3654 _bcm_esw_multicast_type_validate(unit, type)); 3655 3656 if (type == BCM_MULTICAST_TYPE_L2) { 3657 /* Create L2 multicast group */ 3658 return _bcm_esw_multicast_l2_create(unit, flags, group); 3659 } else { 3660 #if defined(INCLUDE_L3) 3661 /* Create L3/Virtual multicast group */ 3662 return _bcm_esw_multicast_l3_create(unit, flags, group); 3663 #endif /* INCLUDE_L3 */ 3664 } 3665 3666 return BCM_E_UNAVAIL; 3667 } 3668 3669 3670 /* Macro to free memory and return code instead of using goto */ 3671 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) 3672 #define BCM_MULTICAST_MEM_FREE_RETURN(_r_) \ 3673 if (local_trunk_port_array) { \ 3674 for (j = 0; j < port_count; j++) { \ 3675 if (local_trunk_port_array[j]) { \ 3676 sal_free(local_trunk_port_array[j]); \ 3677 } \ 3678 } \ 3679 sal_free(local_trunk_port_array); \ 3680 } \ 3681 if (local_port_array) { \ 3682 sal_free(local_port_array); \ 3683 } \ 3684 if (trunk_local_ports) { \ 3685 sal_free(trunk_local_ports); \ 3686 } \ 3687 if (temp_encap_list) { \ 3688 sal_free(temp_encap_list); \ 3689 temp_encap_list = NULL; \ 3690 } \ 3691 if (trunk_pipe_first_member_array) { \ 3692 for (j = 0; j < port_count; j++) { \ 3693 if (trunk_pipe_first_member_array[j]) { \ 3694 sal_free(trunk_pipe_first_member_array[j]); \ 3695 } \ 3696 } \ 3697 sal_free(trunk_pipe_first_member_array); \ 3698 } \ 3699 return _r_; 3700 #else 3701 #define BCM_MULTICAST_MEM_FREE_RETURN(_r_) \ 3702 if (local_trunk_port_array) { \ 3703 for (j = 0; j < port_count; j++) { \ 3704 if (local_trunk_port_array[j]) { \ 3705 sal_free(local_trunk_port_array[j]); \ 3706 } \ 3707 } \ 3708 sal_free(local_trunk_port_array); \ 3709 } \ 3710 if (local_port_array) { \ 3711 sal_free(local_port_array); \ 3712 } \ 3713 if (trunk_local_ports) { \ 3714 sal_free(trunk_local_ports); \ 3715 } \ 3716 if (temp_encap_list) { \ 3717 sal_free(temp_encap_list); \ 3718 temp_encap_list = NULL; \ 3719 } \ 3720 return _r_; 3721 #endif 3722 3723 3724 3725 #if defined(BCM_XGS3_SWITCH_SUPPORT) && defined(INCLUDE_L3) 3726 /* 3727 * Function: 3728 * _bcm_esw_multicast_egress_set 3729 * Purpose: 3730 * Helper function to assign the complete set of egress GPORTs in the 3731 * replication list for the specified multicast index. 3732 * Parameters: 3733 * unit - (IN) Device Number 3734 * group - (IN) Multicast group ID 3735 * port_count - (IN) Number of ports in replication list 3736 * port_array - (IN) List of GPORT Identifiers 3737 * encap_id_array - (IN) List of encap identifiers 3738 * Returns: 3739 * BCM_E_XXX 3740 */ 3741 STATIC int 3742 _bcm_esw_multicast_egress_set(int unit, bcm_multicast_t group, int port_count, 3743 bcm_gport_t *port_array, bcm_if_t *encap_id_array) 3744 { 3745 int mc_index, i, j, rv = BCM_E_NONE; 3746 int gport_id, *temp_encap_list = NULL; 3747 bcm_port_t *local_port_array = NULL, **local_trunk_port_array = NULL; 3748 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) 3749 int max_num_ports = SOC_MAX_NUM_PP_PORTS; 3750 #else 3751 int max_num_ports = SOC_MAX_NUM_PORTS; 3752 #endif 3753 bcm_module_t mod_out; 3754 bcm_port_t port_out; 3755 bcm_pbmp_t l2_pbmp, l3_pbmp; 3756 l2mc_entry_t l2mc_entry; 3757 bcm_trunk_t trunk_id; 3758 soc_mem_t mem; 3759 int idx, idx_max; 3760 int modid_local = 0; 3761 int *trunk_local_ports = NULL; 3762 #if defined (INCLUDE_L3) 3763 int list_count, is_l3 = 0; 3764 bcm_pbmp_t mc_eligible_pbmp, e_pbmp; 3765 bcm_port_t port_iter; 3766 int trunk_local_found; 3767 #endif /* INCLUDE_L3 */ 3768 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 3769 int is_local_subport = FALSE; 3770 #endif 3771 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) 3772 int **trunk_pipe_first_member_array = NULL; 3773 int pos, pipe; 3774 #endif /* BCM_TRIDENT2PLUS_SUPPORT || BCM_TOMAHAWK_SUPPORT */ 3775 3776 /* Input parameters check. */ 3777 mc_index = _BCM_MULTICAST_ID_GET(group); 3778 mem = (_BCM_MULTICAST_L2_OR_FABRIC(unit, group)) ? L2MCm : L3_IPMCm; 3779 /* Table index sanity check. */ 3780 #ifdef BCM_XGS3_FABRIC_SUPPORT 3781 if (SOC_IS_XGS3_FABRIC(unit)) { 3782 BCM_IF_ERROR_RETURN 3783 (_bcm_esw_fabric_multicast_param_check(unit, group, &mc_index)); 3784 } else 3785 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 3786 if ((mc_index < 0) || (mc_index >= soc_mem_index_count(unit, mem))) { 3787 return (BCM_E_PARAM); 3788 } 3789 3790 if (port_count > 0) { 3791 if (NULL == port_array) { 3792 return (BCM_E_PARAM); 3793 } 3794 if (!_BCM_MULTICAST_L2_OR_FABRIC(unit, group) && 3795 (NULL == encap_id_array)) { 3796 return (BCM_E_PARAM); 3797 } 3798 } else if (port_count < 0) { 3799 return (BCM_E_PARAM); 3800 } 3801 3802 #ifdef BCM_XGS3_FABRIC_SUPPORT 3803 if (SOC_IS_XGS3_FABRIC(unit)) { 3804 /* The group was already validated above */ 3805 } else 3806 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 3807 if (!SOC_IS_TRX(unit)) { 3808 if ((0 == _BCM_MULTICAST_IS_L2(group)) && 3809 (0 == _BCM_MULTICAST_IS_L3(group))) { 3810 return (BCM_E_PARAM); 3811 } 3812 } else { 3813 #if defined (INCLUDE_L3) 3814 rv = _bcm_esw_multicast_l3_group_check(unit, group, NULL); 3815 #endif /* INCLUDE_L3 */ 3816 if (BCM_FAILURE(rv) && (0 == _BCM_MULTICAST_IS_L2(group))) { 3817 return BCM_E_PARAM; 3818 } 3819 } 3820 3821 /* Convert GPORT array into local port numbers */ 3822 if (port_count > 0) { 3823 local_port_array = 3824 sal_alloc(sizeof(bcm_port_t) * port_count, "local_port array"); 3825 if (NULL == local_port_array) { 3826 BCM_MULTICAST_MEM_FREE_RETURN(BCM_E_MEMORY); 3827 } 3828 3829 temp_encap_list = 3830 sal_alloc(sizeof(int) * port_count, "temp_encap_list"); 3831 if (NULL == temp_encap_list) { 3832 BCM_MULTICAST_MEM_FREE_RETURN(rv); 3833 } 3834 3835 trunk_local_ports = 3836 sal_alloc(sizeof(int) * port_count, "trunk_local_ports"); 3837 if (NULL == trunk_local_ports) { 3838 BCM_MULTICAST_MEM_FREE_RETURN(BCM_E_MEMORY); 3839 } 3840 3841 local_trunk_port_array = 3842 sal_alloc(sizeof(bcm_port_t *) * port_count, 3843 "local_trunk_port_array pointers"); 3844 if (NULL == local_trunk_port_array) { 3845 BCM_MULTICAST_MEM_FREE_RETURN(BCM_E_MEMORY); 3846 } 3847 3848 for (i = 0; i < port_count; i++) { 3849 local_trunk_port_array[i] = 3850 sal_alloc(sizeof(bcm_port_t) * max_num_ports, 3851 "local_trunk_port_array"); 3852 if (NULL == local_trunk_port_array[i]) { 3853 BCM_MULTICAST_MEM_FREE_RETURN(BCM_E_MEMORY); 3854 } 3855 } 3856 3857 for (i = 0; i < port_count; i++) { 3858 trunk_local_ports[i] = 0; 3859 for (idx = 0; idx < max_num_ports; idx++) { 3860 local_trunk_port_array[i][idx] = 0; 3861 } 3862 } 3863 3864 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) 3865 if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) { 3866 trunk_pipe_first_member_array = 3867 sal_alloc(sizeof(int *) * port_count, 3868 "trunk_pipe_first_member_array pointers"); 3869 if (NULL == trunk_pipe_first_member_array) { 3870 BCM_MULTICAST_MEM_FREE_RETURN(BCM_E_MEMORY); 3871 } 3872 3873 for (i = 0; i < port_count; i++) { 3874 trunk_pipe_first_member_array[i] = 3875 sal_alloc(sizeof(int) * BCM_PIPES_MAX, 3876 "trunk_pipe_first_member_array"); 3877 if (NULL == trunk_pipe_first_member_array[i]) { 3878 BCM_MULTICAST_MEM_FREE_RETURN(BCM_E_MEMORY); 3879 } 3880 } 3881 3882 for (i = 0; i < port_count; i++) { 3883 for (idx = 0; idx < BCM_PIPES_MAX; idx++) { 3884 trunk_pipe_first_member_array[i][idx] = -1; 3885 } 3886 } 3887 } 3888 #endif /* BCM_TRIDENT2PLUS_SUPPORT || BCM_TOMAHAWK_SUPPORT */ 3889 3890 } 3891 3892 3893 for (i = 0; i < port_count ; i++) { 3894 rv = _bcm_esw_gport_resolve(unit, port_array[i], 3895 &mod_out, &port_out, 3896 &trunk_id, &gport_id); 3897 if (BCM_FAILURE(rv)) { 3898 BCM_MULTICAST_MEM_FREE_RETURN(rv); 3899 } 3900 3901 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 3902 rv = _bcm_esw_port_is_local_subport( 3903 unit, port_array[i], mod_out, port_out, 3904 &is_local_subport, &local_port_array[i]); 3905 if (BCM_FAILURE(rv)) { 3906 BCM_MULTICAST_MEM_FREE_RETURN(rv); 3907 } 3908 3909 if (is_local_subport) { 3910 /* Local subport assigned above */ 3911 } else 3912 #endif 3913 3914 if (BCM_TRUNK_INVALID != trunk_id) { 3915 rv = _bcm_esw_trunk_local_members_get(unit, trunk_id, 3916 max_num_ports, local_trunk_port_array[i], 3917 &trunk_local_ports[i]); 3918 if (BCM_FAILURE(rv)) { 3919 BCM_MULTICAST_MEM_FREE_RETURN(rv); 3920 } 3921 /* Record the trunk ID to use later */ 3922 BCM_GPORT_TRUNK_SET(local_port_array[i], trunk_id); 3923 } else { 3924 rv = _bcm_esw_modid_is_local(unit, mod_out, &modid_local); 3925 if (BCM_FAILURE(rv)) { 3926 BCM_MULTICAST_MEM_FREE_RETURN(rv); 3927 } 3928 3929 /* Convert system local_port to physical local_port */ 3930 if (soc_feature(unit, soc_feature_sysport_remap)) { 3931 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 3932 } 3933 3934 if (TRUE != modid_local) { 3935 BCM_MULTICAST_MEM_FREE_RETURN(BCM_E_PARAM); 3936 } 3937 local_port_array[i] = port_out; 3938 } 3939 } 3940 3941 BCM_PBMP_CLEAR(l2_pbmp); 3942 BCM_PBMP_CLEAR(l3_pbmp); 3943 if (_BCM_MULTICAST_L2_OR_FABRIC(unit, group)) { 3944 for (i = 0; i < port_count; i++) { 3945 if (BCM_GPORT_IS_TRUNK(local_port_array[i])) { 3946 for (idx = 0; idx < trunk_local_ports[i]; idx++) { 3947 BCM_PBMP_PORT_ADD(l2_pbmp, 3948 local_trunk_port_array[i][idx]); 3949 } 3950 } else { 3951 BCM_PBMP_PORT_ADD(l2_pbmp, local_port_array[i]); 3952 } 3953 } 3954 3955 /* Update the L2MC port bitmap */ 3956 soc_mem_lock(unit, L2MCm); 3957 rv = soc_mem_read(unit, L2MCm, MEM_BLOCK_ANY, mc_index, &l2mc_entry); 3958 if (BCM_FAILURE(rv)) { 3959 soc_mem_unlock(unit, L2MCm); 3960 BCM_MULTICAST_MEM_FREE_RETURN(rv); 3961 } 3962 soc_mem_pbmp_field_set(unit, L2MCm, &l2mc_entry, PORT_BITMAPf, 3963 &l2_pbmp); 3964 rv = soc_mem_write(unit, L2MCm, MEM_BLOCK_ALL, 3965 mc_index, &l2mc_entry); 3966 soc_mem_unlock(unit, L2MCm); 3967 #if defined(INCLUDE_L3) 3968 } else { 3969 if (_BCM_MULTICAST_IS_L3(group)) { 3970 is_l3 = 1; 3971 } 3972 if (0 == port_count) { 3973 /* Clearing the replication set */ 3974 list_count = 0; 3975 BCM_PBMP_CLEAR(e_pbmp); 3976 BCM_PBMP_ASSIGN(e_pbmp, PBMP_E_ALL(unit)); 3977 #if defined(BCM_TRIDENT2_SUPPORT) 3978 if (SOC_IS_TRIDENT2X(unit)) { 3979 BCM_PBMP_PORT_ADD(e_pbmp,CMIC_PORT(unit)); 3980 } 3981 #endif 3982 #if defined(BCM_KATANA2_SUPPORT) 3983 if (soc_feature(unit, soc_feature_subtag_coe) || 3984 soc_feature(unit, soc_feature_linkphy_coe)) { 3985 _bcm_kt2_subport_pbmp_update(unit, &e_pbmp); 3986 } 3987 #endif 3988 3989 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) 3990 if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) { 3991 BCM_IF_ERROR_RETURN( 3992 _bcm_esw_ipmc_egress_intf_destroy_in_trunk_repl_mode( 3993 unit, mc_index, e_pbmp, is_l3)); 3994 } else 3995 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT2PLUS_SUPPORT */ 3996 { 3997 BCM_PBMP_ITER(e_pbmp, port_iter) { 3998 rv = _bcm_esw_ipmc_egress_intf_set(unit, mc_index, port_iter, 3999 list_count, NULL, is_l3, FALSE); 4000 if (BCM_FAILURE(rv)) { 4001 BCM_MULTICAST_MEM_FREE_RETURN(rv); 4002 } 4003 } 4004 } 4005 } else { 4006 /* 4007 * For each port, walk through the list of GPORTs 4008 * and collect the ones that match the port. 4009 */ 4010 4011 #ifdef BCM_TOMAHAWK3_SUPPORT 4012 if (SOC_IS_TOMAHAWK3(unit)) { 4013 /* MAx number of replications across all ports cannot exceed 4014 * TH3_IPMC_MAX_INTF_COUNT*/ 4015 if (port_count > TH3_IPMC_MAX_INTF_COUNT) { 4016 rv = BCM_E_PARAM; 4017 BCM_MULTICAST_MEM_FREE_RETURN(rv); 4018 } 4019 } 4020 #endif 4021 /* Valid SOC ports plus the CMIC port */ 4022 BCM_PBMP_ASSIGN(mc_eligible_pbmp, PBMP_PORT_ALL(unit)); 4023 BCM_PBMP_PORT_ADD(mc_eligible_pbmp, CMIC_PORT(unit)); 4024 #if defined(BCM_KATANA2_SUPPORT) 4025 if (soc_feature(unit, soc_feature_subtag_coe) || 4026 soc_feature(unit, soc_feature_linkphy_coe)) { 4027 _bcm_kt2_subport_pbmp_update(unit, &mc_eligible_pbmp); 4028 } 4029 #endif 4030 BCM_PBMP_ITER(mc_eligible_pbmp, port_iter) { 4031 list_count = 0; 4032 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) 4033 trunk_id = BCM_TRUNK_INVALID; 4034 pos = -1; 4035 #endif /* BCM_TRIDENT2PLUS_SUPPORT || BCM_TOMAHAWK_SUPPORT */ 4036 for (i = 0; i < port_count ; i++) { 4037 if (BCM_GPORT_IS_TRUNK(local_port_array[i])) { 4038 trunk_local_found = 0; 4039 idx_max = trunk_local_ports[i]; 4040 for (idx = 0; idx < idx_max; idx++) { 4041 if (local_trunk_port_array[i][idx] == port_iter) { 4042 trunk_local_found = 1; 4043 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) 4044 if (trunk_id == BCM_TRUNK_INVALID) { 4045 pos = i; 4046 trunk_id = BCM_GPORT_TRUNK_GET(local_port_array[i]); 4047 } 4048 #endif /* BCM_TRIDENT2PLUS_SUPPORT || BCM_TOMAHAWK_SUPPORT */ 4049 break; 4050 } 4051 } 4052 if (!trunk_local_found) { 4053 continue; 4054 } 4055 } else { 4056 if (local_port_array[i] != port_iter) { 4057 continue; 4058 } 4059 } 4060 if (encap_id_array[i] == BCM_IF_INVALID) { 4061 /* Add port to L2 pbmp */ 4062 BCM_PBMP_PORT_ADD(l2_pbmp, port_iter); 4063 } else { 4064 if (soc_feature(unit, 4065 soc_feature_l3mc_use_egress_next_hop)) { 4066 /* _bcm_esw_ipmc_egress_intf_set() processing the 4067 * real HW index to indicate egress NH object. 4068 */ 4069 temp_encap_list[list_count] = encap_id_array[i] - 4070 BCM_XGS3_EGRESS_IDX_MIN(unit); 4071 } else { 4072 temp_encap_list[list_count] = encap_id_array[i]; 4073 } 4074 list_count++; 4075 } 4076 } 4077 if ((0 == list_count) && (CMIC_PORT(unit) == port_iter)) { 4078 if (!SOC_IS_TRIDENT2(unit)) { 4079 /* Don't install L3 ports on CMIC */ 4080 continue; 4081 } 4082 } 4083 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) 4084 if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) { 4085 if (trunk_id != BCM_TRUNK_INVALID) { 4086 bcm_port_t first_member; 4087 pipe = SOC_INFO(unit).port_pipe[port_iter]; 4088 first_member = trunk_pipe_first_member_array[pos][pipe]; 4089 if (first_member == -1) { 4090 rv = _bcm_esw_ipmc_egress_intf_set_for_trunk_first_member( 4091 unit, mc_index, port_iter, list_count, 4092 temp_encap_list, is_l3, TRUE, trunk_id); 4093 trunk_pipe_first_member_array[pos][pipe] = port_iter; 4094 #if defined(BCM_TOMAHAWK3_SUPPORT) 4095 if(SOC_IS_TOMAHAWK3(unit)) { 4096 int th3_idx; 4097 for(th3_idx = 0; th3_idx < BCM_PIPES_MAX; th3_idx++) { 4098 trunk_pipe_first_member_array[pos][th3_idx] = port_iter; 4099 } 4100 } 4101 #endif 4102 } else { 4103 rv = _bcm_esw_ipmc_egress_intf_set_for_same_pipe_member( 4104 unit, mc_index, port_iter, first_member, 4105 trunk_id); 4106 } 4107 } else { 4108 rv = _bcm_esw_ipmc_egress_intf_set_for_trunk_first_member( 4109 unit, mc_index, port_iter, list_count, 4110 temp_encap_list, is_l3, TRUE, BCM_TRUNK_INVALID); 4111 } 4112 } else 4113 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT2PLUS_SUPPORT */ 4114 { 4115 rv = _bcm_esw_ipmc_egress_intf_set( 4116 unit, mc_index, port_iter, list_count, 4117 temp_encap_list, is_l3, TRUE); 4118 } 4119 if (BCM_FAILURE(rv)) { 4120 BCM_MULTICAST_MEM_FREE_RETURN(rv); 4121 } 4122 if (list_count) { 4123 BCM_PBMP_PORT_ADD(l3_pbmp, port_iter); 4124 } 4125 } 4126 } 4127 rv = _bcm_esw_multicast_ipmc_write(unit, mc_index, l2_pbmp, 4128 l3_pbmp, TRUE); 4129 #endif /* INCLUDE_L3 */ 4130 } 4131 4132 BCM_MULTICAST_MEM_FREE_RETURN(rv); 4133 } 4134 #endif 4135 4136 4137 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 4138 4139 #ifdef BCM_XGS3_FABRIC_SUPPORT 4140 int 4141 _bcm_fabric_multicast_ipmc_group_type_set(int unit, bcm_multicast_t group) 4142 { 4143 uint8 group_type = _BCM_MULTICAST_TYPE_GET(group); 4144 uint32 ipmc_id = _BCM_MULTICAST_ID_GET(group); 4145 4146 /* Don't check if MULTICAST_GROUP_IS_SET because we also want to 4147 * be able to clear a group. */ 4148 4149 4150 /* It's an IPMC type group */ 4151 _fabric_multicast_ipmc_group_types[unit][ipmc_id] = group_type; 4152 4153 #ifdef BCM_WARM_BOOT_SUPPORT 4154 SOC_CONTROL_LOCK(unit); 4155 SOC_CONTROL(unit)->scache_dirty = 1; 4156 SOC_CONTROL_UNLOCK(unit); 4157 #endif 4158 return BCM_E_NONE; 4159 } 4160 4161 int 4162 _bcm_fabric_multicast_ipmc_group_type_get(int unit, uint32 ipmc_id, 4163 bcm_multicast_t *group) 4164 { 4165 if ((NULL != _fabric_multicast_ipmc_group_types[unit]) && /* Verify init */ 4166 (0 != _fabric_multicast_ipmc_group_types[unit][ipmc_id])) { 4167 _BCM_MULTICAST_GROUP_SET(*group, 4168 _fabric_multicast_ipmc_group_types[unit][ipmc_id], 4169 ipmc_id); 4170 return BCM_E_NONE; 4171 } else { 4172 *group = 0; 4173 return BCM_E_NOT_FOUND; 4174 } 4175 return BCM_E_NONE; 4176 } 4177 #ifdef BCM_WARM_BOOT_SUPPORT 4178 STATIC int 4179 _bcm_fabric_multicast_reinit(int unit) 4180 { 4181 int ipmc_base, ipmc_size = 0, alloc_size, ipmc_id; 4182 int index_min, index_max, search_index; 4183 soc_scache_handle_t scache_handle; 4184 uint8 *multicast_scache; 4185 int rv = BCM_E_NONE; 4186 4187 SOC_IF_ERROR_RETURN 4188 (soc_hbx_ipmc_size_get(unit, &ipmc_base, &ipmc_size)); 4189 4190 alloc_size = ipmc_size * sizeof(uint8); 4191 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MULTICAST, 0); 4192 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 4193 0, &multicast_scache, 4194 BCM_FABRIC_IPMC_WB_DEFAULT_VERSION, NULL); 4195 4196 if (BCM_E_NOT_FOUND == rv) { 4197 multicast_scache = NULL; 4198 /* Version which doesnt support fabric IPMC group types. 4199 * Update type as L3. 4200 */ 4201 index_min = BCM_FABRIC_IPMC_BASE(unit); 4202 index_max = BCM_FABRIC_IPMC_MAX(unit); 4203 4204 for (search_index = index_min; search_index <= index_max; 4205 search_index++) { 4206 ipmc_id = search_index - index_min; 4207 /* If that mc index exists */ 4208 if (SHR_BITGET(BCM_FABRIC_MC_USED_BITMAP(unit), 4209 search_index)) { 4210 _fabric_multicast_ipmc_group_types[unit][ipmc_id] = 4211 _BCM_MULTICAST_TYPE_L3; 4212 } 4213 } 4214 } else if (BCM_FAILURE(rv)) { 4215 return rv; 4216 } else { 4217 sal_memcpy(_fabric_multicast_ipmc_group_types[unit], multicast_scache, 4218 alloc_size); 4219 } 4220 return BCM_E_NONE; 4221 } 4222 #endif 4223 /* 4224 * Function: 4225 * _bcm_esw_fabric_multicast_init 4226 * Purpose: 4227 * Initialize the multicast module on XGS3 fabric devices. 4228 * Parameters: 4229 * unit - (IN) Unit number. 4230 * Returns: 4231 * BCM_E_xxx 4232 * Notes: 4233 */ 4234 STATIC int 4235 _bcm_esw_fabric_multicast_init(int unit) 4236 { 4237 int mc_base, mc_size; 4238 int ipmc_base, ipmc_size, alloc_size; 4239 int l2mc_table_size = soc_mem_index_count(unit, L2MCm); 4240 #ifdef BCM_WARM_BOOT_SUPPORT 4241 int rv = BCM_E_NONE; 4242 soc_scache_handle_t scache_handle; 4243 uint8 *multicast_scache; 4244 #endif /* BCM_WARM_BOOT_SUPPORT */ 4245 4246 SOC_IF_ERROR_RETURN 4247 (soc_hbx_mcast_size_get(unit, &mc_base, &mc_size)); 4248 SOC_IF_ERROR_RETURN 4249 (soc_hbx_ipmc_size_get(unit, &ipmc_base, &ipmc_size)); 4250 4251 _bcm_fabric_mc_info[unit].mcast_size = mc_size; 4252 _bcm_fabric_mc_info[unit].ipmc_size = ipmc_size; 4253 4254 if (NULL != _bcm_fabric_mc_info[unit].mcast_used) { 4255 sal_free(_bcm_fabric_mc_info[unit].mcast_used); 4256 _bcm_fabric_mc_info[unit].mcast_used = NULL; 4257 } 4258 alloc_size = SHR_BITALLOCSIZE(l2mc_table_size); 4259 _bcm_fabric_mc_info[unit].mcast_used = 4260 sal_alloc(alloc_size, "Fabric MC entries used"); 4261 if (NULL == _bcm_fabric_mc_info[unit].mcast_used) { 4262 return BCM_E_MEMORY; 4263 } 4264 sal_memset(_bcm_fabric_mc_info[unit].mcast_used, 0, alloc_size); 4265 4266 alloc_size = ipmc_size * sizeof(uint8); 4267 #ifdef BCM_WARM_BOOT_SUPPORT 4268 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 4269 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MULTICAST, 0); 4270 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 4271 (0 == SOC_WARM_BOOT(unit)), 4272 alloc_size, 4273 &multicast_scache, 4274 BCM_FABRIC_IPMC_WB_DEFAULT_VERSION, NULL); 4275 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 4276 return rv; 4277 } 4278 } /* Else, not enough memory, don't allocate scache */ 4279 #endif /* BCM_WARM_BOOT_SUPPORT */ 4280 4281 4282 if (NULL == _fabric_multicast_ipmc_group_types[unit]) { 4283 _fabric_multicast_ipmc_group_types[unit] = 4284 sal_alloc(alloc_size, "fabric_multicast_group_types"); 4285 if (NULL == _fabric_multicast_ipmc_group_types[unit]) { 4286 return BCM_E_MEMORY; 4287 } 4288 } 4289 sal_memset(_fabric_multicast_ipmc_group_types[unit], 0, alloc_size); 4290 4291 #ifdef BCM_WARM_BOOT_SUPPORT 4292 multicast_mode_set[unit] = TRUE; 4293 4294 /* Recover the used multicast entries */ 4295 if (SOC_WARM_BOOT(unit)) { 4296 l2mc_entry_t *l2mc_entry, *l2mc_table; 4297 int index, index_min, index_max, l2mc_tbl_sz; 4298 4299 /* 4300 * Go through L2MC table to find valid entries 4301 */ 4302 index_min = soc_mem_index_min(unit, L2MCm); 4303 index_max = soc_mem_index_max(unit, L2MCm); 4304 4305 l2mc_tbl_sz = sizeof(l2mc_entry_t) * l2mc_table_size; 4306 l2mc_table = soc_cm_salloc(unit, l2mc_tbl_sz, "l2mc tbl dma"); 4307 if (l2mc_table == NULL) { 4308 sal_free(BCM_FABRIC_MC_USED_BITMAP(unit)); 4309 return BCM_E_MEMORY; 4310 } 4311 4312 memset((void *)l2mc_table, 0, l2mc_tbl_sz); 4313 if (soc_mem_read_range(unit, L2MCm, MEM_BLOCK_ANY, 4314 index_min, index_max, l2mc_table) < 0) { 4315 sal_free(BCM_FABRIC_MC_USED_BITMAP(unit)); 4316 soc_cm_sfree(unit, l2mc_table); 4317 return SOC_E_INTERNAL; 4318 } 4319 4320 for (index = index_min; index <= index_max; index++) { 4321 4322 l2mc_entry = soc_mem_table_idx_to_pointer(unit, L2MCm, 4323 l2mc_entry_t *, 4324 l2mc_table, index); 4325 4326 if (!soc_mem_field32_get(unit, L2MCm, l2mc_entry, VALIDf)) { 4327 continue; 4328 } 4329 4330 SHR_BITSET(BCM_FABRIC_MC_USED_BITMAP(unit), index); 4331 } 4332 4333 soc_cm_sfree(unit, l2mc_table); 4334 } 4335 if (SOC_WARM_BOOT(unit)) { 4336 return (_bcm_fabric_multicast_reinit(unit)); 4337 } 4338 #endif /* BCM_WARM_BOOT_SUPPORT */ 4339 4340 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, L2MCm, MEM_BLOCK_ALL, FALSE)); 4341 4342 if (SOC_IS_TITAN2X(unit)) { 4343 BCM_IF_ERROR_RETURN(bcm_xgs3_l2_addr_mcast_delete_all(unit)); 4344 } 4345 4346 return BCM_E_NONE; 4347 } 4348 4349 /* 4350 * Function: 4351 * _bcm_esw_fabric_multicast_detach 4352 * Purpose: 4353 * Detach the multicast module on XGS3 fabric devices. 4354 * Parameters: 4355 * unit - (IN) Unit number. 4356 * Returns: 4357 * BCM_E_xxx 4358 * Notes: 4359 */ 4360 STATIC int 4361 _bcm_esw_fabric_multicast_detach(int unit) 4362 { 4363 #ifdef BCM_WARM_BOOT_SUPPORT 4364 int autosync; 4365 BCM_IF_ERROR_RETURN( 4366 bcm_esw_switch_control_get(unit, bcmSwitchControlAutoSync, &autosync)); 4367 if (autosync) { 4368 BCM_IF_ERROR_RETURN(_bcm_fabric_multicast_sync(unit)); 4369 } 4370 #endif /* BCM_WARM_BOOT_SUPPORT */ 4371 _bcm_fabric_mc_info[unit].mcast_size = 0; 4372 _bcm_fabric_mc_info[unit].ipmc_size = 0; 4373 4374 if (NULL != _bcm_fabric_mc_info[unit].mcast_used) { 4375 sal_free(_bcm_fabric_mc_info[unit].mcast_used); 4376 _bcm_fabric_mc_info[unit].mcast_used = NULL; 4377 } 4378 4379 if (NULL != _fabric_multicast_ipmc_group_types[unit]) { 4380 sal_free(_fabric_multicast_ipmc_group_types[unit]); 4381 _fabric_multicast_ipmc_group_types[unit] = NULL; 4382 } 4383 4384 return BCM_E_NONE; 4385 } 4386 4387 /* 4388 * Function: 4389 * _bcm_esw_fabric_multicast_create 4390 * Purpose: 4391 * Create a multicast group on XGS3 fabric devices. 4392 * Parameters: 4393 * unit - (IN) Unit number. 4394 * Returns: 4395 * BCM_E_xxx 4396 * Notes: 4397 */ 4398 STATIC int 4399 _bcm_esw_fabric_multicast_create(int unit, uint32 flags, bcm_multicast_t *group) 4400 { 4401 uint32 type; 4402 int search_index, fabric_index = -1; 4403 int index_min, index_max, rv; 4404 l2mc_entry_t l2mc; 4405 4406 /* On switch devices, we verify that the particular multicast group 4407 * type is valid and supported on the device. 4408 * We Must Not Do This on Fabrics! 4409 * Fabric devices must be able to pass all group types. We translate 4410 * the type here to what is appropriate on the specific device HW. 4411 */ 4412 type = flags & BCM_MULTICAST_TYPE_MASK; 4413 if (1 != _shr_popcount(type)) { 4414 return BCM_E_PARAM; 4415 } 4416 4417 if (type == BCM_MULTICAST_TYPE_L2) { 4418 index_min = BCM_FABRIC_MCAST_BASE(unit); 4419 index_max = BCM_FABRIC_MCAST_MAX(unit); 4420 if (flags & BCM_MULTICAST_WITH_ID) { 4421 if (!_BCM_MULTICAST_IS_L2(*group)) { 4422 /* Group ID doesn't match creation flag type */ 4423 return BCM_E_PARAM; 4424 } 4425 } 4426 } else { 4427 index_min = BCM_FABRIC_IPMC_BASE(unit); 4428 index_max = BCM_FABRIC_IPMC_MAX(unit); 4429 if (flags & BCM_MULTICAST_WITH_ID) { 4430 if (_BCM_MULTICAST_IS_L2(*group)) { 4431 /* Group ID doesn't match creation flag type */ 4432 return BCM_E_PARAM; 4433 } 4434 } 4435 } 4436 4437 if (flags & BCM_MULTICAST_WITH_ID) { 4438 fabric_index = _BCM_MULTICAST_ID_GET(*group) + index_min; 4439 if ((fabric_index < index_min) || (fabric_index > index_max)) { 4440 /* Group index out of bounds */ 4441 return BCM_E_PARAM; 4442 } 4443 if (SHR_BITGET(BCM_FABRIC_MC_USED_BITMAP(unit), 4444 fabric_index)) { 4445 /* Requested group has already been created */ 4446 return BCM_E_EXISTS; 4447 } 4448 } else { 4449 for (search_index = index_min; search_index <= index_max; 4450 search_index++) { 4451 if (!SHR_BITGET(BCM_FABRIC_MC_USED_BITMAP(unit), 4452 search_index)) { 4453 fabric_index = search_index; 4454 break; 4455 } 4456 } 4457 if (-1 == fabric_index) { 4458 /* Out of free groups */ 4459 return BCM_E_RESOURCE; 4460 } 4461 } 4462 4463 /* Mark HW entry as valid */ 4464 sal_memset(&l2mc, 0, sizeof(l2mc)); 4465 soc_mem_field32_set(unit, L2MCm, &l2mc, VALIDf, 1); 4466 soc_mem_lock(unit, L2MCm); 4467 rv = WRITE_L2MCm(unit, MEM_BLOCK_ALL, fabric_index, &l2mc); 4468 soc_mem_unlock(unit, L2MCm); 4469 if (BCM_FAILURE(rv)) { 4470 return rv; 4471 } 4472 4473 /* Record group allocation */ 4474 SHR_BITSET(BCM_FABRIC_MC_USED_BITMAP(unit), fabric_index); 4475 4476 if (type == BCM_MULTICAST_TYPE_L2) { 4477 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_L2, 4478 fabric_index - index_min); 4479 } else if (type == BCM_MULTICAST_TYPE_L3) { 4480 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_L3, 4481 fabric_index - index_min); 4482 } else if (type == BCM_MULTICAST_TYPE_VPLS) { 4483 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_VPLS, 4484 fabric_index - index_min); 4485 } else if (type == BCM_MULTICAST_TYPE_MIM) { 4486 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_MIM, 4487 fabric_index - index_min); 4488 } else if (type == BCM_MULTICAST_TYPE_WLAN) { 4489 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_WLAN, 4490 fabric_index - index_min); 4491 } else if (type == BCM_MULTICAST_TYPE_SUBPORT) { 4492 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_SUBPORT, 4493 fabric_index - index_min); 4494 }else if (type == BCM_MULTICAST_TYPE_TRILL) { 4495 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_TRILL, 4496 fabric_index - index_min); 4497 } else if (type == BCM_MULTICAST_TYPE_VLAN) { 4498 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_VLAN, 4499 fabric_index - index_min); 4500 } else if (type == BCM_MULTICAST_TYPE_NIV) { 4501 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_NIV, 4502 fabric_index - index_min); 4503 } else if (type == BCM_MULTICAST_TYPE_EGRESS_OBJECT) { 4504 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_EGRESS_OBJECT, 4505 fabric_index - index_min); 4506 } else if (type == BCM_MULTICAST_TYPE_L2GRE) { 4507 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_L2GRE, 4508 fabric_index - index_min); 4509 } else if (type == BCM_MULTICAST_TYPE_VXLAN) { 4510 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_VXLAN, 4511 fabric_index - index_min); 4512 } else if (type == BCM_MULTICAST_TYPE_FLOW) { 4513 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_FLOW, 4514 fabric_index - index_min); 4515 } else if (type == BCM_MULTICAST_TYPE_EXTENDER) { 4516 _BCM_MULTICAST_GROUP_SET(*group, _BCM_MULTICAST_TYPE_EXTENDER, 4517 fabric_index - index_min); 4518 } 4519 4520 /* Record IPMC types for reference */ 4521 BCM_IF_ERROR_RETURN( 4522 _bcm_fabric_multicast_ipmc_group_type_set(unit, *group)); 4523 return BCM_E_NONE; 4524 } 4525 4526 /* 4527 * Function: 4528 * _bcm_esw_fabric_multicast_destroy 4529 * Purpose: 4530 * Destroy a multicast group on XGS3 fabric devices. 4531 * Parameters: 4532 * unit - (IN) Unit number. 4533 * Returns: 4534 * BCM_E_xxx 4535 * Notes: 4536 */ 4537 STATIC int 4538 _bcm_esw_fabric_multicast_destroy(int unit, bcm_multicast_t group) 4539 { 4540 int fabric_index = -1; 4541 int index_min, index_max, rv; 4542 l2mc_entry_t l2mc; 4543 4544 if (_BCM_MULTICAST_IS_L2(group)) { 4545 index_min = BCM_FABRIC_MCAST_BASE(unit); 4546 index_max = BCM_FABRIC_MCAST_MAX(unit); 4547 } else { 4548 /* All non-L2 types are the same on fabric devices */ 4549 index_min = BCM_FABRIC_IPMC_BASE(unit); 4550 index_max = BCM_FABRIC_IPMC_MAX(unit); 4551 } 4552 fabric_index = _BCM_MULTICAST_ID_GET(group) + index_min; 4553 4554 if ((fabric_index < index_min) || (fabric_index > index_max)) { 4555 /* Group index out of bounds */ 4556 return BCM_E_PARAM; 4557 } 4558 if (!SHR_BITGET(BCM_FABRIC_MC_USED_BITMAP(unit), fabric_index)) { 4559 /* Requested group has not been created */ 4560 return BCM_E_NOT_FOUND; 4561 } 4562 4563 /* Mark HW entry as invalid */ 4564 sal_memset(&l2mc, 0, sizeof(l2mc)); 4565 soc_mem_lock(unit, L2MCm); 4566 rv = WRITE_L2MCm(unit, MEM_BLOCK_ALL, fabric_index, &l2mc); 4567 soc_mem_unlock(unit, L2MCm); 4568 if (BCM_FAILURE(rv)) { 4569 return rv; 4570 } 4571 4572 /* Clear group allocation */ 4573 SHR_BITCLR(BCM_FABRIC_MC_USED_BITMAP(unit), fabric_index); 4574 4575 /* Free IPMC type record. fabric_index does not have type info */ 4576 BCM_IF_ERROR_RETURN( 4577 _bcm_fabric_multicast_ipmc_group_type_set(unit, group)); 4578 4579 return BCM_E_NONE; 4580 } 4581 4582 /* 4583 * Function: 4584 * _bcm_esw_fabric_multicast_group_get 4585 * Purpose: 4586 * Retrieve the flags associated with a multicast group. 4587 * Parameters: 4588 * unit - (IN) Unit number. 4589 * group - (IN) Multicast group ID 4590 * flags - (OUT) BCM_MULTICAST_* 4591 * Returns: 4592 * BCM_E_xxx 4593 * Notes: 4594 */ 4595 STATIC int 4596 _bcm_esw_fabric_multicast_group_get(int unit, bcm_multicast_t group, 4597 uint32 *flags) 4598 { 4599 int mc_index , rv = BCM_E_NONE; 4600 uint32 type_flags; 4601 bcm_multicast_t get_group; 4602 4603 /* Check if this is a known group */ 4604 mc_index = _BCM_MULTICAST_ID_GET(group); 4605 BCM_IF_ERROR_RETURN 4606 (_bcm_esw_fabric_multicast_param_check(unit, group, &mc_index)); 4607 4608 /* Check for the type of the multicast group */ 4609 if (_BCM_MULTICAST_IS_L2(group)) { 4610 type_flags = BCM_MULTICAST_TYPE_L2; 4611 } else { 4612 if (!_BCM_MULTICAST_IS_L3(group) && 4613 !_BCM_MULTICAST_IS_VPLS(group) && 4614 !_BCM_MULTICAST_IS_MIM(group) && 4615 !_BCM_MULTICAST_IS_SUBPORT(group) && 4616 !_BCM_MULTICAST_IS_WLAN(group) && 4617 !_BCM_MULTICAST_IS_VLAN(group) && 4618 !_BCM_MULTICAST_IS_TRILL(group) && 4619 !_BCM_MULTICAST_IS_NIV(group) && 4620 !_BCM_MULTICAST_IS_L2GRE(group) && 4621 !_BCM_MULTICAST_IS_VXLAN(group) && 4622 !_BCM_MULTICAST_IS_FLOW(group) && 4623 !_BCM_MULTICAST_IS_EGRESS_OBJECT(group) && 4624 !_BCM_MULTICAST_IS_EXTENDER(group)) { 4625 return BCM_E_PARAM; 4626 } 4627 rv = _bcm_fabric_multicast_ipmc_group_type_get(unit, mc_index, 4628 &get_group); 4629 4630 if (BCM_E_NOT_FOUND == rv) { 4631 type_flags = 0; 4632 } else if (BCM_FAILURE(rv)) { 4633 return rv; 4634 } else if (get_group != group) { 4635 /* IPMC index is allocated, but not to the same group type */ 4636 type_flags = 0; 4637 return BCM_E_NOT_FOUND; 4638 } else { 4639 type_flags = 4640 _bcm_esw_multicast_group_type_to_flags( 4641 _BCM_MULTICAST_TYPE_GET(group)); 4642 } 4643 } 4644 4645 *flags = (type_flags | BCM_MULTICAST_WITH_ID); 4646 4647 return BCM_E_NONE; 4648 } 4649 4650 /* 4651 * Function: 4652 * _bcm_esw_fabric_multicast_group_traverse 4653 * Purpose: 4654 * Iterate over the defined multicast groups of the type 4655 * specified in 'flags'. If all types are desired, use 4656 * MULTICAST_TYPE_MASK. 4657 * Parameters: 4658 * unit - (IN) Unit number. 4659 * trav_fn - (IN) Callback function. 4660 * flags - (IN) BCM_MULTICAST_* 4661 * user_data - (IN) User data to be passed to callback function. 4662 * Returns: 4663 * BCM_E_xxx 4664 * Notes: 4665 */ 4666 int 4667 _bcm_esw_fabric_multicast_group_traverse(int unit, 4668 bcm_multicast_group_traverse_cb_t trav_fn, 4669 uint32 flags, void *user_data) 4670 { 4671 int search_index; 4672 int index_min, index_max; 4673 int rv = BCM_E_NONE; 4674 uint32 group_flags, flags_mask; 4675 bcm_multicast_t group; 4676 4677 /* Create a flags_mask with all flags */ 4678 flags_mask = BCM_MULTICAST_TYPE_L2 | BCM_MULTICAST_TYPE_L3 | 4679 BCM_MULTICAST_TYPE_VPLS | BCM_MULTICAST_TYPE_SUBPORT | 4680 BCM_MULTICAST_TYPE_MIM | BCM_MULTICAST_TYPE_WLAN | 4681 BCM_MULTICAST_TYPE_VLAN | BCM_MULTICAST_TYPE_TRILL | 4682 BCM_MULTICAST_TYPE_NIV | BCM_MULTICAST_TYPE_EGRESS_OBJECT | 4683 BCM_MULTICAST_TYPE_EXTENDER | BCM_MULTICAST_TYPE_VXLAN; 4684 4685 4686 if (0 == (flags & flags_mask)) { 4687 /* No recognized multicast types to traverse */ 4688 return BCM_E_PARAM; 4689 } 4690 4691 flags &= flags_mask; 4692 4693 /* L2 groups */ 4694 if (flags & BCM_MULTICAST_TYPE_L2) { 4695 index_min = BCM_FABRIC_MCAST_BASE(unit); 4696 index_max = BCM_FABRIC_MCAST_MAX(unit); 4697 group_flags = BCM_MULTICAST_TYPE_L2 | BCM_MULTICAST_WITH_ID; 4698 4699 for (search_index = index_min; search_index <= index_max; 4700 search_index++) { 4701 if (SHR_BITGET(BCM_FABRIC_MC_USED_BITMAP(unit), search_index)) { 4702 _BCM_MULTICAST_GROUP_SET(group, _BCM_MULTICAST_TYPE_L2, 4703 search_index); 4704 BCM_IF_ERROR_RETURN 4705 ((*trav_fn)(unit, group, group_flags, user_data)); 4706 } 4707 } 4708 } 4709 4710 /* L3 groups */ 4711 if (flags & ~(BCM_MULTICAST_TYPE_L2)) { 4712 index_min = BCM_FABRIC_IPMC_BASE(unit); 4713 index_max = BCM_FABRIC_IPMC_MAX(unit); 4714 4715 for (search_index = index_min; search_index <= index_max; 4716 search_index++) { 4717 if (SHR_BITGET(BCM_FABRIC_MC_USED_BITMAP(unit), search_index)) { 4718 rv = _bcm_fabric_multicast_ipmc_group_type_get(unit, 4719 search_index - index_min, &group); 4720 4721 if (BCM_E_NOT_FOUND == rv) { 4722 continue; 4723 } else if (BCM_FAILURE(rv)) { 4724 return rv; 4725 } else { 4726 group_flags = 4727 _bcm_esw_multicast_group_type_to_flags( 4728 _BCM_MULTICAST_TYPE_GET(group)) | 4729 BCM_MULTICAST_WITH_ID; 4730 4731 BCM_IF_ERROR_RETURN 4732 ((*trav_fn)(unit, group, group_flags, user_data)); 4733 } 4734 } 4735 } 4736 } 4737 4738 return BCM_E_NONE; 4739 } 4740 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 4741 4742 /* 4743 * Function: 4744 * bcm_esw_multicast_init 4745 * Purpose: 4746 * Initialize the multicast module. 4747 * Parameters: 4748 * unit - (IN) Unit number. 4749 * Returns: 4750 * BCM_E_xxx 4751 * Notes: 4752 */ 4753 int 4754 bcm_esw_multicast_init(int unit) 4755 { 4756 #ifdef BCM_WARM_BOOT_SUPPORT 4757 multicast_mode_set[unit] = FALSE; 4758 #endif /* BCM_WARM_BOOT_SUPPORT */ 4759 4760 #ifdef BCM_XGS3_FABRIC_SUPPORT 4761 if (SOC_IS_XGS3_FABRIC(unit)) { 4762 /* Fabrics must track the multicast groups here, since they 4763 * are not recorded in the mcast or IPMC modules. */ 4764 BCM_IF_ERROR_RETURN(_bcm_esw_fabric_multicast_init(unit)); 4765 multicast_initialized[unit] = TRUE; 4766 return BCM_E_NONE; 4767 } 4768 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 4769 4770 #ifdef BCM_SHADOW_SUPPORT 4771 if (SOC_IS_SHADOW(unit)) { 4772 multicast_initialized[unit] = TRUE; 4773 return BCM_E_NONE; 4774 } 4775 #endif /*BCM_SHADOW_SUPPORT*/ 4776 4777 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 4778 if (SOC_IS_TRX(unit)) { 4779 BCM_IF_ERROR_RETURN(bcm_xgs3_mcast_init(unit)); 4780 BCM_IF_ERROR_RETURN(bcm_trx_multicast_init(unit)); 4781 } 4782 #endif /* BCM_TRX_SUPPORT && INCLUDE_L3 */ 4783 4784 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_SCORPION_SUPPORT) 4785 if (SOC_REG_IS_VALID(unit, IPMC_L3_MTUr)) { 4786 soc_reg_t reg; 4787 uint64 rval64, *rval64s[1]; 4788 uint32 pindex; 4789 /* Create profile for IPMC_L3_MTU register */ 4790 if (_bcm_mtu_profile[unit] == NULL) { 4791 _bcm_mtu_profile[unit] = 4792 sal_alloc(sizeof(soc_profile_reg_t), "MTU size Profile Reg"); 4793 if (_bcm_mtu_profile[unit] == NULL) { 4794 return BCM_E_MEMORY; 4795 } 4796 soc_profile_reg_t_init(_bcm_mtu_profile[unit]); 4797 reg = IPMC_L3_MTUr; 4798 BCM_IF_ERROR_RETURN 4799 (soc_profile_reg_create(unit, ®, 1, _bcm_mtu_profile[unit])); 4800 /* Add a default entry for backward comaptability */ 4801 COMPILER_64_ZERO(rval64); 4802 COMPILER_64_SET(rval64, 0, 0x3fff); 4803 rval64s[0] = &rval64; 4804 BCM_IF_ERROR_RETURN 4805 (soc_profile_reg_add(unit, _bcm_mtu_profile[unit], rval64s, 4806 1, &pindex)); 4807 } 4808 } 4809 #endif 4810 4811 multicast_initialized[unit] = TRUE; 4812 return BCM_E_NONE; 4813 } 4814 4815 /* 4816 * Function: 4817 * bcm_esw_multicast_detach 4818 * Purpose: 4819 * Shut down (uninitialize) the multicast module. 4820 * Parameters: 4821 * unit - (IN) Unit number. 4822 * Returns: 4823 * BCM_E_xxx 4824 * Notes: 4825 */ 4826 int 4827 bcm_esw_multicast_detach(int unit) 4828 { 4829 #ifdef BCM_XGS3_FABRIC_SUPPORT 4830 if (SOC_IS_XGS3_FABRIC(unit)) { 4831 /* Fabrics must track the multicast groups here, since they 4832 * are not recorded in the mcast or IPMC modules. */ 4833 BCM_IF_ERROR_RETURN(_bcm_esw_fabric_multicast_detach(unit)); 4834 multicast_initialized[unit] = FALSE; 4835 return BCM_E_NONE; 4836 } 4837 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 4838 4839 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 4840 if (SOC_IS_TRX(unit)) { 4841 BCM_IF_ERROR_RETURN(bcm_trx_multicast_detach(unit)); 4842 multicast_initialized[unit] = FALSE; 4843 return BCM_E_NONE; 4844 } 4845 #endif /* BCM_TRX_SUPPORT && INCLUDE_L3 */ 4846 4847 multicast_initialized[unit] = FALSE; 4848 return BCM_E_NONE; 4849 } 4850 4851 /* 4852 * Function: 4853 * bcm_multicast_create 4854 * Purpose: 4855 * Allocate a multicast group index 4856 * Parameters: 4857 * unit - (IN) Device Number 4858 * flags - (IN) BCM_MULTICAST_* 4859 * group - (OUT) Group ID 4860 * Returns: 4861 * BCM_E_XXX 4862 */ 4863 int 4864 bcm_esw_multicast_create(int unit, uint32 flags, bcm_multicast_t *group) 4865 { 4866 int rv = BCM_E_UNAVAIL; 4867 4868 MULTICAST_INIT_CHECK(unit); 4869 4870 #ifdef BCM_XGS3_FABRIC_SUPPORT 4871 if (SOC_IS_XGS3_FABRIC(unit)) { 4872 return _bcm_esw_fabric_multicast_create(unit, flags, group); 4873 } 4874 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 4875 4876 #if defined(BCM_XGS3_SWITCH_SUPPORT) 4877 if (SOC_IS_XGS3_SWITCH(unit)) { 4878 #ifdef BCM_TOMAHAWK3_SUPPORT 4879 /* Check for unsupported multicast interface types */ 4880 if (SOC_IS_TOMAHAWK3(unit)) { 4881 uint32 unsupp_flags; 4882 4883 unsupp_flags = BCM_MULTICAST_TYPE_VPLS | 4884 BCM_MULTICAST_TYPE_SUBPORT | 4885 BCM_MULTICAST_TYPE_MIM | 4886 BCM_MULTICAST_TYPE_WLAN | 4887 BCM_MULTICAST_TYPE_VLAN | 4888 BCM_MULTICAST_TYPE_TRILL | 4889 BCM_MULTICAST_TYPE_NIV | 4890 BCM_MULTICAST_TYPE_L2GRE | 4891 BCM_MULTICAST_TYPE_VXLAN | 4892 BCM_MULTICAST_TYPE_EXTENDER | 4893 BCM_MULTICAST_TYPE_MAC | 4894 BCM_MULTICAST_TYPE_PORTS_GROUP | 4895 BCM_MULTICAST_DISABLE_SRC_KNOCKOUT | 4896 BCM_MULTICAST_INGRESS_GROUP | 4897 BCM_MULTICAST_EGRESS_GROUP; 4898 4899 if (flags & unsupp_flags) { 4900 return BCM_E_UNAVAIL; 4901 } 4902 } 4903 #endif /* BCM_TOMAHAWK3_SUPPORT */ 4904 rv = _bcm_esw_multicast_create(unit, flags, group); 4905 4906 #if defined(BCM_WARM_BOOT_SUPPORT) && defined(INCLUDE_L3) 4907 if (BCM_SUCCESS(rv) && !multicast_mode_set[unit]) { 4908 /* Notify IPMC module that we're operating in multicast mode 4909 * for Warm Boot purposes */ 4910 BCM_IF_ERROR_RETURN 4911 (_bcm_esw_ipmc_repl_wb_flags_set(unit, 4912 _BCM_IPMC_WB_MULTICAST_MODE, 4913 _BCM_IPMC_WB_MULTICAST_MODE)); 4914 multicast_mode_set[unit] = TRUE; 4915 } 4916 #endif /* BCM_WARM_BOOT_SUPPORT && INCLUDE_L3 */ 4917 } 4918 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 4919 return rv; 4920 } 4921 4922 /* 4923 * Function: 4924 * bcm_multicast_destroy 4925 * Purpose: 4926 * Free a multicast group index 4927 * Parameters: 4928 * unit - (IN) Device Number 4929 * group - (IN) Group ID 4930 * Returns: 4931 * BCM_E_XXX 4932 */ 4933 int 4934 bcm_esw_multicast_destroy(int unit, bcm_multicast_t group) 4935 { 4936 MULTICAST_INIT_CHECK(unit); 4937 4938 if (!_BCM_MULTICAST_IS_SET(group)) { 4939 return BCM_E_PARAM; 4940 } 4941 4942 #ifdef BCM_XGS3_FABRIC_SUPPORT 4943 if (SOC_IS_XGS3_FABRIC(unit)) { 4944 return _bcm_esw_fabric_multicast_destroy(unit, group); 4945 } 4946 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 4947 4948 #if defined(BCM_XGS3_SWITCH_SUPPORT) 4949 if (SOC_IS_XGS3_SWITCH(unit)) { 4950 if (_BCM_MULTICAST_IS_L2(group)) { 4951 return _bcm_esw_multicast_l2_destroy(unit, group); 4952 } else { 4953 #if defined(INCLUDE_L3) 4954 return _bcm_esw_multicast_l3_destroy(unit, group); 4955 #endif 4956 } 4957 } 4958 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 4959 return BCM_E_UNAVAIL; 4960 } 4961 4962 /* 4963 * Function: 4964 * bcmi_esw_multicast_multi_alloc 4965 * Purpose: 4966 * Create/alloc multiple multicast groups 4967 * Parameters: 4968 * unit - (IN) Unit number. 4969 * info - (IN) info for creating groups. 4970 * base_mc_group - (IN/OUT) base group number 4971 * of multiple groups. 4972 * Returns: 4973 * BCM_E_XXX 4974 * Notes: 4975 */ 4976 int 4977 bcmi_esw_multicast_multi_alloc(int unit, bcm_multicast_multi_info_t info, 4978 bcm_multicast_t *base_mc_group) 4979 { 4980 int rv = BCM_E_NONE; 4981 4982 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 4983 int rv2 = BCM_E_NONE; 4984 ipmc_entry_t entry; 4985 int num_entries = info.number_of_elements; 4986 int i=0,j=0; /* iterators */ 4987 bcm_multicast_t group; 4988 int flags=0, type; 4989 uint32 ipmc_id = 0; 4990 4991 IPMC_INIT(unit); 4992 4993 /* dont allow more than 4 groups allocation */ 4994 if ((info.number_of_elements < 1) || 4995 (info.number_of_elements > 4)) { 4996 return BCM_E_PARAM; 4997 } 4998 4999 IPMC_LOCK(unit); 5000 5001 /* create multi consecutive multicast groups */ 5002 if (info.flags & BCM_MULTICAST_MULTI_WITH_ID) { 5003 ipmc_id = _BCM_MULTICAST_ID_GET(*base_mc_group); 5004 if ((ipmc_id >= (IPMC_GROUP_NUM(unit)) - num_entries) || 5005 (ipmc_id < 1)) { 5006 5007 IPMC_UNLOCK(unit); 5008 return BCM_E_PARAM; 5009 } 5010 i = ipmc_id; 5011 for (j=0; j < num_entries; j++) { 5012 if ((ipmc_id + j) == IPMC_GROUP_NUM(unit)) { 5013 IPMC_UNLOCK(unit); 5014 return BCM_E_FULL; 5015 } 5016 5017 if (IPMC_USED_ISSET(unit, ipmc_id + j)) { 5018 IPMC_UNLOCK(unit); 5019 return BCM_E_EXISTS; 5020 } 5021 } 5022 } else { 5023 for (i = 0; i < (IPMC_GROUP_NUM(unit) - num_entries); i++) { 5024 if (!IPMC_USED_ISSET(unit, i)) { 5025 for (j=1; j<num_entries ; j++) { 5026 if(IPMC_USED_ISSET(unit, (i+j))) { 5027 break; 5028 } 5029 } 5030 } 5031 if (j == num_entries) { 5032 break; 5033 } 5034 } 5035 if (j < num_entries) { 5036 IPMC_UNLOCK(unit); 5037 return BCM_E_FULL; 5038 } 5039 } 5040 5041 IPMC_UNLOCK(unit); 5042 /* 5043 * we only support 2 type of groups till now. 5044 * make L3 type as default 5045 */ 5046 if (info.flags & BCM_MULTICAST_MULTI_TYPE_VPLS) { 5047 flags |= BCM_MULTICAST_TYPE_VPLS; 5048 type = _BCM_MULTICAST_TYPE_VPLS; 5049 } else { 5050 flags |= BCM_MULTICAST_TYPE_L3; 5051 type = _BCM_MULTICAST_TYPE_L3; 5052 } 5053 5054 flags |= BCM_MULTICAST_WITH_ID; 5055 for (j=0; j<num_entries; j++) { 5056 group = i + j; 5057 rv = bcm_esw_multicast_create(unit, flags, &group); 5058 if (BCM_FAILURE(rv)) { 5059 /* we need to clear all the groups that we have created here */ 5060 /* reduce one iteration as this is not successful */ 5061 j--; 5062 goto create_cleanup; 5063 } 5064 IPMC_USED_SET(unit, i+j); 5065 if (j == 0) { 5066 *base_mc_group = group; 5067 } 5068 rv = soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, i+j, &entry); 5069 5070 if (BCM_FAILURE(rv)) { 5071 goto create_cleanup; 5072 } 5073 soc_L3_IPMCm_field32_set(unit, &entry, VALIDf, 1); 5074 rv = soc_mem_write(unit, L3_IPMCm, MEM_BLOCK_ALL, i+j, &entry); 5075 if (BCM_FAILURE(rv)) { 5076 goto create_cleanup; 5077 } 5078 } 5079 rv = bcmi_multicast_multi_count_set(unit, *base_mc_group, num_entries); 5080 if (BCM_FAILURE(rv)) { 5081 goto create_cleanup; 5082 } 5083 5084 return BCM_E_NONE; 5085 5086 create_cleanup: 5087 if (BCM_FAILURE(rv)) { 5088 while (j >= 0) { 5089 _BCM_MULTICAST_GROUP_SET(group, type, i+j); 5090 rv2 = bcm_esw_multicast_destroy(unit, group); 5091 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 5092 "destroy for multicast group 0x%x failed. error : %s \n"), 5093 group, bcm_errmsg(rv2))); 5094 5095 IPMC_USED_CLR(unit, i+j); 5096 /* 5097 * Capturing the error but not returning back. 5098 * We should return the original error. 5099 * But even if this fails, we will have to keep moving 5100 * to report the original error to user. 5101 * Displaying one error message. 5102 */ 5103 rv2 = soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, i+j, &entry); 5104 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 5105 "mem read for L3_IPMCm at index %d failed. error : %s \n"), 5106 i+j, bcm_errmsg(rv2))); 5107 5108 soc_L3_IPMCm_field32_set(unit, &entry, VALIDf, 0); 5109 rv2 = soc_mem_write(unit, L3_IPMCm, MEM_BLOCK_ALL, i+j, &entry); 5110 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 5111 "mem write for L3_IPMCm at index %d failed. error : %s \n"), 5112 i+j, bcm_errmsg(rv2))); 5113 /* reduce the interator for next cycle */ 5114 j--; 5115 } 5116 *base_mc_group = -1; 5117 } 5118 #endif 5119 return rv; 5120 } 5121 5122 /* 5123 * Function: 5124 * bcmi_esw_multicast_multi_free 5125 * Purpose: 5126 * Free multiple multicast groups 5127 * Parameters: 5128 * unit - (IN) Unit number. 5129 * base_mc_group - (IN) base group number 5130 * of multiple groups. 5131 * Returns: 5132 * BCM_E_XXX 5133 * Notes: 5134 */ 5135 int 5136 bcmi_esw_multicast_multi_free(int unit, bcm_multicast_t base_mc_group) 5137 { 5138 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 5139 5140 int rv; 5141 int num_entries = 4; 5142 int i = 0; /* iterators */ 5143 int ipmc_id = _BCM_MULTICAST_ID_GET(base_mc_group); 5144 5145 if (!_BCM_MULTICAST_IS_SET(base_mc_group)) { 5146 return BCM_E_PARAM; 5147 } 5148 5149 if ((ipmc_id < 0) || (ipmc_id >= soc_mem_index_count(unit, L3_IPMCm))) { 5150 return BCM_E_PARAM; 5151 } 5152 5153 IPMC_INIT(unit); 5154 5155 if(!(IPMC_USED_ISSET(unit, ipmc_id))) { 5156 return BCM_E_NOT_FOUND; 5157 } 5158 5159 BCM_IF_ERROR_RETURN( 5160 bcmi_multicast_multi_count_get(unit, base_mc_group, &num_entries)); 5161 5162 if (num_entries == 0) { 5163 /* nothing to be done. just return */ 5164 return BCM_E_NONE; 5165 } 5166 5167 for (; i< num_entries; i++) { 5168 IPMC_USED_CLR(unit, (ipmc_id + i)); 5169 rv = bcm_esw_multicast_destroy(unit, base_mc_group + i); 5170 5171 if (BCM_FAILURE(rv)) { 5172 return rv; 5173 } 5174 5175 } 5176 #endif 5177 return BCM_E_NONE; 5178 } 5179 /* 5180 * Function: 5181 * bcm_multicast_l3_encap_get 5182 * Purpose: 5183 * Get the Encap ID for L3. 5184 * Parameters: 5185 * unit - (IN) Unit number. 5186 * group - (IN) Multicast group ID. 5187 * port - (IN) Physical port. 5188 * intf - (IN) L3 interface ID. 5189 * encap_id - (OUT) Encap ID. 5190 * Returns: 5191 * BCM_E_XXX 5192 * Notes: 5193 */ 5194 int 5195 bcm_esw_multicast_l3_encap_get(int unit, bcm_multicast_t group, 5196 bcm_gport_t port, bcm_if_t intf, 5197 bcm_if_t *encap_id) 5198 { 5199 MULTICAST_INIT_CHECK(unit); 5200 5201 if (encap_id == NULL) { 5202 return BCM_E_PARAM; 5203 } 5204 5205 #ifdef BCM_XGS3_FABRIC_SUPPORT 5206 if (SOC_IS_XGS3_FABRIC(unit)) { 5207 /* Encap ID is not used for fabric devices in XGS3 */ 5208 *encap_id = BCM_IF_INVALID; 5209 return BCM_E_NONE; 5210 } 5211 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 5212 5213 #if defined(BCM_XGS3_SWITCH_SUPPORT) && defined(INCLUDE_L3) 5214 if (SOC_IS_XGS3_SWITCH(unit)) { 5215 if (BCM_GPORT_IS_VLAN_PORT(port) || 5216 BCM_GPORT_IS_NIV_PORT(port) || 5217 BCM_GPORT_IS_EXTENDER_PORT(port)) { 5218 #ifdef BCM_TRIDENT2_SUPPORT 5219 if (soc_feature(unit, soc_feature_virtual_port_routing)) { 5220 return bcm_td2_multicast_l3_vp_encap_get(unit, group, port, 5221 intf, encap_id); 5222 } else 5223 #endif /* BCM_TRIDENT2_SUPPORT */ 5224 { 5225 return BCM_E_UNAVAIL; 5226 } 5227 } 5228 5229 #ifdef BCM_GREYHOUND_SUPPORT 5230 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) { 5231 /* intf for this feature must be egress_nh index 5232 * Note: intf=BCM_IF_INVALID is special process for adding 5233 * l2mc egress. this value must be handled. 5234 */ 5235 if (intf != BCM_IF_INVALID) { 5236 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, intf)){ 5237 return bcm_esw_multicast_egress_object_encap_get(unit, 5238 group, intf, encap_id); 5239 } 5240 } 5241 } 5242 #endif /* BCM_GREYHOUND_SUPPORT */ 5243 5244 /* For L3 IPMC, encap_id is simply the L3 interface ID */ 5245 *encap_id = intf; 5246 return BCM_E_NONE; 5247 } 5248 #endif /* BCM_XGS3_SWITCH_SUPPORT && INCLUDE_L3 */ 5249 5250 return BCM_E_UNAVAIL; 5251 } 5252 5253 /* 5254 * Function: 5255 * bcm_multicast_l2_encap_get 5256 * Purpose: 5257 * Get the Encap ID for L2. 5258 * Parameters: 5259 * unit - (IN) Unit number. 5260 * group - (IN) Multicast group ID. 5261 * port - (IN) Physical port. 5262 * vlan - (IN) Vlan. 5263 * encap_id - (OUT) Encap ID. 5264 * Returns: 5265 * BCM_E_XXX 5266 * Notes: 5267 */ 5268 int 5269 bcm_esw_multicast_l2_encap_get(int unit, bcm_multicast_t group, 5270 bcm_gport_t port, bcm_vlan_t vlan, 5271 bcm_if_t *encap_id) 5272 { 5273 MULTICAST_INIT_CHECK(unit); 5274 5275 if (encap_id == NULL) { 5276 return BCM_E_PARAM; 5277 } 5278 5279 *encap_id = BCM_IF_INVALID; 5280 5281 #if defined(BCM_XGS3_SWITCH_SUPPORT) && defined(INCLUDE_L3) 5282 if (SOC_IS_XGS3_SWITCH(unit)) { 5283 5284 #if defined(BCM_HGPROXY_COE_SUPPORT) 5285 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 5286 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 5287 /* Encap ID is used for L2 in XGS for TD2+CoE GPORT-SUBPORT 5288 types */ 5289 return _bcmi_coe_multicast_subport_encap_get(unit, port, encap_id); 5290 5291 } else 5292 #endif 5293 { 5294 return BCM_E_NONE; 5295 } 5296 } 5297 #endif /* BCM_XGS3_SWITCH_SUPPORT && INCLUDE_L3 */ 5298 return BCM_E_UNAVAIL; 5299 } 5300 5301 /* 5302 * Function: 5303 * bcm_multicast_trill_encap_get 5304 * Purpose: 5305 * Get the Encap ID for a TRILL port. 5306 * Parameters: 5307 * unit - (IN) Unit number. 5308 * group - (IN) Multicast group ID. 5309 * port - (IN) Physical port. 5310 * intf - (IN) L3 interface ID. 5311 * encap_id - (OUT) Encap ID. 5312 * Returns: 5313 * BCM_E_XXX 5314 * Notes: 5315 */ 5316 int 5317 bcm_esw_multicast_trill_encap_get(int unit, bcm_multicast_t group, bcm_gport_t port, 5318 bcm_if_t intf, bcm_if_t *encap_id) 5319 { 5320 MULTICAST_INIT_CHECK(unit); 5321 5322 if (encap_id == NULL) { 5323 return BCM_E_PARAM; 5324 } 5325 5326 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3) 5327 if (soc_feature(unit, soc_feature_trill)) { 5328 /* For TRILL IPMC, encap_id is simply the L3 interface ID */ 5329 *encap_id = intf; 5330 return BCM_E_NONE; 5331 } 5332 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */ 5333 return BCM_E_UNAVAIL; 5334 } 5335 5336 /* 5337 * Function: 5338 * bcm_multicast_vpls_encap_get 5339 * Purpose: 5340 * Get the Encap ID for a MPLS port. 5341 * Parameters: 5342 * unit - (IN) Unit number. 5343 * group - (IN) Multicast group ID. 5344 * port - (IN) Physical port. 5345 * mpls_port_id - (IN) MPLS port ID. 5346 * encap_id - (OUT) Encap ID. 5347 * Returns: 5348 * BCM_E_XXX 5349 * Notes: 5350 */ 5351 int 5352 bcm_esw_multicast_vpls_encap_get(int unit, bcm_multicast_t group, bcm_gport_t port, 5353 bcm_gport_t mpls_port_id, bcm_if_t *encap_id) 5354 { 5355 MULTICAST_INIT_CHECK(unit); 5356 5357 if (encap_id == NULL) { 5358 return BCM_E_PARAM; 5359 } 5360 5361 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 5362 if (SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH2(unit) || 5363 SOC_IS_APOLLO(unit) || SOC_IS_VALKYRIE2(unit) || 5364 SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit)) { 5365 return bcm_tr2_multicast_vpls_encap_get(unit, group, port, 5366 mpls_port_id, encap_id); 5367 } 5368 #endif /* BCM_TRIUMPH2_SUPPORT && INCLUDE_L3 */ 5369 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 5370 if (SOC_IS_TR_VL(unit) && !SOC_IS_HURRICANEX(unit) && 5371 !SOC_IS_GREYHOUND2(unit)) { 5372 return bcm_tr_multicast_vpls_encap_get(unit, group, port, 5373 mpls_port_id, encap_id); 5374 } 5375 #endif /* BCM_TRX_SUPPORT && INCLUDE_L3 */ 5376 return BCM_E_UNAVAIL; 5377 } 5378 5379 /* 5380 * Function: 5381 * bcm_multicast_subport_encap_get 5382 * Purpose: 5383 * Get the Encap ID for a subport. 5384 * Parameters: 5385 * unit - (IN) Unit number. 5386 * group - (IN) Multicast group ID. 5387 * port - (IN) Physical port. 5388 * subport - (IN) Subport ID. 5389 * encap_id - (OUT) Encap ID. 5390 * Returns: 5391 * BCM_E_XXX 5392 * Notes: 5393 */ 5394 int 5395 bcm_esw_multicast_subport_encap_get(int unit, bcm_multicast_t group, bcm_gport_t port, 5396 bcm_gport_t subport, bcm_if_t *encap_id) 5397 { 5398 MULTICAST_INIT_CHECK(unit); 5399 5400 if (encap_id == NULL) { 5401 return BCM_E_PARAM; 5402 } 5403 5404 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 5405 if (SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 5406 SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit) || SOC_IS_KATANAX(unit) || 5407 SOC_IS_TRIUMPH3(unit)) { 5408 return bcm_tr2_multicast_subport_encap_get(unit, group, port, 5409 subport, encap_id); 5410 } 5411 #endif /* BCM_TRIUMPH2_SUPPORT && INCLUDE_L3 */ 5412 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 5413 if (SOC_IS_TRX(unit) && !SOC_IS_SCORPION(unit) && !SOC_IS_HURRICANE(unit) && 5414 !SOC_IS_HURRICANE2(unit) && !SOC_IS_XGS3_FABRIC(unit)) { 5415 return bcm_tr_multicast_subport_encap_get(unit, group, port, 5416 subport, encap_id); 5417 } 5418 #endif /* BCM_TRX_SUPPORT && INCLUDE_L3 */ 5419 return BCM_E_UNAVAIL; 5420 } 5421 5422 /* 5423 * Function: 5424 * bcm_multicast_mim_encap_get 5425 * Purpose: 5426 * Get the Encap ID for MiM. 5427 * Parameters: 5428 * unit - (IN) Unit number. 5429 * group - (IN) Multicast group ID. 5430 * port - (IN) Physical port. 5431 * mim_port - (IN) MiM port ID. 5432 * encap_id - (OUT) Encap ID. 5433 * Returns: 5434 * BCM_E_XXX 5435 * Notes: 5436 */ 5437 int 5438 bcm_esw_multicast_mim_encap_get(int unit, bcm_multicast_t group, bcm_gport_t port, 5439 bcm_gport_t mim_port, bcm_if_t *encap_id) 5440 { 5441 MULTICAST_INIT_CHECK(unit); 5442 5443 if (encap_id == NULL) { 5444 return BCM_E_PARAM; 5445 } 5446 5447 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 5448 if (soc_feature(unit, soc_feature_mim)) { 5449 return bcm_tr2_multicast_mim_encap_get(unit, group, port, 5450 mim_port, encap_id); 5451 } 5452 #endif /* BCM_TRIUMPH2_SUPPORT && INCLUDE_L3 */ 5453 return BCM_E_UNAVAIL; 5454 } 5455 5456 /* 5457 * Function: 5458 * bcm_multicast_wlan_encap_get 5459 * Purpose: 5460 * Get the Encap ID for WLAN. 5461 * Parameters: 5462 * unit - (IN) Unit number. 5463 * group - (IN) Multicast group ID. 5464 * port - (IN) Physical port. 5465 * wlan_port - (IN) WLAN port ID. 5466 * encap_id - (OUT) Encap ID. 5467 * Returns: 5468 * BCM_E_XXX 5469 * Notes: 5470 */ 5471 int 5472 bcm_esw_multicast_wlan_encap_get(int unit, bcm_multicast_t group, bcm_gport_t port, 5473 bcm_gport_t wlan_port, bcm_if_t *encap_id) 5474 { 5475 MULTICAST_INIT_CHECK(unit); 5476 5477 if (encap_id == NULL) { 5478 return BCM_E_PARAM; 5479 } 5480 5481 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 5482 if (soc_feature(unit, soc_feature_wlan)) { 5483 return bcm_tr2_multicast_wlan_encap_get(unit, group, port, 5484 wlan_port, encap_id); 5485 } 5486 #endif /* BCM_TRIUMPH2_SUPPORT && INCLUDE_L3 */ 5487 return BCM_E_UNAVAIL; 5488 } 5489 5490 /* 5491 * Function: 5492 * bcm_multicast_vlan_encap_get 5493 * Purpose: 5494 * Get the Encap ID for VLAN virtual port. 5495 * Parameters: 5496 * unit - (IN) Unit number. 5497 * group - (IN) Multicast group ID. 5498 * port - (IN) Physical port. 5499 * vlan_port - (IN) VLAN port ID. 5500 * encap_id - (OUT) Encap ID. 5501 * Returns: 5502 * BCM_E_XXX 5503 * Notes: 5504 */ 5505 int 5506 bcm_esw_multicast_vlan_encap_get(int unit, bcm_multicast_t group, 5507 bcm_gport_t port, bcm_gport_t vlan_port_id, 5508 bcm_if_t *encap_id) 5509 { 5510 MULTICAST_INIT_CHECK(unit); 5511 5512 if (encap_id == NULL) { 5513 return BCM_E_PARAM; 5514 } 5515 5516 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 5517 if (soc_feature(unit, soc_feature_vlan_vp)) { 5518 int vp; 5519 ing_dvp_table_entry_t dvp; 5520 5521 if (!BCM_GPORT_IS_VLAN_PORT(vlan_port_id)) { 5522 return BCM_E_PARAM; 5523 } 5524 vp = BCM_GPORT_VLAN_PORT_ID_GET(vlan_port_id); 5525 if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) { 5526 return BCM_E_PARAM; 5527 } 5528 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 5529 return BCM_E_PARAM; 5530 } 5531 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 5532 5533 /* Next-hop index is used for multicast replication */ 5534 *encap_id = (bcm_if_t) soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 5535 if (!SOC_IS_ENDURO(unit)) { 5536 *encap_id += BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 5537 } 5538 return BCM_E_NONE; 5539 } 5540 #endif /* BCM_TRIUMPH2_SUPPORT && INCLUDE_L3 */ 5541 5542 return BCM_E_UNAVAIL; 5543 } 5544 5545 /* 5546 * Function: 5547 * bcm_multicast_niv_encap_get 5548 * Purpose: 5549 * Get the Encap ID for NIV virtual port. 5550 * Parameters: 5551 * unit - (IN) Unit number. 5552 * group - (IN) Multicast group ID. 5553 * port - (IN) Physical port. 5554 * niv_port_id - (IN) NIV port ID. 5555 * encap_id - (OUT) Encap ID. 5556 * Returns: 5557 * BCM_E_XXX 5558 * Notes: 5559 */ 5560 int 5561 bcm_esw_multicast_niv_encap_get(int unit, bcm_multicast_t group, bcm_gport_t port, 5562 bcm_gport_t niv_port_id, bcm_if_t *encap_id) 5563 { 5564 MULTICAST_INIT_CHECK(unit); 5565 5566 if (encap_id == NULL) { 5567 return BCM_E_PARAM; 5568 } 5569 5570 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3) 5571 if (soc_feature(unit, soc_feature_niv)) { 5572 int vp; 5573 ing_dvp_table_entry_t dvp; 5574 5575 if (!BCM_GPORT_IS_NIV_PORT(niv_port_id)) { 5576 return BCM_E_PARAM; 5577 } 5578 vp = BCM_GPORT_NIV_PORT_ID_GET(niv_port_id); 5579 if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) { 5580 return BCM_E_PARAM; 5581 } 5582 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) { 5583 return BCM_E_PARAM; 5584 } 5585 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 5586 5587 /* Next-hop index is used for multicast replication */ 5588 *encap_id = (bcm_if_t) soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 5589 *encap_id += BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 5590 5591 return BCM_E_NONE; 5592 } 5593 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */ 5594 5595 return BCM_E_UNAVAIL; 5596 } 5597 5598 /* 5599 * Function: 5600 * bcm_esw_multicast_egress_object_encap_get 5601 * Purpose: 5602 * Get the Encap ID for Egress_object 5603 * Parameters: 5604 * unit - (IN) Unit number. 5605 * group - (IN) Multicast group ID. 5606 * intf - (IN) Egress Object ID. 5607 * encap_id - (OUT) Encap ID. 5608 * Returns: 5609 * BCM_E_XXX 5610 * Notes: 5611 */ 5612 int 5613 bcm_esw_multicast_egress_object_encap_get(int unit, bcm_multicast_t group, bcm_if_t intf, 5614 bcm_if_t *encap_id) 5615 { 5616 MULTICAST_INIT_CHECK(unit); 5617 5618 if (encap_id == NULL) { 5619 return BCM_E_PARAM; 5620 } 5621 5622 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 5623 #if defined(INCLUDE_L3) 5624 if (soc_feature(unit, soc_feature_l3)) { 5625 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, intf)) { 5626 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) { 5627 *encap_id = intf; 5628 } else { 5629 *encap_id = (intf - BCM_XGS3_EGRESS_IDX_MIN(unit)) + 5630 BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 5631 } 5632 } else if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, intf)) { 5633 *encap_id = intf; 5634 } else if (BCM_XGS3_PROXY_EGRESS_IDX_VALID(unit, intf)) { 5635 *encap_id = (intf - BCM_XGS3_PROXY_EGRESS_IDX_MIN(unit)) + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 5636 } else { 5637 return BCM_E_PARAM; 5638 } 5639 return BCM_E_NONE; 5640 } 5641 #endif /* INCLUDE_L3 */ 5642 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND_SUPPORT */ 5643 5644 return BCM_E_UNAVAIL; 5645 } 5646 5647 /* 5648 * Function: 5649 * bcm_esw_multicast_l2gre_encap_get 5650 * Purpose: 5651 * Get the Encap ID for L2GRE virtual port 5652 * Parameters: 5653 * unit - (IN) Unit number. 5654 * group - (IN) Multicast group ID. 5655 * port - (IN) Physical port. 5656 * l2gre_port_id - (IN) L2GRE port ID. 5657 * encap_id - (OUT) Encap ID. 5658 * Returns: 5659 * BCM_E_XXX 5660 * Notes: 5661 */ 5662 int 5663 bcm_esw_multicast_l2gre_encap_get(int unit, bcm_multicast_t group, bcm_gport_t port, 5664 bcm_gport_t l2gre_port_id, bcm_if_t *encap_id) 5665 { 5666 if (encap_id == NULL) { 5667 return BCM_E_PARAM; 5668 } 5669 5670 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3) 5671 if (soc_feature(unit, soc_feature_l2gre)) { 5672 int vp; 5673 ing_dvp_table_entry_t dvp; 5674 5675 if (!BCM_GPORT_IS_L2GRE_PORT(l2gre_port_id)) { 5676 return BCM_E_PARAM; 5677 } 5678 /* Get Multicast DVP index */ 5679 vp = BCM_GPORT_L2GRE_PORT_ID_GET(l2gre_port_id); 5680 if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) { 5681 return BCM_E_PARAM; 5682 } 5683 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) { 5684 return BCM_E_PARAM; 5685 } 5686 /* Multicast DVP will never point to ECMP group */ 5687 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 5688 if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf)) { 5689 return BCM_E_PARAM; 5690 } 5691 5692 /* Next-hop index is used for multicast replication */ 5693 *encap_id = (bcm_if_t) soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 5694 *encap_id += BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 5695 5696 return BCM_E_NONE; 5697 } 5698 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */ 5699 5700 return BCM_E_UNAVAIL; 5701 } 5702 5703 5704 /* 5705 * Function: 5706 * bcm_esw_multicast_vxlan_encap_get 5707 * Purpose: 5708 * Get the Encap ID for VXLAN virtual port 5709 * Parameters: 5710 * unit - (IN) Unit number. 5711 * group - (IN) Multicast group ID. 5712 * port - (IN) Physical port. 5713 * vxlan_port_id - (IN) L2GRE port ID. 5714 * encap_id - (OUT) Encap ID. 5715 * Returns: 5716 * BCM_E_XXX 5717 * Notes: 5718 */ 5719 int 5720 bcm_esw_multicast_vxlan_encap_get(int unit, bcm_multicast_t group, bcm_gport_t port, 5721 bcm_gport_t vxlan_port_id, bcm_if_t *encap_id) 5722 { 5723 #if defined(INCLUDE_L3) 5724 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 5725 int vp = -1; 5726 #endif /* BCM_TRIDENT2_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 5727 #endif /* INCLUDE_L3 */ 5728 5729 if (encap_id == NULL) { 5730 return BCM_E_PARAM; 5731 } 5732 5733 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 5734 if (soc_feature(unit, soc_feature_vxlan)) { 5735 ing_dvp_table_entry_t dvp; 5736 5737 if (!BCM_GPORT_IS_VXLAN_PORT(vxlan_port_id)) { 5738 return BCM_E_PARAM; 5739 } 5740 5741 /* Get Multicast DVP index */ 5742 vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port_id); 5743 if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) { 5744 return BCM_E_PARAM; 5745 } 5746 5747 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) { 5748 return BCM_E_PARAM; 5749 } 5750 5751 /* Multicast DVP will never point to ECMP group */ 5752 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 5753 5754 /* Next-hop index is used for multicast replication */ 5755 *encap_id = (bcm_if_t) soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 5756 *encap_id += BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 5757 5758 return BCM_E_NONE; 5759 } else 5760 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 5761 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(INCLUDE_L3) 5762 if (soc_feature(unit, soc_feature_vxlan_lite)) { 5763 int ecmp = 0, nh_ecmp_index = 0; 5764 5765 if (!BCM_GPORT_IS_VXLAN_PORT(vxlan_port_id)) { 5766 return BCM_E_PARAM; 5767 } 5768 5769 /* Get Multicast DVP index */ 5770 vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port_id); 5771 if (vp == -1) { 5772 return BCM_E_PARAM; 5773 } 5774 5775 if (!bcmi_gh2_vxlan_vp_used_get(unit, vp)) { 5776 return BCM_E_PARAM; 5777 } 5778 5779 BCM_IF_ERROR_RETURN( 5780 bcmi_gh2_vxlan_port_to_nh_ecmp_index(unit, vp, 5781 &ecmp, &nh_ecmp_index)); 5782 if (ecmp) { 5783 return BCM_E_PARAM; 5784 } 5785 5786 /* Next-hop index is used for multicast replication */ 5787 *encap_id = (bcm_if_t)nh_ecmp_index; 5788 *encap_id += BCM_XGS3_EGRESS_IDX_MIN(unit); 5789 5790 return BCM_E_NONE; 5791 } else 5792 #endif /* BCM_GREYHOUND2_SUPPORT && INCLUDE_L3 */ 5793 { 5794 return BCM_E_UNAVAIL; 5795 } 5796 } 5797 5798 /* 5799 * Function: 5800 * bcm_multicast_extender_encap_get 5801 * Purpose: 5802 * Get the Encap ID for Extender virtual port. 5803 * Parameters: 5804 * unit - (IN) Unit number. 5805 * group - (IN) Multicast group ID. 5806 * port - (IN) Physical port. 5807 * extender_port_id - (IN) Extender port ID. 5808 * encap_id - (OUT) Encap ID. 5809 * Returns: 5810 * BCM_E_XXX 5811 * Notes: 5812 */ 5813 int 5814 bcm_esw_multicast_extender_encap_get(int unit, bcm_multicast_t group, 5815 bcm_gport_t port, bcm_gport_t extender_port_id, bcm_if_t *encap_id) 5816 { 5817 MULTICAST_INIT_CHECK(unit); 5818 5819 if (encap_id == NULL) { 5820 return BCM_E_PARAM; 5821 } 5822 5823 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3) 5824 if (soc_feature(unit, soc_feature_port_extension)) { 5825 int vp; 5826 ing_dvp_table_entry_t dvp; 5827 5828 if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port_id)) { 5829 return BCM_E_PARAM; 5830 } 5831 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port_id); 5832 if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) { 5833 return BCM_E_PARAM; 5834 } 5835 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 5836 return BCM_E_PARAM; 5837 } 5838 BCM_IF_ERROR_RETURN 5839 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 5840 5841 /* Next-hop index is used for multicast replication */ 5842 *encap_id = (bcm_if_t) soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 5843 NEXT_HOP_INDEXf); 5844 *encap_id += BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 5845 5846 return BCM_E_NONE; 5847 } 5848 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */ 5849 5850 return BCM_E_UNAVAIL; 5851 } 5852 5853 /* 5854 * Function: 5855 * bcm_multicast_mac_encap_get 5856 * Purpose: 5857 * Get the Encap ID for MAC virtual port. 5858 * Parameters: 5859 * unit - (IN) Unit number. 5860 * group - (IN) Multicast group ID. 5861 * port - (IN) Physical port. 5862 * mac_port_id - (IN) MAC port ID. 5863 * encap_id - (OUT) Encap ID. 5864 * Returns: 5865 * BCM_E_XXX 5866 * Notes: 5867 */ 5868 int 5869 bcm_esw_multicast_mac_encap_get(int unit, bcm_multicast_t group, bcm_gport_t port, 5870 bcm_gport_t mac_port_id, bcm_if_t *encap_id) 5871 { 5872 MULTICAST_INIT_CHECK(unit); 5873 5874 if (encap_id == NULL) { 5875 return BCM_E_PARAM; 5876 } 5877 5878 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 5879 if (soc_feature(unit, soc_feature_mac_virtual_port)) { 5880 int vp; 5881 ing_dvp_table_entry_t dvp; 5882 5883 if (!BCM_GPORT_IS_MAC_PORT(mac_port_id)) { 5884 return BCM_E_PARAM; 5885 } 5886 vp = BCM_GPORT_MAC_PORT_ID_GET(mac_port_id); 5887 if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) { 5888 return BCM_E_PARAM; 5889 } 5890 BCM_IF_ERROR_RETURN(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 5891 5892 /* Next-hop index is used for multicast replication */ 5893 *encap_id = (bcm_if_t) soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 5894 NEXT_HOP_INDEXf); 5895 *encap_id += BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 5896 5897 return BCM_E_NONE; 5898 } 5899 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 5900 5901 return BCM_E_UNAVAIL; 5902 } 5903 5904 /* 5905 * Function: 5906 * bcm_multicast_egress_add 5907 * Purpose: 5908 * Add a GPORT to the replication list 5909 * for the specified multicast index. 5910 * Parameters: 5911 * unit - (IN) Device Number 5912 * group - (IN) Multicast group ID 5913 * port - (IN) GPORT Identifier 5914 * encap_id - (IN) Encap ID. 5915 * Returns: 5916 * BCM_E_XXX 5917 */ 5918 int 5919 bcm_esw_multicast_egress_add(int unit, bcm_multicast_t group, 5920 bcm_gport_t port, bcm_if_t encap_id) 5921 { 5922 int rv=BCM_E_NONE; 5923 5924 MULTICAST_INIT_CHECK(unit); 5925 5926 /* Check whether the given multicast group is available */ 5927 rv = bcm_esw_multicast_group_is_free(unit, group); 5928 if (rv != BCM_E_EXISTS) { 5929 if (BCM_SUCCESS(rv)) { 5930 rv = BCM_E_NOT_FOUND; 5931 } 5932 return rv; 5933 } 5934 5935 #if defined(BCM_XGS3_SWITCH_SUPPORT) 5936 if (SOC_IS_XGS3_SWITCH(unit)) { 5937 if (_BCM_MULTICAST_L2_OR_FABRIC(unit, group)) { 5938 return _bcm_esw_multicast_l2_add(unit, group, port, encap_id); 5939 } else { 5940 #if defined(INCLUDE_L3) 5941 /* If (1) the given group is an IPMC group, (2) the given port is 5942 * a trunk gport, and (3) IPMC trunk resolution is disabled for the 5943 * trunk group in hardware, then encap_id is added to only one 5944 * member of the trunk group. The following procedure finds which 5945 * trunk member the encap_id is mapped to. 5946 */ 5947 bcm_gport_t mapped_port; 5948 BCM_IF_ERROR_RETURN 5949 (_bcm_esw_multicast_egress_encap_id_to_trunk_member_map(unit, 5950 group, 1, &port, &encap_id, &mapped_port)); 5951 return _bcm_esw_multicast_l3_add(unit, group, mapped_port, encap_id); 5952 #endif /* INCLUDE_L3 */ 5953 } 5954 } 5955 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 5956 return BCM_E_UNAVAIL; 5957 } 5958 5959 /* 5960 * Function: 5961 * bcm_multicast_egress_delete 5962 * Purpose: 5963 * Delete GPORT from the replication list 5964 * for the specified multicast index. 5965 * Parameters: 5966 * unit - (IN) Device Number 5967 * group - (IN) Multicast group ID 5968 * port - (IN) GPORT Identifier 5969 * encap_id - (IN) Encap ID. 5970 * Returns: 5971 * BCM_E_XXX 5972 */ 5973 int 5974 bcm_esw_multicast_egress_delete(int unit, bcm_multicast_t group, 5975 bcm_gport_t port, bcm_if_t encap_id) 5976 { 5977 int rv=BCM_E_NONE; 5978 5979 MULTICAST_INIT_CHECK(unit); 5980 5981 /* Check whether the given multicast group is available */ 5982 rv = bcm_esw_multicast_group_is_free(unit, group); 5983 if (rv != BCM_E_EXISTS) { 5984 if (BCM_SUCCESS(rv)) { 5985 rv = BCM_E_NOT_FOUND; 5986 } 5987 return rv; 5988 } 5989 5990 #if defined(BCM_XGS3_SWITCH_SUPPORT) 5991 if (SOC_IS_XGS3_SWITCH(unit)) { 5992 if (_BCM_MULTICAST_L2_OR_FABRIC(unit, group)) { 5993 return _bcm_esw_multicast_l2_delete(unit, group, port, encap_id); 5994 } else { 5995 #if defined(INCLUDE_L3) 5996 /* If (1) the given group is an IPMC group, (2) the given port is 5997 * a trunk gport, and (3) IPMC trunk resolution is disabled for 5998 * the trunk group in hardware, then encap_id resides on only one 5999 * member of the trunk group. The following procedure finds which 6000 * trunk member the encap_id resides on. 6001 */ 6002 bcm_gport_t mapped_port; 6003 BCM_IF_ERROR_RETURN 6004 (_bcm_esw_multicast_egress_mapped_trunk_member_find(unit, 6005 group, port, encap_id, &mapped_port)); 6006 return _bcm_esw_multicast_l3_delete(unit, group, mapped_port, encap_id); 6007 #endif /* INCLUDE_L3 */ 6008 } 6009 } 6010 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6011 return BCM_E_UNAVAIL; 6012 } 6013 6014 /* 6015 * Function: 6016 * bcm_multicast_egress_delete_all 6017 * Purpose: 6018 * Delete all replications for the specified multicast index. 6019 * Parameters: 6020 * unit - (IN) Device Number 6021 * group - (IN) Multicast group ID 6022 * Returns: 6023 * BCM_E_XXX 6024 */ 6025 int 6026 bcm_esw_multicast_egress_delete_all(int unit, bcm_multicast_t group) 6027 { 6028 int rv=BCM_E_NONE; 6029 MULTICAST_INIT_CHECK(unit); 6030 6031 /* Check whether the given multicast group is available */ 6032 rv = bcm_esw_multicast_group_is_free(unit, group); 6033 if (rv != BCM_E_EXISTS) { 6034 if (BCM_SUCCESS(rv)) { 6035 rv = BCM_E_NOT_FOUND; 6036 } 6037 return rv; 6038 } 6039 6040 rv = bcm_esw_multicast_egress_set(unit, group, 0, NULL, NULL); 6041 #if defined(INCLUDE_L3) && defined(BCM_KATANA_SUPPORT) 6042 if ((SOC_IS_SABER2(unit)|| SOC_IS_KATANAX(unit)) && BCM_SUCCESS(rv)) { 6043 return _bcm_esw_multicast_egress_subscriber_delete_all(unit, group); 6044 } 6045 #endif 6046 return rv; 6047 } 6048 /* 6049 * Function: 6050 * bcm_multicast_egress_set 6051 * Purpose: 6052 * Assign the complete set of egress GPORTs in the 6053 * replication list for the specified multicast index. 6054 * Parameters: 6055 * unit - (IN) Device Number 6056 * group - (IN) Multicast group ID 6057 * port_count - (IN) Number of ports in replication list 6058 * port_array - (IN) List of GPORT Identifiers 6059 * encap_id_array - (IN) List of encap identifiers 6060 * Returns: 6061 * BCM_E_XXX 6062 */ 6063 int 6064 bcm_esw_multicast_egress_set(int unit, bcm_multicast_t group, int port_count, 6065 bcm_gport_t *port_array, bcm_if_t *encap_id_array) 6066 { 6067 int rv=BCM_E_NONE; 6068 6069 MULTICAST_INIT_CHECK(unit); 6070 6071 /* Check whether the given multicast group is available */ 6072 rv = bcm_esw_multicast_group_is_free(unit, group); 6073 if (rv != BCM_E_EXISTS) { 6074 if (BCM_SUCCESS(rv)) { 6075 rv = BCM_E_NOT_FOUND; 6076 } 6077 return rv; 6078 } 6079 6080 #if defined(BCM_XGS3_SWITCH_SUPPORT) && defined(INCLUDE_L3) 6081 if (SOC_IS_XGS3_SWITCH(unit)) { 6082 /* If (1) the given group is an IPMC group, (2) the given port is a 6083 * trunk gport, and (3) IPMC trunk resolution is disabled for the 6084 * trunk group in hardware, then each encap_id is added to only one 6085 * member in trunk group. The following procedure maps the encap_ids 6086 * to trunk members. 6087 */ 6088 int rv; 6089 bcm_gport_t *mapped_port_array = NULL; 6090 if (port_count > 0) { 6091 mapped_port_array = sal_alloc(sizeof(bcm_gport_t) * port_count, 6092 "resolved port array"); 6093 if (NULL == mapped_port_array) { 6094 return BCM_E_MEMORY; 6095 } 6096 rv = _bcm_esw_multicast_egress_encap_id_to_trunk_member_map(unit, 6097 group, port_count, port_array, encap_id_array, 6098 mapped_port_array); 6099 if (BCM_FAILURE(rv)) { 6100 sal_free(mapped_port_array); 6101 return rv; 6102 } 6103 } 6104 6105 rv = _bcm_esw_multicast_egress_set(unit, group, port_count, 6106 mapped_port_array, encap_id_array); 6107 6108 if (mapped_port_array) { 6109 sal_free(mapped_port_array); 6110 } 6111 6112 return rv; 6113 } 6114 #endif /* BCM_XGS3_SWITCH_SUPPORT && INCLUDE_L3 */ 6115 return BCM_E_UNAVAIL; 6116 } 6117 6118 #if (defined(BCM_TRX_SUPPORT) || defined(BCM_XGS3_SWITCH_SUPPORT)) && defined(INCLUDE_L3) 6119 /* 6120 * Function: 6121 * _bcm_esw_multicast_egress_get 6122 * Purpose: 6123 * Helper function to API 6124 * Parameters: 6125 * unit - (IN) Device Number 6126 * mc_index - (IN) Multicast index 6127 * port_max - (IN) Number of entries in "port_array" 6128 * port_array - (OUT) List of ports 6129 * encap_id_array - (OUT) List of encap identifiers 6130 * port_count - (OUT) Actual number of ports returned 6131 * Returns: 6132 * BCM_E_XXX 6133 * Notes: 6134 * If the input parameter port_max = 0, return in the output parameter 6135 * port_count the total number of ports/encapsulation IDs in the 6136 * specified multicast group's replication list. 6137 */ 6138 STATIC int 6139 _bcm_esw_multicast_egress_get(int unit, bcm_multicast_t group, int port_max, 6140 bcm_gport_t *port_array, 6141 bcm_if_t *encap_id_array, 6142 int *port_count) 6143 { 6144 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6145 if (SOC_IS_XGS3_SWITCH(unit)) { 6146 if (_BCM_MULTICAST_L2_OR_FABRIC(unit, group)) { 6147 return _bcm_esw_multicast_l2_get(unit, group, port_max, port_array, 6148 encap_id_array, port_count); 6149 } else { 6150 #if defined(INCLUDE_L3) 6151 return _bcm_esw_multicast_l3_get(unit, group, port_max, port_array, 6152 encap_id_array, port_count); 6153 #endif /* INCLUDE_L3 */ 6154 } 6155 } 6156 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6157 6158 return BCM_E_UNAVAIL; 6159 } 6160 #endif 6161 6162 /* 6163 * Function: 6164 * bcm_multicast_egress_get 6165 * Purpose: 6166 * Retrieve a set of egress multicast GPORTs in the 6167 * replication list for the specified multicast index. 6168 * Parameters: 6169 * unit - (IN) Device Number 6170 * mc_index - (IN) Multicast index 6171 * port_max - (IN) Number of entries in "port_array" 6172 * port_array - (OUT) List of ports 6173 * encap_id_array - (OUT) List of encap identifiers 6174 * port_count - (OUT) Actual number of ports returned 6175 * Returns: 6176 * BCM_E_XXX 6177 * Notes: 6178 * If the input parameter port_max = 0, return in the output parameter 6179 * port_count the total number of ports/encapsulation IDs in the 6180 * specified multicast group's replication list. 6181 */ 6182 int 6183 bcm_esw_multicast_egress_get(int unit, bcm_multicast_t group, int port_max, 6184 bcm_gport_t *port_array, 6185 bcm_if_t *encap_id_array, 6186 int *port_count) 6187 { 6188 int rv = BCM_E_UNAVAIL; 6189 #if (defined(BCM_TRX_SUPPORT) || defined(BCM_XGS3_SWITCH_SUPPORT)) && defined(INCLUDE_L3) 6190 int i; 6191 bcm_module_t mod_out, my_modid; 6192 bcm_port_t port_in, port_out; 6193 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 6194 int is_local_subport = FALSE; 6195 #endif 6196 #if defined(BCM_TOMAHAWK_SUPPORT) || defined (BCM_TRIDENT2PLUS_SUPPORT) 6197 int r_rv; 6198 int tgid; 6199 bcm_module_t local_modid = 0; 6200 int trunk_local_ports = 0; 6201 bcm_trunk_info_t tinfo; 6202 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) 6203 bcm_port_t local_trunk_member_ports[SOC_MAX_NUM_PP_PORTS] = {0}; 6204 int max_num_ports = SOC_MAX_NUM_PP_PORTS; 6205 #else 6206 bcm_port_t local_trunk_member_ports[SOC_MAX_NUM_PORTS] = {0}; 6207 int max_num_ports = SOC_MAX_NUM_PORTS; 6208 #endif 6209 #endif 6210 6211 MULTICAST_INIT_CHECK(unit); 6212 6213 /* Check whether the given multicast group is available */ 6214 rv = bcm_esw_multicast_group_is_free(unit, group); 6215 if (rv != BCM_E_EXISTS) { 6216 if (BCM_SUCCESS(rv)) { 6217 rv = BCM_E_NOT_FOUND; 6218 } 6219 return rv; 6220 } 6221 6222 /* port_array and encap_id_array are allowed to be NULL */ 6223 if ((NULL == port_count) || (port_max < 0) ){ 6224 return BCM_E_PARAM; 6225 } 6226 6227 /* If port_max = 0, port_array and encap_id_array must be NULL */ 6228 if (port_max == 0) { 6229 if ((NULL != port_array) || (NULL != encap_id_array)) { 6230 return BCM_E_PARAM; 6231 } 6232 } 6233 6234 BCM_IF_ERROR_RETURN 6235 (_bcm_esw_multicast_egress_get(unit, group, port_max, port_array, 6236 encap_id_array, port_count)); 6237 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) 6238 if (!SOC_IS_TOMAHAWK3(unit)) { 6239 if ((BCM_MC_PER_TRUNK_REPL_MODE(unit)) && (NULL != port_array)) { 6240 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &local_modid)); 6241 r_rv = bcm_esw_trunk_find(unit, local_modid, *port_array, &tgid); 6242 if ((BCM_E_NONE == r_rv) && (BCM_TRUNK_INVALID != tgid)) { 6243 BCM_IF_ERROR_RETURN 6244 (bcm_esw_trunk_get(unit, tgid, &tinfo, 0, NULL, NULL)); 6245 if (!(tinfo.flags & BCM_TRUNK_FLAG_IPMC_CLEAVE)) { 6246 BCM_IF_ERROR_RETURN( 6247 _bcm_esw_trunk_local_members_get(unit, tgid, 6248 max_num_ports, 6249 local_trunk_member_ports, 6250 &trunk_local_ports)); 6251 for (i = 0; i < trunk_local_ports; i++) { 6252 BCM_IF_ERROR_RETURN 6253 (bcm_esw_port_gport_get(unit, local_trunk_member_ports[i], 6254 (port_array + i))); 6255 encap_id_array[i] = encap_id_array[0]; 6256 } 6257 } 6258 } 6259 } 6260 } /* if (!SOC_IS_TOMAHAWK3(unit)) */ 6261 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT2PLUS_SUPPORT */ 6262 if (NULL != port_array) { 6263 /* Convert GPORT_LOCAL format to GPORT_MODPORT format */ 6264 if (bcm_esw_stk_my_modid_get(unit, &my_modid) < 0) { 6265 return BCM_E_INTERNAL; 6266 } 6267 for (i = 0; i < *port_count; i++) { 6268 6269 #if defined(BCM_HGPROXY_COE_SUPPORT) 6270 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 6271 BCM_GPORT_IS_SET(port_array[i]) && 6272 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port_array[i])) { 6273 6274 if(_bcm_xgs5_subport_coe_gport_local(unit, port_array[i])) { 6275 is_local_subport = TRUE; 6276 } 6277 } else 6278 #endif 6279 #if defined(BCM_KATANA2_SUPPORT) 6280 /* For LinkPHY/SubTag subport return in subport_gport format*/ 6281 if (soc_feature(unit, soc_feature_linkphy_coe) || 6282 soc_feature(unit, soc_feature_subtag_coe)) { 6283 is_local_subport = FALSE; 6284 if (BCM_GPORT_IS_SET(port_array[i]) && 6285 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, 6286 port_array[i])) { 6287 is_local_subport = TRUE; 6288 } 6289 } 6290 #endif 6291 6292 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 6293 if (is_local_subport) { 6294 6295 } else 6296 #endif 6297 { 6298 BCM_IF_ERROR_RETURN( 6299 bcm_esw_port_local_get(unit, port_array[i], &port_in)); 6300 6301 BCM_IF_ERROR_RETURN 6302 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 6303 my_modid, port_in, &mod_out, &port_out)); 6304 BCM_GPORT_MODPORT_SET(port_array[i], mod_out, port_out); 6305 } 6306 } 6307 } 6308 6309 rv = BCM_E_NONE; 6310 #endif 6311 6312 return rv; 6313 } 6314 6315 6316 6317 int 6318 bcm_esw_multicast_repl_set(int unit, int mc_index, bcm_port_t port, 6319 bcm_vlan_vector_t vlan_vec) 6320 { 6321 return BCM_E_UNAVAIL; 6322 } 6323 6324 int 6325 bcm_esw_multicast_repl_get(int unit, int index, bcm_port_t port, 6326 bcm_vlan_vector_t vlan_vec) 6327 { 6328 return BCM_E_UNAVAIL; 6329 } 6330 6331 /* 6332 * Function: 6333 * bcm_esw_multicast_group_get 6334 * Purpose: 6335 * Retrieve the flags associated with a multicast group. 6336 * Parameters: 6337 * unit - (IN) Unit number. 6338 * group - (IN) Multicast group ID 6339 * flags - (OUT) BCM_MULTICAST_* 6340 * Returns: 6341 * BCM_E_xxx 6342 * Notes: 6343 */ 6344 int 6345 bcm_esw_multicast_group_get(int unit, bcm_multicast_t group, uint32 *flags) 6346 { 6347 MULTICAST_INIT_CHECK(unit); 6348 6349 #ifdef BCM_XGS3_FABRIC_SUPPORT 6350 if (SOC_IS_XGS3_FABRIC(unit)) { 6351 return _bcm_esw_fabric_multicast_group_get(unit, group, flags); 6352 } 6353 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 6354 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 6355 if (SOC_IS_TRX(unit)) { 6356 return bcm_trx_multicast_group_get(unit, group, flags); 6357 } 6358 #endif /* BCM_TRX_SUPPORT && INCLUDE_L3 */ 6359 #if defined(BCM_XGS3_SWITCH_SUPPORT) && defined(INCLUDE_L3) 6360 if (SOC_IS_XGS3_SWITCH(unit)) { 6361 return bcm_xgs3_multicast_group_get(unit, group, flags); 6362 } 6363 #endif /* BCM_XGS3_SWITCH_SUPPORT && INCLUDE_L3 */ 6364 return BCM_E_UNAVAIL; 6365 } 6366 6367 /* 6368 * Function: 6369 * bcm_esw_multicast_group_is_free 6370 * Purpose: 6371 * Request if the given multicast group is available on the 6372 * device 6373 * Parameters: 6374 * unit - (IN) Unit number. 6375 * group - (IN) Multicast group ID. 6376 * Returns: 6377 * BCM_E_NONE - multicast group is valid and available on the device 6378 * BCM_E_EXISTS - multicast group is valid but already in use 6379 * on this device 6380 * BCM_E_PARAM - multicast group is not valid on this device 6381 * Notes: 6382 */ 6383 int 6384 bcm_esw_multicast_group_is_free(int unit, bcm_multicast_t group) 6385 { 6386 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6387 int mc_index; 6388 int rv = BCM_E_PARAM; 6389 int is_set; 6390 6391 mc_index = _BCM_MULTICAST_ID_GET(group); 6392 6393 #ifdef BCM_XGS3_FABRIC_SUPPORT 6394 if (SOC_IS_XGS3_FABRIC(unit)) { 6395 rv = _bcm_esw_fabric_multicast_param_check(unit, group, &mc_index); 6396 /* Remap return codes */ 6397 if (BCM_E_NOT_FOUND == rv) { 6398 /* Multicast group is available, return without error */ 6399 rv = BCM_E_NONE; 6400 } else if (BCM_E_NONE == rv) { 6401 /* Multicast group is already configured */ 6402 rv = BCM_E_EXISTS; 6403 } 6404 } else 6405 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 6406 if (_BCM_MULTICAST_IS_L2(group)) { 6407 rv = _bcm_xgs3_l2mc_index_is_set(unit, mc_index, &is_set); 6408 if (BCM_SUCCESS(rv)) { 6409 if (is_set) { 6410 rv = BCM_E_EXISTS; 6411 } 6412 } 6413 #if defined(INCLUDE_L3) 6414 } else if (_BCM_MULTICAST_IS_SET(group)) { 6415 uint32 flags; 6416 uint8 group_type; 6417 6418 group_type = _BCM_MULTICAST_TYPE_GET(group); 6419 flags = _bcm_esw_multicast_group_type_to_flags(group_type); 6420 /* Check if this group type is supported on this device. */ 6421 BCM_IF_ERROR_RETURN(_bcm_esw_multicast_type_validate(unit, flags)); 6422 6423 rv = bcm_xgs3_ipmc_id_is_set(unit, mc_index, &is_set); 6424 if (BCM_SUCCESS(rv)) { 6425 if (is_set) { 6426 rv = BCM_E_EXISTS; 6427 } 6428 } 6429 #endif /* INCLUDE_L3 */ 6430 } 6431 6432 return rv; 6433 #else 6434 return BCM_E_UNAVAIL; 6435 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6436 } 6437 6438 /* 6439 * Function: 6440 * bcm_esw_multicast_group_free_range_get 6441 * Purpose: 6442 * Retrieve the minimum and maximum unallocated multicast groups 6443 * for a given multicast type. 6444 * Parameters: 6445 * unit - (IN) Unit number. 6446 * type_flag - (IN) One of BCM_MULTICAST_TYPE_*. 6447 * group_min - (OUT) Minimum available multicast group of specified type. 6448 * group_max - (OUT) Maximum available multicast group of specified type. 6449 * Returns: 6450 * BCM_E_xxx 6451 * Notes: 6452 */ 6453 int 6454 bcm_esw_multicast_group_free_range_get(int unit, uint32 type_flag, 6455 bcm_multicast_t *group_min, 6456 bcm_multicast_t *group_max) 6457 { 6458 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6459 bcm_multicast_t dev_min, dev_max, group, free_min, free_max; 6460 int index_min, index_max, group_type, min_group_index; 6461 int rv = BCM_E_PARAM; 6462 uint32 type; 6463 6464 type = type_flag & BCM_MULTICAST_TYPE_MASK; 6465 if (1 != _shr_popcount(type)) { 6466 return BCM_E_PARAM; 6467 } 6468 6469 #ifdef BCM_XGS3_FABRIC_SUPPORT 6470 if (SOC_IS_XGS3_FABRIC(unit)) { 6471 if (type_flag == BCM_MULTICAST_TYPE_L2) { 6472 index_min = BCM_FABRIC_MCAST_BASE(unit); 6473 index_max = BCM_FABRIC_MCAST_MAX(unit); 6474 min_group_index = 1; 6475 } else { 6476 index_min = BCM_FABRIC_IPMC_BASE(unit); 6477 index_max = BCM_FABRIC_IPMC_MAX(unit); 6478 min_group_index = 0; 6479 } 6480 } else 6481 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 6482 if (type_flag == BCM_MULTICAST_TYPE_L2) { 6483 index_min = soc_mem_index_min(unit, L2MCm); 6484 index_max = soc_mem_index_max(unit, L2MCm); 6485 min_group_index = 1; 6486 } else { 6487 index_min = soc_mem_index_min(unit, L3_IPMCm); 6488 index_max = soc_mem_index_max(unit, L3_IPMCm); 6489 min_group_index = 0; 6490 } 6491 6492 group_type = _bcm_esw_multicast_flags_to_group_type(type_flag); 6493 _BCM_MULTICAST_GROUP_SET(dev_min, group_type, min_group_index); 6494 _BCM_MULTICAST_GROUP_SET(dev_max, group_type, index_max - index_min); 6495 6496 6497 free_min = free_max = 0; /* Invalid multicast group */ 6498 for (group = dev_min; group <= dev_max; group++) { 6499 rv = bcm_esw_multicast_group_is_free(unit, group); 6500 if (BCM_SUCCESS(rv)) { 6501 if (0 == free_min) { 6502 free_min = group; 6503 } 6504 free_max = group; 6505 } else if (BCM_E_EXISTS == rv) { 6506 /* Nothing to do but clear the error */ 6507 rv = BCM_E_NONE; 6508 } else { 6509 /* Real error, return */ 6510 break; 6511 } 6512 } 6513 6514 if (BCM_SUCCESS(rv)) { 6515 if (0 == free_min) { 6516 /* No available groups of this type */ 6517 return BCM_E_NOT_FOUND; 6518 } else { 6519 /* Copy the results */ 6520 *group_min = free_min; 6521 *group_max = free_max; 6522 } 6523 } 6524 6525 return rv; 6526 #else 6527 return BCM_E_UNAVAIL; 6528 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6529 } 6530 6531 /* 6532 * Function: 6533 * bcm_esw_multicast_group_traverse 6534 * Purpose: 6535 * Iterate over the defined multicast groups of the type 6536 * specified in 'flags'. If all types are desired, use 6537 * MULTICAST_TYPE_MASK. 6538 * Parameters: 6539 * unit - (IN) Unit number. 6540 * trav_fn - (IN) Callback function. 6541 * flags - (IN) BCM_MULTICAST_* 6542 * user_data - (IN) User data to be passed to callback function. 6543 * Returns: 6544 * BCM_E_xxx 6545 * Notes: 6546 */ 6547 int 6548 bcm_esw_multicast_group_traverse(int unit, 6549 bcm_multicast_group_traverse_cb_t trav_fn, 6550 uint32 flags, void *user_data) 6551 { 6552 MULTICAST_INIT_CHECK(unit); 6553 6554 #ifdef BCM_XGS3_FABRIC_SUPPORT 6555 if (SOC_IS_XGS3_FABRIC(unit)) { 6556 return _bcm_esw_fabric_multicast_group_traverse(unit, trav_fn, 6557 flags, user_data); 6558 } 6559 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 6560 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 6561 if (SOC_IS_TRX(unit)) { 6562 return bcm_trx_multicast_group_traverse(unit, trav_fn, 6563 flags, user_data); 6564 } 6565 #endif /* BCM_TRX_SUPPORT && INCLUDE_L3 */ 6566 #if defined(BCM_XGS3_SWITCH_SUPPORT) && defined(INCLUDE_L3) 6567 if (SOC_IS_XGS3_SWITCH(unit)) { 6568 return bcm_xgs3_multicast_group_traverse(unit, trav_fn, 6569 flags, user_data); 6570 } 6571 #endif /* BCM_XGS3_SWITCH_SUPPORT && INCLUDE_L3 */ 6572 return BCM_E_UNAVAIL; 6573 } 6574 6575 #if defined(INCLUDE_L3) 6576 /* 6577 * Function: 6578 * _bcm_esw_multicast_remap_group_set 6579 * Purpose: 6580 * Set an IPMC remapping. 6581 * Parameters: 6582 * unit - (IN) Unit number. 6583 * from - (IN) Multicast group ID to map from 6584 * to - (IN) Multicast group ID to map to 6585 * Returns: 6586 * BCM_E_XXX 6587 * Notes: 6588 */ 6589 STATIC int 6590 _bcm_esw_multicast_remap_group_set(int unit, bcm_multicast_t from, int to) 6591 { 6592 int rv = BCM_E_UNAVAIL; 6593 6594 #if defined(BCM_TRIUMPH2_SUPPORT) 6595 if (soc_feature(unit, soc_feature_ipmc_remap)) { 6596 6597 rv = _bcm_esw_multicast_l3_group_check(unit, from, NULL); 6598 BCM_IF_ERROR_RETURN(rv); 6599 6600 rv = _bcm_esw_multicast_l3_group_check(unit, to, NULL); 6601 BCM_IF_ERROR_RETURN(rv); 6602 6603 rv = bcm_tr2_ipmc_remap_set(unit, from, to); 6604 } 6605 #endif 6606 6607 return rv; 6608 } 6609 6610 6611 /* 6612 * Function: 6613 * _bcm_esw_multicast_remap_group_get 6614 * Purpose: 6615 * Set an IPMC remapping. 6616 * Parameters: 6617 * unit - (IN) Unit number. 6618 * from - (IN) Multicast group ID being mapped 6619 * to - (OUT) Pointer to Multicast group ID being mapped to, 6620 * using the same group type as 'from'. 6621 * Returns: 6622 * BCM_E_XXX 6623 * Notes: 6624 */ 6625 STATIC int 6626 _bcm_esw_multicast_remap_group_get(int unit, bcm_multicast_t from, int *to) 6627 { 6628 int rv = BCM_E_UNAVAIL; 6629 6630 #if defined(BCM_TRIUMPH2_SUPPORT) 6631 if (soc_feature(unit, soc_feature_ipmc_remap)) { 6632 6633 rv = _bcm_esw_multicast_l3_group_check(unit, from, NULL); 6634 if (BCM_SUCCESS(rv)) { 6635 rv = bcm_tr2_ipmc_remap_get(unit, from, to); 6636 } 6637 } 6638 #endif 6639 6640 return rv; 6641 } 6642 #endif 6643 6644 /* 6645 * Function: 6646 * bcm_multicast_control_set 6647 * Purpose: 6648 * Set multicast group control. 6649 * Parameters: 6650 * unit - (IN) Unit number. 6651 * group - (IN) Multicast group ID. 6652 * type - (IN) Multicast group control type. 6653 * arg - (IN) Multicast group control argument. 6654 * Returns: 6655 * BCM_E_XXX 6656 */ 6657 int 6658 bcm_esw_multicast_control_set(int unit, 6659 bcm_multicast_t group, 6660 bcm_multicast_control_t type, 6661 int arg) 6662 { 6663 int rv = BCM_E_UNAVAIL; 6664 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6665 #if defined(INCLUDE_L3) 6666 int index; 6667 mtu_values_entry_t l3_mtu_values_entry; 6668 #endif 6669 6670 MULTICAST_INIT_CHECK(unit); 6671 6672 if (!SOC_IS_XGS3_SWITCH(unit)) { 6673 return BCM_E_UNAVAIL; 6674 } 6675 6676 #if defined(INCLUDE_L3) 6677 rv = (_bcm_esw_multicast_l3_group_check(unit, group, NULL)); 6678 #endif 6679 6680 if (!_BCM_MULTICAST_IS_L2(group) && BCM_FAILURE(rv)) { 6681 return rv; 6682 } 6683 6684 switch (type) { 6685 case bcmMulticastControlMtu: 6686 if (_BCM_MULTICAST_IS_L2(group)) { 6687 /* Not applicable to multicast types that uses a L2MC index. 6688 * Only applicable to multicast types that uses a L3MC index. 6689 */ 6690 return BCM_E_PARAM; 6691 } 6692 if (SOC_MEM_IS_VALID(unit, L3_MTU_VALUESm)) { 6693 #if defined(INCLUDE_L3) 6694 index = _BCM_MULTICAST_MTU_TABLE_OFFSET(unit) + 6695 _BCM_MULTICAST_ID_GET(group); 6696 if (!soc_mem_index_valid(unit, L3_MTU_VALUESm, index)) { 6697 return BCM_E_PARAM; 6698 } 6699 6700 SOC_IF_ERROR_RETURN(READ_L3_MTU_VALUESm(unit, MEM_BLOCK_ANY, 6701 index, &l3_mtu_values_entry)); 6702 6703 /* coverity[zero_return : FALSE] */ 6704 /* coverity[large_shift : FALSE] */ 6705 if(!SOC_MEM_FIELD32_VALUE_FIT(unit, L3_MTU_VALUESm, 6706 MTU_SIZEf, arg)) { 6707 return BCM_E_PARAM; 6708 } 6709 soc_L3_MTU_VALUESm_field32_set(unit, &l3_mtu_values_entry, 6710 MTU_SIZEf, arg); 6711 6712 rv = WRITE_L3_MTU_VALUESm(unit, MEM_BLOCK_ALL, 6713 index, &l3_mtu_values_entry); 6714 #endif /* INCLUDE_L3 */ 6715 } else if (SOC_MEM_FIELD_VALID(unit, L3_IPMCm, IPMC_MTU_INDEXf) && 6716 SOC_REG_IS_VALID(unit, IPMC_L3_MTUr)) { 6717 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_SCORPION_SUPPORT) 6718 #if defined(INCLUDE_L3) 6719 uint64 rval64, *rval64s[1]; 6720 uint32 pindex, entry[SOC_MAX_MEM_WORDS]; 6721 6722 rval64s[0] = &rval64; 6723 COMPILER_64_ZERO(rval64); 6724 COMPILER_64_SET(rval64, 0, arg); 6725 index = _BCM_MULTICAST_ID_GET(group); 6726 if (!soc_mem_index_valid(unit, L3_IPMCm, index)) { 6727 return BCM_E_PARAM; 6728 } 6729 BCM_IF_ERROR_RETURN 6730 (soc_profile_reg_add(unit, _bcm_mtu_profile[unit], rval64s, 6731 1, &pindex)); 6732 BCM_IF_ERROR_RETURN 6733 (soc_mem_read(unit, L3_IPMCm, 6734 MEM_BLOCK_ANY, index, &entry)); 6735 soc_mem_field32_set(unit, L3_IPMCm, &entry, 6736 IPMC_MTU_INDEXf, pindex); 6737 BCM_IF_ERROR_RETURN 6738 (soc_mem_write(unit, L3_IPMCm, MEM_BLOCK_ANY, index, 6739 &entry)); 6740 #endif /* INCLUDE_L3 */ 6741 #endif 6742 } else if (soc_feature(unit, soc_feature_l3_nh_attr_table)) { 6743 #if defined(BCM_TRIUMPH3_SUPPORT) 6744 #if defined(INCLUDE_L3) 6745 int mtu_profile_index; 6746 ing_l3_next_hop_attribute_1_index_entry_t mtu_idx_value_buf; 6747 void *null_idx_entry = 6748 soc_mem_entry_null(unit, ING_L3_NEXT_HOP_ATTRIBUTE_1_INDEXm); 6749 6750 index = _BCM_TR3_MULTICAST_MTU_TABLE_OFFSET(unit) + 6751 _BCM_MULTICAST_ID_GET(group); 6752 6753 if (!soc_mem_index_valid(unit, 6754 ING_L3_NEXT_HOP_ATTRIBUTE_1_INDEXm, index)) { 6755 return BCM_E_PARAM; 6756 } 6757 6758 /* coverity[zero_return : FALSE] */ 6759 /* coverity[large_shift : FALSE] */ 6760 if (!SOC_MEM_FIELD32_VALUE_FIT(unit, 6761 ING_L3_NEXT_HOP_ATTRIBUTE_1m, 6762 MTU_SIZEf, arg)) { 6763 return (BCM_E_PARAM); 6764 } 6765 6766 BCM_IF_ERROR_RETURN( 6767 _bcm_tr3_mtu_profile_index_get(unit, arg, 6768 (uint32 *)&mtu_profile_index)); 6769 6770 sal_memcpy(&mtu_idx_value_buf, null_idx_entry, 6771 sizeof(ing_l3_next_hop_attribute_1_index_entry_t)); 6772 soc_mem_field32_set(unit, ING_L3_NEXT_HOP_ATTRIBUTE_1_INDEXm, 6773 &mtu_idx_value_buf, INDEXf, mtu_profile_index); 6774 6775 rv = WRITE_ING_L3_NEXT_HOP_ATTRIBUTE_1_INDEXm(unit, MEM_BLOCK_ALL, 6776 index, &mtu_idx_value_buf); 6777 6778 #endif /* INCLUDE_L3 */ 6779 #endif /* BCM_TRIUMPH3_SUPPORT */ 6780 } else { 6781 return BCM_E_UNAVAIL; 6782 } 6783 break; 6784 6785 case bcmMulticastVpTrunkResolve: 6786 if (_BCM_MULTICAST_IS_L2(group)) { 6787 /* Not applicable to multicast types that uses a L2MC index. */ 6788 return BCM_E_PARAM; 6789 } 6790 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 6791 if (soc_feature(unit, soc_feature_vp_lag)) { 6792 egr_ipmc_entry_t egr_ipmc_entry; 6793 6794 index = _BCM_MULTICAST_ID_GET(group); 6795 BCM_IF_ERROR_RETURN(READ_EGR_IPMCm(unit, MEM_BLOCK_ANY, index, 6796 &egr_ipmc_entry)); 6797 soc_EGR_IPMCm_field32_set(unit, &egr_ipmc_entry, 6798 ENABLE_VPLAG_RESOLUTIONf, arg ? TRUE : FALSE); 6799 BCM_IF_ERROR_RETURN(WRITE_EGR_IPMCm(unit, MEM_BLOCK_ALL, index, 6800 &egr_ipmc_entry)); 6801 } else 6802 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 6803 { 6804 return BCM_E_PARAM; 6805 } 6806 break; 6807 6808 #if defined(INCLUDE_L3) 6809 case bcmMulticastRemapGroup: 6810 rv = _bcm_esw_multicast_remap_group_set(unit, group, arg); 6811 break; 6812 #endif 6813 6814 default: 6815 return BCM_E_PARAM; 6816 } 6817 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6818 return rv; 6819 } 6820 6821 /* 6822 * Function: 6823 * bcm_multicast_control_get 6824 * Purpose: 6825 * Get multicast group control. 6826 * Parameters: 6827 * unit - (IN) Unit number. 6828 * group - (IN) Multicast group ID. 6829 * type - (IN) Multicast group control type. 6830 * arg - (OUT) Multicast group control argument. 6831 * Returns: 6832 * BCM_E_XXX 6833 */ 6834 int 6835 bcm_esw_multicast_control_get(int unit, 6836 bcm_multicast_t group, 6837 bcm_multicast_control_t type, 6838 int *arg) 6839 { 6840 int rv = BCM_E_UNAVAIL; 6841 6842 6843 #if defined(BCM_XGS3_SWITCH_SUPPORT) 6844 #if defined(INCLUDE_L3) 6845 mtu_values_entry_t l3_mtu_values_entry; 6846 int index; 6847 #endif 6848 6849 MULTICAST_INIT_CHECK(unit); 6850 6851 if (!SOC_IS_XGS3_SWITCH(unit)) { 6852 return BCM_E_UNAVAIL; 6853 } 6854 6855 #if defined(INCLUDE_L3) 6856 rv = (_bcm_esw_multicast_l3_group_check(unit, group, NULL)); 6857 #endif 6858 6859 if (!_BCM_MULTICAST_IS_L2(group) && BCM_FAILURE(rv)) { 6860 return rv; 6861 } 6862 6863 switch (type) { 6864 case bcmMulticastControlMtu: 6865 if (_BCM_MULTICAST_IS_L2(group)) { 6866 /* Not applicable to multicast types that uses a L2MC index. 6867 * Only applicable to multicast types that uses a L3MC index. 6868 */ 6869 return BCM_E_PARAM; 6870 } 6871 6872 if (SOC_MEM_IS_VALID(unit, L3_MTU_VALUESm)) { 6873 #if defined(INCLUDE_L3) 6874 index = _BCM_MULTICAST_MTU_TABLE_OFFSET(unit) + 6875 _BCM_MULTICAST_ID_GET(group); 6876 if (!soc_mem_index_valid(unit, L3_MTU_VALUESm, index)) { 6877 return BCM_E_PARAM; 6878 } 6879 6880 SOC_IF_ERROR_RETURN(READ_L3_MTU_VALUESm(unit, MEM_BLOCK_ANY, 6881 index, &l3_mtu_values_entry)); 6882 *arg = soc_L3_MTU_VALUESm_field32_get(unit, 6883 &l3_mtu_values_entry, MTU_SIZEf); 6884 /* if no error assume success */ 6885 rv = BCM_E_NONE; 6886 #endif /* INCLUDE_L3 */ 6887 } else if (SOC_MEM_FIELD_VALID(unit, L3_IPMCm, IPMC_MTU_INDEXf) && 6888 SOC_REG_IS_VALID(unit, IPMC_L3_MTUr)) { 6889 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_SCORPION_SUPPORT) 6890 #if defined(INCLUDE_L3) 6891 uint64 rval64, *rval64s[1]; 6892 uint32 pindex, entry[SOC_MAX_MEM_WORDS]; 6893 6894 rval64s[0] = &rval64; 6895 index = _BCM_MULTICAST_ID_GET(group); 6896 if (!soc_mem_index_valid(unit, L3_IPMCm, index)) { 6897 return BCM_E_PARAM; 6898 } 6899 BCM_IF_ERROR_RETURN 6900 (soc_mem_read(unit, L3_IPMCm, 6901 MEM_BLOCK_ANY, index, &entry)); 6902 pindex = soc_mem_field32_get(unit, L3_IPMCm, &entry, 6903 IPMC_MTU_INDEXf); 6904 BCM_IF_ERROR_RETURN 6905 (soc_profile_reg_get(unit, _bcm_mtu_profile[unit], pindex, 6906 1, rval64s)); 6907 *arg = COMPILER_64_LO(rval64); 6908 #endif /* INCLUDE_L3 */ 6909 #endif 6910 } else if (soc_feature(unit, soc_feature_l3_nh_attr_table)) { 6911 #if defined(BCM_TRIUMPH3_SUPPORT) 6912 #if defined(INCLUDE_L3) 6913 6914 /* Buffer for mtu idx */ 6915 ing_l3_next_hop_attribute_1_index_entry_t mtu_idx_value_buf; 6916 /* Buffer for mtu profile table entry */ 6917 ing_l3_next_hop_attribute_1_entry_t mtu_value_buf; 6918 int mtu_profile_index; 6919 6920 index = _BCM_TR3_MULTICAST_MTU_TABLE_OFFSET(unit) + 6921 _BCM_MULTICAST_ID_GET(group); 6922 6923 if (!soc_mem_index_valid(unit, 6924 ING_L3_NEXT_HOP_ATTRIBUTE_1_INDEXm, index)) { 6925 return BCM_E_PARAM; 6926 } 6927 6928 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, 6929 ING_L3_NEXT_HOP_ATTRIBUTE_1_INDEXm, 6930 index, 6931 (uint32 *)&mtu_idx_value_buf)); 6932 6933 mtu_profile_index = 6934 soc_mem_field32_get(unit, ING_L3_NEXT_HOP_ATTRIBUTE_1_INDEXm, 6935 (uint32 *)&mtu_idx_value_buf, INDEXf); 6936 6937 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, 6938 ING_L3_NEXT_HOP_ATTRIBUTE_1m, 6939 mtu_profile_index, (uint32 *)&mtu_value_buf)); 6940 *arg = 6941 soc_mem_field32_get(unit, ING_L3_NEXT_HOP_ATTRIBUTE_1m, 6942 (uint32 *)&mtu_value_buf, MTU_SIZEf); 6943 6944 /* if no error assume success */ 6945 rv = BCM_E_NONE; 6946 #endif /* INCLUDE_L3 */ 6947 #endif /* BCM_TRIUMPH3_SUPPORT */ 6948 } else { 6949 return BCM_E_UNAVAIL; 6950 } 6951 break; 6952 6953 case bcmMulticastVpTrunkResolve: 6954 if (_BCM_MULTICAST_IS_L2(group)) { 6955 /* Not applicable to multicast types that uses a L2MC index. */ 6956 return BCM_E_PARAM; 6957 } 6958 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 6959 if (soc_feature(unit, soc_feature_vp_lag)) { 6960 egr_ipmc_entry_t egr_ipmc_entry; 6961 6962 index = _BCM_MULTICAST_ID_GET(group); 6963 BCM_IF_ERROR_RETURN(READ_EGR_IPMCm(unit, MEM_BLOCK_ANY, index, 6964 &egr_ipmc_entry)); 6965 *arg = soc_EGR_IPMCm_field32_get(unit, &egr_ipmc_entry, 6966 ENABLE_VPLAG_RESOLUTIONf); 6967 } else 6968 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 6969 { 6970 return BCM_E_PARAM; 6971 } 6972 break; 6973 6974 #if defined(INCLUDE_L3) 6975 case bcmMulticastRemapGroup: 6976 rv = _bcm_esw_multicast_remap_group_get(unit, group, arg); 6977 break; 6978 #endif 6979 6980 default: 6981 return BCM_E_PARAM; 6982 } 6983 6984 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 6985 return rv; 6986 } 6987 6988 /* 6989 * Function: 6990 * _bcm_esw_ipmc_subscriber_egress_intf_add 6991 * Purpose: 6992 * Helper function to add ipmc egress interface on different devices. 6993 * Parameters: 6994 * unit - (IN) Device Number 6995 * ipmc_id - (IN) ipmc id 6996 * port - (IN) Port number 6997 * nh_index - (IN) Next Hop index 6998 * subscriber_queue - (IN) Subscriber gport 6999 * is_l3 - (IN) Identifier of L2/L3 IPMC interface, relevant only for FB 7000 * queue_count - (OUT) number of queues in the extended queue list 7001 * Returns: 7002 * BCM_E_XXX 7003 */ 7004 int 7005 _bcm_esw_ipmc_subscriber_egress_intf_add(int unit, int ipmc_id, 7006 bcm_port_t port, 7007 int nh_index, 7008 bcm_gport_t subscriber_queue, 7009 int is_l3, 7010 int *queue_count, 7011 int *q_count_increased) 7012 { 7013 #if defined (INCLUDE_L3) 7014 #if defined(BCM_KATANA_SUPPORT) 7015 int id; 7016 7017 #if defined(BCM_SABER2_SUPPORT) 7018 if (SOC_IS_SABER2(unit)) { 7019 id = nh_index; 7020 return _bcm_sb2_ipmc_subscriber_egress_intf_add(unit, ipmc_id, port, 7021 id, subscriber_queue, is_l3, 7022 queue_count, q_count_increased); 7023 } 7024 #endif 7025 if (SOC_IS_KATANAX(unit)) { 7026 id = nh_index; 7027 7028 return _bcm_kt_ipmc_subscriber_egress_intf_set(unit, ipmc_id, port, 1, 7029 &id, subscriber_queue, is_l3, 7030 queue_count, q_count_increased); 7031 } 7032 #endif /* BCM_KATANA_SUPPORT */ 7033 #endif /* INCLUDE_L3 */ 7034 return BCM_E_UNAVAIL; 7035 } 7036 7037 /* 7038 * Function: 7039 * _bcm_esw_ipmc_subscriber_egress_intf_delete 7040 * Purpose: 7041 * Helper function to add ipmc egress interface on different devices. 7042 * Parameters: 7043 * unit - (IN) Device Number 7044 * ipmc_id - (IN) ipmc id 7045 * port - (IN) Port number 7046 * nh_index - (IN) Next Hop index 7047 * subscriber_queue - (IN) Subscriber gport 7048 * is_l3 - (IN) Identifier of L2/L3 IPMC interface, relevant only for FB 7049 * queue_count - (OUT) number of queues in the extended queue list 7050 * Returns: 7051 * BCM_E_XXX 7052 */ 7053 int 7054 _bcm_esw_ipmc_subscriber_egress_intf_delete(int unit, int ipmc_id, 7055 bcm_port_t port, 7056 int nh_index, 7057 bcm_gport_t subscriber_queue, 7058 int is_l3, 7059 int *queue_count, 7060 int *q_count_decreased) 7061 { 7062 #if defined (INCLUDE_L3) 7063 7064 #if defined(BCM_KATANA_SUPPORT) 7065 #if defined(BCM_SABER2_SUPPORT) 7066 if (SOC_IS_SABER2(unit)) { 7067 return _bcm_sb2_ipmc_subscriber_egress_intf_delete(unit, ipmc_id, port, 7068 nh_index, subscriber_queue, 7069 queue_count, q_count_decreased); 7070 7071 } 7072 #endif 7073 7074 if (SOC_IS_KATANAX(unit)) { 7075 return _bcm_kt_ipmc_subscriber_egress_intf_delete(unit, ipmc_id, port, 7076 nh_index, subscriber_queue, 7077 queue_count, q_count_decreased); 7078 } 7079 #endif /* BCM_KATANA_SUPPORT */ 7080 #endif /* INCLUDE_L3 */ 7081 return BCM_E_UNAVAIL; 7082 } 7083 7084 /* 7085 * Function: 7086 * _bcm_esw_ipmc_subscriber_egress_intf_set 7087 * Purpose: 7088 * Helper function to add ipmc egress interface on different devices. 7089 * Parameters: 7090 * unit - (IN) Device Number 7091 * ipmc_id - (IN) ipmc id 7092 * port - (IN) Port number 7093 * nh_index - (IN) Next Hop index 7094 * subscriber_queue - (IN) Subscriber gport 7095 * is_l3 - (IN) Identifier of L2/L3 IPMC interface, relevant only for FB 7096 * queue_count - (OUT) number of queues in the extended queue list 7097 * Returns: 7098 * BCM_E_XXX 7099 */ 7100 int 7101 _bcm_esw_ipmc_subscriber_egress_intf_set(int unit, int ipmc_id, 7102 bcm_port_t port, 7103 int if_count, 7104 int *if_array, 7105 bcm_gport_t subscriber_queue, 7106 int is_l3, 7107 int *queue_count, 7108 int *q_count_increased) 7109 { 7110 #if defined (INCLUDE_L3) 7111 #if defined(BCM_KATANA_SUPPORT) 7112 #if defined(BCM_SABER2_SUPPORT) 7113 if (SOC_IS_SABER2(unit)) { 7114 return _bcm_sb2_ipmc_subscriber_egress_intf_set(unit, ipmc_id, port, 7115 if_count, if_array, 7116 subscriber_queue, is_l3, 7117 queue_count, 7118 q_count_increased); 7119 7120 } 7121 #endif 7122 7123 if (SOC_IS_KATANAX(unit)) { 7124 return _bcm_kt_ipmc_subscriber_egress_intf_set(unit, ipmc_id, port, 7125 if_count, if_array, 7126 subscriber_queue, is_l3, 7127 queue_count, 7128 q_count_increased); 7129 } 7130 #endif /* BCM_KATANA_SUPPORT */ 7131 #endif /* INCLUDE_L3 */ 7132 return BCM_E_UNAVAIL; 7133 } 7134 7135 /* 7136 * Function: 7137 * _bcm_esw_ipmc_subscriber_egress_intf_get 7138 * Purpose: 7139 * Helper function to add ipmc egress interface on different devices. 7140 * Parameters: 7141 * unit - (IN) Device Number 7142 * ipmc_id - (IN) ipmc id 7143 * port - (IN) Port number 7144 * nh_index - (IN) Next Hop index 7145 * subscriber_queue - (IN) Subscriber gport 7146 * is_l3 - (IN) Identifier of L2/L3 IPMC interface, relevant only for FB 7147 * Returns: 7148 * BCM_E_XXX 7149 */ 7150 int 7151 _bcm_esw_ipmc_subscriber_egress_intf_get(int unit, bcm_multicast_t group, 7152 int port_count, 7153 bcm_gport_t *port_array, 7154 bcm_if_t *encap_id_array, 7155 bcm_gport_t *subscriber_queue_array, 7156 int *count) 7157 { 7158 #if defined (INCLUDE_L3) 7159 #if defined(BCM_KATANA_SUPPORT) 7160 #if defined(BCM_SABER2_SUPPORT) 7161 if (SOC_IS_SABER2(unit)) { 7162 return _bcm_sb2_ipmc_subscriber_egress_intf_get(unit, group, port_count, 7163 port_array, encap_id_array, 7164 subscriber_queue_array, count); 7165 } 7166 #endif 7167 7168 if (SOC_IS_KATANAX(unit)) { 7169 return _bcm_kt_ipmc_subscriber_egress_intf_get(unit, group, port_count, 7170 port_array, encap_id_array, 7171 subscriber_queue_array, count); 7172 } 7173 #endif /* BCM_KATANA_SUPPORT */ 7174 #endif /* INCLUDE_L3 */ 7175 return BCM_E_UNAVAIL; 7176 } 7177 7178 /* 7179 * Function: 7180 * _bcm_esw_ipmc_mmu_mc_remap_ptr 7181 * Purpose: 7182 * Helper function to set/get ipmc mmu remap pointer 7183 * Parameters: 7184 * unit - (IN) Device Number 7185 * ipmc_id - (IN) ipmc id 7186 * remap_id - (IN/OUT) set/get remap id 7187 * set - (IN) set/get input 7188 * Returns: 7189 * BCM_E_XXX 7190 */ 7191 int 7192 _bcm_esw_ipmc_mmu_mc_remap_ptr(int unit, int ipmc_id, 7193 int *remap_id, int set) 7194 { 7195 #if defined (INCLUDE_L3) 7196 #if defined(BCM_KATANA_SUPPORT) 7197 if (SOC_IS_KATANAX(unit)) { 7198 return _bcm_kt_ipmc_mmu_mc_remap_ptr(unit, ipmc_id, 7199 remap_id, set); 7200 } 7201 #endif /* BCM_KATANA_SUPPORT */ 7202 #endif /* INCLUDE_L3 */ 7203 return BCM_E_UNAVAIL; 7204 } 7205 7206 /* 7207 * Function: 7208 * _bcm_esw_ipmc_set_remap_group 7209 * Purpose: 7210 * Helper function to set/get ipmc mmu remap pointer 7211 * Parameters: 7212 * unit - (IN) Device Number 7213 * ipmc_id - (IN) ipmc id 7214 * port - (IN) port id 7215 * count - (IN) count 7216 * Returns: 7217 * BCM_E_XXX 7218 */ 7219 int 7220 _bcm_esw_ipmc_set_remap_group(int unit, int ipmc_id, 7221 bcm_port_t port_out, 7222 int count) 7223 { 7224 #if defined (INCLUDE_L3) 7225 #if defined(BCM_KATANA_SUPPORT) 7226 7227 #if defined(BCM_SABER2_SUPPORT) 7228 if (SOC_IS_SABER2(unit)) { 7229 return _bcm_sb2_ipmc_set_remap_group(unit, ipmc_id, 7230 port_out, count); 7231 } 7232 #endif 7233 7234 if (SOC_IS_KATANAX(unit)) { 7235 return _bcm_kt_ipmc_set_remap_group(unit, ipmc_id, 7236 port_out, count); 7237 } 7238 #endif /* BCM_KATANA_SUPPORT */ 7239 #endif /* INCLUDE_L3 */ 7240 return BCM_E_UNAVAIL; 7241 } 7242 7243 #if defined(BCM_KATANA_SUPPORT) 7244 7245 /* Macro to free memory and return code instead of using goto */ 7246 7247 #define BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(_r_) \ 7248 if (local_port_array) { \ 7249 sal_free(local_port_array); \ 7250 } \ 7251 if (temp_encap_list) { \ 7252 sal_free(temp_encap_list); \ 7253 temp_encap_list = NULL; \ 7254 } \ 7255 return _r_; 7256 7257 /* 7258 * Function: 7259 * _bcm_esw_multicast_egress_subscriber_set 7260 * Purpose: 7261 * Set the replication list 7262 * for the specified multicast index. 7263 * Parameters: 7264 * unit - (IN) Device Number 7265 * group - (IN) Multicast group ID 7266 * port_max - (IN) Maximum ports 7267 * port_array - (IN) GPORT array 7268 * encap_array - (IN) Encap ID array. 7269 * subscriber_array - (IN) Subscriber array 7270 * Returns: 7271 * BCM_E_XXX 7272 */ 7273 7274 STATIC int 7275 _bcm_esw_multicast_egress_subscriber_set(int unit, bcm_multicast_t group, 7276 int port_count, 7277 bcm_gport_t *port_array, 7278 bcm_if_t *encap_id_array, 7279 bcm_gport_t *subscriber_queue_array) 7280 { 7281 int mc_index, i, rv = BCM_E_NONE; 7282 int gport_id, *temp_encap_list = NULL; 7283 bcm_port_t *local_port_array = NULL; 7284 bcm_module_t mod_out; 7285 bcm_port_t port_out; 7286 bcm_pbmp_t l2_pbmp; 7287 l2mc_entry_t l2mc_entry; 7288 bcm_trunk_t trunk_id; 7289 soc_mem_t mem; 7290 int modid_local = 0; 7291 #if defined (INCLUDE_L3) 7292 int list_count; 7293 bcm_pbmp_t mc_eligible_pbmp, e_pbmp; 7294 bcm_port_t port_iter; 7295 int q_id = 0; 7296 int remap_index; 7297 int q_count = 0; 7298 int q_count_increased = 0; 7299 #endif /* INCLUDE_L3 */ 7300 #if defined(BCM_KATANA2_SUPPORT) 7301 int pp_port; 7302 #endif 7303 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 7304 int is_local_subport = FALSE; 7305 #endif 7306 7307 /* Input parameters check. */ 7308 mc_index = _BCM_MULTICAST_ID_GET(group); 7309 mem = (_BCM_MULTICAST_L2_OR_FABRIC(unit, group)) ? L2MCm : L3_IPMCm; 7310 7311 /* BCM_XGS3_FABRIC_SUPPORT */ 7312 if ((mc_index < 0) || (mc_index >= soc_mem_index_count(unit, mem))) { 7313 return (BCM_E_PARAM); 7314 } 7315 7316 if (port_count > 0) { 7317 if (NULL == port_array) { 7318 return (BCM_E_PARAM); 7319 } 7320 if (!_BCM_MULTICAST_L2_OR_FABRIC(unit, group) && 7321 (NULL == encap_id_array || NULL == subscriber_queue_array)) { 7322 return (BCM_E_PARAM); 7323 } 7324 } else { 7325 return (BCM_E_PARAM); 7326 } 7327 7328 #if defined (INCLUDE_L3) 7329 rv = _bcm_esw_multicast_l3_group_check(unit, group, NULL); 7330 #endif /* INCLUDE_L3 */ 7331 if (BCM_FAILURE(rv) && (0 == _BCM_MULTICAST_IS_L2(group))) { 7332 return BCM_E_PARAM; 7333 } 7334 7335 /* Convert GPORT array into local port numbers */ 7336 if (port_count > 0) { 7337 local_port_array = 7338 sal_alloc(sizeof(bcm_port_t) * port_count, "local_port array"); 7339 if (NULL == local_port_array) { 7340 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(BCM_E_MEMORY); 7341 } 7342 7343 temp_encap_list = 7344 sal_alloc(sizeof(int) * port_count, "temp_encap_list"); 7345 if (NULL == temp_encap_list) { 7346 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(rv); 7347 } 7348 } 7349 7350 for (i = 0; i < port_count ; i++) { 7351 rv = _bcm_esw_gport_resolve(unit, port_array[i], 7352 &mod_out, &port_out, 7353 &trunk_id, &gport_id); 7354 if (BCM_FAILURE(rv)) { 7355 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(rv); 7356 } 7357 7358 #if defined(BCM_HGPROXY_COE_SUPPORT) 7359 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 7360 BCM_GPORT_IS_SET(port_array[i]) && 7361 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port_array[i])) { 7362 7363 if(_bcm_xgs5_subport_coe_gport_local(unit, port_array[i])) { 7364 is_local_subport = TRUE; 7365 rv = _bcmi_coe_subport_physical_port_get(unit, 7366 port_array[i], 7367 &local_port_array[i]); 7368 if(rv != BCM_E_NONE) { 7369 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(BCM_E_PORT); 7370 } 7371 } else { 7372 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(BCM_E_PORT); 7373 } 7374 7375 } else 7376 #endif 7377 7378 #if defined(BCM_KATANA2_SUPPORT) 7379 if (soc_feature(unit, soc_feature_linkphy_coe) || 7380 soc_feature(unit, soc_feature_subtag_coe)) { 7381 if (BCM_GPORT_IS_SET(port_array[i]) && 7382 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, 7383 port_array[i])) { 7384 if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_out) == BCM_E_NONE) { 7385 pp_port = BCM_GPORT_SUBPORT_PORT_GET(port_array[i]); 7386 if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, pp_port)) { 7387 is_local_subport = TRUE; 7388 local_port_array[i] = pp_port; 7389 } 7390 } 7391 if (is_local_subport == FALSE) { 7392 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(BCM_E_PORT); 7393 } 7394 } 7395 } 7396 #endif 7397 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 7398 if (is_local_subport) { 7399 /* Local subport assigned above */ 7400 } else 7401 #endif 7402 if (BCM_TRUNK_INVALID != trunk_id) { 7403 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(BCM_E_PARAM); 7404 } else { 7405 rv = _bcm_esw_modid_is_local(unit, mod_out, &modid_local); 7406 if (BCM_FAILURE(rv)) { 7407 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(rv); 7408 } 7409 7410 if ((0 == IS_E_PORT(unit, port_out)) && 7411 !(_BCM_MULTICAST_IS_L2(group) || 7412 (BCM_IF_INVALID == encap_id_array[i]))) { 7413 /* Stack ports should not perform interface replication */ 7414 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(BCM_E_PARAM); 7415 } 7416 if (TRUE != modid_local) { 7417 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(BCM_E_PARAM); 7418 } 7419 local_port_array[i] = port_out; 7420 } 7421 } 7422 7423 BCM_PBMP_CLEAR(l2_pbmp); 7424 if (_BCM_MULTICAST_L2_OR_FABRIC(unit, group)) { 7425 for (i = 0; i < port_count; i++) { 7426 BCM_PBMP_PORT_ADD(l2_pbmp, local_port_array[i]); 7427 } 7428 7429 /* Update the L2MC port bitmap */ 7430 soc_mem_lock(unit, L2MCm); 7431 rv = soc_mem_read(unit, L2MCm, MEM_BLOCK_ANY, mc_index, &l2mc_entry); 7432 if (BCM_FAILURE(rv)) { 7433 soc_mem_unlock(unit, L2MCm); 7434 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(rv); 7435 } 7436 soc_mem_pbmp_field_set(unit, L2MCm, &l2mc_entry, PORT_BITMAPf, 7437 &l2_pbmp); 7438 rv = soc_mem_write(unit, L2MCm, MEM_BLOCK_ALL, 7439 mc_index, &l2mc_entry); 7440 soc_mem_unlock(unit, L2MCm); 7441 #if defined(INCLUDE_L3) 7442 } else { 7443 BCM_PBMP_CLEAR(e_pbmp); 7444 BCM_PBMP_ASSIGN(e_pbmp, PBMP_E_ALL(unit)); 7445 /* 7446 * For each port, walk through the list of GPORTs 7447 * and collect the ones that match the port. 7448 */ 7449 /* Valid SOC ports plus the CMIC port */ 7450 BCM_PBMP_ASSIGN(mc_eligible_pbmp, PBMP_PORT_ALL(unit)); 7451 BCM_PBMP_PORT_ADD(mc_eligible_pbmp, CMIC_PORT(unit)); 7452 #if defined(BCM_KATANA2_SUPPORT) 7453 if (soc_feature(unit, soc_feature_subtag_coe) || 7454 soc_feature(unit, soc_feature_linkphy_coe)) { 7455 _bcm_kt2_subport_pbmp_update(unit, &mc_eligible_pbmp); 7456 _bcm_kt2_subport_pbmp_update(unit, &e_pbmp); 7457 } 7458 #endif 7459 7460 BCM_PBMP_ITER(mc_eligible_pbmp, port_iter) { 7461 list_count = 0; 7462 for (i = 0; i < port_count ; i++) { 7463 if (local_port_array[i] != port_iter) { 7464 continue; 7465 } 7466 if (encap_id_array[i] == BCM_IF_INVALID) { 7467 /* Add port to L2 pbmp */ 7468 BCM_PBMP_PORT_ADD(l2_pbmp, port_iter); 7469 } else if (0 == BCM_PBMP_MEMBER(e_pbmp, port_iter)) { 7470 /* Must be a front-panel port to have an 7471 * interface replication list. */ 7472 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(BCM_E_PARAM); 7473 } else { 7474 if (!list_count) { 7475 q_id = subscriber_queue_array[i]; 7476 } else { 7477 if (q_id != subscriber_queue_array[i]) { 7478 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(BCM_E_PARAM); 7479 } 7480 } 7481 temp_encap_list[list_count] = encap_id_array[i]; 7482 list_count++; 7483 } 7484 } 7485 7486 if (list_count) { 7487 rv = _bcm_esw_ipmc_mmu_mc_remap_ptr(unit, mc_index, &remap_index, FALSE); 7488 if (BCM_FAILURE(rv)) { 7489 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(rv); 7490 } 7491 7492 q_count_increased = 0; 7493 if (!SOC_PORT_VALID(unit, port_iter)) { 7494 rv = BCM_E_PORT; 7495 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(rv); 7496 } 7497 rv = _bcm_esw_ipmc_subscriber_egress_intf_set(unit, 7498 remap_index, port_iter, list_count, 7499 temp_encap_list,q_id, TRUE, &q_count, 7500 &q_count_increased); 7501 if (BCM_FAILURE(rv)) { 7502 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(rv); 7503 } else { 7504 if (q_count_increased) { 7505 #if defined(BCM_SABER2_SUPPORT) 7506 if (SOC_IS_SABER2(unit)) { 7507 /* coverity[overrun-call : FALSE] */ 7508 _bcm_sb2_ipmc_port_ext_queue_count_increment(unit, 7509 mc_index, port_iter); 7510 } else 7511 #endif 7512 { 7513 /* coverity[overrun-call : FALSE] */ 7514 _bcm_kt_ipmc_port_ext_queue_count_increment( 7515 unit, mc_index, port_iter); 7516 } 7517 } 7518 /* coverity[overrun-call : FALSE] */ 7519 rv = _bcm_esw_ipmc_set_remap_group(unit, mc_index, 7520 port_iter, q_count); 7521 if (BCM_FAILURE(rv)) { 7522 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(rv); 7523 } 7524 } 7525 } 7526 } 7527 #endif /* INCLUDE_L3 */ 7528 } 7529 7530 BCM_SUBSCRIBER_MULTICAST_MEM_FREE_RETURN(rv); 7531 } 7532 7533 /* 7534 * Function: 7535 * _bcm_esw_multicast_egress_subscriber_get 7536 * Purpose: 7537 * Get the replication list 7538 * for the specified multicast index. 7539 * Parameters: 7540 * unit - (IN) Device Number 7541 * group - (IN) Multicast group ID 7542 * port_max - (IN) Maximum ports 7543 * port_array - (OUT) GPORT array 7544 * encap_array - (OUT) Encap ID array. 7545 * subscriber_array - (OUT) Subscriber array 7546 * Returns: 7547 * BCM_E_XXX 7548 */ 7549 7550 STATIC int 7551 _bcm_esw_multicast_egress_subscriber_get(int unit, bcm_multicast_t group, 7552 int port_max, bcm_gport_t *port_array, 7553 bcm_if_t *encap_id_array, 7554 bcm_gport_t *queue_array, 7555 int *port_count) 7556 { 7557 int mc_index, i, rv; 7558 int count = 0; 7559 bcm_port_t port; 7560 int remap_index; 7561 int uc_queue ; 7562 int temp_queue = 0; 7563 i= 0; 7564 rv = BCM_E_NONE; 7565 7566 mc_index = _BCM_MULTICAST_ID_GET(group); 7567 if ((mc_index < 0) || 7568 (mc_index >= soc_mem_index_count(unit, L3_IPMCm))) { 7569 return BCM_E_PARAM; 7570 } 7571 7572 #if defined (INCLUDE_L3) 7573 BCM_IF_ERROR_RETURN(_bcm_esw_multicast_l3_group_check(unit, group, NULL)); 7574 #endif /* INCLUDE_L3 */ 7575 if (port_max <= 0) { 7576 return BCM_E_PARAM; 7577 } 7578 7579 BCM_IF_ERROR_RETURN 7580 (_bcm_esw_ipmc_mmu_mc_remap_ptr(unit, mc_index, &remap_index, FALSE)); 7581 BCM_IF_ERROR_RETURN 7582 (_bcm_esw_ipmc_subscriber_egress_intf_get(unit, remap_index, port_max, 7583 port_array, encap_id_array, 7584 queue_array, &count)); 7585 7586 *port_count = count; 7587 for (i = 0; i < count; i++) { 7588 uc_queue = 0; 7589 if (NULL != port_array && NULL != queue_array) { 7590 /* Convert to GPORT values */ 7591 #ifdef BCM_KATANA2_SUPPORT 7592 if (SOC_IS_KATANA2(unit)) { 7593 BCM_IF_ERROR_RETURN 7594 (bcm_kt2_cosq_port_get(unit, queue_array[i], &port)); 7595 } else 7596 #endif /* BCM_KATANA2_SUPPORT */ 7597 { 7598 BCM_IF_ERROR_RETURN 7599 (bcm_kt_cosq_port_get(unit, queue_array[i], &port)); 7600 } 7601 #ifdef BCM_KATANA2_SUPPORT 7602 if (SOC_IS_KATANA2(unit)) { 7603 temp_queue = queue_array[i]; 7604 rv = bcm_kt2_sw_hw_queue(unit, &queue_array[i]); 7605 if (BCM_FAILURE(rv)) { 7606 queue_array[i] = temp_queue; 7607 BCM_IF_ERROR_RETURN(_bcm_kt_hw_to_sw_queue(unit, 7608 &queue_array[i], 7609 &port)); 7610 uc_queue = 0; 7611 } else { 7612 bcm_kt2_is_uc_queue(unit, queue_array[i], &uc_queue); 7613 } 7614 if(uc_queue){ 7615 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(queue_array[i],port, 7616 queue_array[i]); 7617 } 7618 else 7619 { 7620 if (BCM_SUCCESS(rv)) { 7621 bcm_kt2_cosq_subscriber_qid_set(unit, &queue_array[i], 7622 queue_array[i]); 7623 } else { 7624 rv = _bcm_kt2_subscriber_sw_qid_set(unit, 7625 &queue_array[i], 7626 queue_array[i]); 7627 } 7628 } 7629 } else 7630 #endif /* BCM_KATANA2_SUPPORT */ 7631 { 7632 temp_queue = queue_array[i]; 7633 rv = bcm_kt_sw_hw_queue(unit, &queue_array[i]); 7634 if (BCM_FAILURE(rv)) { 7635 queue_array[i] = temp_queue; 7636 rv = _bcm_kt_hw_to_sw_queue(unit, &queue_array[i], 7637 &port); 7638 uc_queue = 0; 7639 } else { 7640 bcm_kt_is_uc_queue(unit, queue_array[i], &uc_queue); 7641 } 7642 if (uc_queue) 7643 { 7644 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET 7645 (queue_array[i],port,queue_array[i]); 7646 } 7647 else 7648 { 7649 bcm_kt_cosq_subscriber_qid_set(unit, &queue_array[i], 7650 queue_array[i]); 7651 } 7652 } 7653 if(!uc_queue){ 7654 queue_array[i] |= (port << 16); 7655 } 7656 #if defined(BCM_KATANA2_SUPPORT) 7657 /* 7658 * Encode with subport type if this is a subport 7659 */ 7660 if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, port)) { 7661 _BCM_KT2_SUBPORT_PORT_ID_SET(port_array[i], port); 7662 if (BCM_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm, 7663 port)) { 7664 _BCM_KT2_SUBPORT_PORT_TYPE_SET(port_array[i], 7665 _BCM_KT2_SUBPORT_TYPE_LINKPHY); 7666 } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm, 7667 port)) { 7668 _BCM_KT2_SUBPORT_PORT_TYPE_SET(port_array[i], 7669 _BCM_KT2_SUBPORT_TYPE_SUBTAG); 7670 } else { 7671 return BCM_E_PORT; 7672 } 7673 } else 7674 #endif 7675 { 7676 BCM_IF_ERROR_RETURN 7677 (bcm_esw_port_gport_get(unit, port, (port_array + i))); 7678 } 7679 } 7680 if (i == port_max) { 7681 *port_count = port_max; 7682 break; 7683 } 7684 } 7685 7686 return rv; 7687 } 7688 7689 /* 7690 * Function: 7691 * _bcm_esw_multicast_egress_subscriber_qos_map_set 7692 * Purpose: 7693 * Assign the complete set of egress GPORTs in the 7694 * replication list for the specified multicast index. 7695 * Parameters: 7696 * unit - (IN) Device Number 7697 * group - (IN) Multicast group ID 7698 * port - (IN) GPORT Identifier 7699 * subscriber queue - (IN) Subscriber queue group GPORT Identifiers 7700 * qos_map_id - (IN) Qos Map ID 7701 * Returns: 7702 * BCM_E_XXX 7703 */ 7704 STATIC int 7705 _bcm_esw_multicast_egress_subscriber_qos_map_set(int unit, 7706 bcm_multicast_t group, 7707 bcm_gport_t port, 7708 bcm_gport_t subscriber_queue, 7709 int qos_map_id) 7710 { 7711 int mc_index; 7712 int remap_index; 7713 int rv = BCM_E_NONE; 7714 7715 mc_index = _BCM_MULTICAST_ID_GET(group); 7716 if ((mc_index < 0) || 7717 (mc_index >= soc_mem_index_count(unit, L3_IPMCm))) { 7718 return BCM_E_PARAM; 7719 } 7720 7721 #if defined (INCLUDE_L3) 7722 BCM_IF_ERROR_RETURN(_bcm_esw_multicast_l3_group_check(unit, group, NULL)); 7723 #endif /* INCLUDE_L3 */ 7724 BCM_IF_ERROR_RETURN 7725 (_bcm_esw_ipmc_mmu_mc_remap_ptr(unit, mc_index, &remap_index, FALSE)); 7726 #if defined(BCM_KATANA2_SUPPORT) && defined(INCLUDE_L3) 7727 #if defined(BCM_SABER2_SUPPORT) 7728 if(SOC_IS_SABER2(unit)) { 7729 rv = _bcm_sb2_ipmc_subscriber_egress_intf_qos_map_set(unit, 7730 remap_index, 7731 port, subscriber_queue, 7732 qos_map_id); 7733 } else 7734 #endif 7735 if (SOC_IS_KATANA2(unit)) { 7736 rv = _bcm_kt2_ipmc_subscriber_egress_intf_qos_map_set(unit, 7737 remap_index, 7738 port, subscriber_queue, 7739 qos_map_id); 7740 } 7741 #endif 7742 return rv; 7743 } 7744 7745 /* 7746 * Function: 7747 * _bcm_esw_multicast_egress_subscriber_qos_map_get 7748 * Purpose: 7749 * Get QOS Map ID associated with 7750 * multicast subscriber queue replication list. 7751 * Parameters: 7752 * unit - (IN) Device Number 7753 * group - (IN) Multicast group ID 7754 * port - (IN) GPORT Identifier 7755 * subscriber queue - (IN) Subscriber queue group GPORT Identifiers 7756 * qos_map_id - (OUT) Qos Map ID 7757 * Returns: 7758 * BCM_E_XXX 7759 */ 7760 STATIC int 7761 _bcm_esw_multicast_egress_subscriber_qos_map_get(int unit, 7762 bcm_multicast_t group, 7763 bcm_gport_t port, 7764 bcm_gport_t subscriber_queue, 7765 int *qos_map_id) 7766 { 7767 int mc_index, rv; 7768 int remap_index; 7769 7770 rv = BCM_E_NONE; 7771 7772 mc_index = _BCM_MULTICAST_ID_GET(group); 7773 if ((mc_index < 0) || 7774 (mc_index >= soc_mem_index_count(unit, L3_IPMCm))) { 7775 return BCM_E_PARAM; 7776 } 7777 7778 #if defined (INCLUDE_L3) 7779 BCM_IF_ERROR_RETURN(_bcm_esw_multicast_l3_group_check(unit, group, NULL)); 7780 #endif /* INCLUDE_L3 */ 7781 BCM_IF_ERROR_RETURN 7782 (_bcm_esw_ipmc_mmu_mc_remap_ptr(unit, mc_index, &remap_index, FALSE)); 7783 #if defined (BCM_KATANA2_SUPPORT) && defined(INCLUDE_L3) 7784 #if defined (BCM_SABER2_SUPPORT) 7785 if (SOC_IS_SABER2(unit)) { 7786 rv =_bcm_sb2_ipmc_subscriber_egress_intf_qos_map_get(unit, remap_index, 7787 port, subscriber_queue, 7788 qos_map_id); 7789 } else 7790 #endif 7791 if (SOC_IS_KATANA2(unit)) { 7792 rv =_bcm_kt2_ipmc_subscriber_egress_intf_qos_map_get(unit, remap_index, 7793 port, subscriber_queue, 7794 qos_map_id); 7795 } 7796 #endif 7797 return rv; 7798 } 7799 7800 /* 7801 * Function: 7802 * _bcm_esw_multicast_egress_subscriber_add 7803 * Purpose: 7804 * Add a GPORT to the replication list 7805 * for the specified multicast index. 7806 * Parameters: 7807 * unit - (IN) Device Number 7808 * group - (IN) Multicast group ID 7809 * port - (IN) GPORT Identifier 7810 * encap_id - (IN) Encap ID. 7811 * subscriber_queue - (IN) Subscriber gport 7812 * Returns: 7813 * BCM_E_XXX 7814 */ 7815 7816 STATIC int 7817 _bcm_esw_multicast_egress_subscriber_add(int unit, bcm_multicast_t group, 7818 bcm_gport_t port, 7819 bcm_if_t encap_id, 7820 bcm_gport_t subscriber_queue) 7821 { 7822 int mc_index, is_l3, gport_id; 7823 bcm_module_t mod_out; 7824 bcm_port_t port_out; 7825 bcm_trunk_t trunk_id; 7826 int modid_local, rv = BCM_E_NONE; 7827 bcm_pbmp_t l2_pbmp, l3_pbmp, old_pbmp, *new_pbmp; 7828 int remap_index; 7829 int q_count = 0; 7830 int q_count_increased = 0; 7831 int q_count_decreased = 0; 7832 int if_max = BCM_MULTICAST_PORT_MAX; 7833 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 7834 int is_local_subport = FALSE; 7835 #endif 7836 #if defined(BCM_ENDURO_SUPPORT) 7837 uint16 dev_id; 7838 uint8 rev_id; 7839 #if defined(BCM_KATANA2_SUPPORT) 7840 int my_modid = 0, pp_port; 7841 #endif 7842 7843 if (SOC_IS_ENDURO(unit)) { 7844 soc_cm_get_id(unit, &dev_id, &rev_id); 7845 7846 if ((dev_id == BCM56230_DEVICE_ID) || (dev_id == BCM56231_DEVICE_ID)){ 7847 /* 7848 * Because the size of "L3 Next Hop Table" 7849 * is reduced to 2K only on Dagger (Enduro Variant), 7850 * the if_max needs to be changed to the size of "L3 Next Hop 7851 * Table (2K)" instead of "BCM_MULTICAST_PORT_MAX(4K)". 7852 */ 7853 if_max = soc_mem_index_count(unit, ING_L3_NEXT_HOPm); 7854 } 7855 } 7856 #endif /* BCM_ENDURO_SUPPORT */ 7857 7858 is_l3 = 0; 7859 modid_local = FALSE; 7860 7861 mc_index = _BCM_MULTICAST_ID_GET(group); 7862 7863 if ((mc_index < 0) || 7864 (mc_index >= soc_mem_index_count(unit, L3_IPMCm))) { 7865 return BCM_E_PARAM; 7866 } 7867 7868 if (!(BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(subscriber_queue)) 7869 && !(BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(subscriber_queue)) 7870 && !(BCM_GPORT_IS_UCAST_QUEUE_GROUP(subscriber_queue))) { 7871 return BCM_E_PARAM; 7872 } 7873 7874 #if defined (INCLUDE_L3) 7875 BCM_IF_ERROR_RETURN(_bcm_esw_multicast_l3_group_check(unit, group, &is_l3)); 7876 #endif /* INCLUDE_L3 */ 7877 7878 BCM_IF_ERROR_RETURN 7879 (_bcm_esw_gport_resolve(unit, port, &mod_out, &port_out, 7880 &trunk_id, &gport_id)); 7881 7882 #if defined(BCM_HGPROXY_COE_SUPPORT) 7883 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 7884 BCM_GPORT_IS_SET(port) && 7885 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 7886 7887 if(_bcm_xgs5_subport_coe_gport_local(unit, port)) { 7888 is_local_subport = TRUE; 7889 BCM_IF_ERROR_RETURN( 7890 _bcmi_coe_subport_physical_port_get(unit, 7891 port, 7892 &port_out)); 7893 } else { 7894 return BCM_E_PORT; 7895 } 7896 7897 } else 7898 #endif 7899 7900 #if defined(BCM_KATANA2_SUPPORT) 7901 if (soc_feature(unit, soc_feature_linkphy_coe) || 7902 soc_feature(unit, soc_feature_subtag_coe)) { 7903 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 7904 if (BCM_GPORT_IS_SET(port) && 7905 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port)) { 7906 if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_out) == BCM_E_NONE) { 7907 pp_port = BCM_GPORT_SUBPORT_PORT_GET(port); 7908 if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, pp_port)) { 7909 is_local_subport = TRUE; 7910 port_out = pp_port; 7911 } 7912 } 7913 if (is_local_subport == FALSE) { 7914 return BCM_E_PORT; 7915 } 7916 } 7917 } 7918 #endif 7919 7920 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 7921 if (is_local_subport) { 7922 /* Local subport assigned above */ 7923 } else 7924 #endif 7925 7926 if (BCM_TRUNK_INVALID != trunk_id) { 7927 return BCM_E_PARAM; 7928 } else { 7929 BCM_IF_ERROR_RETURN 7930 (_bcm_esw_modid_is_local(unit, mod_out, &modid_local)); 7931 7932 if ((!IS_E_PORT(unit, port_out)) && (BCM_IF_INVALID != encap_id)) { 7933 /* Stack ports should not perform interface replication */ 7934 return BCM_E_PORT; 7935 } 7936 if (TRUE != modid_local) { 7937 /* Only add this to replication set if destination is local */ 7938 return BCM_E_PORT; 7939 } 7940 /* Convert system port to physical port */ 7941 if (soc_feature(unit, soc_feature_sysport_remap)) { 7942 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 7943 } 7944 } 7945 if (!SOC_PORT_VALID(unit, port_out)) { 7946 return BCM_E_PORT; 7947 } 7948 if (BCM_IF_INVALID != encap_id) { 7949 /* Add the required port to the multicast egress interface */ 7950 BCM_IF_ERROR_RETURN(_bcm_esw_ipmc_mmu_mc_remap_ptr(unit, 7951 mc_index, &remap_index, FALSE)); 7952 7953 rv = _bcm_esw_ipmc_subscriber_egress_intf_add(unit, remap_index, 7954 port_out, encap_id, subscriber_queue, is_l3, &q_count, 7955 &q_count_increased); 7956 if (BCM_SUCCESS(rv)) { 7957 new_pbmp = &l3_pbmp; 7958 #if defined(INCLUDE_L3) 7959 if (q_count_increased) { 7960 #if defined(BCM_SABER2_SUPPORT) 7961 if (SOC_IS_SABER2(unit)) { 7962 /* coverity[overrun-call : FALSE] */ 7963 _bcm_sb2_ipmc_port_ext_queue_count_increment(unit, 7964 mc_index, port_out); 7965 } else 7966 #endif 7967 { 7968 /* coverity[overrun-call : FALSE] */ 7969 _bcm_kt_ipmc_port_ext_queue_count_increment(unit, mc_index, 7970 port_out); 7971 } 7972 } 7973 #endif 7974 } else { 7975 return rv; 7976 } 7977 } else { 7978 if (!_BCM_MULTICAST_IS_VPLS(group)) { 7979 /* Updating the L2 bitmap */ 7980 new_pbmp = &l2_pbmp; 7981 } else { 7982 return BCM_E_PARAM; 7983 } 7984 } 7985 /* coverity[overrun-call : FALSE] */ 7986 BCM_IF_ERROR_RETURN 7987 (_bcm_esw_ipmc_set_remap_group(unit, mc_index, port_out, q_count)); 7988 7989 rv = _bcm_esw_multicast_ipmc_read(unit, mc_index, &l2_pbmp, &l3_pbmp); 7990 7991 if (BCM_SUCCESS(rv) && (BCM_IF_INVALID == encap_id)) { 7992 BCM_PBMP_ASSIGN(old_pbmp, *new_pbmp); 7993 BCM_PBMP_PORT_ADD(*new_pbmp, port_out); 7994 7995 if (BCM_PBMP_NEQ(old_pbmp, *new_pbmp)) { 7996 7997 /* Inside ipmc_write update num_copies, int, ext and 7998 * redirection pointer need to manage the work around 7999 */ 8000 rv = _bcm_esw_multicast_ipmc_write(unit, mc_index, l2_pbmp, 8001 l3_pbmp, TRUE); 8002 } 8003 } 8004 8005 if (BCM_FAILURE(rv)) { 8006 (void) _bcm_esw_ipmc_subscriber_egress_intf_delete(unit, mc_index, 8007 port_out, if_max, 8008 encap_id, is_l3, &q_count, 8009 &q_count_decreased); 8010 } 8011 8012 return rv; 8013 } 8014 8015 #if defined (BCM_KATANA_SUPPORT) && defined(INCLUDE_L3) 8016 STATIC int 8017 _bcm_esw_ipmc_subscriber_egress_intf_delete_all(int unit, int remap_index, 8018 bcm_port_t *port_array, 8019 int *encap_array, 8020 bcm_if_t *q_array, 8021 int port_count, int mc_index) 8022 { 8023 int q_count_decrease = 0; 8024 int index; 8025 bcm_port_t temp_port = BCM_GPORT_INVALID; 8026 int temp_queue, rv = BCM_E_NONE; 8027 8028 #if defined (BCM_SABER2_SUPPORT) 8029 if (SOC_IS_SABER2(unit)) { 8030 BCM_IF_ERROR_RETURN( 8031 _bcm_sb2_ipmc_subscriber_egress_intf_delete_all(unit, remap_index, 8032 port_array, encap_array, q_array, &q_count_decrease)); 8033 8034 } else 8035 #endif /* BCM_SABER2_SUPPORT */ 8036 { 8037 BCM_IF_ERROR_RETURN( 8038 _bcm_kt_ipmc_subscriber_egress_intf_delete_all(unit, remap_index, 8039 port_count, port_array, encap_array, q_array, 8040 &q_count_decrease)); 8041 } 8042 8043 if (q_count_decrease) { 8044 for (index = 0; index < port_count; index++) { 8045 #ifdef BCM_KATANA2_SUPPORT 8046 if (SOC_IS_KATANA2(unit) || SOC_IS_SABER2(unit)) { 8047 BCM_IF_ERROR_RETURN(bcm_kt2_cosq_port_get(unit, q_array[index], 8048 &temp_port)); 8049 } else 8050 #endif /* BCM_KATANA2_SUPPORT */ 8051 { 8052 BCM_IF_ERROR_RETURN(bcm_kt_cosq_port_get(unit, q_array[index], 8053 &temp_port)); 8054 } 8055 #if defined (BCM_SABER2_SUPPORT) 8056 if (SOC_IS_SABER2(unit)) { 8057 if (SOC_PORT_VALID(unit, temp_port)) { 8058 /* coverity[overrun-call : FALSE] */ 8059 _bcm_sb2_ipmc_port_ext_queue_count_decrement(unit, mc_index, 8060 temp_port); 8061 } else { 8062 return BCM_E_PORT; 8063 } 8064 } else 8065 #endif /* BCM_SABER2_SUPPORT */ 8066 { 8067 temp_queue = q_array[index]; 8068 #ifdef BCM_KATANA2_SUPPORT 8069 if (SOC_IS_KATANA2(unit)) { 8070 rv = bcm_kt2_sw_hw_queue(unit, &q_array[index]); 8071 } else 8072 #endif /* BCM_KATANA2_SUPPORT */ 8073 { 8074 rv = bcm_kt_sw_hw_queue(unit, &q_array[index]); 8075 } 8076 if (BCM_FAILURE(rv)) { 8077 q_array[index] = temp_queue; 8078 BCM_IF_ERROR_RETURN(_bcm_kt_hw_to_sw_queue(unit, 8079 &q_array[index], 8080 &temp_port)); 8081 } 8082 if (SOC_PORT_VALID(unit, temp_port)) { 8083 /* coverity[overrun-call : FALSE] */ 8084 _bcm_kt_ipmc_port_ext_queue_count_decrement(unit, mc_index, 8085 temp_port); 8086 } else { 8087 return BCM_E_PORT; 8088 } 8089 } 8090 } 8091 if (temp_port != BCM_GPORT_INVALID) { 8092 /* coverity[overrun-call : FALSE] */ 8093 BCM_IF_ERROR_RETURN(_bcm_esw_ipmc_set_remap_group(unit, mc_index, 8094 temp_port, 0)); 8095 } 8096 } 8097 return BCM_E_NONE; 8098 } 8099 8100 8101 STATIC int 8102 _bcm_esw_multicast_egress_subscriber_delete_all(int unit, 8103 bcm_multicast_t group) 8104 { 8105 int mc_index; 8106 bcm_gport_t *port_array; 8107 bcm_if_t *encap_array; 8108 int *q_array; 8109 int if_max = BCM_MULTICAST_PORT_MAX; 8110 int remap_index; 8111 bcm_error_t rv = BCM_E_NONE; 8112 int port_count = 0; 8113 /*get multicast index for multicast group */ 8114 mc_index = _BCM_MULTICAST_ID_GET(group); 8115 if ((mc_index < 0) || 8116 (mc_index >= soc_mem_index_count(unit, L3_IPMCm))) { 8117 return BCM_E_UNAVAIL; 8118 } 8119 8120 /*get the port_array, encap array and q_array */ 8121 port_array = sal_alloc(if_max * sizeof(bcm_gport_t), 8122 "mcast port array"); 8123 if (port_array == NULL) { 8124 return BCM_E_MEMORY; 8125 } 8126 encap_array = sal_alloc(if_max * sizeof(bcm_if_t), 8127 "mcast encap array"); 8128 if (encap_array == NULL) { 8129 sal_free (port_array); 8130 return BCM_E_MEMORY; 8131 } 8132 q_array = sal_alloc(if_max * sizeof(bcm_if_t), 8133 "mcast q array"); 8134 if (q_array == NULL) { 8135 sal_free (port_array); 8136 sal_free (encap_array); 8137 return BCM_E_MEMORY; 8138 } 8139 sal_memset(q_array, 0, (if_max * sizeof(bcm_if_t))); 8140 8141 /*get the encap array and port array associated with the group*/ 8142 rv = _bcm_esw_ipmc_mmu_mc_remap_ptr(unit, mc_index, &remap_index, FALSE); 8143 if (BCM_FAILURE(rv)) { 8144 goto failure; 8145 } 8146 8147 rv = (_bcm_esw_ipmc_subscriber_egress_intf_get(unit, remap_index, (if_max -1), 8148 port_array, encap_array, 8149 q_array, &port_count)); 8150 8151 if (BCM_FAILURE(rv)) { 8152 goto failure; 8153 } 8154 8155 if (port_count) { 8156 rv = _bcm_esw_ipmc_subscriber_egress_intf_delete_all (unit, 8157 remap_index,port_array, 8158 encap_array, q_array, port_count, mc_index); 8159 } 8160 failure: 8161 sal_free (port_array); 8162 sal_free (encap_array); 8163 sal_free (q_array); 8164 return rv; 8165 } 8166 #endif 8167 8168 8169 /* 8170 * Function: 8171 * _bcm_esw_multicast_egress_subscriber_delete 8172 * Purpose: 8173 * Delete a GPORT from the replication list 8174 * for the specified multicast index. 8175 * Parameters: 8176 * unit - (IN) Device Number 8177 * group - (IN) Multicast group ID 8178 * port - (IN) GPORT Identifier 8179 * encap_id - (IN) Encap ID. 8180 * subscriber_queue - (IN) Subscriber gport 8181 * Returns: 8182 * BCM_E_XXX 8183 */ 8184 8185 STATIC int 8186 _bcm_esw_multicast_egress_subscriber_delete(int unit, bcm_multicast_t group, 8187 bcm_gport_t port, 8188 bcm_if_t encap_id, 8189 bcm_gport_t subscriber_queue) 8190 { 8191 int mc_index, is_l3, gport_id; 8192 bcm_module_t mod_out; 8193 bcm_port_t port_out; 8194 bcm_trunk_t trunk_id; 8195 int modid_local, rv = BCM_E_NONE; 8196 bcm_pbmp_t l2_pbmp, l3_pbmp, old_pbmp; 8197 int remap_index; 8198 int q_count = 0; 8199 int q_count_decreased = 0; 8200 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 8201 int is_local_subport = FALSE; 8202 #endif 8203 #if defined(BCM_KATANA2_SUPPORT) 8204 int pp_port; 8205 #endif 8206 8207 is_l3 = 0; 8208 modid_local = FALSE; 8209 8210 mc_index = _BCM_MULTICAST_ID_GET(group); 8211 8212 if ((mc_index < 0) || 8213 (mc_index >= soc_mem_index_count(unit, L3_IPMCm))) { 8214 return BCM_E_PARAM; 8215 } 8216 8217 #if defined (INCLUDE_L3) 8218 BCM_IF_ERROR_RETURN(_bcm_esw_multicast_l3_group_check(unit, group, &is_l3)); 8219 #endif /* INCLUDE_L3 */ 8220 BCM_IF_ERROR_RETURN 8221 (_bcm_esw_gport_resolve(unit, port, &mod_out, &port_out, 8222 &trunk_id, &gport_id)); 8223 8224 8225 #if defined(BCM_HGPROXY_COE_SUPPORT) 8226 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 8227 BCM_GPORT_IS_SET(port) && 8228 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 8229 8230 if(_bcm_xgs5_subport_coe_gport_local(unit, port)) { 8231 is_local_subport = TRUE; 8232 BCM_IF_ERROR_RETURN( 8233 _bcmi_coe_subport_physical_port_get(unit, 8234 port, 8235 &port_out)); 8236 } else { 8237 return BCM_E_PORT; 8238 } 8239 8240 } else 8241 #endif 8242 8243 #if defined(BCM_KATANA2_SUPPORT) 8244 if (soc_feature(unit, soc_feature_linkphy_coe) || 8245 soc_feature(unit, soc_feature_subtag_coe)) { 8246 if (BCM_GPORT_IS_SET(port) && 8247 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port)) { 8248 if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_out) == BCM_E_NONE) { 8249 pp_port = BCM_GPORT_SUBPORT_PORT_GET(port); 8250 if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, pp_port)) { 8251 is_local_subport = TRUE; 8252 port_out = pp_port; 8253 } 8254 } 8255 if (is_local_subport == FALSE) { 8256 return BCM_E_PORT; 8257 } 8258 } 8259 } 8260 #endif 8261 8262 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT) 8263 if (is_local_subport) { 8264 /* Local subport assigned above */ 8265 } else 8266 #endif 8267 8268 if (BCM_TRUNK_INVALID != trunk_id) { 8269 return BCM_E_PARAM; 8270 } else { 8271 BCM_IF_ERROR_RETURN 8272 (_bcm_esw_modid_is_local(unit, mod_out, &modid_local)); 8273 8274 if ((!IS_E_PORT(unit, port_out)) && (BCM_IF_INVALID != encap_id)) { 8275 /* Stack ports should not perform interface replication */ 8276 return BCM_E_PORT; 8277 } 8278 if (TRUE != modid_local) { 8279 /* Only add this to replication set if destination is local */ 8280 return BCM_E_PORT; 8281 } 8282 /* Convert system port to physical port */ 8283 if (soc_feature(unit, soc_feature_sysport_remap)) { 8284 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 8285 } 8286 } 8287 8288 if (encap_id == BCM_IF_INVALID) { 8289 /* Remove L2 port */ 8290 if (_BCM_MULTICAST_IS_VPLS(group)) { 8291 return BCM_E_PARAM; 8292 } 8293 8294 soc_mem_lock(unit, L3_IPMCm); 8295 /* Delete the port from the IPMC L2_BITMAP */ 8296 rv = _bcm_esw_multicast_ipmc_read(unit, mc_index, 8297 &l2_pbmp, &l3_pbmp); 8298 if (BCM_SUCCESS(rv)) { 8299 BCM_PBMP_ASSIGN(old_pbmp, l2_pbmp); 8300 8301 BCM_PBMP_PORT_REMOVE(l2_pbmp, port_out); 8302 8303 if (BCM_PBMP_NEQ(old_pbmp, l2_pbmp)) { 8304 rv = _bcm_esw_multicast_ipmc_write(unit, mc_index, 8305 l2_pbmp, l3_pbmp, TRUE); 8306 } else { 8307 rv = BCM_E_NOT_FOUND; 8308 } 8309 } 8310 soc_mem_unlock(unit, L3_IPMCm); 8311 return rv; 8312 } 8313 8314 BCM_IF_ERROR_RETURN 8315 (_bcm_esw_ipmc_mmu_mc_remap_ptr(unit, mc_index, &remap_index, FALSE)); 8316 if (!SOC_PORT_VALID(unit, port_out)) { 8317 return BCM_E_PORT; 8318 } 8319 rv = _bcm_esw_ipmc_subscriber_egress_intf_delete(unit, 8320 remap_index, port_out, encap_id, subscriber_queue, 8321 is_l3, &q_count, &q_count_decreased); 8322 if (BCM_SUCCESS(rv)) { 8323 #if defined(INCLUDE_L3) 8324 if (q_count_decreased) { 8325 #if defined(BCM_SABER2_SUPPORT) 8326 if (SOC_IS_SABER2(unit)) { 8327 /* coverity[overrun-call : FALSE] */ 8328 _bcm_sb2_ipmc_port_ext_queue_count_decrement(unit, 8329 mc_index, port_out); 8330 } else 8331 #endif 8332 { 8333 /* coverity[overrun-call : FALSE] */ 8334 _bcm_kt_ipmc_port_ext_queue_count_decrement(unit, mc_index, 8335 port_out); 8336 } 8337 } 8338 #endif 8339 /* coverity[overrun-call : FALSE] */ 8340 BCM_IF_ERROR_RETURN(_bcm_esw_ipmc_set_remap_group(unit, mc_index, 8341 port_out, q_count)); 8342 } 8343 8344 return rv; 8345 } 8346 8347 #endif /* BCM_KATANA_SUPPORT */ 8348 8349 /* 8350 * Function: 8351 * bcm_esw_multicast_egress_subscriber_add 8352 * Purpose: 8353 * Add a GPORT to the replication list 8354 * for the specified multicast index. 8355 * Parameters: 8356 * unit - (IN) Device Number 8357 * group - (IN) Multicast group ID 8358 * port - (IN) GPORT Identifier 8359 * encap_id - (IN) Encap ID. 8360 * subscriber_queue - (IN) Subscriber gport 8361 * Returns: 8362 * BCM_E_XXX 8363 */ 8364 int 8365 bcm_esw_multicast_egress_subscriber_add(int unit, bcm_multicast_t group, 8366 bcm_gport_t port, 8367 bcm_if_t encap_id, 8368 bcm_gport_t subscriber_queue) 8369 { 8370 MULTICAST_INIT_CHECK(unit); 8371 8372 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_L3) 8373 if (SOC_IS_KATANAX(unit)) { 8374 return _bcm_esw_multicast_egress_subscriber_add(unit, group, port, 8375 encap_id, subscriber_queue); 8376 } 8377 #endif /* BCM_KATANA_SUPPORT && INCLUDE_L3 */ 8378 return BCM_E_UNAVAIL; 8379 } 8380 8381 /* 8382 * Function: 8383 * bcm_esw_multicast_egress_subscriber_delete 8384 * Purpose: 8385 * Delete a GPORT from the replication list 8386 * for the specified multicast index. 8387 * Parameters: 8388 * unit - (IN) Device Number 8389 * group - (IN) Multicast group ID 8390 * port - (IN) GPORT Identifier 8391 * encap_id - (IN) Encap ID. 8392 * subscriber_queue - (IN) Subscriber gport 8393 * Returns: 8394 * BCM_E_XXX 8395 */ 8396 int 8397 bcm_esw_multicast_egress_subscriber_delete(int unit, bcm_multicast_t group, 8398 bcm_gport_t port, 8399 bcm_if_t encap_id, 8400 bcm_gport_t subscriber_queue) 8401 { 8402 MULTICAST_INIT_CHECK(unit); 8403 8404 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_L3) 8405 if (SOC_IS_KATANAX(unit)) { 8406 return _bcm_esw_multicast_egress_subscriber_delete(unit, group, port, 8407 encap_id, subscriber_queue); 8408 } 8409 #endif /* BCM_KATANA_SUPPORT && INCLUDE_L3 */ 8410 return BCM_E_UNAVAIL; 8411 } 8412 8413 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_L3) 8414 8415 int 8416 _bcm_esw_multicast_egress_subscriber_set_update(int unit, bcm_multicast_t group, 8417 int port_count, bcm_gport_t *port_array, bcm_if_t *encap_id_array, 8418 bcm_gport_t *subscriber_queue_array) 8419 8420 { 8421 bcm_gport_t *cur_port_array, *new_port_array; 8422 bcm_if_t *cur_encap_array, *new_encap_array; 8423 bcm_gport_t *cur_q_array, *new_q_array; 8424 int if_max = BCM_MULTICAST_PORT_MAX; 8425 bcm_error_t rv = BCM_E_NONE; 8426 int if_index, if_cur_index, cur_port_count = 0, new_port_count = 0; 8427 8428 /*Allocate memory for current and new port_array, encap array and q_array */ 8429 cur_port_array = sal_alloc(if_max * sizeof(bcm_gport_t), 8430 "current mcast port array"); 8431 if (cur_port_array == NULL) { 8432 return BCM_E_MEMORY; 8433 } 8434 cur_encap_array = sal_alloc(if_max * sizeof(bcm_if_t), 8435 "current mcast encap array"); 8436 if (cur_encap_array == NULL) { 8437 sal_free (cur_port_array); 8438 return BCM_E_MEMORY; 8439 } 8440 cur_q_array = sal_alloc(if_max * sizeof(bcm_gport_t), 8441 "current mcast q array"); 8442 if (cur_q_array == NULL) { 8443 sal_free (cur_port_array); 8444 sal_free (cur_encap_array); 8445 return BCM_E_MEMORY; 8446 } 8447 8448 sal_memset(cur_port_array, 0, (if_max * sizeof(bcm_gport_t))); 8449 sal_memset(cur_encap_array, 0, (if_max * sizeof(bcm_if_t))); 8450 sal_memset(cur_q_array, 0, (if_max * sizeof(bcm_gport_t))); 8451 8452 new_port_array = sal_alloc(port_count * sizeof(bcm_gport_t), 8453 "new mcast port array"); 8454 if (new_port_array == NULL) { 8455 sal_free (cur_port_array); 8456 sal_free (cur_encap_array); 8457 sal_free (cur_q_array); 8458 return BCM_E_MEMORY; 8459 } 8460 new_encap_array = sal_alloc(port_count * sizeof(bcm_if_t), 8461 "new mcast encap array"); 8462 if (new_encap_array == NULL) { 8463 sal_free (cur_port_array); 8464 sal_free (cur_encap_array); 8465 sal_free (cur_q_array); 8466 sal_free (new_port_array); 8467 return BCM_E_MEMORY; 8468 } 8469 new_q_array = sal_alloc(port_count * sizeof(bcm_gport_t), 8470 "new mcast q array"); 8471 if (new_q_array == NULL) { 8472 sal_free (cur_port_array); 8473 sal_free (cur_encap_array); 8474 sal_free (cur_q_array); 8475 sal_free (new_port_array); 8476 sal_free (new_encap_array); 8477 return BCM_E_MEMORY; 8478 } 8479 8480 sal_memset(new_port_array, 0, (port_count * sizeof(bcm_gport_t))); 8481 sal_memset(new_encap_array, 0, (port_count * sizeof(bcm_if_t))); 8482 sal_memset(new_q_array, 0, (port_count * sizeof(bcm_gport_t))); 8483 8484 /* get the port array, encap array, queue array associated with the group */ 8485 rv = _bcm_esw_multicast_egress_subscriber_get(unit, group, (if_max -1), 8486 cur_port_array, 8487 cur_encap_array, cur_q_array, 8488 &cur_port_count); 8489 if (BCM_FAILURE(rv)) { 8490 goto done; 8491 } 8492 8493 for (if_index = 0; if_index < port_count; if_index++) { 8494 for (if_cur_index=0; if_cur_index < cur_port_count; if_cur_index++) { 8495 if ((encap_id_array[if_index] == cur_encap_array[if_cur_index]) && 8496 (subscriber_queue_array[if_index] == 8497 cur_q_array[if_cur_index])) { 8498 /* This replication is already attached to the queue and should 8499 * not be deleted. 8500 */ 8501 cur_encap_array[if_cur_index] = -1; 8502 break; 8503 } 8504 } 8505 8506 if (if_cur_index == cur_port_count) { 8507 /* This is the new replication yet to be attached to the queue */ 8508 new_port_array[new_port_count] = port_array[if_index]; 8509 new_encap_array[new_port_count] = encap_id_array[if_index]; 8510 new_q_array[new_port_count] = subscriber_queue_array[if_index]; 8511 new_port_count++; 8512 } 8513 } 8514 8515 if (new_port_count != 0) { 8516 rv = _bcm_esw_multicast_egress_subscriber_set(unit, group, 8517 new_port_count, new_port_array, new_encap_array, 8518 new_q_array); 8519 if (BCM_FAILURE(rv)) { 8520 goto done; 8521 } 8522 } 8523 8524 for (if_cur_index=0; if_cur_index < cur_port_count; if_cur_index++) { 8525 if (cur_encap_array[if_cur_index] == -1) { 8526 /* Skip deleting the replication entry already attached */ 8527 continue; 8528 } else { 8529 /* Delete the replication which is not present in the input list */ 8530 rv = _bcm_esw_multicast_egress_subscriber_delete(unit, group, 8531 cur_port_array[if_cur_index], 8532 cur_encap_array[if_cur_index], cur_q_array[if_cur_index]); 8533 if (BCM_FAILURE(rv)) { 8534 goto done; 8535 } 8536 } 8537 } 8538 done: 8539 if (cur_port_array) { 8540 sal_free (cur_port_array); 8541 } 8542 if (cur_encap_array) { 8543 sal_free (cur_encap_array); 8544 } 8545 if (cur_q_array) { 8546 sal_free (cur_q_array); 8547 } 8548 if (new_port_array) { 8549 sal_free (new_port_array); 8550 } 8551 if (new_encap_array) { 8552 sal_free (new_encap_array); 8553 } 8554 if (new_q_array) { 8555 sal_free (new_q_array); 8556 } 8557 return rv; 8558 } 8559 8560 #endif 8561 8562 /* 8563 * Function: 8564 * bcm_esw_multicast_egress_subscriber_set 8565 * Purpose: 8566 * Assign the complete set of egress GPORTs in the 8567 * replication list for the specified multicast index. 8568 * Parameters: 8569 * unit - (IN) Device Number 8570 * group - (IN) Multicast group ID 8571 * port_count - (IN) Number of ports in replication list 8572 * port_array - (IN) List of GPORT Identifiers 8573 * encap_id_array - (IN) List of encap identifiers 8574 * subscriber_queue_array - (IN) Subscriber array 8575 * Returns: 8576 * BCM_E_XXX 8577 */ 8578 int 8579 bcm_esw_multicast_egress_subscriber_set(int unit, bcm_multicast_t group, 8580 int port_count, bcm_gport_t *port_array, 8581 bcm_if_t *encap_id_array, 8582 bcm_gport_t *subscriber_queue_array) 8583 { 8584 bcm_error_t rv = BCM_E_UNAVAIL; 8585 MULTICAST_INIT_CHECK(unit); 8586 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_L3) 8587 if (SOC_IS_KATANAX(unit)) { 8588 if (port_count == 0) { 8589 BCM_IF_ERROR_RETURN(_bcm_esw_multicast_egress_subscriber_delete_all 8590 (unit, group)); 8591 8592 /* If port_count is 0, then there is nothing to set and we can 8593 * return BCM_E_NONE since all replications were already deleted 8594 * using _bcm_esw_multicast_egress_subscriber_delete_all. 8595 */ 8596 return BCM_E_NONE; 8597 } 8598 rv = _bcm_esw_multicast_egress_subscriber_set_update(unit, group, 8599 port_count, port_array, encap_id_array, 8600 subscriber_queue_array); 8601 } 8602 #endif /* BCM_KATANA_SUPPORT && INCLUDE_L3 */ 8603 return rv; 8604 } 8605 8606 /* 8607 * Function: 8608 * bcm_esw_multicast_egress_subscriber_get 8609 * Purpose: 8610 * Get the complete set of egress GPORTs in the 8611 * replication list for the specified multicast index. 8612 * Parameters: 8613 * unit - (IN) Device Number 8614 * group - (IN) Multicast group ID 8615 * port_count - (IN) Number of ports in replication list 8616 * port_array - (OUT) List of GPORT Identifiers 8617 * encap_id_array - (OUT) List of encap identifiers 8618 * subscriber_queue_array - (OUT) Subscriber array 8619 * Returns: 8620 * BCM_E_XXX 8621 */ 8622 int 8623 bcm_esw_multicast_egress_subscriber_get(int unit, bcm_multicast_t group, 8624 int port_max, 8625 bcm_gport_t *port_array, 8626 bcm_if_t *encap_id_array, 8627 bcm_gport_t *subscriber_queue_array, 8628 int *port_count) 8629 { 8630 MULTICAST_INIT_CHECK(unit); 8631 8632 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_L3) 8633 if (SOC_IS_KATANAX(unit)) { 8634 return _bcm_esw_multicast_egress_subscriber_get(unit, group, 8635 port_max, port_array, 8636 encap_id_array, 8637 subscriber_queue_array, 8638 port_count); 8639 } 8640 #endif /* BCM_KATANA_SUPPORT && INCLUDE_L3 */ 8641 return BCM_E_UNAVAIL; 8642 } 8643 8644 /* 8645 * Function: 8646 * bcm_esw_multicast_egress_subscriber_qos_map_set 8647 * Purpose: 8648 * Assign the complete set of egress GPORTs in the 8649 * replication list for the specified multicast index. 8650 * Parameters: 8651 * unit - (IN) Device Number 8652 * group - (IN) Multicast group ID 8653 * port - (IN) GPORT Identifier 8654 * subscriber queue - (IN) Subscriber queue group GPORT Identifiers 8655 * qos_map_id - (IN) Qos Map ID 8656 * Returns: 8657 * BCM_E_XXX 8658 */ 8659 int 8660 bcm_esw_multicast_egress_subscriber_qos_map_set(int unit, 8661 bcm_multicast_t group, 8662 bcm_gport_t port, 8663 bcm_gport_t subscriber_queue, 8664 int qos_map_id) 8665 { 8666 MULTICAST_INIT_CHECK(unit); 8667 8668 #if defined(BCM_KATANA2_SUPPORT) && defined(INCLUDE_L3) 8669 if (SOC_IS_KATANA2(unit)) { 8670 return _bcm_esw_multicast_egress_subscriber_qos_map_set(unit, 8671 group, port, 8672 subscriber_queue, 8673 qos_map_id); 8674 } 8675 #endif /* BCM_KATANA_SUPPORT && INCLUDE_L3 */ 8676 return BCM_E_UNAVAIL; 8677 8678 } 8679 8680 /* 8681 * Function: 8682 * bcm_esw_multicast_egress_subscriber_qos_map_get 8683 * Purpose: 8684 * Get QOS Map ID associated with 8685 * multicast subscriber queue replication list. 8686 * Parameters: 8687 * unit - (IN) Device Number 8688 * group - (IN) Multicast group ID 8689 * port - (IN) GPORT Identifier 8690 * subscriber queue - (IN) Subscriber queue group GPORT Identifiers 8691 * qos_map_id - (OUT) Qos Map ID 8692 * Returns: 8693 * BCM_E_XXX 8694 */ 8695 int 8696 bcm_esw_multicast_egress_subscriber_qos_map_get(int unit, 8697 bcm_multicast_t group, 8698 bcm_gport_t port, 8699 bcm_gport_t subscriber_queue, 8700 int *qos_map_id) 8701 { 8702 MULTICAST_INIT_CHECK(unit); 8703 8704 #if defined(BCM_KATANA2_SUPPORT) && defined(INCLUDE_L3) 8705 if (SOC_IS_KATANA2(unit)) { 8706 return _bcm_esw_multicast_egress_subscriber_qos_map_get(unit, group, 8707 port, 8708 subscriber_queue, 8709 qos_map_id); 8710 } 8711 #endif /* BCM_KATANA_SUPPORT && INCLUDE_L3 */ 8712 return BCM_E_UNAVAIL; 8713 } 8714 8715 /* 8716 * Function: 8717 * bcm_esw_multicast_multi_alloc 8718 * Purpose: 8719 * Allocates multiple multicast groups consecutively. 8720 * Parameters: 8721 * unit - (IN) Device Number 8722 * mc_multi_info - (IN) informtaion to create multicast mc groups. 8723 * base_mc_group - (IN/OUT) base group id for allocated multiple groups. 8724 * Returns: 8725 * BCM_E_XXX 8726 */ 8727 int 8728 bcm_esw_multicast_multi_alloc( int unit, 8729 bcm_multicast_multi_info_t mc_multi_info, 8730 bcm_multicast_t *base_mc_group) 8731 { 8732 int rv = BCM_E_UNAVAIL; 8733 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 8734 MULTICAST_INIT_CHECK(unit); 8735 rv = bcmi_esw_multicast_multi_alloc(unit, mc_multi_info, base_mc_group); 8736 #endif 8737 return rv; 8738 } 8739 8740 /* 8741 * Function: 8742 * bcm_esw_multicast_multi_free 8743 * Purpose: 8744 * Frees multiple multicast groups. 8745 * Parameters: 8746 * unit - (IN) Device Number 8747 * base_mc_group - (IN) base group id for multiple groups. 8748 * Returns: 8749 * BCM_E_XXX 8750 */ 8751 int 8752 bcm_esw_multicast_multi_free(int unit, bcm_multicast_t base_mc_group) 8753 { 8754 int rv = BCM_E_UNAVAIL; 8755 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 8756 MULTICAST_INIT_CHECK(unit); 8757 rv = bcmi_esw_multicast_multi_free(unit, base_mc_group); 8758 #endif 8759 return rv; 8760 8761 } 8762 8763 8764 8765 #ifndef BCM_SW_STATE_DUMP_DISABLE 8766 /* 8767 * Function: 8768 * _bcm_esw_multicast_sw_dump_cb 8769 * Purpose: 8770 * Callback to print Multicast info 8771 * Parameters: 8772 * unit - (IN) Device Number 8773 * group - (IN) Group ID 8774 * flags - (OUT) BCM_MULTICAST_* 8775 * user_data - (IN) User data to be passed to callback function. 8776 * Returns: 8777 * BCM_E_XXX 8778 */ 8779 STATIC int 8780 _bcm_esw_multicast_sw_dump_cb(int unit, bcm_multicast_t group, 8781 uint32 flags, void *user_data) 8782 { 8783 LOG_CLI((BSL_META_U(unit, 8784 " 0x%08x 0x%08x "), group, flags)); 8785 if (flags & BCM_MULTICAST_TYPE_L2) { 8786 LOG_CLI((BSL_META_U(unit, 8787 " L2"))); 8788 } 8789 if (flags & BCM_MULTICAST_TYPE_L3) { 8790 LOG_CLI((BSL_META_U(unit, 8791 " L3"))); 8792 } 8793 if (flags & BCM_MULTICAST_TYPE_VPLS) { 8794 LOG_CLI((BSL_META_U(unit, 8795 " VPLS"))); 8796 } 8797 if (flags & BCM_MULTICAST_TYPE_SUBPORT) { 8798 LOG_CLI((BSL_META_U(unit, 8799 " SUBPORT"))); 8800 } 8801 if (flags & BCM_MULTICAST_TYPE_MIM) { 8802 LOG_CLI((BSL_META_U(unit, 8803 " MIM"))); 8804 } 8805 if (flags & BCM_MULTICAST_TYPE_WLAN) { 8806 LOG_CLI((BSL_META_U(unit, 8807 " WLAN"))); 8808 } 8809 if (flags & BCM_MULTICAST_TYPE_VLAN) { 8810 LOG_CLI((BSL_META_U(unit, 8811 " VLAN"))); 8812 } 8813 if (flags & BCM_MULTICAST_TYPE_TRILL) { 8814 LOG_CLI((BSL_META_U(unit, 8815 " TRILL"))); 8816 } 8817 if (flags & BCM_MULTICAST_TYPE_NIV) { 8818 LOG_CLI((BSL_META_U(unit, 8819 " NIV"))); 8820 } 8821 if (flags & BCM_MULTICAST_TYPE_EGRESS_OBJECT) { 8822 LOG_CLI((BSL_META_U(unit, 8823 " MPLS P2MP"))); 8824 } 8825 if (flags & BCM_MULTICAST_TYPE_L2GRE) { 8826 LOG_CLI((BSL_META_U(unit, 8827 " L2GRE"))); 8828 } 8829 if (flags & BCM_MULTICAST_TYPE_VXLAN) { 8830 LOG_CLI((BSL_META_U(unit, 8831 " VXLAN"))); 8832 } 8833 if (flags & BCM_MULTICAST_TYPE_EXTENDER) { 8834 LOG_CLI((BSL_META_U(unit, 8835 " EXTENDER"))); 8836 } 8837 if (flags & BCM_MULTICAST_WITH_ID) { 8838 LOG_CLI((BSL_META_U(unit, 8839 " ID"))); 8840 } 8841 LOG_CLI((BSL_META_U(unit, 8842 "\n"))); 8843 return BCM_E_NONE; 8844 } 8845 8846 /* 8847 * Function: 8848 * _bcm_multicast_sw_dump 8849 * Purpose: 8850 * Displays Multicast information maintained by software. 8851 * Parameters: 8852 * unit - Device unit number 8853 * Returns: 8854 * None 8855 * Note: 8856 * The multicast info is really handled by other modules, but 8857 * this is a handy summary of the information. 8858 * Dump of l2_data is skipped. 8859 */ 8860 void 8861 _bcm_multicast_sw_dump(int unit) 8862 { 8863 int rv; 8864 8865 LOG_CLI((BSL_META_U(unit, 8866 "\nSW Information Multicast - Unit %d\n"), unit)); 8867 LOG_CLI((BSL_META_U(unit, 8868 " Initialized: %d\n"), multicast_initialized[unit])); 8869 LOG_CLI((BSL_META_U(unit, 8870 " Groups: Flag value: Flags:\n"))); 8871 8872 rv = bcm_esw_multicast_group_traverse(unit, 8873 &_bcm_esw_multicast_sw_dump_cb, 8874 BCM_MULTICAST_TYPE_MASK, NULL); 8875 8876 if (BCM_FAILURE(rv)) { 8877 LOG_CLI((BSL_META_U(unit, 8878 "\n *** Multicast traverse error ***: %s\n"), 8879 bcm_errmsg(rv))); 8880 } 8881 8882 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_SCORPION_SUPPORT) 8883 #if defined(INCLUDE_L3) 8884 if (SOC_REG_IS_VALID(unit, IPMC_L3_MTUr) && (NULL != _bcm_mtu_profile)) { 8885 int i, num_entries, ref_count; 8886 uint64 rval64, *rval64s[1]; 8887 8888 rval64s[0] = &rval64; 8889 num_entries = SOC_REG_NUMELS(unit, IPMC_L3_MTUr); 8890 LOG_CLI((BSL_META_U(unit, 8891 " IPMC_L3_MTU\n"))); 8892 LOG_CLI((BSL_META_U(unit, 8893 " Number of entries: %d\n"), num_entries)); 8894 LOG_CLI((BSL_META_U(unit, 8895 " Index RefCount - IPMC_L3_MTU\n"))); 8896 8897 for (i = 0; i < num_entries; i++) { 8898 rv = soc_profile_reg_ref_count_get(unit, 8899 _bcm_mtu_profile[unit], 8900 i, &ref_count); 8901 if (SOC_FAILURE(rv)) { 8902 LOG_CLI((BSL_META_U(unit, 8903 " *** Error retrieving profile reference: %d ***\n"), 8904 rv)); 8905 break; 8906 } 8907 if (ref_count <= 0) { 8908 continue; 8909 } 8910 rv = soc_profile_reg_get(unit, _bcm_mtu_profile[unit], i, 8911 1, rval64s); 8912 if (SOC_FAILURE(rv)) { 8913 LOG_CLI((BSL_META_U(unit, 8914 " *** Error retrieving profile value: %d ***\n"), 8915 rv)); 8916 break; 8917 } 8918 LOG_CLI((BSL_META_U(unit, 8919 " %5d %8d 0x%08x\n"), 8920 i, ref_count, COMPILER_64_LO(rval64))); 8921 } 8922 LOG_CLI((BSL_META_U(unit, 8923 "\n"))); 8924 } 8925 #endif /* INCLUDE_L3 */ 8926 #endif 8927 8928 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 8929 if (soc_feature(unit, soc_feature_virtual_port_routing)) { 8930 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 8931 bcm_td2_multicast_l3_vp_sw_dump(unit); 8932 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */ 8933 } 8934 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 8935 8936 return; 8937 } 8938 int 8939 _bcm_fabric_multicast_ipmc_group_types_dump(int unit) 8940 { 8941 #ifdef BCM_XGS3_FABRIC_SUPPORT 8942 int search_index, index_min, index_max,ipmc_id; 8943 if (SOC_IS_XGS3_FABRIC(unit)) { 8944 8945 index_min = BCM_FABRIC_IPMC_BASE(unit); 8946 index_max = BCM_FABRIC_IPMC_MAX(unit); 8947 8948 for (search_index = index_min; search_index <= index_max; 8949 search_index++) { 8950 8951 ipmc_id = search_index - index_min; 8952 8953 /* If that mc index exists */ 8954 if (SHR_BITGET(BCM_FABRIC_MC_USED_BITMAP(unit), 8955 search_index)) { 8956 LOG_CLI((BSL_META_U(unit, "Unit %d IPMC ID %d Group type %d\r\n"), 8957 unit, ipmc_id, 8958 _fabric_multicast_ipmc_group_types[unit][ipmc_id])); 8959 } 8960 } 8961 }else { 8962 return BCM_E_PARAM; 8963 } 8964 #endif 8965 return BCM_E_NONE; 8966 } 8967 #endif /* BCM_SW_STATE_DUMP_DISABLE */