brd_chassis_smlb.c (58938B)
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: brd_chassis_smlb.c 8 * Purpose: BCM956000 Chassis source-modid based load balancing 9 */ 10 11 #include <shared/bsl.h> 12 #include <shared/alloc.h> 13 14 #include <bcm/error.h> 15 #include <bcm/stack.h> 16 #include <bcm/topo.h> 17 #include <bcm/mirror.h> 18 #include <appl/stktask/topo_brd.h> 19 #include <appl/stktask/stktask.h> /* bcm_st_reserved_modid_enable_get */ 20 #include <appl/cputrans/nh_tx.h> /* nh_tx_src_get */ 21 #include <appl/cputrans/cpu2cpu.h> /* nh_tx_src_get */ 22 23 #include "topo_int.h" 24 #include "brd_chassis_int.h" 25 26 #if defined(INCLUDE_CHASSIS) 27 28 /* 29 * Chassis cfm board 30 * 5675 31 * External stack ports are unit 0 ports 1-8 32 */ 33 34 /* 35 * Support functions for programming XGS3 switches connected to an XGS 36 * fabric. XGS3 switches may have more than one Higig port that could 37 * connect to a fabric, so it is no longer possible to rely on 38 * bcm_stk_port_set() to return 'the' stack port; board programming 39 * has to be told which port to use. The connection array, indexed by 40 * unit, contains the connectivity. connection.from is the switch port 41 * of the indexed unit, connection.to is the fabric port (on unit 42 * 'funit'). 43 */ 44 45 #define EVEN_IDX 0 46 #define ODD_IDX 1 47 #define IS_ODD(i) (i % 2) 48 #define IS_EVEN(i) (!IS_ODD(i)) 49 #define EVEN_ODD_IDX_GET(i) ((IS_EVEN(i)) ? EVEN_IDX : ODD_IDX) 50 51 /* 52 * Function: topo_chassis_modids_assign 53 * 54 * Purpose: 55 * Assign module IDs to the specified CPU database. 56 * Parameters: 57 * db_ref - Pointer to CPU database 58 * Returns: 59 * BCM_E_NONE 60 */ 61 62 int 63 topo_chassis_modids_assign(cpudb_ref_t db_ref) 64 { 65 cpudb_entry_t *entry; 66 int unit; 67 bcm_module_t modid; 68 69 /* 70 * Notes: 71 * Since the board type can only be inquired locally, 72 * the 'mod_ids_req' field will be used to assign mod ids. 73 * 74 * Eventually, we want the master to know the 75 * board type for each slot. Perhaps, this information 76 * can be passed around during discovery, or, the board 77 * type can be programmed in the EEPROM which can be accessed 78 * by the master module. 79 */ 80 81 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 82 (BSL_META("TOPO: Assigning chassis mod ids\n"))); 83 CPUDB_FOREACH_ENTRY(db_ref, entry) { 84 modid = MODID_OFFSET_GET(entry->base.slot_id); 85 86 if (entry->base.num_units == 2) { 87 /* 88 * Special modID assignment for LM XGS3-48G 89 * Unit0 connected to CFM1 needs an ODD modID 90 * Unit1 connected to CFM0 needs an EVEN modID 91 * Since the modID for a LM starts at an even number, 92 * increment to get odd for unit0. 93 */ 94 modid++; 95 } 96 97 /* 98 * Special modID assignment for 1 unit LMs based 99 * on LM even/odd slot, 100 * LM on odd slot get an ODD modID 101 * LM on even slot get an EVEN modID 102 */ 103 if ((IS_LM_SLOT(entry->base.slot_id)) && 104 (entry->base.num_units == 1)){ 105 if (IS_ODD(entry->base.slot_id)) { 106 /* This assumes that modID for a LM starts at even number */ 107 modid++; 108 } 109 } 110 111 for (unit = 0; unit < entry->base.num_units; unit++) { 112 if (entry->base.mod_ids_req[unit] > 0) { 113 entry->mod_ids[unit] = modid; 114 modid += entry->base.mod_ids_req[unit]; 115 } 116 } 117 } 118 119 return BCM_E_NONE; 120 } 121 122 /* 123 * Function: is_slot_valid 124 * 125 * Purpose: 126 * Checks if specified slot is valid. 127 * Parameters: 128 * slot - Slot to check 129 * db_ref - Pointer to CPU database 130 * Returns: 131 * TRUE - If slot is valid 132 * FALSE - If slot is not valid 133 * Notes: 134 * Currently, a slot is considered valid if the slot is 135 * found in the CPU database. 136 */ 137 STATIC int 138 is_slot_valid(int slot, cpudb_ref_t db_ref) 139 { 140 cpudb_entry_t *cur; 141 142 if (db_ref) { 143 CPUDB_FOREACH_ENTRY(db_ref, cur) { 144 if (cur->base.slot_id == slot) { 145 return TRUE; 146 } 147 } 148 } 149 150 return FALSE; 151 } 152 153 /* 154 * Function: chassis_unit_modid_get 155 * 156 * Purpose: 157 * Returns the mod ID for given unit. 158 * (-1) indicates an invalid mod ID. 159 */ 160 STATIC int 161 chassis_unit_modid_get(int unit, cpudb_entry_t *entry) 162 { 163 int modid = -1; 164 165 /* 166 * Notes: 167 * If the 'board type' is known for all remote devices, 168 * the module ID can be extracted using the 'slot' and 'unit', 169 * without using the cpudb information. 170 */ 171 if (entry->base.mod_ids_req[unit] > 0) { 172 modid = entry->mod_ids[unit]; 173 } 174 175 return modid; 176 } 177 178 179 /* 180 * The following function wrappers help isolate the device specific 181 * BCM call for setting the modport mapping. 182 */ 183 184 /* 185 * Function: xgs2_modport_set_hport 186 * 187 * Purpose: 188 * Set the dstmod-port mapping on specified HiGig stack port for 189 * given unit. 190 * Notes: 191 * The mod-port mapping is ONLY set for the indicated HiGig port. 192 */ 193 STATIC int 194 xgs2_modport_set_hport(int unit, bcm_port_t hport, 195 int dst_modid, bcm_port_t stk_port) 196 { 197 bcm_pbmp_t empty; 198 bcm_pbmp_t pbmp; 199 200 BCM_PBMP_CLEAR(empty); 201 BCM_PBMP_PORT_SET(pbmp, stk_port); 202 BCM_IF_ERROR_RETURN(bcm_stk_ucbitmap_set(unit, hport, dst_modid, 203 hport == stk_port ? 204 empty : pbmp)); 205 return BCM_E_NONE; 206 } 207 208 209 /* 210 * The following function wrappers help isolate the device specific 211 * BCM call for setting the modport mapping. 212 */ 213 214 /* 215 * Function: xxx_modport_set 216 * 217 * Purpose: 218 * Set the dstmod-port mapping on given unit. 219 */ 220 STATIC int 221 xgs2_modport_set(int unit, int dst_modid, bcm_port_t stk_port) 222 { 223 bcm_port_config_t config; 224 bcm_port_t hport; 225 bcm_pbmp_t empty; 226 bcm_pbmp_t pbmp; 227 228 BCM_IF_ERROR_RETURN(bcm_port_config_get(unit, &config)); 229 BCM_PBMP_CLEAR(empty); 230 BCM_PBMP_PORT_SET(pbmp, stk_port); 231 BCM_PBMP_ITER(config.hg, hport) { 232 BCM_IF_ERROR_RETURN(bcm_stk_ucbitmap_set(unit, hport, dst_modid, 233 hport == stk_port ? 234 empty : pbmp)); 235 } 236 237 return BCM_E_NONE; 238 } 239 STATIC int 240 xgs3_modport_set(int unit, int dst_modid, bcm_port_t stk_port) 241 { 242 return bcm_stk_modport_set(unit, dst_modid, stk_port); 243 } 244 245 /* 246 * Function: xxx_internal_sp_set 247 * 248 * Purpose: 249 * Notify BCM layer of internal stack ports on given unit. 250 */ 251 STATIC int 252 xgs3_internal_sp_set(int unit, int dst_unit, bcm_port_t stk_port) 253 { 254 COMPILER_REFERENCE(dst_unit); 255 256 /* Notify BCM layer of internal stack ports */ 257 BCM_IF_ERROR_RETURN(bcm_board_internal_stk_port_add(unit, stk_port)); 258 259 return BCM_E_NONE; 260 } 261 STATIC int 262 xgs2_internal_sp_set(int unit, int dst_unit, bcm_port_t stk_port) 263 { 264 uint32 flags; 265 266 /* Notify BCM layer of internal stack ports */ 267 BCM_IF_ERROR_RETURN(bcm_board_internal_stk_port_add(unit, stk_port)); 268 269 if (bcm_stk_port_get(dst_unit, BCM_STK_USE_HG_IF, &flags) < 0) { 270 LOG_WARN(BSL_LS_TKS_TOPOLOGY, 271 (BSL_META_U(unit, 272 "Could not get IPIC stack info for unit %d\n"), 273 dst_unit)); 274 } else { 275 if (!(flags & BCM_STK_ENABLE)) { 276 BCM_IF_ERROR_RETURN(bcm_stk_port_set(dst_unit, 277 BCM_STK_USE_HG_IF, 278 BCM_BOARD_INT_STK_FLAGS)); 279 } 280 } 281 282 return BCM_E_NONE; 283 } 284 285 /* 286 * Function: chassis_iroute 287 * 288 * Purpose: 289 * Set the forwarding of UC packets among local units on given board. 290 */ 291 STATIC int 292 chassis_iroute(int num_units, to_unit_t *to_unit, cpudb_ref_t db_ref) 293 { 294 cpudb_entry_t *l_entry; 295 int src_unit; 296 bcm_port_t stk_port; 297 int dst_unit; 298 int dst_num_units; 299 bcm_module_t modid; 300 modport_set_f modport_set; 301 int_sp_set_f internal_sp_set; 302 to_unit_t *to_unit_ptr; 303 int u, i; 304 int auto_trunk; 305 306 307 /* Set routes to local units */ 308 l_entry = db_ref->local_entry; 309 to_unit_ptr = to_unit; 310 311 BCM_IF_ERROR_RETURN(bcm_board_auto_trunk_get(&auto_trunk)); 312 for (src_unit = 0; src_unit < num_units; src_unit++, to_unit_ptr++) { 313 dst_num_units = to_unit_ptr->unit_cnt; 314 modport_set = to_unit_ptr->modport_set_fn; 315 internal_sp_set = to_unit_ptr->internal_sp_set_fn; 316 317 for (u = 0; u < dst_num_units; u++) { 318 dst_unit = to_unit_ptr->unit[u].dst; 319 stk_port = to_unit_ptr->unit[u].sp.port[0]; 320 modid = chassis_unit_modid_get(dst_unit, l_entry); 321 if (modid >= 0) { 322 BCM_IF_ERROR_RETURN(modport_set(src_unit, modid, stk_port)); 323 } 324 325 for (i = 0; i < to_unit_ptr->unit[u].sp.port_cnt; i++) { 326 stk_port = to_unit_ptr->unit[u].sp.port[i]; 327 BCM_IF_ERROR_RETURN(internal_sp_set(src_unit, dst_unit, stk_port)); 328 329 /* Only allow 1 internal stack port, if auto trunk is disabled */ 330 if (!auto_trunk) { 331 break; 332 } 333 } 334 } 335 } 336 337 return BCM_E_NONE; 338 } 339 340 /* 341 * Function: chassis_eroute_cfm 342 * 343 * Purpose: 344 * Set the forwarding of UC packets to CFMs on specified LM. 345 * Notes: 346 * 'sp_list' returns the list of valid stack ports for CFMs: 347 * The port in index 0 will contain the stack port for the even slot CFM, 348 * the port in index 1 will contain the stack port for the odd slot CFM. 349 */ 350 STATIC int 351 chassis_eroute_lm_cfm(int num_units, to_slot_t *to_cfm, sp_list_t *sp_list, 352 cpudb_ref_t db_ref) 353 { 354 int dst_slot; 355 bcm_port_t stk_port; 356 int cfm; 357 int unit; 358 int sp_cnt; 359 int sp_idx; 360 bcm_module_t dst_modid; 361 modport_set_f modport_set; 362 363 364 /* Init sp list */ 365 for (unit = 0; unit < num_units; unit++) { 366 sp_list[unit].port_cnt = 0; 367 for (sp_idx = 0; sp_idx < STK_PORTS_MAX; sp_idx++) { 368 sp_list[unit].port[sp_idx] = -1; 369 } 370 } 371 372 /* Set routes to CFMs */ 373 for (unit = 0; unit < num_units; unit++) { 374 sp_cnt = sp_idx= 0; 375 376 for (cfm = 0; cfm < to_cfm[unit].slot_cnt; cfm++) { 377 dst_slot = to_cfm[unit].slot[cfm].dst; 378 if (!is_slot_valid(dst_slot, db_ref)) { 379 continue; 380 } 381 stk_port = to_cfm[unit].slot[cfm].sp.port[0]; 382 modport_set = to_cfm[unit].modport_set_fn; 383 384 FOREACH_MODID(dst_slot, dst_modid) { 385 BCM_IF_ERROR_RETURN(modport_set(unit, dst_modid, stk_port)); 386 } 387 388 /* Add port to list of available external stack ports */ 389 sp_idx = EVEN_ODD_IDX_GET(dst_slot); 390 sp_list[unit].port[sp_idx] = stk_port; 391 sp_cnt++; 392 } 393 sp_list[unit].port_cnt = sp_cnt; 394 } 395 396 return BCM_E_NONE; 397 } 398 399 /* 400 * Function: chassis_xgs2_eroute_lm_lm 401 * 402 * Purpose: 403 * Set the forwarding of UC packets on given unit (XGS2 fabric) 404 * to other LMs. 405 */ 406 STATIC int 407 chassis_xgs2_eroute_lm_lm(int unit, to_unit_t *to_unit, 408 sp_list_t *sp_list, cpudb_ref_t db_ref) 409 { 410 cpudb_entry_t *l_entry; 411 int l_slot; 412 int dst_slot; 413 bcm_port_t hport; 414 bcm_port_t stk_port; 415 bcm_module_t src_modid; 416 bcm_module_t dst_modid; 417 int i; 418 419 if (sp_list->port_cnt == 0) { 420 return BCM_E_NONE; 421 } 422 423 l_entry = db_ref->local_entry; 424 l_slot = l_entry->base.slot_id; 425 for (i = 0; i < to_unit->unit_cnt; i++) { 426 src_modid = chassis_unit_modid_get(to_unit->unit[i].dst, l_entry); 427 if (src_modid < 0) { 428 continue; 429 } 430 431 if (IS_EVEN(src_modid)) { 432 if ((stk_port = sp_list->port[EVEN_IDX]) < 0) { 433 if ((stk_port = sp_list->port[ODD_IDX]) < 0) { 434 continue; /* No valid stack port */ 435 } 436 } 437 } else { 438 if ((stk_port = sp_list->port[ODD_IDX]) < 0) { 439 if ((stk_port = sp_list->port[EVEN_IDX]) < 0) { 440 continue; /* No valid stack port */ 441 } 442 } 443 } 444 445 hport = to_unit->unit[i].sp.port[0]; 446 for (dst_slot = LM_SLOT_OFFSET; dst_slot < NUM_SLOT; dst_slot++) { 447 if (dst_slot == l_slot) { /* Skip local slot */ 448 continue; 449 } 450 FOREACH_MODID(dst_slot, dst_modid) { 451 BCM_IF_ERROR_RETURN(xgs2_modport_set_hport(unit, hport, 452 dst_modid, stk_port)); 453 } 454 } 455 } 456 457 return BCM_E_NONE; 458 } 459 460 /* 461 * Function: chassis_xgs3_eroute_lm_lm 462 * 463 * Purpose: 464 * Set the forwarding of UC packets on specified unit (XGS3 switch) 465 * with indicated stack port to other LMs. 466 */ 467 STATIC int 468 chassis_xgs3_eroute_lm_lm(int unit, bcm_port_t stk_port, int l_slot) 469 { 470 int dst_slot; 471 bcm_module_t dst_modid; 472 473 /* Set routes to other LMs */ 474 for (dst_slot = LM_SLOT_OFFSET; dst_slot < NUM_SLOT; dst_slot++) { 475 if (dst_slot == l_slot) { /* Skip local slot */ 476 continue; 477 } 478 FOREACH_MODID(dst_slot, dst_modid) { 479 BCM_IF_ERROR_RETURN(bcm_stk_modport_set(unit, dst_modid, stk_port)); 480 } 481 } 482 483 return BCM_E_NONE; 484 } 485 486 /* 487 * Function: chassis_internal_modid_filter 488 * 489 * Purpose: 490 * Set source mod IDs filtering for internal stack ports. 491 */ 492 /* 493 * Function: chassis_internal_modid_filter 494 * 495 * Purpose: 496 * Set source mod IDs filtering for internal stack ports. 497 */ 498 STATIC int 499 chassis_internal_modid_filter(int num_units, 500 sp_list_t *internal_sp) 501 { 502 int unit; 503 int i; 504 bcm_port_t stk_port; 505 506 /* Allow any mod IDs for internal stack ports */ 507 for (unit = 0; unit < num_units; unit++) { 508 for(i = 0; i < internal_sp[unit].port_cnt; i++) { 509 stk_port = internal_sp[unit].port[i]; 510 BCM_IF_ERROR_RETURN(bcm_port_modid_enable_set(unit, stk_port, 511 -1, TRUE)); 512 } 513 } 514 515 return BCM_E_NONE; 516 } 517 518 /* 519 * Function: chassis_external_modid_filter 520 * 521 * Purpose: 522 * Set mod IDs filtering for external stack ports on 523 * specified unit. 524 */ 525 STATIC int 526 chassis_external_modid_filter(int unit, sp_list_t *external_sp, int l_slot, 527 cpudb_ref_t db_ref) 528 { 529 bcm_port_t stk_port; 530 bcm_module_t src_modid; 531 int slot; 532 int enable; 533 int i; 534 535 536 /* Enable CPU source mod ID */ 537 BCM_IF_ERROR_RETURN(c2c_src_mod_get(&src_modid)); 538 for (i = 0; i < external_sp->port_cnt; i++) { 539 stk_port = external_sp->port[i]; 540 BCM_IF_ERROR_RETURN(bcm_port_modid_enable_set(unit, stk_port, 541 src_modid, TRUE)); 542 } 543 544 /* Enable source mod IDs from other valid slots */ 545 for (slot = 0; slot < NUM_SLOT; slot++) { 546 if ((is_slot_valid(slot, db_ref)) && (slot != l_slot)) { 547 enable = TRUE; 548 } else { 549 enable = FALSE; 550 } 551 552 FOREACH_MODID(slot, src_modid) { 553 for(i = 0; i < external_sp->port_cnt; i++) { 554 stk_port = external_sp->port[i]; 555 BCM_IF_ERROR_RETURN(bcm_port_modid_enable_set(unit, stk_port, 556 src_modid, 557 enable)); 558 } 559 } 560 } 561 562 return BCM_E_NONE; 563 } 564 565 566 /* 567 * Function: chassis_nh_modid_filter 568 * 569 * Purpose: 570 * Enable NH source mod ID in external stack ports. 571 */ 572 STATIC int 573 chassis_nh_modid_filter(int num_units, 574 sp_list_t *external_sp) 575 { 576 int unit; 577 int i; 578 bcm_port_t stk_port; 579 int nhmod, nhport; 580 int num_modids; 581 582 /* Enable NH mod ID for external stack ports */ 583 BCM_IF_ERROR_RETURN(bcm_board_num_modid_get(&num_modids)); 584 for (unit = 0; unit < num_units; unit++) { 585 for (i = 0; i < external_sp[unit].port_cnt; i++) { 586 stk_port = external_sp[unit].port[i]; 587 nhmod = -1; 588 if (bcm_st_reserved_modid_enable_get() || 589 nh_tx_src_mod_port_get(unit, stk_port, &nhmod, &nhport) < 0 || 590 nhmod < 0) { 591 if (nh_tx_src_get(&nhmod, &nhport) < 0 || nhmod < 0) { 592 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 593 (BSL_META_U(unit, 594 "TOPO: Could not get default NH src modid.\n"))); 595 } 596 } 597 if (nhmod >= 0 && nhmod < num_modids) { 598 BCM_IF_ERROR_RETURN(bcm_port_modid_enable_set(unit, stk_port, 599 nhmod, TRUE)); 600 } 601 } 602 } 603 604 return BCM_E_NONE; 605 } 606 607 /* 608 * Function: chassis_xgs2_flood_set 609 * 610 * Purpose: 611 * Set the appropriate flood block flag in stack ports to 612 * prevent looping. 613 */ 614 STATIC int 615 chassis_xgs2_flood_set(int unit, sp_list_t *external_sp, 616 to_slot_t *to_cfm, cpudb_ref_t db_ref) 617 { 618 int rv; 619 bcm_pbmp_t external_all; 620 bcm_pbmp_t external_disable; 621 bcm_port_t port, eport; 622 bcm_port_config_t *config = NULL; 623 uint32 flags; 624 int cfm; 625 int i; 626 627 config = sal_alloc(sizeof(bcm_port_config_t), "bcm_port_config_t"); 628 if (config == NULL) { 629 return BCM_E_MEMORY; 630 } 631 bcm_port_config_t_init(config); 632 633 rv = bcm_port_config_get(unit, config); 634 if (BCM_FAILURE(rv)) { 635 sal_free(config); 636 return (rv); 637 } 638 639 BCM_PBMP_CLEAR(external_all); 640 BCM_PBMP_CLEAR(external_disable); 641 for (i = 0; i < external_sp->port_cnt; i++) { 642 BCM_PBMP_PORT_ADD(external_all, external_sp->port[i]); 643 } 644 645 for (cfm = 0; cfm < to_cfm->slot_cnt; cfm++) { 646 if (!is_slot_valid(to_cfm->slot[cfm].dst, db_ref)) { 647 for (i = 0; i < to_cfm->slot[cfm].sp.port_cnt; i++) { 648 port = to_cfm->slot[cfm].sp.port[i]; 649 if (BCM_PBMP_MEMBER(external_all, port)) { 650 BCM_PBMP_PORT_ADD(external_disable, port); 651 } 652 } 653 } 654 } 655 656 BCM_PBMP_ITER(config->hg, port) { 657 BCM_PBMP_ITER(config->hg, eport) { 658 if ((BCM_PBMP_MEMBER(external_disable, port)) || 659 (BCM_PBMP_MEMBER(external_disable, eport))) { 660 flags = DISABLE_FLOOD; 661 } else { 662 flags = ENABLE_FLOOD; 663 } 664 bcm_port_flood_block_set(unit, port, eport, flags); 665 } 666 } 667 sal_free(config); 668 669 return BCM_E_NONE; 670 } 671 672 /* 673 * Function: chassis_xgs3_flood_set 674 * 675 * Purpose: 676 * Set the appropriate flood block flag in stack ports to 677 * prevent looping. 678 */ 679 STATIC int 680 chassis_xgs3_flood_set(int unit, sp_list_t *external_sp, 681 to_slot_t *to_cfm, cpudb_ref_t db_ref, int num_cfms) 682 { 683 int rv; 684 bcm_pbmp_t external_all; 685 bcm_pbmp_t flood_ports; 686 bcm_port_t port, eport; 687 bcm_port_config_t *config = NULL; 688 bcm_module_t src_modid; 689 uint32 flags; 690 int cfm; 691 int i; 692 693 config = sal_alloc(sizeof(bcm_port_config_t), "bcm_port_config_t"); 694 if (config == NULL) { 695 return BCM_E_MEMORY; 696 } 697 bcm_port_config_t_init(config); 698 699 /* 0 or 1 CFM */ 700 if (num_cfms < 2) { /* Just like the xgs2 fabric */ 701 sal_free(config); 702 return chassis_xgs2_flood_set(unit, external_sp, to_cfm, db_ref); 703 } 704 705 /* 2 CFMs */ 706 rv = bcm_port_config_get(unit, config); 707 if (BCM_FAILURE(rv)) { 708 sal_free(config); 709 return (rv); 710 } 711 712 BCM_PBMP_CLEAR(external_all); 713 BCM_PBMP_CLEAR(flood_ports); 714 for (i = 0; i < external_sp->port_cnt; i++) { 715 BCM_PBMP_PORT_ADD(external_all, external_sp->port[i]); 716 } 717 718 /* Determine the egress ports for flooding */ 719 src_modid = chassis_unit_modid_get(unit, db_ref->local_entry); 720 if (IS_EVEN(src_modid)) { 721 cfm = EVEN_IDX; 722 } else { 723 cfm = ODD_IDX; 724 } 725 for (i = 0; i < to_cfm->slot[cfm].sp.port_cnt; i++) { 726 BCM_PBMP_PORT_ADD(flood_ports, to_cfm->slot[cfm].sp.port[i]); 727 } 728 729 /* 730 * Ether Ports 731 * If external stack ports are flood ports, enable egress to 732 * external stack ports, disable otherwise 733 */ 734 BCM_PBMP_ITER(config->e, port) { 735 BCM_PBMP_ITER(external_all, eport) { 736 if (BCM_PBMP_MEMBER(flood_ports, eport)) { 737 flags = ENABLE_FLOOD; 738 } else { 739 flags = DISABLE_FLOOD; 740 } 741 bcm_port_flood_block_set(unit, port, eport, flags); 742 } 743 } 744 745 /* 746 * HiGig Ports 747 * Block internal to external stack port IF external is 748 * member of the flood ports 749 */ 750 BCM_PBMP_ITER(config->hg, port) { 751 BCM_PBMP_ITER(config->hg, eport) { 752 if ((!BCM_PBMP_MEMBER(external_all, port)) && 753 (BCM_PBMP_MEMBER(external_all, eport)) && 754 (BCM_PBMP_MEMBER(flood_ports, eport))) { 755 flags = DISABLE_FLOOD; 756 } else { 757 flags = ENABLE_FLOOD; 758 } 759 bcm_port_flood_block_set(unit, port, eport, flags); 760 } 761 } 762 sal_free(config); 763 764 return BCM_E_NONE; 765 } 766 767 768 769 /* 770 * Function: chassis_xgs2_mirror_to_set 771 * 772 * Purpose: 773 * Set the appropriate mirrored-to-port for given unit to send 774 * mirrored packets through correct CFM. This routine should be 775 * called by LMs XGS-2 Fabric devices with external stack ports. 776 * 777 * Note: 778 * This routine MUST be called AFTER the external lm routes 779 * are set through chassis_xgs2_eroute_lm_lm() or 780 * chassis_xgs3_eroute_lm_lm(). 781 */ 782 STATIC int 783 chassis_xgs2_mirror_to_set(int unit, sp_list_t *external_sp, 784 int l_slot, cpudb_ref_t db_ref) 785 { 786 cpudb_entry_t *cur; 787 bcm_module_t mirror_modid; 788 bcm_port_config_t config; 789 bcm_port_t hport; 790 bcm_pbmp_t pbmp; 791 bcm_pbmp_t pbmp_ext; 792 int i; 793 794 /* Since LB is based on src-mod ID, any valid non-local LM 795 dest-mod ID will work to get the righ MTP */ 796 mirror_modid = -1; 797 CPUDB_FOREACH_ENTRY(db_ref, cur) { 798 if ((cur->base.slot_id != l_slot) && IS_LM_SLOT(cur->base.slot_id)){ 799 mirror_modid = MODID_OFFSET_GET(cur->base.slot_id); 800 break; 801 } 802 } 803 if (mirror_modid < 0) { 804 return BCM_E_NONE; 805 } 806 807 /* 808 * XGS-2 Fabric device needs to use the UC bitmap 809 * to set each HiGig port individually 810 */ 811 812 BCM_PBMP_CLEAR(pbmp_ext); 813 for (i = 0; i < external_sp->port_cnt; i++) { 814 BCM_PBMP_PORT_ADD(pbmp_ext, external_sp->port[i]); 815 } 816 817 BCM_IF_ERROR_RETURN(bcm_port_config_get(unit, &config)); 818 BCM_PBMP_ITER(config.hg, hport) { 819 BCM_PBMP_CLEAR(pbmp); 820 BCM_IF_ERROR_RETURN(bcm_mirror_to_pbmp_get(unit, hport, &pbmp)); 821 822 /* If MTP is set and is an external stack port, update */ 823 if (BCM_PBMP_NOT_NULL(pbmp)) { 824 BCM_PBMP_AND(pbmp, pbmp_ext); 825 if (BCM_PBMP_NOT_NULL(pbmp)) { 826 BCM_IF_ERROR_RETURN(bcm_stk_ucbitmap_get(unit, hport, 827 mirror_modid, &pbmp)); 828 BCM_IF_ERROR_RETURN(bcm_mirror_to_pbmp_set(unit, hport, pbmp)); 829 } 830 831 } 832 } 833 834 return BCM_E_NONE; 835 } 836 837 838 /* 839 * Function: chassis_xgs3_mirror_to_set 840 * 841 * Purpose: 842 * Set the appropriate mirrored-to-port for given unit to send 843 * mirrored packets through correct CFM. This routine should be 844 * called by LMs XGS-3 Switch devices with external stack ports. 845 * 846 * Note: 847 * This routine MUST be called AFTER the external lm routes 848 * are set through chassis_xgs2_eroute_lm_lm() or 849 * chassis_xgs3_eroute_lm_lm(). 850 */ 851 STATIC int 852 chassis_xgs3_mirror_to_set(int unit, sp_list_t *external_sp, 853 int l_slot, cpudb_ref_t db_ref) 854 { 855 cpudb_entry_t *cur; 856 bcm_module_t mirror_modid; 857 bcm_port_config_t config; 858 bcm_port_t mtp; 859 bcm_pbmp_t pbmp_ext; 860 int i; 861 862 /* Since LB is based on src-mod ID, any valid non-local LM 863 dest-mod ID will work to get the righ MTP */ 864 mirror_modid = -1; 865 CPUDB_FOREACH_ENTRY(db_ref, cur) { 866 if ((cur->base.slot_id != l_slot) && IS_LM_SLOT(cur->base.slot_id)){ 867 mirror_modid = MODID_OFFSET_GET(cur->base.slot_id); 868 break; 869 } 870 } 871 if (mirror_modid < 0) { 872 return BCM_E_NONE; 873 } 874 875 876 BCM_IF_ERROR_RETURN(bcm_mirror_to_get(unit, &mtp)); 877 878 BCM_PBMP_CLEAR(pbmp_ext); 879 for (i = 0; i < external_sp->port_cnt; i++) { 880 BCM_PBMP_PORT_ADD(pbmp_ext, external_sp->port[i]); 881 } 882 883 /* If MTP is set and is an external stack port, update it */ 884 if ((mtp >= 0) && BCM_PBMP_MEMBER(pbmp_ext, mtp)) { 885 BCM_IF_ERROR_RETURN(bcm_port_config_get(unit, &config)); 886 if (BCM_PBMP_MEMBER(config.hg, mtp)) { 887 BCM_IF_ERROR_RETURN(bcm_topo_port_get(unit, mirror_modid, &mtp)); 888 BCM_IF_ERROR_RETURN(bcm_mirror_to_set(unit, mtp)); 889 } 890 } 891 892 return BCM_E_NONE; 893 } 894 895 896 /* 897 * Function: chassis_smlb_cfm_xgs2 898 * 899 * Purpose: 900 * Program the XGS2 CFM board using Chassis Load Balancing. 901 */ 902 int 903 chassis_smlb_cfm_xgs2(topo_cpu_t *tp_cpu, cpudb_ref_t db_ref) 904 { 905 cpudb_entry_t *l_entry; 906 int l_slot; 907 int unit; 908 bcm_port_t stk_port; 909 int dst_slot; 910 int src_modid; 911 int peer_cfm_slot; 912 bcm_module_t modid; 913 int lm_to_cfm; 914 int lm; 915 int i, j; 916 int enable; 917 int lb_even_odd; 918 bcm_board_cfm_info_t cfm_info; 919 bcm_port_config_t config; 920 921 static sp_list_t external_sp = {8, {1, 2, 3, 4, 5, 6, 7, 8}}; 922 static to_slot_t to_lm = { 923 xgs2_modport_set, 924 4, {{2, {2, {1, 2}}}, 925 {3, {2, {3, 4}}}, 926 {4, {2, {5, 6}}}, 927 {5, {2, {7, 8}}}} 928 }; 929 930 COMPILER_REFERENCE(tp_cpu); 931 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 932 (BSL_META("TOPO: XGS 5675 BCM956000 CFM (Load Balancing)\n"))); 933 934 /* Only 1 unit */ 935 unit = 0; 936 l_entry = db_ref->local_entry; 937 l_slot = l_entry->base.slot_id; 938 bcm_board_cfm_info(db_ref, &cfm_info); 939 940 /* Set mod ID for fabric unit */ 941 modid = l_entry->dest_mod; 942 BCM_IF_ERROR_RETURN(bcm_stk_my_modid_set(0, modid)); 943 BCM_IF_ERROR_RETURN(bcm_port_config_get(unit, &config)); 944 BCM_PBMP_ITER(config.hg, stk_port) { 945 BCM_IF_ERROR_RETURN(bcm_stk_ucbitmap_set(unit, stk_port, modid, 946 config.cpu)); 947 } 948 949 /* Set and enable CPU source mod ID */ 950 BCM_IF_ERROR_RETURN(c2c_src_mod_get(&src_modid)); 951 for (i = 0; i < external_sp.port_cnt; i++) { 952 stk_port = external_sp.port[i]; 953 BCM_IF_ERROR_RETURN(bcm_port_modid_enable_set(unit, stk_port, 954 src_modid, TRUE)); 955 } 956 957 /* 958 * Set source mod ID filtering for LMs 959 * If one CFM 960 * accept all mod IDs, 961 * Else 962 * CFM on even slot should only accept even mod IDs 963 * CFM on odd slot should only accept odd mod IDs 964 */ 965 966 /* For each external CFM stack port */ 967 for (i = 0; i < external_sp.port_cnt; i++) { 968 stk_port = external_sp.port[i]; 969 970 /* For each LM */ 971 for (lm = 0; lm < to_lm.slot_cnt; lm++) { 972 enable = FALSE; 973 lb_even_odd = FALSE; 974 dst_slot = to_lm.slot[lm].dst; 975 976 /* 977 * If LM is valid and external stack port is 978 * connected directly to LM: 979 * - If only 1 CFM, allow all mod IDs from LM 980 * - If 2 CFMs, allow mod IDs based on even/odd logic 981 */ 982 if (is_slot_valid(dst_slot, db_ref)) { 983 for (j = 0; j < to_lm.slot[lm].sp.port_cnt; j++) { 984 if (stk_port == to_lm.slot[lm].sp.port[j]) { 985 if (cfm_info.count == 1) { 986 enable = TRUE; 987 } else { 988 lb_even_odd = TRUE; 989 } 990 break; 991 } 992 } 993 } 994 995 /* For each mod ID that corresponds to a given LM */ 996 FOREACH_MODID(dst_slot, modid) { 997 if (lb_even_odd) { 998 if (((IS_EVEN(l_slot)) && (IS_EVEN(modid))) || 999 ((IS_ODD(l_slot)) && (IS_ODD(modid)))) { 1000 enable = TRUE; 1001 } 1002 else { 1003 enable = FALSE; 1004 } 1005 } 1006 BCM_IF_ERROR_RETURN(bcm_port_modid_enable_set(unit, stk_port, 1007 modid, enable)); 1008 } 1009 } 1010 } 1011 1012 /* Set source module filtering for NH */ 1013 chassis_nh_modid_filter(1, &external_sp); 1014 1015 /* Set routes to LMs */ 1016 lm_to_cfm = -1; 1017 for (lm = 0; lm < to_lm.slot_cnt; lm++) { 1018 dst_slot = to_lm.slot[lm].dst; 1019 if (!is_slot_valid(dst_slot, db_ref)) { 1020 continue; 1021 } 1022 1023 /* Use first port, other ports will be trunked */ 1024 stk_port = to_lm.slot[lm].sp.port[0]; 1025 lm_to_cfm = lm; 1026 FOREACH_MODID(dst_slot, modid) { 1027 BCM_IF_ERROR_RETURN(xgs2_modport_set(unit, modid, stk_port)); 1028 } 1029 } 1030 1031 1032 /* If there is an available external stack port, set route to peer CFM */ 1033 if (lm_to_cfm >= 0) { 1034 if (l_entry->base.slot_id == 0) { 1035 peer_cfm_slot = 1; 1036 } else { 1037 peer_cfm_slot = 0; 1038 } 1039 if (is_slot_valid(peer_cfm_slot, db_ref)) { 1040 /* Enable peer CFM source mod ID in all external stack ports */ 1041 for (i = 0; i < external_sp.port_cnt; i++) { 1042 stk_port = external_sp.port[i]; 1043 FOREACH_MODID(peer_cfm_slot, modid) { 1044 BCM_IF_ERROR_RETURN(bcm_port_modid_enable_set(unit, 1045 stk_port, 1046 modid, 1047 TRUE)); 1048 } 1049 } 1050 stk_port = to_lm.slot[lm_to_cfm].sp.port[0]; 1051 FOREACH_MODID(peer_cfm_slot, modid) { 1052 BCM_IF_ERROR_RETURN(xgs2_modport_set(unit, modid, stk_port)); 1053 } 1054 } 1055 } 1056 1057 /* Set trunks */ 1058 BCM_IF_ERROR_RETURN(bcm_board_trunk_system(l_entry, db_ref, 1059 BCM_BOARD_TRUNK_NORMAL)); 1060 1061 /* Set mod IDs */ 1062 /* Mod ID for fabric is set by caller */ 1063 bcm_board_unknown_src_modid_setup(l_entry); 1064 1065 return BCM_E_NONE; 1066 } 1067 1068 1069 /* 1070 * Function: chassis_smlb_xgs2_48g 1071 * 1072 * Purpose: 1073 * Program the XGS2-48G LM board using Chassis Load Balancing. 1074 */ 1075 #define NUM_UNIT_XGS2_48G 5 1076 int 1077 chassis_smlb_xgs2_48g(topo_cpu_t *tp_cpu, cpudb_ref_t db_ref) 1078 { 1079 cpudb_entry_t *l_entry; 1080 int unit; 1081 int num_units; 1082 bcm_module_t modid; 1083 sp_list_t sp_list; 1084 1085 static sp_list_t internal_sp = {4, {1, 2, 3, 4}}; 1086 static sp_list_t external_sp = {4, {5, 6, 7, 8}}; 1087 static to_unit_t to_unit = { 1088 xgs2_modport_set, xgs2_internal_sp_set, /* Unit 0:5675 */ 1089 4, {{1, {1, {1}}}, 1090 {2, {1, {2}}}, 1091 {3, {1, {3}}}, 1092 {4, {1, {4}}}} 1093 }; 1094 static to_slot_t to_cfm = { 1095 xgs2_modport_set, /* Unit 0:5675 */ 1096 2, {{0, {2, {5, 7}}}, 1097 {1, {2, {6, 8}}}} 1098 }; 1099 1100 COMPILER_REFERENCE(tp_cpu); 1101 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 1102 (BSL_META("TOPO: XGS 569x 48GE BCM956000 LM (Load Balancing)\n"))); 1103 1104 /* 1105 * Note: 1106 * Although this LM has 5 units, units 1-4 are 5695s. 1107 * The 5695 does not need its stack ports to be programmed. 1108 */ 1109 num_units = 1; 1110 l_entry = db_ref->local_entry; 1111 1112 /* Set packet forwarding tables */ 1113 BCM_IF_ERROR_RETURN(chassis_iroute(num_units, &to_unit, db_ref)); 1114 BCM_IF_ERROR_RETURN(chassis_eroute_lm_cfm(num_units, 1115 &to_cfm, &sp_list, db_ref)); 1116 BCM_IF_ERROR_RETURN(chassis_xgs2_eroute_lm_lm(0, &to_unit, &sp_list, db_ref)); 1117 1118 1119 /* Set source module filtering */ 1120 BCM_IF_ERROR_RETURN(chassis_internal_modid_filter(num_units, &internal_sp)); 1121 BCM_IF_ERROR_RETURN(chassis_external_modid_filter(0, &external_sp, 1122 l_entry->base.slot_id, 1123 db_ref)); 1124 BCM_IF_ERROR_RETURN(chassis_nh_modid_filter(num_units, &external_sp)); 1125 1126 /* Set flood blocking */ 1127 BCM_IF_ERROR_RETURN(chassis_xgs2_flood_set(0, &external_sp, 1128 &to_cfm, db_ref)); 1129 1130 /* Set trunks */ 1131 BCM_IF_ERROR_RETURN(bcm_board_trunk_system(l_entry, db_ref, 1132 BCM_BOARD_TRUNK_NORMAL)); 1133 1134 /* Set mirroring */ 1135 BCM_IF_ERROR_RETURN(chassis_xgs2_mirror_to_set(0, &external_sp, 1136 l_entry->base.slot_id, 1137 db_ref)); 1138 1139 /* Set mod IDs */ 1140 bcm_board_unknown_src_modid_setup(l_entry); 1141 for (unit = 0; unit < NUM_UNIT_XGS2_48G; unit++) { 1142 if ((modid = chassis_unit_modid_get(unit, l_entry)) < 0) { 1143 continue; 1144 } 1145 BCM_IF_ERROR_RETURN(bcm_stk_my_modid_set(unit, modid)); 1146 BCM_IF_ERROR_RETURN(bcm_stk_modport_clear_all(unit)); 1147 } 1148 1149 return BCM_E_NONE; 1150 } 1151 1152 /* 1153 * Function: chassis_smlb_xgs2_6x 1154 * 1155 * Purpose: 1156 * Program the XGS2-6X LM board using Chassis Load Balancing. 1157 */ 1158 #define NUM_UNIT_XGS2_6X 7 1159 int 1160 chassis_smlb_xgs2_6x(topo_cpu_t *tp_cpu, cpudb_ref_t db_ref) 1161 { 1162 cpudb_entry_t *l_entry; 1163 int unit; 1164 int num_units; 1165 bcm_module_t modid; 1166 sp_list_t sp_list; 1167 1168 static sp_list_t internal_sp = {6, {6, 7, 8, 1, 2, 3}}; 1169 static sp_list_t external_sp = {2, {4, 5}}; 1170 static to_unit_t to_unit = { 1171 xgs2_modport_set, xgs2_internal_sp_set, /* Unit 0:5675 */ 1172 6, {{1, {1, {6}}}, 1173 {2, {1, {7}}}, 1174 {3, {1, {8}}}, 1175 {4, {1, {1}}}, 1176 {5, {1, {2}}}, 1177 {6, {1, {3}}}} 1178 }; 1179 static to_slot_t to_cfm = { 1180 xgs2_modport_set, /* Unit 0:5675 */ 1181 2, {{0, {1, {4}}}, 1182 {1, {1, {5}}}} 1183 }; 1184 1185 COMPILER_REFERENCE(tp_cpu); 1186 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 1187 (BSL_META("TOPO: XGS 5674 6X BCM956000 LM (Load Balancing)\n"))); 1188 1189 /* 1190 * Note: 1191 * Although this LM has 7 units, units 1-6 are 5674s. 1192 * The 5674 does not need its stack ports to be programmed. 1193 */ 1194 num_units = 1; 1195 l_entry = db_ref->local_entry; 1196 1197 /* Set packet forwarding tables */ 1198 BCM_IF_ERROR_RETURN(chassis_iroute(num_units, &to_unit, db_ref)); 1199 BCM_IF_ERROR_RETURN(chassis_eroute_lm_cfm(num_units, 1200 &to_cfm, &sp_list, db_ref)); 1201 BCM_IF_ERROR_RETURN(chassis_xgs2_eroute_lm_lm(0, &to_unit, &sp_list, db_ref)); 1202 1203 1204 /* Set source module filtering */ 1205 BCM_IF_ERROR_RETURN(chassis_internal_modid_filter(num_units, &internal_sp)); 1206 BCM_IF_ERROR_RETURN(chassis_external_modid_filter(0, &external_sp, 1207 l_entry->base.slot_id, 1208 db_ref)); 1209 BCM_IF_ERROR_RETURN(chassis_nh_modid_filter(num_units, &external_sp)); 1210 1211 /* Set flood blocking */ 1212 BCM_IF_ERROR_RETURN(chassis_xgs2_flood_set(0, &external_sp, 1213 &to_cfm, db_ref)); 1214 /* Set mirroring */ 1215 BCM_IF_ERROR_RETURN(chassis_xgs2_mirror_to_set(0, &external_sp, 1216 l_entry->base.slot_id, 1217 db_ref)); 1218 1219 /* Set mod IDs */ 1220 bcm_board_unknown_src_modid_setup(l_entry); 1221 for (unit = 0; unit < NUM_UNIT_XGS2_6X; unit++) { 1222 if ((modid = chassis_unit_modid_get(unit, l_entry)) < 0) { 1223 continue; 1224 } 1225 BCM_IF_ERROR_RETURN(bcm_stk_my_modid_set(unit, modid)); 1226 BCM_IF_ERROR_RETURN(bcm_stk_modport_clear_all(unit)); 1227 } 1228 1229 return BCM_E_NONE; 1230 } 1231 1232 /* 1233 * Function: chassis_smlb_xgs3_12x 1234 * 1235 * Purpose: 1236 * Program the XGS3-12X LM board using Chassis Load Balancing. 1237 */ 1238 #define NUM_UNIT_XGS3_12X 5 1239 int 1240 chassis_smlb_xgs3_12x(topo_cpu_t *tp_cpu, cpudb_ref_t db_ref) 1241 { 1242 cpudb_entry_t *l_entry; 1243 int unit; 1244 bcm_module_t modid; 1245 sp_list_t sp_list[NUM_UNIT_XGS3_12X]; 1246 1247 static sp_list_t internal_sp_tbl[NUM_UNIT_XGS3_12X] = { 1248 {4, {1, 2, 7, 8}}, /* Unit 0 */ 1249 {1, {27}}, {1, {27}}, {1, {27}}, {1, {27}} /* Units 1-4 */ 1250 }; 1251 static sp_list_t external_sp_tbl[NUM_UNIT_XGS3_12X] = { 1252 {4, {3, 4, 5, 6}}, /* Unit 0 */ 1253 {0}, {0}, {0}, {0} /* Units 1-4 */ 1254 }; 1255 static to_unit_t to_unit_tbl[NUM_UNIT_XGS3_12X] = { 1256 { xgs2_modport_set, xgs3_internal_sp_set, /* Unit 0: 5675 */ 1257 4, {{1, {1, {7}}}, 1258 {2, {1, {8}}}, 1259 {3, {1, {1}}}, 1260 {4, {1, {2}}}} }, 1261 { xgs3_modport_set, xgs3_internal_sp_set, /* Unit 1: 56501 */ 1262 4, {{0, {1, {27}}}, 1263 {2, {1, {27}}}, 1264 {3, {1, {27}}}, 1265 {4, {1, {27}}}} }, 1266 { xgs3_modport_set, xgs3_internal_sp_set, /* Unit 2: 56501 */ 1267 4, {{0, {1, {27}}}, 1268 {1, {1, {27}}}, 1269 {3, {1, {27}}}, 1270 {4, {1, {27}}}} }, 1271 { xgs3_modport_set, xgs3_internal_sp_set, /* Unit 3: 56501 */ 1272 4, {{0, {1, {27}}}, 1273 {1, {1, {27}}}, 1274 {2, {1, {27}}}, 1275 {4, {1, {27}}}} }, 1276 { xgs3_modport_set, xgs3_internal_sp_set, /* Unit 4: 56501 */ 1277 4, {{0, {1, {27}}}, 1278 {1, {1, {27}}}, 1279 {2, {1, {27}}}, 1280 {3, {1, {27}}}} }, 1281 }; 1282 static to_slot_t to_cfm8[NUM_UNIT_XGS3_12X] = { 1283 { xgs2_modport_set, 1284 2, {{0, {2, {3, 5}}}, /* Unit 0: 5675 */ 1285 {1, {2, {4, 6}}}} }, 1286 { xgs3_modport_set, 1287 2, {{0, {1, {27}}}, /* Unit 1: 5695 */ 1288 {1, {1, {27}}}} }, 1289 { xgs3_modport_set, 1290 2, {{0, {1, {27}}}, /* Unit 2: 5695 */ 1291 {1, {1, {27}}}} }, 1292 { xgs3_modport_set, 1293 2, {{0, {1, {27}}}, /* Unit 3: 5695 */ 1294 {1, {1, {27}}}} }, 1295 { xgs3_modport_set, 1296 2, {{0, {1, {27}}}, /* Unit 4: 5695 */ 1297 {1, {1, {27}}}} } 1298 }; 1299 static to_slot_t to_cfm16[NUM_UNIT_XGS3_12X] = { 1300 { xgs2_modport_set, 1301 2, {{0, {2, {3, 6}}}, /* Unit 0: 5675 */ 1302 {1, {2, {4, 5}}}} }, 1303 { xgs3_modport_set, 1304 2, {{0, {1, {27}}}, /* Unit 1: 5695 */ 1305 {1, {1, {27}}}} }, 1306 { xgs3_modport_set, 1307 2, {{0, {1, {27}}}, /* Unit 2: 5695 */ 1308 {1, {1, {27}}}} }, 1309 { xgs3_modport_set, 1310 2, {{0, {1, {27}}}, /* Unit 3: 5695 */ 1311 {1, {1, {27}}}} }, 1312 { xgs3_modport_set, 1313 2, {{0, {1, {27}}}, /* Unit 4: 5695 */ 1314 {1, {1, {27}}}} } 1315 }; 1316 1317 int master_slot; 1318 to_slot_t *to_cfm; 1319 1320 COMPILER_REFERENCE(tp_cpu); 1321 1322 to_cfm = (db_ref->master_entry != NULL && 1323 db_ref->master_entry->base.flags & CPUDB_BASE_F_CHASSIS_10SLOT) ? 1324 to_cfm16 : to_cfm8; 1325 1326 master_slot = db_ref->master_entry ? 1327 db_ref->master_entry->base.slot_id : -1; 1328 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 1329 (BSL_META("TOPO: XGS3 56501 12XE BCM956000 LM (Load Balancing)\n"))); 1330 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 1331 (BSL_META(" master on slot %d\n"), 1332 master_slot)); 1333 1334 l_entry = db_ref->local_entry; 1335 1336 /* Set forwarding to local units */ 1337 BCM_IF_ERROR_RETURN(chassis_iroute(NUM_UNIT_XGS3_12X, 1338 to_unit_tbl, db_ref)); 1339 /* Set forwarding to CFMs */ 1340 BCM_IF_ERROR_RETURN(chassis_eroute_lm_cfm(NUM_UNIT_XGS3_12X, 1341 to_cfm, sp_list, db_ref)); 1342 /* Set forwarding to LMs */ 1343 unit = 0; 1344 BCM_IF_ERROR_RETURN(chassis_xgs2_eroute_lm_lm(unit, &to_unit_tbl[unit], 1345 &sp_list[unit], db_ref)); 1346 for (unit = 1; unit < NUM_UNIT_XGS3_12X; unit++){ 1347 BCM_IF_ERROR_RETURN(chassis_xgs3_eroute_lm_lm(unit, 1348 internal_sp_tbl[unit].port[0], 1349 l_entry->base.slot_id)); 1350 } 1351 1352 1353 /* Set source module filtering */ 1354 unit = 0; 1355 BCM_IF_ERROR_RETURN(chassis_internal_modid_filter(NUM_UNIT_XGS3_12X, 1356 internal_sp_tbl)); 1357 BCM_IF_ERROR_RETURN(chassis_external_modid_filter(unit, &external_sp_tbl[unit], 1358 l_entry->base.slot_id, 1359 db_ref)); 1360 BCM_IF_ERROR_RETURN(chassis_nh_modid_filter(NUM_UNIT_XGS3_12X, 1361 external_sp_tbl)); 1362 1363 /* Set flood blocking */ 1364 BCM_IF_ERROR_RETURN(chassis_xgs2_flood_set(unit, &external_sp_tbl[unit], 1365 &to_cfm[unit], db_ref)); 1366 1367 1368 /* Set trunks */ 1369 BCM_IF_ERROR_RETURN(bcm_board_trunk_system(l_entry, db_ref, 1370 BCM_BOARD_TRUNK_NORMAL)); 1371 1372 /* Set mirroring */ 1373 BCM_IF_ERROR_RETURN(chassis_xgs2_mirror_to_set(0, &external_sp_tbl[unit], 1374 l_entry->base.slot_id, 1375 db_ref)); 1376 1377 /* Set mod IDs */ 1378 bcm_board_unknown_src_modid_setup(l_entry); 1379 for (unit = 0; unit < NUM_UNIT_XGS3_12X; unit++) { 1380 if ((modid = chassis_unit_modid_get(unit, l_entry)) < 0) { 1381 continue; 1382 } 1383 BCM_IF_ERROR_RETURN(bcm_stk_my_modid_set(unit, modid)); 1384 } 1385 1386 return BCM_E_NONE; 1387 } 1388 1389 1390 /* 1391 * Function: chassis_smlb_xgs3_48g 1392 * 1393 * Purpose: 1394 * Program the XGS3-48G LM board using Chassis Load Balancing. 1395 */ 1396 #define NUM_UNIT_XGS3_48G 2 1397 1398 #define FB_UNIT0 0 1399 #define FB_UNIT1 1 1400 1401 int 1402 chassis_smlb_xgs3_48g(topo_cpu_t *tp_cpu, cpudb_ref_t db_ref) 1403 { 1404 cpudb_entry_t *l_entry; 1405 int unit; 1406 bcm_module_t src_modid; 1407 bcm_module_t dst_modid; 1408 bcm_port_t stk_port; 1409 sp_list_t sp_list[NUM_UNIT_XGS3_48G]; 1410 bcm_board_cfm_info_t cfm_info; 1411 int master_slot; 1412 1413 static sp_list_t internal_sp_tbl[NUM_UNIT_XGS3_48G] = { 1414 {2, {26, 27}}, /* Unit 0 */ 1415 {2, {26, 27}} /* Unit 1 */ 1416 }; 1417 static sp_list_t external_sp_tbl[NUM_UNIT_XGS3_48G] = { 1418 {2, {24, 25}}, /* Unit 0 */ 1419 {2, {24, 25}} /* Unit 1 */ 1420 }; 1421 static to_unit_t to_unit_tbl[NUM_UNIT_XGS3_48G] = { 1422 { xgs3_modport_set, xgs3_internal_sp_set, /* Unit 0: 56504 */ 1423 1, {{1, {2, {26, 27}}}} }, 1424 { xgs3_modport_set, xgs3_internal_sp_set, /* Unit 1: 56504 */ 1425 1, {{0, {2, {26, 27}}}} } 1426 }; 1427 1428 static to_slot_t to_cfm8[NUM_UNIT_XGS3_48G] = { 1429 { xgs3_modport_set, 1430 2, {{0, {2, {26, 27}}}, /* Unit 0: 56504 */ 1431 {1, {2, {24, 25}}}} }, 1432 { xgs3_modport_set, 1433 2, {{0, {2, {24, 25}}}, /* Unit 1: 56504 */ 1434 {1, {2, {26, 27}}}} } 1435 }; 1436 1437 static to_slot_t to_cfm16[NUM_UNIT_XGS3_48G] = { 1438 { xgs3_modport_set, 1439 2, {{0, {2, {24, 25}}}, /* Unit 0: 56504 */ 1440 {1, {2, {26, 27}}}} }, 1441 { xgs3_modport_set, 1442 2, {{0, {2, {26, 27}}}, /* Unit 1: 56504 */ 1443 {1, {2, {24, 25}}}} } 1444 }; 1445 1446 to_slot_t *to_cfm; 1447 1448 to_cfm = (db_ref->master_entry != NULL && 1449 db_ref->master_entry->base.flags & CPUDB_BASE_F_CHASSIS_10SLOT) ? 1450 to_cfm16 : to_cfm8; 1451 1452 /* If there's no master yet, set self as master */ 1453 master_slot = db_ref->master_entry ? 1454 db_ref->master_entry->base.slot_id : -1; 1455 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 1456 (BSL_META("TOPO: XGS3 56504 48GE BCM956000 LM (Load Balancing)\n"))); 1457 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 1458 (BSL_META(" master on slot %d\n"), 1459 master_slot)); 1460 1461 l_entry = db_ref->local_entry; 1462 bcm_board_cfm_info(db_ref, &cfm_info); 1463 1464 /* Set forwarding to local units */ 1465 BCM_IF_ERROR_RETURN(chassis_iroute(NUM_UNIT_XGS3_48G, 1466 to_unit_tbl, db_ref)); 1467 /* Set forwarding to CFMs */ 1468 sal_memset(sp_list, 0, sizeof(sp_list)); 1469 BCM_IF_ERROR_RETURN(chassis_eroute_lm_cfm(NUM_UNIT_XGS3_48G, 1470 to_cfm, sp_list, db_ref)); 1471 /* Set forwarding to LMs */ 1472 /* Use unit's source mod ID even/odd */ 1473 for (unit = 0; unit < NUM_UNIT_XGS3_48G; unit++){ 1474 src_modid = chassis_unit_modid_get(unit, l_entry); 1475 if (IS_EVEN(src_modid)) { 1476 if ((stk_port = sp_list[unit].port[EVEN_IDX]) < 0) { 1477 if ((stk_port = sp_list[unit].port[ODD_IDX]) < 0) { 1478 continue; 1479 } 1480 } 1481 } else { 1482 if ((stk_port = sp_list[unit].port[ODD_IDX]) < 0) { 1483 if ((stk_port = sp_list[unit].port[EVEN_IDX]) < 0) { 1484 continue; 1485 } 1486 } 1487 } 1488 BCM_IF_ERROR_RETURN(chassis_xgs3_eroute_lm_lm(unit, stk_port, 1489 l_entry->base.slot_id)); 1490 } 1491 1492 /* Set module filtering */ 1493 BCM_IF_ERROR_RETURN(chassis_internal_modid_filter(NUM_UNIT_XGS3_48G, 1494 internal_sp_tbl)); 1495 for (unit = 0; unit < NUM_UNIT_XGS3_48G; unit++) { 1496 /* Ignore error, since some FB revs do not support source modID filter */ 1497 (void)chassis_external_modid_filter(unit, 1498 &external_sp_tbl[unit], 1499 l_entry->base.slot_id, 1500 db_ref); 1501 } 1502 BCM_IF_ERROR_RETURN(chassis_nh_modid_filter(NUM_UNIT_XGS3_48G, 1503 external_sp_tbl)); 1504 1505 /* Set flood blocking */ 1506 for (unit = 0; unit < NUM_UNIT_XGS3_48G; unit++) { 1507 BCM_IF_ERROR_RETURN(chassis_xgs3_flood_set(unit, &external_sp_tbl[unit], 1508 &to_cfm[unit], db_ref, 1509 cfm_info.count)); 1510 } 1511 1512 1513 /* Set trunks */ 1514 /* External stack ports */ 1515 BCM_IF_ERROR_RETURN(bcm_board_trunk_system(l_entry, db_ref, 1516 BCM_BOARD_TRUNK_NORMAL)); 1517 /* Intraboard trunk */ 1518 BCM_IF_ERROR_RETURN(_bcm_board_setup_trunk_lm_xgs3_48g()); 1519 1520 /* Set mirroring */ 1521 for (unit = 0; unit < NUM_UNIT_XGS3_48G; unit++) { 1522 BCM_IF_ERROR_RETURN(chassis_xgs3_mirror_to_set(unit, 1523 &external_sp_tbl[unit], 1524 l_entry->base.slot_id, 1525 db_ref)); 1526 } 1527 1528 /* Set mod IDs */ 1529 for (unit = 0; unit < NUM_UNIT_XGS3_48G; unit++) { 1530 if ((dst_modid = chassis_unit_modid_get(unit, l_entry)) < 0) { 1531 continue; 1532 } 1533 BCM_IF_ERROR_RETURN(bcm_stk_my_modid_set(unit, dst_modid)); 1534 } 1535 1536 #ifdef BCM_BOARD_AUTO_E2E 1537 /* intra-board end to end flow control, if available */ 1538 BCM_IF_ERROR_RETURN 1539 (_bcm_board_dual_xgs3_e2e_set(FB_UNIT0, 1540 tp_cpu->local_entry.mod_ids[0], 1541 FB_UNIT1, 1542 tp_cpu->local_entry.mod_ids[1])); 1543 #endif /* BCM_BOARD_AUTO_E2E */ 1544 1545 return BCM_E_NONE; 1546 } 1547 1548 #undef FB_UNIT0 1549 #undef FB_UNIT1 1550 1551 /* 1552 * Function: chassis_smlb_cfm_xgs3 1553 * 1554 * Purpose: 1555 * Program the XGS3 CFM board using Chassis Load Balancing. 1556 */ 1557 int 1558 chassis_smlb_cfm_xgs3(topo_cpu_t *tp_cpu, cpudb_ref_t db_ref) 1559 { 1560 cpudb_entry_t *l_entry; 1561 int l_slot; 1562 int unit; 1563 bcm_port_t stk_port; 1564 int dst_slot; 1565 int src_modid; 1566 int peer_cfm_slot; 1567 bcm_module_t modid; 1568 int lm_to_cfm; 1569 int lm; 1570 int i, j; 1571 int enable; 1572 int lb_even_odd; 1573 bcm_board_cfm_info_t cfm_info; 1574 bcm_port_config_t config; 1575 bcm_port_t port; 1576 1577 static sp_list_t external_sp = { 1578 16, 1579 {0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17} 1580 }; 1581 static to_slot_t to_lm = { 1582 xgs3_modport_set, 1583 8, {{2, {2, {7, 10}}}, 1584 {3, {2, {6, 11}}}, 1585 {4, {2, {5, 12}}}, 1586 {5, {2, {4, 13}}}, 1587 {6, {2, {3, 14}}}, 1588 {7, {2, {2, 15}}}, 1589 {8, {2, {1, 16}}}, 1590 {9, {2, {0, 17}}}}}; 1591 1592 1593 COMPILER_REFERENCE(tp_cpu); 1594 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 1595 (BSL_META("TOPO: XGS 56700 BCM956010 CFM (Load Balancing)\n"))); 1596 1597 /* Only 1 unit */ 1598 unit = 0; 1599 l_entry = db_ref->local_entry; 1600 l_slot = l_entry->base.slot_id; 1601 bcm_board_cfm_info(db_ref, &cfm_info); 1602 1603 /* Set CPU mod ID for fabric unit */ 1604 modid = l_entry->dest_mod; 1605 BCM_IF_ERROR_RETURN(bcm_port_config_get(unit, &config)); 1606 BCM_PBMP_ITER(config.cpu, port) { 1607 break; /* Get CPU port */ 1608 } 1609 1610 BCM_IF_ERROR_RETURN(bcm_stk_my_modid_set(0, modid)); 1611 BCM_IF_ERROR_RETURN(bcm_stk_modport_set(unit, modid, port)); 1612 1613 /* Set and enable CPU source mod ID */ 1614 BCM_IF_ERROR_RETURN(c2c_src_mod_get(&src_modid)); 1615 for (i = 0; i < external_sp.port_cnt; i++) { 1616 stk_port = external_sp.port[i]; 1617 BCM_IF_ERROR_RETURN(bcm_port_modid_enable_set(unit, stk_port, 1618 src_modid, TRUE)); 1619 } 1620 1621 /* 1622 * Set source mod ID filtering for LMs 1623 * If one CFM 1624 * accept all mod IDs, 1625 * Else 1626 * CFM on even slot should only accept even mod IDs 1627 * CFM on odd slot should only accept odd mod IDs 1628 */ 1629 1630 /* For each external CFM stack port */ 1631 for (i = 0; i < external_sp.port_cnt; i++) { 1632 stk_port = external_sp.port[i]; 1633 1634 /* For each LM */ 1635 for (lm = 0; lm < to_lm.slot_cnt; lm++) { 1636 enable = FALSE; 1637 lb_even_odd = FALSE; 1638 dst_slot = to_lm.slot[lm].dst; 1639 1640 /* 1641 * If LM is valid and external stack port is 1642 * connected directly to LM: 1643 * - If only 1 CFM, allow all mod IDs from LM 1644 * - If 2 CFMs, allow mod IDs based on even/odd logic 1645 */ 1646 if (is_slot_valid(dst_slot, db_ref)) { 1647 for (j = 0; j < to_lm.slot[lm].sp.port_cnt; j++) { 1648 if (stk_port == to_lm.slot[lm].sp.port[j]) { 1649 if (cfm_info.count == 1) { 1650 enable = TRUE; 1651 } else { 1652 lb_even_odd = TRUE; 1653 } 1654 break; 1655 } 1656 } 1657 } 1658 1659 /* For each mod ID that corresponds to a given LM */ 1660 FOREACH_MODID(dst_slot, modid) { 1661 if (lb_even_odd) { 1662 if (((IS_EVEN(l_slot)) && (IS_EVEN(modid))) || 1663 ((IS_ODD(l_slot)) && (IS_ODD(modid)))) { 1664 enable = TRUE; 1665 } 1666 else { 1667 enable = FALSE; 1668 } 1669 } 1670 BCM_IF_ERROR_RETURN(bcm_port_modid_enable_set(unit, stk_port, 1671 modid, enable)); 1672 } 1673 } 1674 } 1675 1676 /* Set source module filtering for NH */ 1677 chassis_nh_modid_filter(1, &external_sp); 1678 1679 /* Set routes to LMs */ 1680 lm_to_cfm = -1; 1681 for (lm = 0; lm < to_lm.slot_cnt; lm++) { 1682 dst_slot = to_lm.slot[lm].dst; 1683 if (!is_slot_valid(dst_slot, db_ref)) { 1684 continue; 1685 } 1686 1687 /* Use first port, other ports will be trunked */ 1688 stk_port = to_lm.slot[lm].sp.port[0]; 1689 lm_to_cfm = lm; 1690 FOREACH_MODID(dst_slot, modid) { 1691 BCM_IF_ERROR_RETURN(xgs3_modport_set(unit, modid, stk_port)); 1692 } 1693 } 1694 1695 1696 /* If there is an available external stack port, set route to peer CFM */ 1697 if (lm_to_cfm >= 0) { 1698 if (l_entry->base.slot_id == 0) { 1699 peer_cfm_slot = 1; 1700 } else { 1701 peer_cfm_slot = 0; 1702 } 1703 if (is_slot_valid(peer_cfm_slot, db_ref)) { 1704 /* Enable peer CFM source mod ID in all external stack ports */ 1705 for (i = 0; i < external_sp.port_cnt; i++) { 1706 stk_port = external_sp.port[i]; 1707 FOREACH_MODID(peer_cfm_slot, modid) { 1708 BCM_IF_ERROR_RETURN(bcm_port_modid_enable_set(unit, 1709 stk_port, 1710 modid, 1711 TRUE)); 1712 } 1713 } 1714 stk_port = to_lm.slot[lm_to_cfm].sp.port[0]; 1715 FOREACH_MODID(peer_cfm_slot, modid) { 1716 BCM_IF_ERROR_RETURN(xgs3_modport_set(unit, modid, stk_port)); 1717 } 1718 } 1719 } 1720 1721 /* Set trunks */ 1722 BCM_IF_ERROR_RETURN(bcm_board_trunk_system(l_entry, db_ref, 1723 BCM_BOARD_TRUNK_NORMAL)); 1724 1725 /* Set mod IDs */ 1726 /* Mod ID for fabric is set by caller */ 1727 bcm_board_unknown_src_modid_setup(l_entry); 1728 1729 return BCM_E_NONE; 1730 } 1731 1732 int 1733 chassis_smlb_56800_12x(topo_cpu_t *tp_cpu, cpudb_ref_t db_ref) 1734 { 1735 cpudb_entry_t *l_entry; 1736 int num_units; 1737 sp_list_t sp_list; 1738 bcm_board_cfm_info_t cfm_info; 1739 bcm_port_config_t config; 1740 bcm_port_t port; 1741 bcm_port_t stk_port; 1742 bcm_module_t src_modid; 1743 1744 static sp_list_t external_sp = {4, {0, 1, 2, 3}}; 1745 static to_slot_t to_cfm = { 1746 xgs3_modport_set, /* Unit 0:56800 */ 1747 2, {{0, {2, {1, 3}}}, 1748 {1, {2, {0, 2}}}} 1749 }; 1750 1751 LOG_VERBOSE(BSL_LS_TKS_TOPOLOGY, 1752 (BSL_META("TOPO: XGS3 56800 LM (Load Balancing)\n"))); 1753 1754 BCM_IF_ERROR_RETURN(bcm_port_config_get(0, &config)); 1755 1756 bcm_board_cfm_info(db_ref, &cfm_info); 1757 num_units = 1; 1758 l_entry = db_ref->local_entry; 1759 1760 /* Set CPU port */ 1761 BCM_PBMP_ITER(config.cpu, port) { 1762 break; /* Get CPU port */ 1763 } 1764 BCM_IF_ERROR_RETURN(bcm_stk_modport_set(0, l_entry->mod_ids[0], port)); 1765 1766 1767 /* Set packet forwarding tables */ 1768 BCM_IF_ERROR_RETURN(chassis_eroute_lm_cfm(num_units, 1769 &to_cfm, &sp_list, db_ref)); 1770 1771 src_modid = chassis_unit_modid_get(0, l_entry); 1772 if (IS_EVEN(src_modid)) { 1773 if ((stk_port = sp_list.port[EVEN_IDX]) < 0) { 1774 stk_port = sp_list.port[ODD_IDX]; 1775 } 1776 } else { 1777 if ((stk_port = sp_list.port[ODD_IDX]) < 0) { 1778 stk_port = sp_list.port[EVEN_IDX]; 1779 } 1780 } 1781 1782 if (stk_port >= 0) { 1783 BCM_IF_ERROR_RETURN(chassis_xgs3_eroute_lm_lm(0, stk_port, 1784 l_entry->base.slot_id)); 1785 } 1786 /* Set source module filtering */ 1787 BCM_IF_ERROR_RETURN(chassis_external_modid_filter(0, &external_sp, 1788 l_entry->base.slot_id, 1789 db_ref)); 1790 BCM_IF_ERROR_RETURN(chassis_nh_modid_filter(num_units, &external_sp)); 1791 1792 /* Set flood blocking */ 1793 BCM_IF_ERROR_RETURN(chassis_xgs3_flood_set(0, &external_sp, 1794 &to_cfm, db_ref, 1795 cfm_info.count)); 1796 1797 /* Set trunks */ 1798 BCM_IF_ERROR_RETURN(bcm_board_trunk_system(l_entry, db_ref, 1799 BCM_BOARD_TRUNK_NORMAL)); 1800 1801 /* Set mirroring */ 1802 BCM_IF_ERROR_RETURN(chassis_xgs3_mirror_to_set(0, &external_sp, 1803 l_entry->base.slot_id, 1804 db_ref)); 1805 1806 /* Set mod IDs */ 1807 bcm_board_unknown_src_modid_setup(l_entry); 1808 BCM_IF_ERROR_RETURN(bcm_stk_my_modid_set(0, l_entry->dest_mod)); 1809 1810 return BCM_E_NONE; 1811 } 1812 1813 #else 1814 int _brd_chassis_smlb_not_empty; 1815 #endif /* INCLUDE_CHASSIS */