mcast.c (29907B)
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 * Multicast Table Management 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <sal/core/libc.h> 13 #include <soc/drv.h> 14 #include <soc/feature.h> 15 #include <soc/mem.h> 16 #if defined(BCM_BRADLEY_SUPPORT) 17 #include <soc/bradley.h> 18 #endif /* BCM_BRADLEY_SUPPORT */ 19 20 #include <bcm/error.h> 21 #include <bcm/mcast.h> 22 23 #include <bcm_int/esw/mbcm.h> 24 #include <bcm_int/esw/mcast.h> 25 #include <bcm_int/esw/firebolt.h> 26 #include <bcm_int/common/multicast.h> 27 #if defined(BCM_WARM_BOOT_SUPPORT) && defined(INCLUDE_L3) 28 #include <bcm_int/esw/ipmc.h> 29 #endif /* BCM_WARM_BOOT_SUPPORT && INCLUDE_L3 */ 30 31 #include <bcm_int/esw_dispatch.h> 32 33 #define MCAST_INIT_RETURN(unit) \ 34 if (!_bcm_mcast_init[unit]) {return BCM_E_INIT;} 35 36 static int _bcm_mcast_init[BCM_MAX_NUM_UNITS]; 37 static int _bcm_mcast_idx_ret_type[BCM_MAX_NUM_UNITS]; 38 39 /* 40 * Function: 41 * _bcm_esw_mcast_detach 42 * Purpose: 43 * De-initialize multicast bcm routines. 44 * Parameters: 45 * unit - (IN) BCM device number. 46 * Returns: 47 * BCM_E_XXX 48 */ 49 50 int 51 _bcm_esw_mcast_detach(int unit) 52 { 53 int rv; 54 55 rv = mbcm_driver[unit]->mbcm_mcast_detach(unit); 56 if (BCM_FAILURE(rv)) { 57 return rv; 58 } 59 60 _bcm_mcast_init[unit] = FALSE; 61 62 return rv; 63 } 64 65 /* 66 * Function: 67 * bcm_esw_mcast_init 68 * Purpose: 69 * Initialize multicast bcm routines. 70 * Parameters: 71 * unit - StrataSwitch unit # 72 * Returns: 73 * Mcast table size for XGS, or BCM_E_NONE for Strata 74 * BCM_E_INTERNAL if table write failed. 75 */ 76 77 int 78 bcm_esw_mcast_init(int unit) 79 { 80 int rv; 81 82 LOG_INFO(BSL_LS_BCM_MCAST, 83 (BSL_META_U(unit, 84 "MCAST %d: Init\n"), 85 unit)); 86 if (SOC_IS_SHADOW(unit)) { 87 return BCM_E_UNAVAIL; 88 } 89 90 rv = mbcm_driver[unit]->mbcm_mcast_init(unit); 91 if (rv < 0) { 92 return rv; 93 } 94 95 _bcm_mcast_init[unit] = TRUE; 96 _bcm_mcast_idx_ret_type[unit] = 0; 97 98 #if defined(BCM_WARM_BOOT_SUPPORT) && defined(INCLUDE_L3) 99 if (SOC_WARM_BOOT(unit) && soc_feature(unit, soc_feature_l3)) { 100 int rv2; /* Don't change return value holding mcast table size. */ 101 uint8 flags; 102 rv2 = _bcm_esw_ipmc_repl_wb_flags_get(unit, 103 _BCM_IPMC_WB_L2MC_GROUP_TYPE_MULTICAST, &flags); 104 if (BCM_SUCCESS(rv2)) { 105 _bcm_mcast_idx_ret_type[unit] = (0 != flags); 106 } else if (BCM_E_UNAVAIL != rv2) { 107 return rv2; 108 } /* Else ignore unavailable error. */ 109 } 110 #endif /* BCM_WARM_BOOT_SUPPORT && INCLUDE_L3 */ 111 112 return rv; 113 } 114 115 /* 116 * Function: 117 * bcm_esw_mcast_port_add 118 * Purpose: 119 * Add ports to an existing entry in the multicast table 120 * Parameters: 121 * unit - unit number. 122 * mcaddr - Pointer to fully filled-in bcm_mcast_addr_t 123 * Returns: 124 * BCM_E_NONE 125 * BCM_E_INTERNAL if table write failed. 126 */ 127 128 int 129 bcm_esw_mcast_port_add(int unit, bcm_mcast_addr_t *mcaddr) 130 { 131 MCAST_INIT_RETURN(unit); 132 133 LOG_INFO(BSL_LS_BCM_MCAST, 134 (BSL_META_U(unit, 135 "MCAST %d: port add %2x:%2x:%2x:%2x:%2x:%2x, vid %d\n"), 136 unit, mcaddr->mac[0], mcaddr->mac[1], mcaddr->mac[2], 137 mcaddr->mac[3], mcaddr->mac[4], mcaddr->mac[5], 138 mcaddr->vid)); 139 LOG_VERBOSE(BSL_LS_BCM_MCAST, 140 (BSL_META_U(unit, 141 " : l2 idx %u, cos dest %d, ports 0x%x, ut 0x%x\n"), 142 mcaddr->l2mc_index, mcaddr->cos_dst, 143 SOC_PBMP_WORD_GET(mcaddr->pbmp, 0), 144 SOC_PBMP_WORD_GET(mcaddr->ubmp, 0))); 145 146 /* Remove inactive stack ports; all from untagged */ 147 BCM_PBMP_REMOVE(mcaddr->pbmp, SOC_PBMP_STACK_INACTIVE(unit)); 148 BCM_PBMP_REMOVE(mcaddr->ubmp, SOC_PBMP_STACK_CURRENT(unit)); 149 return mbcm_driver[unit]->mbcm_mcast_port_add(unit, mcaddr); 150 } 151 152 /* 153 * Function: 154 * bcm_esw_mcast_port_remove 155 * Purpose: 156 * Remove ports from an existing entry in the multicast table 157 * Parameters: 158 * unit - unit number. 159 * mcaddr - Pointer to fully filled-in bcm_mcast_addr_t 160 * Returns: 161 * BCM_E_NONE 162 * BCM_E_INTERNAL if table write failed. 163 */ 164 165 int 166 bcm_esw_mcast_port_remove(int unit, bcm_mcast_addr_t *mcaddr) 167 { 168 MCAST_INIT_RETURN(unit); 169 170 LOG_INFO(BSL_LS_BCM_MCAST, 171 (BSL_META_U(unit, 172 "MCAST %d: port remove %2x:%2x:%2x:%2x:%2x:%2x, vid %d\n"), 173 unit, mcaddr->mac[0], mcaddr->mac[1], mcaddr->mac[2], 174 mcaddr->mac[3], mcaddr->mac[4], mcaddr->mac[5], 175 mcaddr->vid)); 176 LOG_VERBOSE(BSL_LS_BCM_MCAST, 177 (BSL_META_U(unit, 178 " : l2 idx %u, cos dest %d, ports 0x%x, ut 0x%x\n"), 179 mcaddr->l2mc_index, mcaddr->cos_dst, 180 SOC_PBMP_WORD_GET(mcaddr->pbmp, 0), 181 SOC_PBMP_WORD_GET(mcaddr->ubmp, 0))); 182 183 /* Remove stack ports */ 184 BCM_PBMP_REMOVE(mcaddr->pbmp, SOC_PBMP_STACK_CURRENT(unit)); 185 BCM_PBMP_REMOVE(mcaddr->ubmp, SOC_PBMP_STACK_CURRENT(unit)); 186 return mbcm_driver[unit]->mbcm_mcast_port_remove(unit, mcaddr); 187 } 188 189 /* Add stack ports */ 190 191 STATIC void 192 _esw_mcast_addr_update(int unit, bcm_mcast_addr_t *mcaddr) 193 { 194 bcm_pbmp_t active; 195 196 SOC_PBMP_STACK_ACTIVE_GET(unit, active); 197 BCM_PBMP_OR(mcaddr->pbmp, active); 198 BCM_PBMP_REMOVE(mcaddr->ubmp, SOC_PBMP_STACK_CURRENT(unit)); 199 } 200 201 /* 202 * Function: 203 * _bcm_esw_mcast_convert_mcindex_m2h 204 * Purpose: 205 * Convert a bcm_multicast_t l2mc index to a hardware l2mc index. 206 * Parameters: 207 * mcindex - (IN/OUT) Pointer to a multicast index 208 * Returns: 209 * BCM_E_NONE 210 * BCM_E_PARAM If bcm_multicast_t is not L2 type 211 */ 212 213 STATIC int 214 _bcm_esw_mcast_convert_mcindex_m2h(unsigned int *mcindex) 215 { 216 /* If the input parameter mc_index is a L2 type bcm_multicast_t, 217 * convert it to a hardware l2mc index. 218 */ 219 if (_BCM_MULTICAST_IS_SET(*mcindex)) { 220 if (_BCM_MULTICAST_IS_L2(*mcindex)) { 221 *mcindex = _BCM_MULTICAST_ID_GET(*mcindex); 222 } else { 223 return BCM_E_PARAM; 224 } 225 } 226 227 return BCM_E_NONE; 228 } 229 230 /* 231 * Function: 232 * _bcm_esw_mcast_convert_mcindex_h2m 233 * Purpose: 234 * Convert a hardware l2mc index to a bcm_multicast_t l2mc index. 235 * Parameters: 236 * unit - unit number. 237 * mcindex - (IN/OUT) Pointer to a multicast index 238 * Returns: 239 * None. 240 */ 241 242 STATIC void 243 _bcm_esw_mcast_convert_mcindex_h2m(int unit, unsigned int *mcindex) 244 { 245 if (_bcm_mcast_idx_ret_type[unit]) { 246 /* Convert hardware l2mc index to L2 type bcm_multicast_t */ 247 _BCM_MULTICAST_GROUP_SET(*mcindex, _BCM_MULTICAST_TYPE_L2, *mcindex); 248 } 249 } 250 251 /* 252 * Function: 253 * bcm_esw_mcast_addr_add_w_l2mcindex 254 * Purpose: 255 * Add an entry in the multicast table with l2mc index provided 256 * Parameters: 257 * unit - unit number. 258 * mcaddr - Pointer to fully filled-in bcm_mcast_addr_t 259 * Returns: 260 * BCM_E_NONE 261 * BCM_E_INTERNAL if table write failed. 262 */ 263 264 int 265 bcm_esw_mcast_addr_add_w_l2mcindex(int unit, bcm_mcast_addr_t *mcaddr) 266 { 267 int rv; 268 int orig_mcindex; 269 270 MCAST_INIT_RETURN(unit); 271 272 LOG_INFO(BSL_LS_BCM_MCAST, 273 (BSL_META_U(unit, 274 "MCAST %d: addr add w/ idx. %2x:%2x:%2x:%2x:%2x:%2x, vid %d\n"), 275 unit, mcaddr->mac[0], mcaddr->mac[1], mcaddr->mac[2], 276 mcaddr->mac[3], mcaddr->mac[4], mcaddr->mac[5], 277 mcaddr->vid)); 278 LOG_VERBOSE(BSL_LS_BCM_MCAST, 279 (BSL_META_U(unit, 280 " : l2 idx %u, cos dest %d, ports 0x%x, ut 0x%x\n"), 281 mcaddr->l2mc_index, mcaddr->cos_dst, 282 SOC_PBMP_WORD_GET(mcaddr->pbmp, 0), 283 SOC_PBMP_WORD_GET(mcaddr->ubmp, 0))); 284 _esw_mcast_addr_update(unit, mcaddr); 285 286 orig_mcindex = mcaddr->l2mc_index; 287 BCM_IF_ERROR_RETURN(_bcm_esw_mcast_convert_mcindex_m2h(&mcaddr->l2mc_index)); 288 289 rv = mbcm_driver[unit]->mbcm_mcast_addr_add_w_l2mcindex(unit, mcaddr); 290 291 /* Restore user-specified index */ 292 mcaddr->l2mc_index = orig_mcindex; 293 294 return rv; 295 } 296 297 298 /* 299 * Function: 300 * bcm_esw_mcast_addr_add 301 * Purpose: 302 * Add an entry in the multicast table 303 * Parameters: 304 * unit - StrataSwitch unit number. 305 * mcaddr - Pointer to fully filled-in bcm_mcast_addr_t 306 * Returns: 307 * BCM_E_NONE 308 * BCM_E_INTERNAL if table write failed. 309 */ 310 311 int 312 bcm_esw_mcast_addr_add(int unit, bcm_mcast_addr_t *mcaddr) 313 { 314 MCAST_INIT_RETURN(unit); 315 316 _esw_mcast_addr_update(unit, mcaddr); 317 LOG_INFO(BSL_LS_BCM_MCAST, 318 (BSL_META_U(unit, 319 "MCAST %d: addr add %2x:%2x:%2x:%2x:%2x:%2x, vid %d\n"), 320 unit, mcaddr->mac[0], mcaddr->mac[1], mcaddr->mac[2], 321 mcaddr->mac[3], mcaddr->mac[4], mcaddr->mac[5], 322 mcaddr->vid)); 323 LOG_VERBOSE(BSL_LS_BCM_MCAST, 324 (BSL_META_U(unit, 325 " : l2 idx %u, cos dest %d, ports 0x%x, ut 0x%x\n"), 326 mcaddr->l2mc_index, mcaddr->cos_dst, 327 SOC_PBMP_WORD_GET(mcaddr->pbmp, 0), 328 SOC_PBMP_WORD_GET(mcaddr->ubmp, 0))); 329 330 return mbcm_driver[unit]->mbcm_mcast_addr_add(unit, mcaddr); 331 } 332 333 /* 334 * Function: 335 * bcm_esw_mcast_addr_remove_w_l2mcindex 336 * Purpose: 337 * Delete an entry from the multicast table and provide l2mcindex in 338 * bcm_mcast_addr_t of the deleted entry 339 * Parameters: 340 * unit - unit number. 341 * mcaddr - Pointer to filled-in bcm_mcast_addr_t with mac addr and vid 342 * l2mc_index is provided as output 343 * Returns: 344 * BCM_E_NONE 345 * BCM_E_XXXX 346 */ 347 348 int 349 bcm_esw_mcast_addr_remove_w_l2mcindex(int unit, bcm_mcast_addr_t *mcaddr) 350 { 351 int rv; 352 int orig_mcindex; 353 354 MCAST_INIT_RETURN(unit); 355 356 LOG_INFO(BSL_LS_BCM_MCAST, 357 (BSL_META_U(unit, 358 "MCAST %d: addr rmv w/ idx %d\n"), 359 unit, mcaddr->l2mc_index)); 360 361 orig_mcindex = mcaddr->l2mc_index; 362 BCM_IF_ERROR_RETURN(_bcm_esw_mcast_convert_mcindex_m2h(&mcaddr->l2mc_index)); 363 364 rv = mbcm_driver[unit]->mbcm_mcast_addr_remove_w_l2mcindex(unit, mcaddr); 365 366 /* Restore user-specified index */ 367 mcaddr->l2mc_index = orig_mcindex; 368 369 return rv; 370 } 371 372 /* 373 * Function: 374 * bcm_esw_mcast_addr_remove 375 * Purpose: 376 * Delete an entry from the multicast table 377 * Parameters: 378 * unit - StrataSwitch unit number. 379 * mac - mac address 380 * vid - vlan id 381 * Returns: 382 * BCM_E_NONE 383 * BCM_E_XXXX 384 */ 385 386 int 387 bcm_esw_mcast_addr_remove(int unit, sal_mac_addr_t mac, bcm_vlan_t vid) 388 { 389 MCAST_INIT_RETURN(unit); 390 391 LOG_INFO(BSL_LS_BCM_MCAST, 392 (BSL_META_U(unit, 393 "MCAST %d: addr remove %2x:%2x:%2x:%2x:%2x:%2x, vid %d\n"), 394 unit, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], vid)); 395 396 return mbcm_driver[unit]->mbcm_mcast_addr_remove(unit, mac, vid); 397 } 398 399 /* 400 * Function: 401 * bcm_esw_mcast_port_get 402 * Purpose: 403 * Get membership and untagged port bit maps for a MC group 404 * Parameters: 405 * unit - StrataSwitch unit #. 406 * mac - mac address used for lookup. 407 * vid - vlan id used for lookup. 408 * mcaddr - pointer to bcm_mcast_addr_t that is fully filled in 409 * Returns: 410 * BCM_E_NONE Success (mcaddr filled in) 411 * BCM_E_INTERNAL Chip access failure 412 * BCM_E_NOT_FOUND Address not found (mcaddr not filled in) 413 */ 414 415 int 416 bcm_esw_mcast_port_get(int unit, 417 sal_mac_addr_t mac, bcm_vlan_t vid, 418 bcm_mcast_addr_t *mcaddr) 419 { 420 int rv; 421 422 MCAST_INIT_RETURN(unit); 423 424 rv = mbcm_driver[unit]->mbcm_mcast_port_get(unit, mac, vid, mcaddr); 425 426 _bcm_esw_mcast_convert_mcindex_h2m(unit, &mcaddr->l2mc_index); 427 428 return rv; 429 } 430 431 /* 432 * Function: 433 * bcm_esw_mcast_leave 434 * Purpose: 435 * This function removes the given port from the group membership 436 * of the given mcast mac address. 437 * Parameters: 438 * unit - device number 439 * mac - Multicast MAC Address 440 * vlan - Vlan ID 441 * port - port to be removed from the given multicast address 442 * Returns: 443 * BCM_MCAST_LEAVE_DELETED - If the entry with the given mcast 444 * addr is deleted from H/W table 445 * BCM_MCAST_LEAVE_UPDATED - If the mcast address is found in 446 * the table and bitmap is updated. 447 * BCM_MCAST_LEAVE_NOTFOUND - If the mcast address is not found in 448 * the table 449 * BCM_E_XXX - an error occurred 450 * Notes: 451 * BCM_MCAST_LEAVE_XXX values are non-negative success codes 452 */ 453 454 int 455 bcm_esw_mcast_leave(int unit, bcm_mac_t mac, bcm_vlan_t vlan, bcm_port_t port) 456 { 457 int rv; 458 bcm_mcast_addr_t mcaddr; 459 bcm_mcast_addr_t rtaddr; 460 461 MCAST_INIT_RETURN(unit); 462 463 bcm_mcast_addr_t_init(&mcaddr, mac, vlan); 464 if (BCM_GPORT_IS_SET(port)) { 465 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 466 } 467 468 BCM_PBMP_PORT_SET(mcaddr.pbmp, port); 469 BCM_IF_ERROR_RETURN(bcm_esw_mcast_port_remove(unit, &mcaddr)); 470 BCM_IF_ERROR_RETURN(bcm_esw_mcast_port_get(unit, mac, vlan, &mcaddr)); 471 472 if (SOC_MCAST_ADD_ALL_ROUTER_PORTS(unit)) { 473 rv = bcm_esw_mcast_port_get(unit, (uint8 *)_soc_mac_all_routers, vlan, 474 &rtaddr); 475 if (rv < 0) { 476 bcm_mcast_addr_t_init(&rtaddr, (uint8 *)_soc_mac_all_routers, vlan); 477 } 478 /* Coverity: rtaddr.pbmp is initialized above by bcm_esw_mcast_port_get */ 479 /* coverity[uninit_use : FALSE] */ 480 BCM_PBMP_REMOVE(mcaddr.pbmp, rtaddr.pbmp); 481 } 482 483 484 if (BCM_PBMP_IS_NULL(mcaddr.pbmp)) { 485 BCM_IF_ERROR_RETURN(bcm_esw_mcast_addr_remove(unit, mac, vlan)); 486 return BCM_MCAST_LEAVE_DELETED; 487 } 488 return BCM_MCAST_LEAVE_UPDATED; 489 } 490 491 /* 492 * Function: 493 * bcm_esw_mcast_join 494 * Purpose: 495 * This function adds the given port to the membership of the 496 * given mcast mac address. 497 * Parameters: 498 * unit - device number 499 * mac - Multicast MAC Address 500 * vlan - Vlan ID 501 * port - port to be added to the mulicast address 502 * mcaddr - (OUT) If not NULL, returns the updated mcast_addr_t for 503 * the given multicast address 504 * all_router_pbmp - (OUT) If not NULL, returns the ports associated with 505 * the all routers multicast address 506 * 507 * Returns: 508 * BCM_MCAST_JOIN_ADDED - If a new entry is created for the 509 * given mcast address. 510 * BCM_MCAST_JOIN_UPDATED - If the mcast address is found in 511 * the table and bitmap is updated. 512 * BCM_E_XXX - an error occurred 513 * Notes: 514 * BCM_MCAST_JOIN_XXX values are non-negative success codes 515 */ 516 517 int 518 bcm_esw_mcast_join(int unit, bcm_mac_t mac, bcm_vlan_t vlan, bcm_port_t port, 519 bcm_mcast_addr_t *mcaddr, 520 bcm_pbmp_t *all_router_pbmp) 521 { 522 int rv; 523 bcm_mcast_addr_t newmc; 524 525 MCAST_INIT_RETURN(unit); 526 527 /* 528 * Fill in all_routers port bitmap 529 */ 530 if (all_router_pbmp != NULL) { 531 rv = bcm_esw_mcast_port_get(unit, (uint8 *)_soc_mac_all_routers, vlan, 532 &newmc); 533 if (rv == BCM_E_NOT_FOUND) { 534 BCM_PBMP_CLEAR(*all_router_pbmp); 535 } else if (rv < 0) { 536 return rv; 537 } else { 538 /* Coverity: newmc.pbmp is initialized above by bcm_esw_mcast_port_get */ 539 /* coverity[uninit_use : FALSE] */ 540 BCM_PBMP_ASSIGN(*all_router_pbmp, newmc.pbmp); 541 } 542 } 543 544 /* 545 * Now, join the actual multicast group 546 */ 547 bcm_mcast_addr_t_init(&newmc, mac, vlan); 548 if (BCM_GPORT_IS_SET(port)) { 549 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port)); 550 } 551 552 BCM_PBMP_PORT_SET(newmc.pbmp, port); 553 rv = bcm_esw_mcast_port_add(unit, &newmc); 554 555 if (rv == BCM_E_NOT_FOUND) { 556 BCM_IF_ERROR_RETURN(bcm_esw_mcast_addr_add(unit, &newmc)); 557 rv = BCM_MCAST_JOIN_ADDED; 558 } else if (rv < 0) { 559 return rv; 560 } else { 561 rv = BCM_MCAST_JOIN_UPDATED; 562 } 563 if (mcaddr != NULL) { 564 BCM_IF_ERROR_RETURN(bcm_esw_mcast_port_get(unit, mac, vlan, mcaddr)); 565 } 566 return rv; 567 } 568 569 /* 570 * Function: bcm_mcast_bitmap_max_get 571 * Purpose: provides maximum mcast index that this fabric can handle 572 * Parameters: unit - device 573 * max_index - (OUT) returned number of entries 574 * Returns: BCM_E_* 575 * Note: 576 * Fabric only 577 */ 578 int 579 bcm_esw_mcast_bitmap_max_get(int unit, int *max_index) 580 { 581 #ifdef BCM_XGS12_FABRIC_SUPPORT 582 if (SOC_IS_XGS12_FABRIC(unit)) { 583 *max_index = soc_mem_index_count(unit, MEM_MCm); 584 return BCM_E_NONE; 585 } 586 #endif /* BCM_XGS12_FABRIC_SUPPORT */ 587 588 #ifdef BCM_XGS3_FABRIC_SUPPORT 589 if (SOC_IS_XGS3_FABRIC(unit)) { 590 int mc_base, mc_size; 591 592 SOC_IF_ERROR_RETURN 593 (soc_hbx_mcast_size_get(unit, &mc_base, &mc_size)); 594 *max_index = mc_size; 595 return BCM_E_NONE; 596 } 597 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 598 599 *max_index = 0; 600 return BCM_E_UNAVAIL; 601 } 602 603 /* 604 * Function: 605 * bcm_esw_mcast_bitmap_set 606 * Purpose: 607 * Set the L2 MC forwarding port bitmap 608 * Parameters: 609 * unit - SOC unit # 610 * index - the MC index carried in HiGig header 611 * in_port - ingress port number 612 * pbmp - IPMC forwarding port bitmap 613 * Returns: 614 * BCM_E_XXX 615 * Note: 616 * Fabric only 617 */ 618 int 619 bcm_esw_mcast_bitmap_set(int unit, int index, bcm_port_t in_port, bcm_pbmp_t pbmp) 620 { 621 #ifdef BCM_XGS12_FABRIC_SUPPORT 622 if (SOC_IS_XGS12_FABRIC(unit)) { 623 mem_mc_entry_t entry; 624 int blk, rv; 625 626 if (BCM_GPORT_IS_SET(in_port)) { 627 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, in_port, &in_port)); 628 } 629 if (!SOC_PORT_VALID(unit, in_port)) { 630 return BCM_E_PORT; 631 } 632 if (index < 0 || index > soc_mem_index_max(unit, MEM_MCm)) { 633 return BCM_E_PARAM; 634 } 635 636 /* Make sure packet never goes back */ 637 BCM_PBMP_PORT_REMOVE(pbmp, in_port); 638 639 blk = SOC_PORT_BLOCK(unit, in_port); 640 641 sal_memset(&entry, 0, sizeof(entry)); 642 643 soc_mem_lock(unit, MEM_MCm); 644 rv = READ_MEM_MCm(unit, blk, index, &entry); 645 if (rv >= 0) { 646 soc_MEM_MCm_field32_set(unit, &entry, MCBITMAPf, 647 SOC_PBMP_WORD_GET(pbmp, 0)); 648 rv = WRITE_MEM_MCm(unit, blk, index, &entry); 649 } 650 soc_mem_unlock(unit, MEM_MCm); 651 652 return rv; 653 } 654 #endif /* BCM_XGS12_FABRIC_SUPPORT */ 655 656 #ifdef BCM_XGS3_FABRIC_SUPPORT 657 if (SOC_IS_XGS3_FABRIC(unit)) { 658 int rv, mc_base, mc_size; 659 l2mc_entry_t l2mc; 660 661 COMPILER_REFERENCE(in_port); 662 663 BCM_IF_ERROR_RETURN(_bcm_esw_mcast_convert_mcindex_m2h((unsigned int*)&index)); 664 665 SOC_IF_ERROR_RETURN 666 (soc_hbx_mcast_size_get(unit, &mc_base, &mc_size)); 667 if (index < 0 || index > mc_size) { 668 return BCM_E_PARAM; 669 } 670 index += mc_base; 671 672 soc_mem_lock(unit, L2MCm); 673 rv = READ_L2MCm(unit, MEM_BLOCK_ANY, index, &l2mc); 674 if (rv >= 0) { 675 soc_mem_pbmp_field_set(unit, L2MCm, &l2mc, PORT_BITMAPf, &pbmp); 676 soc_mem_field32_set(unit, L2MCm, &l2mc, VALIDf, 1); 677 rv = WRITE_L2MCm(unit, MEM_BLOCK_ALL, index, &l2mc); 678 } 679 soc_mem_unlock(unit, L2MCm); 680 return rv; 681 } 682 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 683 684 return BCM_E_UNAVAIL; 685 } 686 687 /* 688 * Function: 689 * bcm_esw_mcast_bitmap_get 690 * Purpose: 691 * Get the L2 MC forwarding port bitmap 692 * Parameters: 693 * unit - SOC unit # 694 * index - the L2 MC index carried in HiGig header 695 * in_port - ingress port number 696 * pbmp - IPMC forwarding port bitmap 697 * Returns: 698 * BCM_E_xxxx 699 * Note: 700 * Fabric only 701 */ 702 int 703 bcm_esw_mcast_bitmap_get(int unit, int index, bcm_port_t in_port, 704 bcm_pbmp_t *pbmp) 705 { 706 #ifdef BCM_XGS12_FABRIC_SUPPORT 707 708 if (SOC_IS_XGS12_FABRIC(unit)) { 709 mem_mc_entry_t entry; 710 int blk; 711 uint32 pword; 712 713 if (BCM_GPORT_IS_SET(in_port)) { 714 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, in_port, &in_port)); 715 } 716 if (!SOC_PORT_VALID(unit, in_port)) { 717 return BCM_E_PORT; 718 } 719 if (index < 0 || index > soc_mem_index_max(unit, MEM_MCm)) { 720 return BCM_E_PARAM; 721 } 722 723 blk = SOC_PORT_BLOCK(unit, in_port); 724 SOC_IF_ERROR_RETURN(READ_MEM_MCm(unit, blk, index, &entry)); 725 pword = soc_MEM_MCm_field32_get(unit, &entry, MCBITMAPf); 726 SOC_PBMP_CLEAR(*pbmp); 727 SOC_PBMP_WORD_SET(*pbmp, 0, pword); 728 return BCM_E_NONE; 729 } 730 #endif /* BCM_XGS12_FABRIC_SUPPORT */ 731 732 #ifdef BCM_XGS3_FABRIC_SUPPORT 733 if (SOC_IS_XGS3_FABRIC(unit)) { 734 int mc_base, mc_size; 735 l2mc_entry_t l2mc; 736 737 COMPILER_REFERENCE(in_port); 738 739 BCM_IF_ERROR_RETURN(_bcm_esw_mcast_convert_mcindex_m2h((unsigned int*)&index)); 740 741 SOC_IF_ERROR_RETURN 742 (soc_hbx_mcast_size_get(unit, &mc_base, &mc_size)); 743 if (index < 0 || index > mc_size) { 744 return BCM_E_PARAM; 745 } 746 index += mc_base; 747 748 SOC_IF_ERROR_RETURN(READ_L2MCm(unit, MEM_BLOCK_ANY, index, &l2mc)); 749 soc_mem_pbmp_field_get(unit, L2MCm, &l2mc, PORT_BITMAPf, pbmp); 750 return BCM_E_NONE; 751 } 752 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 753 754 return BCM_E_UNAVAIL; 755 } 756 757 /* 758 * Function: 759 * bcm_esw_mcast_bitmap_del 760 * Purpose: 761 * Remove L2 MC forwarding port bitmap 762 * Parameters: 763 * unit - SOC unit # 764 * index - the L2 MC index carried in HiGig header 765 * in_port - ingress port number 766 * pbmp - IPMC forwarding port bitmap 767 * Returns: 768 * BCM_E_xxxx 769 * Note: 770 * Fabric only 771 */ 772 int 773 bcm_esw_mcast_bitmap_del(int unit, int index, bcm_port_t in_port, bcm_pbmp_t pbmp) 774 { 775 #ifdef BCM_XGS12_FABRIC_SUPPORT 776 if (SOC_IS_XGS12_FABRIC(unit)) { 777 mem_mc_entry_t entry; 778 uint32 pword; 779 int rv, blk; 780 781 if (BCM_GPORT_IS_SET(in_port)) { 782 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, in_port, &in_port)); 783 } 784 if (!SOC_PORT_VALID(unit, in_port)) { 785 return BCM_E_PORT; 786 } 787 if (index < 0 || index > soc_mem_index_max(unit, MEM_MCm)) { 788 return BCM_E_PARAM; 789 } 790 791 blk = SOC_PORT_BLOCK(unit, in_port); 792 793 soc_mem_lock(unit, MEM_MCm); 794 795 rv = READ_MEM_MCm(unit, blk, index, &entry); 796 if (rv >= 0) { 797 pword = soc_MEM_MCm_field32_get(unit, &entry, MCBITMAPf); 798 pword &= ~SOC_PBMP_WORD_GET(pbmp, 0); 799 soc_MEM_MCm_field32_set(unit, &entry, MCBITMAPf, pword); 800 rv = WRITE_MEM_MCm(unit, blk, index, &entry); 801 } 802 803 soc_mem_unlock(unit, MEM_MCm); 804 805 return rv; 806 } 807 #endif /* BCM_XGS12_FABRIC_SUPPORT */ 808 809 #ifdef BCM_XGS3_FABRIC_SUPPORT 810 if (SOC_IS_XGS3_FABRIC(unit)) { 811 int rv, mc_base, mc_size; 812 l2mc_entry_t l2mc; 813 bcm_pbmp_t tmp_pbmp; 814 815 COMPILER_REFERENCE(in_port); 816 817 BCM_IF_ERROR_RETURN(_bcm_esw_mcast_convert_mcindex_m2h((unsigned int*)&index)); 818 819 SOC_IF_ERROR_RETURN 820 (soc_hbx_mcast_size_get(unit, &mc_base, &mc_size)); 821 if (index < 0 || index > mc_size) { 822 return BCM_E_PARAM; 823 } 824 index += mc_base; 825 826 soc_mem_lock(unit, L2MCm); 827 rv = READ_L2MCm(unit, MEM_BLOCK_ANY, index, &l2mc); 828 if (rv >= 0) { 829 soc_mem_pbmp_field_get(unit, L2MCm, &l2mc, PORT_BITMAPf, 830 &tmp_pbmp); 831 SOC_PBMP_REMOVE(tmp_pbmp, pbmp); 832 soc_mem_pbmp_field_set(unit, L2MCm, &l2mc, PORT_BITMAPf, 833 &tmp_pbmp); 834 soc_mem_field32_set(unit, L2MCm, &l2mc, VALIDf, 1); 835 rv = WRITE_L2MCm(unit, MEM_BLOCK_ALL, index, &l2mc); 836 } 837 soc_mem_unlock(unit, L2MCm); 838 return rv; 839 } 840 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 841 842 return BCM_E_UNAVAIL; 843 } 844 845 STATIC int 846 _xgs12_mcast_stk_update(int unit, bcm_pbmp_t add_ports, 847 bcm_pbmp_t remove_ports) 848 { 849 int rv = BCM_E_NONE; /* Ignore if unavailable */ 850 851 #if defined(BCM_XGS12_SWITCH_SUPPORT) 852 int i; 853 bcm_pbmp_t new_ports, old_ports; 854 l2x_mc_entry_t l2mc; 855 int changed = 0; 856 857 soc_mem_lock(unit, L2X_MCm); 858 for (i = soc_mem_index_min(unit, L2X_MCm); 859 i <= soc_mem_index_max(unit, L2X_MCm); 860 i++) { 861 862 rv = soc_mem_read(unit, L2X_MCm, MEM_BLOCK_ANY, i, &l2mc); 863 if (rv < 0) { 864 break; 865 } 866 if (soc_L2X_MCm_field32_get(unit, &l2mc, VALIDf) == 0) { 867 continue; 868 } 869 _bcm_l2mcentry_pbmp_get(unit, &l2mc, &old_ports); 870 BCM_PBMP_ASSIGN(new_ports, old_ports); 871 BCM_PBMP_OR(new_ports, add_ports); 872 BCM_PBMP_REMOVE(new_ports, remove_ports); 873 if (BCM_PBMP_NEQ(new_ports, old_ports)) { 874 ++changed; 875 _bcm_l2mcentry_pbmp_set(unit, &l2mc, new_ports); 876 rv = soc_mem_write(unit, L2X_MCm, MEM_BLOCK_ALL, i, &l2mc); 877 if (rv < 0) { 878 break; 879 } 880 } 881 } 882 soc_mem_unlock(unit, L2X_MCm); 883 884 if (changed) { 885 LOG_VERBOSE(BSL_LS_BCM_MCAST, 886 (BSL_META_U(unit, 887 "L2MC %d: xgs stk update changed %d entries\n"), 888 unit, changed)); 889 } 890 #endif 891 892 return rv; 893 } 894 895 STATIC int 896 _xgs3_fb_mcast_stk_update(int unit, bcm_pbmp_t add_ports, 897 bcm_pbmp_t remove_ports) 898 { 899 int rv = BCM_E_NONE; /* Ignore if unavailable */ 900 901 #if defined(BCM_FIREBOLT_SUPPORT) 902 int i; 903 bcm_pbmp_t new_ports, old_ports; 904 l2mc_entry_t l2mc; 905 int changed = 0; 906 907 soc_mem_lock(unit, L2MCm); 908 for (i = soc_mem_index_min(unit, L2MCm); 909 i <= soc_mem_index_max(unit, L2MCm); 910 i++) { 911 912 rv = soc_mem_read(unit, L2MCm, MEM_BLOCK_ANY, i, &l2mc); 913 if (rv < 0) { 914 break; 915 } 916 if (soc_L2MCm_field32_get(unit, &l2mc, VALIDf) == 0) { 917 continue; 918 } 919 soc_mem_pbmp_field_get(unit, L2MCm, &l2mc, PORT_BITMAPf, &old_ports); 920 BCM_PBMP_ASSIGN(new_ports, old_ports); 921 BCM_PBMP_OR(new_ports, add_ports); 922 BCM_PBMP_REMOVE(new_ports, remove_ports); 923 if (BCM_PBMP_NEQ(new_ports, old_ports)) { 924 ++changed; 925 soc_mem_pbmp_field_set(unit, L2MCm, &l2mc, PORT_BITMAPf, 926 &new_ports); 927 rv = soc_mem_write(unit, L2MCm, MEM_BLOCK_ALL, i, &l2mc); 928 if (rv < 0) { 929 break; 930 } 931 } 932 } 933 soc_mem_unlock(unit, L2MCm); 934 935 if (changed) { 936 LOG_VERBOSE(BSL_LS_BCM_MCAST, 937 (BSL_META_U(unit, 938 "L2MC %d: xgs stk update changed %d entries\n"), 939 unit, changed)); 940 } 941 #endif 942 943 return rv; 944 } 945 946 /* 947 * Function: 948 * _bcm_esw_mcast_stk_update 949 * Purpose: 950 * Update port bitmaps after stack change 951 * Parameters: 952 * 953 * Returns: 954 * BCM_E_XXX 955 * Notes: 956 */ 957 958 959 int 960 _bcm_esw_mcast_stk_update(int unit, uint32 flags) 961 { 962 bcm_pbmp_t add_ports, remove_ports; 963 int rv = BCM_E_NONE; 964 965 /* Calculate ports that should and should not be in bitmap */ 966 SOC_PBMP_ASSIGN(add_ports, SOC_PBMP_STACK_CURRENT(unit)); 967 SOC_PBMP_REMOVE(add_ports, SOC_PBMP_STACK_INACTIVE(unit)); 968 969 /* Remove ports no longer stacking, or explicitly inactive */ 970 SOC_PBMP_ASSIGN(remove_ports, SOC_PBMP_STACK_PREVIOUS(unit)); 971 SOC_PBMP_REMOVE(remove_ports, SOC_PBMP_STACK_CURRENT(unit)); 972 SOC_PBMP_OR(remove_ports, SOC_PBMP_STACK_INACTIVE(unit)); 973 974 if (SOC_IS_XGS12_SWITCH(unit)) { 975 rv = _xgs12_mcast_stk_update(unit, add_ports, remove_ports); 976 } else if (SOC_IS_XGS3_SWITCH(unit)) { 977 rv = _xgs3_fb_mcast_stk_update(unit, add_ports, remove_ports); 978 } else { /* May update fabric in the future, but not needed yet */ 979 rv = BCM_E_NONE; /* Ignore if unavailable */ 980 } 981 982 return rv; 983 } 984 985 #ifdef BCM_WARM_BOOT_SUPPORT 986 int 987 _bcm_mcast_cleanup(int unit) 988 { 989 int rv = BCM_E_NONE; 990 991 #ifdef BCM_XGS3_SWITCH_SUPPORT 992 if (SOC_IS_FB_FX_HX(unit)) { 993 rv = _bcm_xgs3_mcast_detach(unit); 994 } 995 #endif 996 return rv; 997 } 998 #endif /* BCM_WARM_BOOT_SUPPORT */ 999 1000 #ifndef BCM_SW_STATE_DUMP_DISABLE 1001 /* 1002 * Function: 1003 * _bcm_mcast_sw_dump 1004 * Purpose: 1005 * Displays mcast information maintained by software. 1006 * Parameters: 1007 * unit - Device unit number 1008 * Returns: 1009 * None 1010 */ 1011 void 1012 _bcm_mcast_sw_dump(int unit) 1013 { 1014 1015 LOG_CLI((BSL_META_U(unit, 1016 "\nSW Information MCAST - Unit %d\n"), unit)); 1017 LOG_CLI((BSL_META_U(unit, 1018 " Init : %d\n"), _bcm_mcast_init[unit])); 1019 LOG_CLI((BSL_META_U(unit, 1020 " Multicast Index Return Type : %d\n"), _bcm_mcast_idx_ret_type[unit])); 1021 1022 #ifdef BCM_XGS3_SWITCH_SUPPORT 1023 if (SOC_IS_XGS3_SWITCH(unit)) { 1024 _bcm_xgs3_mcast_sw_dump(unit); 1025 } 1026 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 1027 1028 LOG_CLI((BSL_META_U(unit, 1029 "\n"))); 1030 1031 return; 1032 } 1033 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 1034 1035 /* 1036 * Function: 1037 * _bcm_esw_mcast_idx_ret_type_set 1038 * Purpose: 1039 * Set multicast index return type. 1040 * Parameters: 1041 * unit - StrataSwitch unit # 1042 * arg - 0 means hardware multicast index, 1 means bcm_multicast_t 1043 * Returns: 1044 * BCM_E_NONE 1045 * BCM_E_UNAVAIL 1046 */ 1047 1048 int 1049 _bcm_esw_mcast_idx_ret_type_set(int unit, int arg) 1050 { 1051 if (SOC_IS_XGS3_SWITCH(unit)) { 1052 MCAST_INIT_RETURN(unit); 1053 _bcm_mcast_idx_ret_type[unit] = arg; 1054 1055 #if defined(BCM_WARM_BOOT_SUPPORT) && defined(INCLUDE_L3) 1056 /* Record this value in HW for Warm Boot recovery. */ 1057 BCM_IF_ERROR_NOT_UNAVAIL_RETURN 1058 (_bcm_esw_ipmc_repl_wb_flags_set(unit, 1059 (arg ? _BCM_IPMC_WB_L2MC_GROUP_TYPE_MULTICAST : 0), 1060 _BCM_IPMC_WB_L2MC_GROUP_TYPE_MULTICAST)); 1061 #endif /* BCM_WARM_BOOT_SUPPORT && INCLUDE_L3 */ 1062 1063 return BCM_E_NONE; 1064 } 1065 1066 return BCM_E_UNAVAIL; 1067 } 1068 1069 /* 1070 * Function: 1071 * _bcm_esw_mcast_idx_ret_type_get 1072 * Purpose: 1073 * Get multicast index return type. 1074 * Parameters: 1075 * unit - StrataSwitch unit # 1076 * arg - Pointer to where retrieved value will be written 1077 * Returns: 1078 * BCM_E_NONE 1079 * BCM_E_UNAVAIL 1080 */ 1081 1082 int 1083 _bcm_esw_mcast_idx_ret_type_get(int unit, int *arg) 1084 { 1085 if (SOC_IS_XGS3_SWITCH(unit)) { 1086 MCAST_INIT_RETURN(unit); 1087 *arg = _bcm_mcast_idx_ret_type[unit]; 1088 return BCM_E_NONE; 1089 } 1090 1091 return BCM_E_UNAVAIL; 1092 } 1093