extender.c (236626B)
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: extender.c 8 * Purpose: Implements Port Extension APIs for Triumph3. 9 */ 10 11 #include <soc/defs.h> 12 #include <sal/core/libc.h> 13 14 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3) 15 16 #include <soc/drv.h> 17 #include <soc/scache.h> 18 #include <soc/hash.h> 19 #include <soc/l2x.h> 20 #if defined(BCM_TRIDENT3_SUPPORT) 21 #include <soc/trident3.h> 22 #endif 23 #include <shared/bsl.h> 24 #include <bcm/error.h> 25 #include <bcm_int/esw/switch.h> 26 27 #include <bcm_int/esw_dispatch.h> 28 #include <bcm_int/api_xlate_port.h> 29 #include <bcm_int/common/multicast.h> 30 #include <bcm_int/esw/stack.h> 31 #include <bcm_int/esw/virtual.h> 32 #include <bcm_int/esw/port.h> 33 #include <bcm_int/esw/trx.h> 34 #include <bcm_int/esw/triumph2.h> 35 #include <bcm_int/esw/triumph3.h> 36 #include <bcm_int/esw/qos.h> 37 #include <bcm_int/esw/failover.h> 38 #include <bcm_int/esw/trident2.h> 39 #include <bcm_int/esw/tomahawk.h> 40 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 41 #include <bcm_int/esw/trident2plus.h> 42 #include <bcm_int/esw/xgs5.h> 43 #endif /* BCM_TRIDENT2PLUS_SUPPORT*/ 44 #if defined(BCM_SABER2_SUPPORT) 45 #include <soc/saber2.h> 46 #endif /* BCM_SABER2_SUPPORT */ 47 48 #define TD_EXTENDER_PORT_HASH_BKT_SIZE 32 49 /* 50 * Extender EGR_L3_NEXT_HOP View 51 */ 52 #define _BCM_EXTENDER_EGR_NEXT_HOP_SDTAG_VIEW 0x2 53 #define _BCM_EXTENDER_EGR_NEXT_HOP_L3MC_VIEW 0x7 54 55 /* 56 * Extender EGR_L3_NEXT_HOP VNTAG ACTIONS 57 */ 58 enum _BCM_EXTENDEREGR_NEXT_HOP_VNTAG_ACTIONS { 59 ETAG_NOOP = 0, 60 VNTAG_ADD_OR_REPLACE = 1, 61 ETAG_ADD_OR_REPLACE = 2, 62 ETAG_DELETE = 3, 63 VNTAG_ACTIONS_COUNT 64 }; 65 66 /* 67 * Software book keeping for Port Extension information 68 */ 69 typedef struct _bcm_tr3_extender_egress_s { 70 uint32 flags; 71 bcm_gport_t port; 72 uint16 extended_port_vid; 73 bcm_vlan_t match_vlan; 74 bcm_extender_pcp_de_select_t pcp_de_select; 75 int qos_map_id; 76 uint8 pcp; 77 uint8 de; 78 int service_qos_map_id; 79 uint16 service_tpid; 80 bcm_vlan_t service_vlan; 81 uint8 service_pri; 82 uint8 service_cfi; 83 int next_hop_index; 84 bcm_if_t intf; 85 uint32 multicast_flags; 86 struct _bcm_tr3_extender_egress_s *next; /* Pointer to next Extender egress 87 object */ 88 } _bcm_tr3_extender_egress_t; 89 90 typedef struct _bcm_tr3_extender_nh_info_s { 91 bcm_port_t port; 92 int nh_ref_cnt; 93 struct _bcm_tr3_extender_nh_info_s *next; 94 } _bcm_tr3_extender_nh_info_t; 95 96 typedef struct _bcm_tr3_extender_port_info_s { 97 uint32 flags; 98 bcm_gport_t port; 99 uint16 extended_port_vid; 100 bcm_extender_pcp_de_select_t pcp_de_select; 101 int qos_map_id; 102 uint8 pcp; 103 uint8 de; 104 bcm_vlan_t match_vlan; 105 _bcm_tr3_extender_egress_t *egress_list; /* Linked list of Extender egress 106 objects */ 107 _bcm_tr3_extender_nh_info_t *mc_nh_info; 108 /* nh info for multicast egress objects. */ 109 } _bcm_tr3_extender_port_info_t; 110 111 /* Structure to facilitate passing of SD-tag parameters */ 112 typedef struct _bcm_tr3_extender_sd_tag_s { 113 uint32 flags; 114 uint16 service_tpid; 115 bcm_vlan_t service_vlan; 116 uint8 service_pri; 117 uint8 service_cfi; 118 int service_qos_map_id; 119 } _bcm_tr3_extender_sd_tag_t; 120 121 typedef struct _bcm_tr3_extender_bookkeeping_s { 122 _bcm_tr3_extender_port_info_t *port_info; /* VP state */ 123 int invalid_next_hop_index; 124 } _bcm_tr3_extender_bookkeeping_t; 125 126 static _bcm_tr3_extender_bookkeeping_t _bcm_tr3_extender_bk_info[BCM_MAX_NUM_UNITS]; 127 128 #define EXTENDER_INFO(unit) (&_bcm_tr3_extender_bk_info[unit]) 129 #define EXTENDER_PORT_INFO(unit, vp) (&EXTENDER_INFO(unit)->port_info[vp]) 130 #define EXTENDER_PORT_HASH_BKT(unit, vp, idx) \ 131 (&(EXTENDER_PORT_INFO(unit, vp)->egress_list[idx])) 132 #define EXTENDER_PORT_MC_NH_INFO(unit, vp) (EXTENDER_PORT_INFO(unit, vp)->mc_nh_info) 133 134 STATIC int 135 _bcm_tr3_extender_egress_pbmp_add(int unit, int vp, bcm_pbmp_t pbmp); 136 137 STATIC int 138 _bcm_tr3_extender_egress_hash_calc(int unit, void *hash_key, uint16 *hash); 139 140 /* 141 * Function: 142 * _bcm_tr3_extender_port_cnt_update 143 * Purpose: 144 * Update port's VP count. 145 * Parameters: 146 * unit - (IN) SOC unit number. 147 * gport - (IN) GPORT ID. 148 * vp - (IN) Virtual port number. 149 * incr - (IN) If TRUE, increment VP count, else decrease VP count. 150 * Returns: 151 * BCM_X_XXX 152 */ 153 STATIC int 154 _bcm_tr3_extender_port_cnt_update(int unit, bcm_gport_t gport, 155 int vp, int incr) 156 { 157 int mod_out, port_out, tgid_out, id_out; 158 bcm_port_t local_member_array[SOC_MAX_NUM_PORTS]; 159 int local_member_count; 160 int idx; 161 int mod_local; 162 _bcm_port_info_t *port_info; 163 uint32 port_flags; 164 165 BCM_IF_ERROR_RETURN 166 (_bcm_esw_gport_resolve(unit, gport, &mod_out, 167 &port_out, &tgid_out, &id_out)); 168 if (-1 != id_out) { 169 return BCM_E_PARAM; 170 } 171 172 /* Update the physical port's SW state. If associated with a trunk, 173 * update each local physical port's SW state. 174 */ 175 176 if (BCM_TRUNK_INVALID != tgid_out) { 177 178 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid_out, 179 SOC_MAX_NUM_PORTS, local_member_array, &local_member_count)); 180 181 for (idx = 0; idx < local_member_count; idx++) { 182 _bcm_port_info_access(unit, local_member_array[idx], &port_info); 183 if (incr) { 184 port_info->vp_count++; 185 } else { 186 port_info->vp_count--; 187 } 188 BCM_IF_ERROR_RETURN( 189 bcm_esw_port_vlan_member_get( 190 unit, local_member_array[idx], &port_flags)); 191 BCM_IF_ERROR_RETURN( 192 bcm_esw_port_vlan_member_set( 193 unit, local_member_array[idx], port_flags)); 194 } 195 } else { 196 BCM_IF_ERROR_RETURN 197 (_bcm_esw_modid_is_local(unit, mod_out, &mod_local)); 198 if (mod_local) { 199 if (soc_feature(unit, soc_feature_sysport_remap)) { 200 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 201 } 202 _bcm_port_info_access(unit, port_out, &port_info); 203 if (incr) { 204 port_info->vp_count++; 205 } else { 206 port_info->vp_count--; 207 } 208 BCM_IF_ERROR_RETURN( 209 bcm_esw_port_vlan_member_get( 210 unit, port_out, &port_flags)); 211 BCM_IF_ERROR_RETURN( 212 bcm_esw_port_vlan_member_set( 213 unit, port_out, port_flags)); 214 } 215 } 216 217 return BCM_E_NONE; 218 } 219 220 #ifdef BCM_WARM_BOOT_SUPPORT 221 222 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 223 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_0 224 225 /* 226 * Function: 227 * _bcm_tr3_extender_egress_hash_recover 228 * Purpose: 229 * Recover the vp based hash table according to hardware information. 230 * Parameters: 231 * unit - (IN) SOC unit Number 232 * vp - (IN) Virtual port number. 233 * node - (IN) extender egress hardware information. 234 * Returns: 235 * BCM_E_XXX 236 */ 237 STATIC int 238 _bcm_tr3_extender_egress_hash_recover( 239 int unit, int vp, _bcm_tr3_extender_egress_t *node) 240 { 241 int bkt_idx, alloc_size; 242 uint16 hash_val; 243 bcm_extender_egress_t extender_egress; 244 _bcm_tr3_extender_egress_t *temp_ptr = NULL; 245 246 bcm_extender_egress_t_init(&extender_egress); 247 extender_egress.flags = node->flags; 248 extender_egress.port = node->port; 249 extender_egress.intf = node->intf; 250 extender_egress.service_tpid = node->service_tpid; 251 extender_egress.service_vlan = node->service_vlan; 252 extender_egress.service_pri = node->service_pri; 253 extender_egress.service_cfi = node->service_cfi; 254 extender_egress.service_qos_map_id = node->service_qos_map_id; 255 extender_egress.extended_port_vid = node->extended_port_vid; 256 extender_egress.pcp = node->pcp; 257 extender_egress.de = node->de; 258 BCM_IF_ERROR_RETURN( 259 _bcm_tr3_extender_egress_hash_calc(unit, (void *)&extender_egress, 260 &hash_val)); 261 bkt_idx = hash_val % TD_EXTENDER_PORT_HASH_BKT_SIZE; 262 if ((EXTENDER_PORT_INFO(unit, vp)->egress_list == NULL)) { 263 alloc_size = sizeof(_bcm_tr3_extender_egress_t) * 264 TD_EXTENDER_PORT_HASH_BKT_SIZE; 265 temp_ptr = sal_alloc(alloc_size, "EXTENDER egress object"); 266 if (NULL == temp_ptr) { 267 return BCM_E_MEMORY; 268 } 269 sal_memset(temp_ptr, 0, alloc_size); 270 EXTENDER_PORT_INFO(unit, vp)->egress_list = temp_ptr; 271 } 272 node->next = EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next; 273 EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next = node; 274 275 return BCM_E_NONE; 276 } 277 278 /* 279 * Function: 280 * bcm_tr3_extender_required_scache_size_get 281 * Purpose: 282 * Get required Extender module scache size for Level 2 Warm Boot 283 * Parameters: 284 * unit - StrataSwitch unit number. 285 * size - (OUT) Required scache size. 286 * Returns: 287 * BCM_E_XXX 288 */ 289 int 290 bcm_tr3_extender_required_scache_size_get(int unit, uint32 *size) 291 { 292 int num_vp; 293 int num_nh; 294 int num_ports; 295 296 *size = 0; 297 /* Add size required to store the bitmap of Extender VPs that 298 * were created without match criteria. 299 */ 300 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 301 *size += SHR_BITALLOCSIZE(num_vp); 302 303 /* Add size required to store the bitmap of next hops that 304 * are associated with Extender egress objects. 305 */ 306 num_nh = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 307 *size += SHR_BITALLOCSIZE(num_nh); 308 309 /* Add size required to store an array of physical port bitmaps. 310 * The size of the array equals to the number of next hops. 311 * A next hop entry may be shared by multiple Extender egress objects that 312 * have identical attributes except for the physical port. Hence, 313 * the physical port of each Extender egress object cannot be recovered 314 * from hardware and needs to be stored in the next hop's physical 315 * port bitmap. 316 */ 317 num_ports = soc_mem_field_length(unit, L3_IPMCm, L3_BITMAPf); 318 *size += (SHR_BITALLOCSIZE(num_ports) * num_nh); 319 320 /* Add size required to store match_vlan. There can be at most 321 * one match_vlan per Extender virtual port. 322 */ 323 *size += (sizeof(bcm_vlan_t) * num_vp); 324 325 /* Add size required to store the bitmap of next hops which 326 * are associated with BCM_EXTENDER_EGRESS_MULTICAST. 327 */ 328 *size += SHR_BITALLOCSIZE(num_nh); 329 330 return BCM_E_NONE; 331 } 332 333 /* 334 * Function: 335 * bcm_tr3_extender_sync 336 * Purpose: 337 * Record persistent info into the scache. 338 * Parameters: 339 * unit - StrataSwitch unit # 340 * scache_ptr - (IN/OUT) Scache pointer 341 * Returns: 342 * BCM_E_xxx 343 */ 344 345 int 346 _bcm_tr3_extender_sync(int unit, uint8 **scache_ptr) 347 { 348 int rv = BCM_E_NONE; 349 int num_vp, num_nh, num_ports; 350 SHR_BITDCL *match_none_vp_bitmap = NULL; 351 SHR_BITDCL *nh_bitmap = NULL; 352 SHR_BITDCL *mc_nh_bitmap = NULL; 353 SHR_BITDCL **pbmp_ptr_array = NULL; 354 bcm_vlan_t *match_vlan_array = NULL; 355 int i; 356 _bcm_tr3_extender_egress_t *curr_ptr; 357 int nh_index; 358 bcm_module_t mod_out; 359 bcm_port_t port_out; 360 bcm_trunk_t tgid_out; 361 int id_out; 362 bcm_port_t local_member_array[SOC_MAX_NUM_PORTS]; 363 int local_member_count; 364 int mod_local; 365 int bkt_idx, bkt_size; 366 int vp_mc = 0; 367 #if defined(BCM_SABER2_SUPPORT) 368 uint32 source_vp_sb2_5626x = 0xFED5ABC7; 369 #endif /* BCM_SABER2_SUPPORT */ 370 371 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 372 num_nh = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 373 num_ports = soc_mem_field_length(unit, L3_IPMCm, L3_BITMAPf); 374 375 /* Allocate a bitmap of Extender VPs that were created without match criteria */ 376 match_none_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), 377 "Bitmap of Extender VPs without match criteria"); 378 if (NULL == match_none_vp_bitmap) { 379 rv = BCM_E_MEMORY; 380 goto cleanup; 381 } 382 sal_memset(match_none_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp)); 383 384 /* Allocate a bitmap of next hops associated with Extender egress objects */ 385 nh_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_nh), "Bitmap of NHs"); 386 if (NULL == nh_bitmap) { 387 rv = BCM_E_MEMORY; 388 goto cleanup; 389 } 390 sal_memset(nh_bitmap, 0, SHR_BITALLOCSIZE(num_nh)); 391 392 /* Allocate an array of pointers to port bitmaps */ 393 pbmp_ptr_array = sal_alloc(sizeof(SHR_BITDCL *) * num_nh, 394 "Array of pointers to pbmp"); 395 if (NULL == pbmp_ptr_array) { 396 rv = BCM_E_MEMORY; 397 goto cleanup; 398 } 399 sal_memset(pbmp_ptr_array, 0, sizeof(SHR_BITDCL *) * num_nh); 400 401 /* Allocate an array of match_vlan */ 402 match_vlan_array = sal_alloc(sizeof(bcm_vlan_t) * num_vp, 403 "Array of match_vlan"); 404 if (NULL == match_vlan_array) { 405 rv = BCM_E_MEMORY; 406 goto cleanup; 407 } 408 sal_memset(match_vlan_array, 0, sizeof(bcm_vlan_t) * num_vp); 409 410 /* Allocate a bitmap of next hops associated with multicast Extender egress objects */ 411 mc_nh_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_nh), "Bitmap of multicast NHs"); 412 if (NULL == mc_nh_bitmap) { 413 rv = BCM_E_MEMORY; 414 goto cleanup; 415 } 416 sal_memset(mc_nh_bitmap, 0, SHR_BITALLOCSIZE(num_nh)); 417 418 /* Traverse Extender VPs */ 419 for (i = 0; i < num_vp; i++) { 420 if (EXTENDER_PORT_INFO(unit, i)->flags & BCM_EXTENDER_PORT_MATCH_NONE) { 421 SHR_BITSET(match_none_vp_bitmap, i); 422 /* Traverse this Extender VP's list of Extender egress objects */ 423 vp_mc = 0; 424 if (EXTENDER_PORT_MC_NH_INFO(unit, i) != NULL) { 425 /* The shared vp associates with mulicast egress objects. */ 426 if (EXTENDER_PORT_INFO(unit, i)->egress_list == NULL) { 427 rv = BCM_E_INTERNAL; 428 goto cleanup; 429 } 430 vp_mc = 1; 431 } 432 bkt_size = vp_mc ? TD_EXTENDER_PORT_HASH_BKT_SIZE : 1; 433 for (bkt_idx = 0; bkt_idx < bkt_size; bkt_idx++) { 434 if (vp_mc) { 435 curr_ptr = EXTENDER_PORT_HASH_BKT(unit, i, bkt_idx)->next; 436 } else { 437 curr_ptr = EXTENDER_PORT_INFO(unit, i)->egress_list; 438 } 439 440 while (NULL != curr_ptr) { 441 if (curr_ptr->match_vlan) { 442 /* Match_vlan can be nonzero only for unicast Extender egress 443 * objects, and there can be at most one unicast Extender 444 * egress object in the Extender port's egress_list. These 445 * constraints are enforced by bcm_tr3_extender_egress_add. 446 */ 447 match_vlan_array[i] = curr_ptr->match_vlan; 448 } 449 450 nh_index = curr_ptr->next_hop_index; 451 SHR_BITSET(nh_bitmap, nh_index); 452 453 if (curr_ptr->flags & BCM_EXTENDER_EGRESS_MULTICAST) { 454 SHR_BITSET(mc_nh_bitmap, nh_index); 455 } 456 457 /* If not already done, allocate a port bitmap for this 458 * next hop index. 459 */ 460 if (NULL == pbmp_ptr_array[nh_index]) { 461 pbmp_ptr_array[nh_index] = 462 sal_alloc(SHR_BITALLOCSIZE(num_ports), "NH pbmp"); 463 sal_memset(pbmp_ptr_array[nh_index], 0, 464 SHR_BITALLOCSIZE(num_ports)); 465 } 466 467 /* Set the bit in the port bitmap corresponding to the 468 * physical port this Extender egress object resides on. 469 */ 470 rv = _bcm_esw_gport_resolve(unit, curr_ptr->port, 471 &mod_out, &port_out, &tgid_out, &id_out); 472 if (BCM_FAILURE(rv)) { 473 goto cleanup; 474 } 475 if (BCM_TRUNK_INVALID != tgid_out) { 476 rv = _bcm_esw_trunk_local_members_get(unit, 477 tgid_out, SOC_MAX_NUM_PORTS, local_member_array, 478 &local_member_count); 479 if (BCM_FAILURE(rv)) { 480 goto cleanup; 481 } 482 /* Only one member needs to be added for warm boot recovery 483 * of the trunk group ID. 484 */ 485 if (local_member_count > 0) { 486 SHR_BITSET(pbmp_ptr_array[nh_index], local_member_array[0]); 487 } 488 } else { 489 rv = _bcm_esw_modid_is_local(unit, mod_out, &mod_local); 490 if (BCM_FAILURE(rv)) { 491 goto cleanup; 492 } 493 if (mod_local) { 494 SHR_BITSET(pbmp_ptr_array[nh_index], port_out); 495 } else { 496 rv = BCM_E_INTERNAL; 497 goto cleanup; 498 } 499 } 500 501 /* Advance to next egress object */ 502 curr_ptr = curr_ptr->next; 503 } 504 } 505 } else { /* BCM_EXTENDER_PORT_MATCH_NONE is not set */ 506 if (EXTENDER_PORT_INFO(unit, i)->match_vlan) { 507 match_vlan_array[i] = EXTENDER_PORT_INFO(unit, i)->match_vlan; 508 } 509 } 510 } 511 512 /* Maximum virtual port supported on saber2 5626x devices are 4K 513 * This fix is related to scaling down of vpn from 8K to 4K 514 */ 515 #if defined(BCM_SABER2_SUPPORT) 516 if (soc_sb2_5626x_devtype(unit)) { 517 sal_memcpy(*scache_ptr, &source_vp_sb2_5626x, sizeof(source_vp_sb2_5626x)); 518 *scache_ptr += sizeof(source_vp_sb2_5626x); 519 } 520 #endif /* BCM_SABER2_SUPPORT */ 521 522 /* Store in scache the bitmap of Extender VPs that were created without 523 * match criteria. 524 */ 525 sal_memcpy(*scache_ptr, match_none_vp_bitmap, SHR_BITALLOCSIZE(num_vp)); 526 *scache_ptr += SHR_BITALLOCSIZE(num_vp); 527 528 /* Store in scache the bitmap of next hops associated with 529 * Extender egress objects. 530 */ 531 sal_memcpy(*scache_ptr, nh_bitmap, SHR_BITALLOCSIZE(num_nh)); 532 *scache_ptr += SHR_BITALLOCSIZE(num_nh); 533 534 /* Store in scache the physical port bitmap of the next hops 535 * associated with Extender egress objects. 536 */ 537 for (i = 0; i < num_nh; i++) { 538 if (SHR_BITGET(nh_bitmap, i)) { 539 sal_memcpy(*scache_ptr, pbmp_ptr_array[i], 540 SHR_BITALLOCSIZE(num_ports)); 541 *scache_ptr += SHR_BITALLOCSIZE(num_ports); 542 } 543 } 544 545 /* Store in scache the array of match_vlan */ 546 sal_memcpy(*scache_ptr, match_vlan_array, sizeof(bcm_vlan_t) * num_vp); 547 *scache_ptr += (sizeof(bcm_vlan_t) * num_vp); 548 549 /* 550 * Store in scache the bitmap of next hops which are associated 551 * with BCM_EXTENDER_EGRESS_MULTICAST. 552 */ 553 sal_memcpy(*scache_ptr, mc_nh_bitmap, SHR_BITALLOCSIZE(num_nh)); 554 *scache_ptr += SHR_BITALLOCSIZE(num_nh); 555 556 cleanup: 557 if (NULL != match_none_vp_bitmap) { 558 sal_free(match_none_vp_bitmap); 559 } 560 if (NULL != nh_bitmap) { 561 sal_free(nh_bitmap); 562 } 563 if (NULL != pbmp_ptr_array) { 564 for (i = 0; i < num_nh; i++) { 565 if (NULL != pbmp_ptr_array[i]) { 566 /* pbmp_ptr_array[i] is not null when nh_bitmap[bit i] is set */ 567 sal_free(pbmp_ptr_array[i]); 568 } 569 } 570 sal_free(pbmp_ptr_array); 571 } 572 if (NULL != match_vlan_array) { 573 sal_free(match_vlan_array); 574 } 575 if (NULL != mc_nh_bitmap) { 576 sal_free(mc_nh_bitmap); 577 } 578 579 return rv; 580 } 581 582 /* 583 * Function: 584 * _bcm_tr3_extender_sd_tag_recover 585 * Purpose: 586 * Recover SD-tag fields from a egress next hop entry. 587 * Parameters: 588 * unit - Device Number 589 * egr_nh - Egress next hop entry 590 * sd_tag - (OUT) SD-tag fields 591 * Returns: 592 * BCM_E_XXX 593 */ 594 595 STATIC int 596 _bcm_tr3_extender_sd_tag_recover(int unit, egr_l3_next_hop_entry_t *egr_nh, 597 _bcm_tr3_extender_sd_tag_t *sd_tag) 598 { 599 int sd_tag_action_if_not_present; 600 int sd_tag_add; 601 int sd_tag_action_if_present; 602 int sd_tag_replace_vlan; 603 int sd_tag_replace_pri; 604 int sd_tag_replace_tpid; 605 int sd_tag_delete; 606 int tpid_index; 607 int pri_select; 608 int mapping_ptr; 609 int qos_map_type; 610 611 sal_memset(sd_tag, 0, sizeof(_bcm_tr3_extender_sd_tag_t)); 612 613 /* GET SD-tag action if packet doesn't have a SD-tag */ 614 sd_tag_action_if_not_present = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 615 egr_nh, SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf); 616 if (1 == sd_tag_action_if_not_present) { 617 sd_tag_add = TRUE; 618 } else { 619 sd_tag_add = FALSE; 620 } 621 622 /* GET SD-tag action if packet already has a SD-tag */ 623 sd_tag_action_if_present = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 624 egr_nh, SD_TAG__SD_TAG_ACTION_IF_PRESENTf); 625 sd_tag_replace_vlan = FALSE; 626 sd_tag_replace_pri = FALSE; 627 sd_tag_replace_tpid = FALSE; 628 sd_tag_delete = FALSE; 629 switch (sd_tag_action_if_present) { 630 case 1: /* REPLACE_VID_TPID */ 631 sd_tag_replace_vlan = TRUE; 632 sd_tag_replace_tpid = TRUE; 633 break; 634 case 2: /* REPLACE_VID_ONLY */ 635 sd_tag_replace_vlan = TRUE; 636 break; 637 case 3: /* DELETE SD-TAG */ 638 sd_tag_delete = TRUE; 639 break; 640 case 4: /* REPLACE_VID_PRI_TPID */ 641 sd_tag_replace_vlan = TRUE; 642 sd_tag_replace_pri = TRUE; 643 sd_tag_replace_tpid = TRUE; 644 break; 645 case 5: /* REPLACE_VID_PRI_ONLY */ 646 sd_tag_replace_vlan = TRUE; 647 sd_tag_replace_pri = TRUE; 648 break; 649 case 6: /* REPLACE_PRI_ONLY */ 650 sd_tag_replace_pri = TRUE; 651 break; 652 case 7: /* REPLACE_TPID_ONLY */ 653 sd_tag_replace_tpid = TRUE; 654 break; 655 default: 656 break; 657 } 658 659 /* Recover BCM_EXTENDER_EGRESS_SERVICE_xxx flags */ 660 if (sd_tag_add) { 661 sd_tag->flags |= BCM_EXTENDER_EGRESS_SERVICE_VLAN_ADD; 662 } 663 if (sd_tag_delete) { 664 sd_tag->flags |= BCM_EXTENDER_EGRESS_SERVICE_VLAN_DELETE; 665 } 666 if (sd_tag_replace_vlan) { 667 sd_tag->flags |= BCM_EXTENDER_EGRESS_SERVICE_VLAN_REPLACE; 668 } 669 if (sd_tag_replace_pri) { 670 sd_tag->flags |= BCM_EXTENDER_EGRESS_SERVICE_PRI_REPLACE; 671 } 672 if (sd_tag_replace_tpid) { 673 sd_tag->flags |= BCM_EXTENDER_EGRESS_SERVICE_TPID_REPLACE; 674 } 675 676 /* Recover SD-tag TPID */ 677 if (sd_tag_add || sd_tag_replace_tpid) { 678 tpid_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 679 egr_nh, SD_TAG__SD_TAG_TPID_INDEXf); 680 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_tab_ref_count_add(unit, 681 tpid_index, 1)); 682 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_get(unit, 683 &sd_tag->service_tpid, tpid_index)); 684 } 685 686 /* Recover SD-tag VLAN ID */ 687 if (sd_tag_add || sd_tag_replace_vlan) { 688 sd_tag->service_vlan = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 689 egr_nh, SD_TAG__SD_TAG_VIDf); 690 } 691 692 /* Recover SD-tag Priority, CFI, and Qos Map ID */ 693 pri_select = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 694 egr_nh, SD_TAG__SD_TAG_DOT1P_PRI_SELECTf); 695 if (pri_select) { 696 mapping_ptr = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 697 egr_nh, SD_TAG__SD_TAG_DOT1P_MAPPING_PTRf); 698 qos_map_type = 2; /* _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS */ 699 BCM_IF_ERROR_RETURN(_bcm_tr2_qos_idx2id(unit, mapping_ptr, 700 qos_map_type, &sd_tag->service_qos_map_id)); 701 } else { 702 sd_tag->service_pri = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 703 egr_nh, SD_TAG__NEW_PRIf); 704 sd_tag->service_cfi = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 705 egr_nh, SD_TAG__NEW_CFIf); 706 } 707 708 return BCM_E_NONE; 709 } 710 711 /* 712 * Function: 713 * _bcm_tr3_extender_reinit 714 * Purpose: 715 * Warm boot recovery for the Extender module 716 * Parameters: 717 * unit - Device Number 718 * Returns: 719 * BCM_E_XXX 720 */ 721 STATIC int 722 _bcm_tr3_extender_reinit(int unit) 723 { 724 int rv = BCM_E_NONE; 725 int num_vp, num_nh, num_ports; 726 SHR_BITDCL *match_none_vp_bitmap = NULL; 727 SHR_BITDCL *extender_vp_bitmap = NULL; 728 SHR_BITDCL *nh_bitmap = NULL; 729 SHR_BITDCL *mc_nh_bitmap = NULL; 730 SHR_BITDCL **pbmp_ptr_array = NULL; 731 bcm_vlan_t *match_vlan_array = NULL; 732 soc_scache_handle_t scache_handle; 733 uint8 *scache_ptr; 734 uint16 recovered_ver; 735 int stable_size; 736 uint32 additional_scache_size = 0; 737 uint8 *ing_nh_buf = NULL; 738 ing_l3_next_hop_entry_t *ing_nh_entry; 739 uint8 *egr_nh_buf = NULL; 740 egr_l3_next_hop_entry_t *egr_nh_entry; 741 int i, index_min, index_max; 742 uint32 entry_type = 0, vp = 0, trunk_bit = 0, vntag_action = 0; 743 int lower_th, higher_th; 744 #ifdef BCM_TRIDENT2_SUPPORT 745 int etag_dot1p_mapping_ptr, map_id; 746 #endif 747 uint32 pcp_de_select_mode = 0; 748 _bcm_tr3_extender_sd_tag_t extender_sd_tag; 749 bcm_trunk_t tgid = 0; 750 bcm_module_t modid = 0, mod_out = 0; 751 bcm_port_t port_num = 0, port_out = 0; 752 int num_valid_ports; 753 int j; 754 _bcm_tr3_extender_egress_t *curr_ptr = NULL; 755 bcm_gport_t gport; 756 uint8 *svp_buf = NULL; 757 source_vp_entry_t *svp_entry; 758 int tpid_enable; 759 int vp_mc, mc_flags; 760 bcm_pbmp_t pbmp; 761 _bcm_vp_info_t vp_info; 762 int old_num_vp = 0; 763 #if defined(BCM_SABER2_SUPPORT) 764 uint32 source_vp_sb2_5626x = 0; 765 #endif /* BCM_SABER2_SUPPORT */ 766 soc_field_t entry_type_field; 767 uint32 dv, dt = SOC_MEM_FIF_DEST_INVALID; 768 769 _bcm_vp_info_init(&vp_info); 770 vp_info.vp_type = _bcmVpTypeExtender; 771 772 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 773 num_nh = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 774 num_ports = soc_mem_field_length(unit, L3_IPMCm, L3_BITMAPf); 775 776 /* Allocate a bitmap of Extender VPs that were created without match criteria */ 777 match_none_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), 778 "Bitmap of Extender VPs without match criteria"); 779 if (NULL == match_none_vp_bitmap) { 780 rv = BCM_E_MEMORY; 781 goto cleanup; 782 } 783 sal_memset(match_none_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp)); 784 785 /* Allocate a bitmap of Extender VPs */ 786 extender_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "Bitmap of Extender VPs"); 787 if (NULL == extender_vp_bitmap) { 788 rv = BCM_E_MEMORY; 789 goto cleanup; 790 } 791 sal_memset(extender_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp)); 792 793 /* Allocate a bitmap of next hops associated with Extender egress objects */ 794 nh_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_nh), "Bitmap of NHs"); 795 if (NULL == nh_bitmap) { 796 rv = BCM_E_MEMORY; 797 goto cleanup; 798 } 799 sal_memset(nh_bitmap, 0, SHR_BITALLOCSIZE(num_nh)); 800 801 /* Allocate an array of pointers to port bitmaps */ 802 pbmp_ptr_array = sal_alloc(sizeof(SHR_BITDCL *) * num_nh, 803 "Array of pointers to pbmp"); 804 if (NULL == pbmp_ptr_array) { 805 rv = BCM_E_MEMORY; 806 goto cleanup; 807 } 808 sal_memset(pbmp_ptr_array, 0, sizeof(SHR_BITDCL *) * num_nh); 809 810 /* Allocate an array of match_vlan */ 811 match_vlan_array = sal_alloc(sizeof(bcm_vlan_t) * num_vp, 812 "Array of match_vlan"); 813 if (NULL == match_vlan_array) { 814 rv = BCM_E_MEMORY; 815 goto cleanup; 816 } 817 sal_memset(match_vlan_array, 0, sizeof(bcm_vlan_t) * num_vp); 818 819 /* Allocate a bitmap of next hops associated with multicast Extender egress objects */ 820 mc_nh_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_nh), "Bitmap of multicast NHs"); 821 if (NULL == mc_nh_bitmap) { 822 rv = BCM_E_MEMORY; 823 goto cleanup; 824 } 825 sal_memset(mc_nh_bitmap, 0, SHR_BITALLOCSIZE(num_nh)); 826 827 rv = soc_stable_size_get(unit, &stable_size); 828 if (SOC_FAILURE(rv)) { 829 goto cleanup; 830 } 831 832 /* Read scache */ 833 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_EXTENDER, 0); 834 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 835 0, &scache_ptr, BCM_WB_DEFAULT_VERSION, &recovered_ver); 836 837 if (BCM_E_NOT_FOUND == rv) { 838 if ((stable_size == 0) || SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 839 rv = BCM_E_NONE; 840 } else { 841 /* Get scache size required for default version */ 842 rv = bcm_tr3_extender_required_scache_size_get(unit, 843 &additional_scache_size); 844 if (BCM_FAILURE(rv)) { 845 goto cleanup; 846 } 847 848 /* Upgrading from SDK release that does not have warmboot state */ 849 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 850 additional_scache_size, &scache_ptr, 851 BCM_WB_DEFAULT_VERSION, NULL); 852 if (BCM_FAILURE(rv)) { 853 goto cleanup; 854 } 855 } 856 857 } else if (BCM_FAILURE(rv)) { 858 goto cleanup; 859 } else { 860 /* Maximum virtual port supported on saber2 5626x devices are 4K 861 * This fix is related to scaling down of vpn from 8K to 4K 862 */ 863 #if defined(BCM_SABER2_SUPPORT) 864 if (soc_sb2_5626x_devtype(unit)) { 865 sal_memcpy(&source_vp_sb2_5626x, scache_ptr, 866 sizeof(source_vp_sb2_5626x)); 867 if (source_vp_sb2_5626x == 0xFED5ABC7) { 868 scache_ptr += sizeof(source_vp_sb2_5626x); 869 } else { 870 old_num_vp = 1; 871 } 872 } 873 #endif /* BCM_SABER2_SUPPORT */ 874 /* Recover the bitmap of Extender VPs that were created without 875 * match criteria. 876 */ 877 sal_memcpy(match_none_vp_bitmap, scache_ptr, SHR_BITALLOCSIZE(num_vp)); 878 if (old_num_vp) { 879 scache_ptr += SHR_BITALLOCSIZE(num_vp * 2); 880 } else { 881 scache_ptr += SHR_BITALLOCSIZE(num_vp); 882 } 883 884 /* Recover the bitmap of next hops associated with 885 * Extender egress objects. 886 */ 887 sal_memcpy(nh_bitmap, scache_ptr, SHR_BITALLOCSIZE(num_nh)); 888 scache_ptr += SHR_BITALLOCSIZE(num_nh); 889 890 /* Recover the physical port bitmap of the next hops associated 891 * with Extender egress objects. 892 */ 893 for (i = 0; i < num_nh; i++) { 894 if (SHR_BITGET(nh_bitmap, i)) { 895 pbmp_ptr_array[i] = sal_alloc(SHR_BITALLOCSIZE(num_ports), 896 "NH pbmp"); 897 sal_memcpy(pbmp_ptr_array[i], scache_ptr, 898 SHR_BITALLOCSIZE(num_ports)); 899 scache_ptr += SHR_BITALLOCSIZE(num_ports); 900 } 901 } 902 903 sal_memcpy(match_vlan_array, scache_ptr, sizeof(bcm_vlan_t) * num_vp); 904 if (old_num_vp) { 905 scache_ptr += (sizeof(bcm_vlan_t) * num_vp * 2); 906 } else { 907 scache_ptr += (sizeof(bcm_vlan_t) * num_vp); 908 } 909 910 /* Recover the bitmap of next hops associated with 911 * multicast Extender egress objects. 912 */ 913 sal_memcpy(mc_nh_bitmap, scache_ptr, SHR_BITALLOCSIZE(num_nh)); 914 scache_ptr += SHR_BITALLOCSIZE(num_nh); 915 916 if (additional_scache_size > 0) { 917 rv = soc_scache_realloc(unit, scache_handle,additional_scache_size); 918 if(BCM_FAILURE(rv)) { 919 goto cleanup; 920 } 921 } 922 } 923 924 /* Recover the BCM_EXTENDER_PORT_MATCH_NONE from match_none_vp_bitmap */ 925 for (i = 0; i < num_vp; i++) { 926 if (SHR_BITGET(match_none_vp_bitmap, i)) { 927 EXTENDER_PORT_INFO(unit, i)->flags |= BCM_EXTENDER_PORT_MATCH_NONE; 928 } 929 } 930 931 /* Copy match_none_vp_bitmap to extender_vp_bitmap */ 932 sal_memcpy(extender_vp_bitmap, match_none_vp_bitmap, SHR_BITALLOCSIZE(num_vp)); 933 934 /* Recover EXTENDER ports and EXTENDER egress objects from next hop tables */ 935 ing_nh_buf = soc_cm_salloc(unit, 936 SOC_MEM_TABLE_BYTES(unit, ING_L3_NEXT_HOPm), "Ing Next Hop buffer"); 937 if (NULL == ing_nh_buf) { 938 rv = BCM_E_MEMORY; 939 goto cleanup; 940 } 941 index_min = soc_mem_index_min(unit, ING_L3_NEXT_HOPm); 942 index_max = soc_mem_index_max(unit, ING_L3_NEXT_HOPm); 943 rv = soc_mem_read_range(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 944 index_min, index_max, ing_nh_buf); 945 if (SOC_FAILURE(rv)) { 946 goto cleanup; 947 } 948 949 egr_nh_buf = soc_cm_salloc(unit, 950 SOC_MEM_TABLE_BYTES(unit, EGR_L3_NEXT_HOPm), "Egr Next Hop buffer"); 951 if (NULL == egr_nh_buf) { 952 rv = BCM_E_MEMORY; 953 goto cleanup; 954 } 955 index_min = soc_mem_index_min(unit, EGR_L3_NEXT_HOPm); 956 index_max = soc_mem_index_max(unit, EGR_L3_NEXT_HOPm); 957 rv = soc_mem_read_range(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 958 index_min, index_max, egr_nh_buf); 959 if (SOC_FAILURE(rv)) { 960 goto cleanup; 961 } 962 963 /* Get multicast E-VID range */ 964 rv = bcm_esw_switch_control_get(unit, 965 bcmSwitchExtenderMulticastLowerThreshold, &lower_th); 966 if (SOC_FAILURE(rv)) { 967 goto cleanup; 968 } 969 rv = bcm_esw_switch_control_get(unit, 970 bcmSwitchExtenderMulticastHigherThreshold, &higher_th); 971 if (SOC_FAILURE(rv)) { 972 goto cleanup; 973 } 974 975 /* Check entry type */ 976 if (SOC_IS_TRIDENT3X(unit)) { 977 entry_type_field = DATA_TYPEf; 978 } else { 979 entry_type_field = ENTRY_TYPEf; 980 } 981 982 for (i = index_min; i <= index_max; i++) { 983 egr_nh_entry = soc_mem_table_idx_to_pointer(unit, EGR_L3_NEXT_HOPm, 984 egr_l3_next_hop_entry_t *, egr_nh_buf, i); 985 986 /* Check entry type */ 987 entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 988 entry_type_field); 989 990 if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_SDTAG_VIEW) { 991 /* Check that VN-tag action is ADD */ 992 vntag_action = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 993 SD_TAG__VNTAG_ACTIONSf); 994 if ((ETAG_ADD_OR_REPLACE!= vntag_action) && (ETAG_NOOP != vntag_action)) { 995 continue; 996 } 997 998 /* Check pcp_de_select mode */ 999 pcp_de_select_mode = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1000 SD_TAG__ETAG_PCP_DE_SOURCEf); 1001 if ((BCM_EXTENDER_PCP_DE_SELECT_DEFAULT != pcp_de_select_mode) 1002 && (BCM_EXTENDER_PCP_DE_SELECT_PHB != pcp_de_select_mode)) { 1003 continue; 1004 } 1005 1006 } else if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_L3MC_VIEW) { 1007 if (!soc_feature(unit, soc_feature_virtual_port_routing)) { 1008 continue; 1009 } 1010 1011 /* Check that VN-tag action is ADD */ 1012 vntag_action = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1013 L3MC__VNTAG_ACTIONSf); 1014 if ((ETAG_ADD_OR_REPLACE != vntag_action) && (ETAG_NOOP != vntag_action)) { 1015 continue; 1016 } 1017 1018 /* Check pcp_de_select mode */ 1019 pcp_de_select_mode = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1020 L3MC__ETAG_PCP_DE_SOURCEf); 1021 if ((BCM_EXTENDER_PCP_DE_SELECT_DEFAULT != pcp_de_select_mode) 1022 && (BCM_EXTENDER_PCP_DE_SELECT_PHB != pcp_de_select_mode)) { 1023 continue; 1024 } 1025 } else { 1026 /* Not Extender virtual port entry type */ 1027 continue; 1028 } 1029 1030 if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_SDTAG_VIEW) { 1031 /* Recover VP */ 1032 vp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1033 SD_TAG__DVPf); 1034 } else if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_L3MC_VIEW) { 1035 /* L3MC*/ 1036 vp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1037 L3MC__DVPf); 1038 } 1039 1040 if ((stable_size == 0) || SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 1041 rv = _bcm_vp_used_set(unit, vp, vp_info); 1042 if (BCM_FAILURE(rv)) { 1043 goto cleanup; 1044 } 1045 } else { 1046 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 1047 /* VP bitmap is recovered by virtual_init */ 1048 continue; 1049 } 1050 } 1051 1052 /* Add VP to EXTENDER VP bitmap */ 1053 SHR_BITSET(extender_vp_bitmap, vp); 1054 1055 if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) { 1056 if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_SDTAG_VIEW) { 1057 /* Recover ETAG PCP and DE info */ 1058 if (BCM_EXTENDER_PCP_DE_SELECT_DEFAULT == pcp_de_select_mode) { 1059 EXTENDER_PORT_INFO(unit, vp)->pcp_de_select = 1060 BCM_EXTENDER_PCP_DE_SELECT_DEFAULT; 1061 EXTENDER_PORT_INFO(unit, vp)->pcp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 1062 egr_nh_entry, SD_TAG__ETAG_PCPf); 1063 EXTENDER_PORT_INFO(unit, vp)->de = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 1064 egr_nh_entry, SD_TAG__ETAG_DEf); 1065 } else if (BCM_EXTENDER_PCP_DE_SELECT_PHB == pcp_de_select_mode) { 1066 EXTENDER_PORT_INFO(unit, vp)->pcp_de_select = 1067 BCM_EXTENDER_PCP_DE_SELECT_PHB; 1068 #ifdef BCM_TRIDENT2_SUPPORT 1069 /* Get ETAG priority mapping profile pointer */ 1070 etag_dot1p_mapping_ptr = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 1071 egr_nh_entry, SD_TAG__ETAG_DOT1P_MAPPING_PTRf); 1072 #ifdef BCM_TOMAHAWK_SUPPORT 1073 if (SOC_IS_TOMAHAWKX(unit)) { 1074 rv = bcm_th_qos_egr_etag_profile2id(unit, etag_dot1p_mapping_ptr, 1075 &map_id); 1076 } else 1077 #endif 1078 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TRIDENT3X(unit)) { 1079 rv = bcm_td2_qos_egr_etag_profile2id(unit, etag_dot1p_mapping_ptr, 1080 &map_id); 1081 } else { 1082 rv = BCM_E_BADID; 1083 } 1084 if (rv == BCM_E_NONE) { 1085 EXTENDER_PORT_INFO(unit, vp)->qos_map_id = map_id; 1086 } 1087 #endif 1088 } 1089 1090 /* Recover ETAG VID */ 1091 EXTENDER_PORT_INFO(unit, vp)->extended_port_vid = 1092 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1093 SD_TAG__VNTAG_DST_VIFf); 1094 1095 /* Recover multicast flag */ 1096 if ((EXTENDER_PORT_INFO(unit, vp)->extended_port_vid >= lower_th) && 1097 (EXTENDER_PORT_INFO(unit, vp)->extended_port_vid <= higher_th)) { 1098 EXTENDER_PORT_INFO(unit, vp)->flags |= BCM_EXTENDER_PORT_MULTICAST; 1099 } 1100 1101 /* Recover transparent flag */ 1102 if (vntag_action == ETAG_NOOP) { 1103 EXTENDER_PORT_INFO(unit, vp)->flags |= 1104 BCM_EXTENDER_PORT_EGRESS_TRANSPARENT; 1105 } 1106 1107 /* Recover physical trunk or port from ingress next hop table */ 1108 ing_nh_entry = soc_mem_table_idx_to_pointer(unit, 1109 ING_L3_NEXT_HOPm, ing_l3_next_hop_entry_t *, ing_nh_buf, i); 1110 if (soc_feature(unit, soc_feature_generic_dest)) { 1111 dv = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, ing_nh_entry, 1112 DESTINATIONf, &dt); 1113 if (dt == SOC_MEM_FIF_DEST_LAG) { 1114 tgid = dv; 1115 trunk_bit = 1; 1116 } else { 1117 trunk_bit = 0; 1118 port_num = dv & SOC_MEM_FIF_DGPP_PORT_MASK; 1119 modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 1120 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 1121 } 1122 } else { 1123 trunk_bit = soc_ING_L3_NEXT_HOPm_field32_get(unit, ing_nh_entry, Tf); 1124 if (trunk_bit) { 1125 tgid = soc_ING_L3_NEXT_HOPm_field32_get(unit, ing_nh_entry, 1126 TGIDf); 1127 } else { 1128 modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, ing_nh_entry, 1129 MODULE_IDf); 1130 port_num = soc_ING_L3_NEXT_HOPm_field32_get(unit, ing_nh_entry, 1131 PORT_NUMf); 1132 } 1133 } 1134 1135 if (trunk_bit) { 1136 BCM_GPORT_TRUNK_SET(EXTENDER_PORT_INFO(unit, vp)->port, tgid); 1137 } else { 1138 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 1139 modid, port_num, &mod_out, &port_out); 1140 if (BCM_FAILURE(rv)) { 1141 goto cleanup; 1142 } 1143 BCM_GPORT_MODPORT_SET(EXTENDER_PORT_INFO(unit, vp)->port, 1144 mod_out, port_out); 1145 } 1146 1147 /* The match_vlan can be recovered from either match_vlan_array 1148 * or EGR_L3_NEXT_HOP.SD_TAG_VID field. The latter approach 1149 * is taken since older SDKs stored match_vlan in EGR_L3_NEXT_HOP 1150 * entry, not in scache. 1151 */ 1152 EXTENDER_PORT_INFO(unit, vp)->match_vlan = 1153 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1154 SD_TAG__SD_TAG_VIDf); 1155 1156 if (stable_size == 0) { 1157 /* In the Port module, a port's VP count is not recovered in 1158 * level 1 Warm Boot. 1159 */ 1160 rv = _bcm_tr3_extender_port_cnt_update(unit, 1161 EXTENDER_PORT_INFO(unit, vp)->port, vp, TRUE); 1162 if (BCM_FAILURE(rv)) { 1163 goto cleanup; 1164 } 1165 } 1166 } 1167 } else { /* The Extender port was created without match criteria */ 1168 vp_mc = 0; 1169 BCM_PBMP_CLEAR(pbmp); 1170 if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_SDTAG_VIEW) { 1171 rv = _bcm_tr3_extender_sd_tag_recover(unit, egr_nh_entry, &extender_sd_tag); 1172 if (BCM_FAILURE(rv)) { 1173 goto cleanup; 1174 } 1175 1176 num_valid_ports = 0; 1177 for (j = 0; j < num_ports; j++) { 1178 if ((pbmp_ptr_array[i] != NULL) ? 1179 (SHR_BITGET(pbmp_ptr_array[i], j)) : 0) { 1180 /* Insert a new Extender egress object into VP's egress list */ 1181 curr_ptr = sal_alloc(sizeof(_bcm_tr3_extender_egress_t), 1182 "Extender egress object"); 1183 if (NULL == curr_ptr) { 1184 rv = BCM_E_MEMORY; 1185 goto cleanup; 1186 } 1187 sal_memset(curr_ptr, 0, sizeof(_bcm_tr3_extender_egress_t)); 1188 1189 curr_ptr->extended_port_vid = 1190 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1191 SD_TAG__VNTAG_DST_VIFf); 1192 1193 /* Recover multicast flag */ 1194 if (curr_ptr->extended_port_vid >= lower_th && 1195 curr_ptr->extended_port_vid <= higher_th) { 1196 curr_ptr->flags |= BCM_EXTENDER_EGRESS_MULTICAST; 1197 } 1198 1199 if (BCM_EXTENDER_PCP_DE_SELECT_DEFAULT == pcp_de_select_mode) { 1200 curr_ptr->pcp_de_select = 1201 BCM_EXTENDER_PCP_DE_SELECT_DEFAULT; 1202 curr_ptr->pcp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 1203 egr_nh_entry, SD_TAG__ETAG_PCPf); 1204 curr_ptr->de = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 1205 egr_nh_entry, SD_TAG__ETAG_DEf); 1206 } else if (BCM_EXTENDER_PCP_DE_SELECT_PHB == pcp_de_select_mode) { 1207 curr_ptr->pcp_de_select = BCM_EXTENDER_PCP_DE_SELECT_PHB; 1208 #ifdef BCM_TRIDENT2_SUPPORT 1209 /* Get ETAG priority mapping profile pointer */ 1210 etag_dot1p_mapping_ptr = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 1211 egr_nh_entry, SD_TAG__ETAG_DOT1P_MAPPING_PTRf); 1212 rv = bcm_td2_qos_egr_etag_profile2id(unit, 1213 etag_dot1p_mapping_ptr, &map_id); 1214 if (rv == BCM_E_NONE) { 1215 curr_ptr->qos_map_id = map_id; 1216 } 1217 #endif 1218 } 1219 rv = bcm_esw_port_gport_get(unit, j, &gport); 1220 if (BCM_FAILURE(rv)) { 1221 sal_free(curr_ptr); 1222 goto cleanup; 1223 } 1224 rv = bcm_esw_trunk_find(unit, BCM_MODID_INVALID, gport, &tgid); 1225 if (BCM_SUCCESS(rv)) { 1226 BCM_GPORT_TRUNK_SET(curr_ptr->port, tgid); 1227 } else if (rv == BCM_E_NOT_FOUND) { 1228 rv = BCM_E_NONE; 1229 curr_ptr->port = gport; 1230 } else { 1231 sal_free(curr_ptr); 1232 goto cleanup; 1233 } 1234 1235 curr_ptr->match_vlan = match_vlan_array[vp]; 1236 curr_ptr->flags |= extender_sd_tag.flags; 1237 curr_ptr->service_tpid = extender_sd_tag.service_tpid; 1238 curr_ptr->service_vlan = extender_sd_tag.service_vlan; 1239 curr_ptr->service_pri = extender_sd_tag.service_pri; 1240 curr_ptr->service_cfi = extender_sd_tag.service_cfi; 1241 curr_ptr->service_qos_map_id = extender_sd_tag.service_qos_map_id; 1242 curr_ptr->next_hop_index = i; 1243 curr_ptr->next = EXTENDER_PORT_INFO(unit, vp)->egress_list; 1244 if (curr_ptr->flags & BCM_EXTENDER_EGRESS_MULTICAST) { 1245 vp_mc = 1; 1246 rv = _bcm_tr3_extender_egress_hash_recover(unit, vp, curr_ptr); 1247 if (BCM_FAILURE(rv)) { 1248 sal_free(curr_ptr); 1249 goto cleanup; 1250 } 1251 BCM_PBMP_PORT_ADD(pbmp, j); 1252 } else { 1253 EXTENDER_PORT_INFO(unit, vp)->egress_list = curr_ptr; 1254 } 1255 1256 /* Increment the number of ports in port bitmap */ 1257 num_valid_ports++; 1258 } 1259 } 1260 1261 /* During warm boot, L3 module had already incremented reference 1262 * count for non-null next hop entries. Hence, the next hop's 1263 * reference count should be incremented further by num_valid_ports 1264 * minus one. 1265 */ 1266 for (j = 0; j < num_valid_ports - 1; j++) { 1267 _bcm_xgs3_nh_ref_cnt_incr(unit, i); 1268 } 1269 } else if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_L3MC_VIEW) { 1270 num_valid_ports = 0; 1271 vp_mc = 1; 1272 for (j = 0; j < num_ports; j++) { 1273 if ((pbmp_ptr_array[i] != NULL) ? 1274 (!SHR_BITGET(pbmp_ptr_array[i], j)) : 1) { 1275 continue; 1276 } 1277 /* Insert a new Extender egress object into VP's egress list */ 1278 curr_ptr = sal_alloc(sizeof(_bcm_tr3_extender_egress_t), 1279 "Extender egress object"); 1280 if (NULL == curr_ptr) { 1281 rv = BCM_E_MEMORY; 1282 goto cleanup; 1283 } 1284 sal_memset(curr_ptr, 0, sizeof(_bcm_tr3_extender_egress_t)); 1285 1286 /*entry_type == 7, L3MC */ 1287 curr_ptr->flags |= BCM_EXTENDER_EGRESS_L3; 1288 1289 if (BCM_EXTENDER_PCP_DE_SELECT_DEFAULT == pcp_de_select_mode) { 1290 curr_ptr->pcp_de_select = BCM_EXTENDER_PCP_DE_SELECT_DEFAULT; 1291 curr_ptr->pcp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 1292 egr_nh_entry, L3MC__ETAG_PCPf); 1293 curr_ptr->de = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 1294 egr_nh_entry, L3MC__ETAG_DEf); 1295 } else if (BCM_EXTENDER_PCP_DE_SELECT_PHB == pcp_de_select_mode) { 1296 curr_ptr->pcp_de_select = BCM_EXTENDER_PCP_DE_SELECT_PHB; 1297 #ifdef BCM_TRIDENT2_SUPPORT 1298 /* Get ETAG priority mapping profile pointer */ 1299 etag_dot1p_mapping_ptr = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 1300 egr_nh_entry, L3MC__ETAG_DOT1P_MAPPING_PTRf); 1301 rv = bcm_td2_qos_egr_etag_profile2id(unit, 1302 etag_dot1p_mapping_ptr, &map_id); 1303 if (rv == BCM_E_NONE) { 1304 curr_ptr->qos_map_id = map_id; 1305 } 1306 #endif 1307 } 1308 rv = bcm_esw_port_gport_get(unit, j, &gport); 1309 if (BCM_FAILURE(rv)) { 1310 sal_free(curr_ptr); 1311 goto cleanup; 1312 } 1313 rv = bcm_esw_trunk_find(unit, BCM_MODID_INVALID, gport, &tgid); 1314 if (BCM_SUCCESS(rv)) { 1315 BCM_GPORT_TRUNK_SET(curr_ptr->port, tgid); 1316 } else if (rv == BCM_E_NOT_FOUND) { 1317 rv = BCM_E_NONE; 1318 curr_ptr->port = gport; 1319 } else { 1320 sal_free(curr_ptr); 1321 goto cleanup; 1322 } 1323 curr_ptr->extended_port_vid = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1324 L3MC__VNTAG_DST_VIFf); 1325 /* Recover multicast flag */ 1326 if (curr_ptr->extended_port_vid >= lower_th && 1327 curr_ptr->extended_port_vid <= higher_th) { 1328 curr_ptr->flags |= BCM_EXTENDER_EGRESS_MULTICAST; 1329 } 1330 curr_ptr->next_hop_index = i; 1331 curr_ptr->intf = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1332 L3MC__INTF_NUMf); 1333 1334 mc_flags = 0; 1335 if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1336 L3MC__L2_MC_DA_DISABLEf)) { 1337 mc_flags |= BCM_L3_MULTICAST_L2_DEST_PRESERVE; 1338 } 1339 if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1340 L3MC__L2_MC_SA_DISABLEf)) { 1341 mc_flags |= BCM_L3_MULTICAST_L2_SRC_PRESERVE; 1342 } 1343 if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1344 L3MC__L2_MC_VLAN_DISABLEf)) { 1345 mc_flags |= BCM_L3_MULTICAST_L2_VLAN_PRESERVE; 1346 } 1347 if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1348 L3MC__L3_MC_TTL_DISABLEf)) { 1349 mc_flags |= BCM_L3_MULTICAST_TTL_PRESERVE; 1350 } 1351 if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1352 L3MC__L3_MC_DA_DISABLEf)) { 1353 mc_flags |= BCM_L3_MULTICAST_DEST_PRESERVE; 1354 } 1355 if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1356 L3MC__L3_MC_SA_DISABLEf)) { 1357 mc_flags |= BCM_L3_MULTICAST_SRC_PRESERVE; 1358 } 1359 if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1360 L3MC__L3_MC_VLAN_DISABLEf)) { 1361 mc_flags |= BCM_L3_MULTICAST_VLAN_PRESERVE; 1362 } 1363 if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1364 L3MC__L3_DROPf)) { 1365 mc_flags |= BCM_L3_MULTICAST_L3_DROP; 1366 } 1367 if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, 1368 L3MC__L2_DROPf)) { 1369 mc_flags |= BCM_L3_MULTICAST_L2_DROP; 1370 } 1371 curr_ptr->multicast_flags |= mc_flags; 1372 rv = _bcm_tr3_extender_egress_hash_recover( 1373 unit, vp, curr_ptr); 1374 if (BCM_FAILURE(rv)) { 1375 sal_free(curr_ptr); 1376 goto cleanup; 1377 } 1378 /* Increment the number of ports in port bitmap */ 1379 num_valid_ports++; 1380 BCM_PBMP_PORT_ADD(pbmp, j); 1381 } 1382 1383 /* During warm boot, L3 module had already incremented reference 1384 * count for non-null next hop entries. Hence, the next hop's 1385 * reference count should be incremented further by num_valid_ports 1386 * minus one. 1387 */ 1388 for (j = 0; j < num_valid_ports - 1; j++) { 1389 _bcm_xgs3_nh_ref_cnt_incr(unit, i); 1390 } 1391 } 1392 1393 if (vp_mc) { 1394 rv = _bcm_tr3_extender_egress_pbmp_add(unit, vp, pbmp); 1395 if (BCM_FAILURE(rv)) { 1396 sal_free(curr_ptr); 1397 goto cleanup; 1398 } 1399 } 1400 } 1401 } 1402 1403 /* Recover SD-tag TPID reference count from SOURCE_VP table */ 1404 if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_SDTAG_VIEW) { 1405 svp_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, SOURCE_VPm), 1406 "SOURCE_VP buffer"); 1407 if (NULL == svp_buf) { 1408 rv = BCM_E_MEMORY; 1409 goto cleanup; 1410 } 1411 index_min = soc_mem_index_min(unit, SOURCE_VPm); 1412 index_max = soc_mem_index_max(unit, SOURCE_VPm); 1413 rv = soc_mem_read_range(unit, SOURCE_VPm, MEM_BLOCK_ANY, 1414 index_min, index_max, svp_buf); 1415 if (SOC_FAILURE(rv)) { 1416 goto cleanup; 1417 } 1418 for (i = index_min; i <= index_max; i++) { 1419 svp_entry = soc_mem_table_idx_to_pointer 1420 (unit, SOURCE_VPm, source_vp_entry_t *, svp_buf, i); 1421 tpid_enable = soc_SOURCE_VPm_field32_get(unit, svp_entry, TPID_ENABLEf); 1422 if (tpid_enable) { 1423 for (j = 0; j < soc_mem_field_length(unit, SOURCE_VPm, TPID_ENABLEf); 1424 j++) { 1425 if (tpid_enable & (1 << j)) { 1426 rv = _bcm_fb2_outer_tpid_tab_ref_count_add(unit, j, 1); 1427 if (SOC_FAILURE(rv)) { 1428 goto cleanup; 1429 } 1430 } 1431 } 1432 } 1433 } 1434 } 1435 1436 cleanup: 1437 if (match_none_vp_bitmap) { 1438 sal_free(match_none_vp_bitmap); 1439 } 1440 if (extender_vp_bitmap) { 1441 sal_free(extender_vp_bitmap); 1442 } 1443 if (nh_bitmap) { 1444 sal_free(nh_bitmap); 1445 } 1446 if (mc_nh_bitmap) { 1447 sal_free(mc_nh_bitmap); 1448 } 1449 if (pbmp_ptr_array) { 1450 for (i = 0; i < num_nh; i++) { 1451 if (pbmp_ptr_array[i]) { 1452 sal_free(pbmp_ptr_array[i]); 1453 } 1454 } 1455 sal_free(pbmp_ptr_array); 1456 } 1457 if (match_vlan_array) { 1458 sal_free(match_vlan_array); 1459 } 1460 if (ing_nh_buf) { 1461 soc_cm_sfree(unit, ing_nh_buf); 1462 } 1463 if (egr_nh_buf) { 1464 soc_cm_sfree(unit, egr_nh_buf); 1465 } 1466 if (svp_buf) { 1467 soc_cm_sfree(unit, svp_buf); 1468 } 1469 1470 return rv; 1471 } 1472 #endif /* BCM_WARM_BOOT_SUPPORT */ 1473 1474 /* 1475 * Function: 1476 * _bcm_tr3_extender_free_resources 1477 * Purpose: 1478 * Free all allocated tables and memory 1479 * Parameters: 1480 * unit - SOC unit number 1481 * Returns: 1482 * Nothing 1483 */ 1484 STATIC void 1485 _bcm_tr3_extender_free_resources(int unit) 1486 { 1487 if (EXTENDER_INFO(unit)->port_info) { 1488 sal_free(EXTENDER_INFO(unit)->port_info); 1489 EXTENDER_INFO(unit)->port_info = NULL; 1490 } 1491 } 1492 1493 /* 1494 * Function: 1495 * bcm_tr3_extender_init 1496 * Purpose: 1497 * Initialize the Extender module. 1498 * Parameters: 1499 * unit - SOC unit number. 1500 * Returns: 1501 * BCM_E_XXX 1502 */ 1503 int 1504 bcm_tr3_extender_init(int unit) 1505 { 1506 int num_vp; 1507 int rv = BCM_E_NONE; 1508 1509 sal_memset(EXTENDER_INFO(unit), 0, 1510 sizeof(_bcm_tr3_extender_bookkeeping_t)); 1511 1512 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 1513 if (NULL == EXTENDER_INFO(unit)->port_info) { 1514 EXTENDER_INFO(unit)->port_info = sal_alloc 1515 (sizeof(_bcm_tr3_extender_port_info_t) * num_vp, 1516 "extender_port_info"); 1517 if (NULL == EXTENDER_INFO(unit)->port_info) { 1518 _bcm_tr3_extender_free_resources(unit); 1519 return BCM_E_MEMORY; 1520 } 1521 } 1522 sal_memset(EXTENDER_INFO(unit)->port_info, 0, 1523 sizeof(_bcm_tr3_extender_port_info_t) * num_vp); 1524 /* When creating a EXTENDER virtual port without any match criteria, 1525 * the ING_DVP_TABLE.NEXT_HOP_INDEX is configured with an invalid 1526 * next hop index, which is assigned to be the black hole next hop index. 1527 */ 1528 EXTENDER_INFO(unit)->invalid_next_hop_index = BCM_XGS3_L3_BLACK_HOLE_NH_IDX(unit); 1529 1530 #ifdef BCM_WARM_BOOT_SUPPORT 1531 if (SOC_WARM_BOOT(unit)) { 1532 /* Warm Boot recovery */ 1533 rv = _bcm_tr3_extender_reinit(unit); 1534 if (BCM_FAILURE(rv)) { 1535 _bcm_tr3_extender_free_resources(unit); 1536 } 1537 } else 1538 #endif /* BCM_WARM_BOOT_SUPPORT */ 1539 { 1540 /* Initialize ETAG VID multicast range */ 1541 BCM_IF_ERROR_RETURN(bcm_esw_switch_control_set(unit, 1542 bcmSwitchExtenderMulticastLowerThreshold, 0x1000)); 1543 BCM_IF_ERROR_RETURN(bcm_esw_switch_control_set(unit, 1544 bcmSwitchExtenderMulticastHigherThreshold, 0x3fff)); 1545 } 1546 1547 #ifdef BCM_TRIDENT3_SUPPORT 1548 if (SOC_IS_TRIDENT3X(unit)) { 1549 soc_td3_rx_etype_pe[unit] = 0; 1550 } 1551 #endif 1552 1553 return rv; 1554 } 1555 1556 /* 1557 * Function: 1558 * bcm_tr3_extender_cleanup 1559 * Purpose: 1560 * Detach the Extender module. 1561 * Parameters: 1562 * unit - SOC unit number. 1563 * Returns: 1564 * BCM_E_XXX 1565 */ 1566 int 1567 bcm_tr3_extender_cleanup(int unit) 1568 { 1569 _bcm_tr3_extender_free_resources(unit); 1570 1571 #ifdef BCM_TRIDENT3_SUPPORT 1572 if (SOC_IS_TRIDENT3X(unit)) { 1573 soc_td3_rx_etype_pe[unit] = 0; 1574 } 1575 #endif 1576 1577 return BCM_E_NONE; 1578 } 1579 1580 /* 1581 * Function: 1582 * _bcm_tr3_extender_failover_add 1583 * Purpose: 1584 * Setup a failover extender port id. 1585 * Parameters: 1586 * unit - (IN) SOC unit number. 1587 * extender_port - (IN) Pointer to Extender port structure. 1588 * vp - (IN) Virtual port number. 1589 * Returns: 1590 * BCM_X_XXX 1591 */ 1592 STATIC int 1593 _bcm_tr3_extender_failover_add(int unit, bcm_extender_port_t *extender_port, int vp) 1594 { 1595 int rv = BCM_E_NONE; 1596 ing_dvp_table_entry_t dvp_entry; 1597 int nh_index, failover_vp = -1, failover_nh_index = 0; 1598 uint32 protection_flags = 0; 1599 bcm_extender_port_t *ep = extender_port; 1600 1601 if (_BCM_MULTICAST_IS_SET(ep->failover_mc_group)) { 1602 protection_flags |= _BCM_FAILOVER_1_PLUS_PROTECTION; 1603 } else { 1604 /* Get egress next-hop index from Failover EXTENDER gport */ 1605 failover_vp = 1606 BCM_GPORT_EXTENDER_PORT_ID_GET(ep->failover_port_id); 1607 if (failover_vp != -1) { 1608 BCM_IF_ERROR_RETURN( 1609 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, failover_vp, 1610 &dvp_entry)); 1611 failover_nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 1612 NEXT_HOP_INDEXf); 1613 } 1614 } 1615 1616 BCM_IF_ERROR_RETURN( 1617 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 1618 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 1619 NEXT_HOP_INDEXf); 1620 /* Set the failover to a given extender port */ 1621 rv = _bcm_esw_failover_prot_nhi_create(unit, protection_flags, 1622 nh_index, failover_nh_index, 1623 ep->failover_mc_group, 1624 ep->failover_id); 1625 BCM_IF_ERROR_RETURN(rv); 1626 1627 return BCM_E_NONE; 1628 } 1629 1630 /* 1631 * Function: 1632 * _bcm_tr3_extender_failover_delete 1633 * Purpose: 1634 * Delete a failover extender port id. 1635 * Parameters: 1636 * unit - (IN) SOC unit number. 1637 * gport - (IN) Extender GPORT ID. 1638 * Returns: 1639 * BCM_X_XXX 1640 */ 1641 STATIC int 1642 _bcm_tr3_extender_failover_delete(int unit, bcm_gport_t gport) 1643 { 1644 int rv = BCM_E_NONE; 1645 int nh_index; 1646 uint32 vp; 1647 ing_dvp_table_entry_t dvp_entry; 1648 1649 /* Get egress next-hop index from EXTENDER gport */ 1650 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport); 1651 1652 BCM_IF_ERROR_RETURN( 1653 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 1654 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 1655 NEXT_HOP_INDEXf); 1656 /* Cleanup the failover from a given extender port */ 1657 rv = _bcm_esw_failover_prot_nhi_cleanup(unit, nh_index); 1658 if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE)) { 1659 return rv; 1660 } 1661 1662 return BCM_E_NONE; 1663 } 1664 1665 /* 1666 * Function: 1667 * _bcm_tr3_extender_failover_get 1668 * Purpose: 1669 * Setup a failover extender port id. 1670 * Parameters: 1671 * unit - (IN) SOC unit number. 1672 * extender_port - (IN) extender port Id. 1673 * failover_port - (OUT) failover extender port Id. 1674 * failover_id - (OUT) failover object index.. 1675 * failover_mc_group - (OUT) failover multicast group id. 1676 * Returns: 1677 * BCM_X_XXX 1678 */ 1679 STATIC int 1680 _bcm_tr3_extender_failover_get(int unit, bcm_gport_t extender_port, 1681 bcm_gport_t *failover_port, 1682 bcm_failover_t *failover_id, 1683 bcm_multicast_t *failover_mc_group) 1684 { 1685 int failover_vp; 1686 uint32 vp; 1687 int nh_index, prot_nh_index = -1, multicast_group = 0; 1688 bcm_failover_t fo_id; 1689 ing_dvp_table_entry_t dvp_entry; 1690 egr_l3_next_hop_entry_t egr_nh; 1691 1692 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port); 1693 1694 BCM_IF_ERROR_RETURN 1695 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 1696 /* Get the next hop index */ 1697 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 1698 NEXT_HOP_INDEXf); 1699 /* Get the protecting information of this next hop index */ 1700 BCM_IF_ERROR_RETURN 1701 (_bcm_esw_failover_prot_nhi_get(unit, nh_index, &fo_id, 1702 &prot_nh_index, &multicast_group)); 1703 if (fo_id > 0) { 1704 if (_BCM_MULTICAST_IS_SET(multicast_group)) { 1705 if (failover_mc_group) { 1706 *failover_mc_group = multicast_group; 1707 } 1708 } else { 1709 if (failover_port) { 1710 /* Read the existing egress next_hop entry */ 1711 BCM_IF_ERROR_RETURN 1712 (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 1713 prot_nh_index, &egr_nh)); 1714 /* retrieve the failover virtual port from egress next hop entry */ 1715 failover_vp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 1716 SD_TAG__DVPf); 1717 /* failover port should also be a extender port */ 1718 if (!_bcm_vp_used_get(unit, failover_vp, _bcmVpTypeExtender)) { 1719 return BCM_E_PARAM; 1720 } 1721 BCM_GPORT_EXTENDER_PORT_ID_SET(*failover_port, failover_vp); 1722 } 1723 } 1724 if (failover_id) { 1725 *failover_id = fo_id; 1726 } 1727 1728 return BCM_E_NONE; 1729 } 1730 1731 return BCM_E_NOT_FOUND; 1732 } 1733 1734 /* 1735 * Function: 1736 * _bcm_tr3_extender_nh_info_set 1737 * Purpose: 1738 * Get a next hop index and configure next hop tables. 1739 * Parameters: 1740 * unit - (IN) SOC unit number. 1741 * extender_port - (IN) Pointer to Extender port structure. 1742 * vp - (IN) Virtual port number. 1743 * drop - (IN) Drop indication. 1744 * nh_index - (IN/OUT) Next hop index. 1745 * Returns: 1746 * BCM_X_XXX 1747 */ 1748 STATIC int 1749 _bcm_tr3_extender_nh_info_set(int unit, bcm_extender_port_t *extender_port, 1750 _bcm_tr3_extender_sd_tag_t *sd_tag, int vp, int drop, int *nh_index) 1751 { 1752 int rv; 1753 uint32 nh_flags; 1754 bcm_l3_egress_t nh_info; 1755 egr_l3_next_hop_entry_t egr_nh; 1756 uint8 egr_nh_entry_type; 1757 int etag_dot1p_mapping_ptr; 1758 bcm_module_t mod_out; 1759 bcm_port_t port_out; 1760 bcm_trunk_t trunk_id; 1761 int id; 1762 int ing_nh_port; 1763 int ing_nh_module; 1764 int ing_nh_trunk; 1765 ing_l3_next_hop_entry_t ing_nh; 1766 initial_ing_l3_next_hop_entry_t initial_ing_nh; 1767 int sd_tag_add = 0; 1768 int sd_tag_delete = 0; 1769 int sd_tag_replace_vlan = 0; 1770 int sd_tag_replace_pri = 0; 1771 int sd_tag_replace_tpid = 0; 1772 int tpid_index; 1773 int mapping_ptr; 1774 soc_field_t ent_type_f = ENTRY_TYPEf; 1775 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, DATA_TYPEf)) { 1776 ent_type_f = DATA_TYPEf; 1777 } 1778 1779 /* Get a next hop index */ 1780 1781 if (extender_port->flags & BCM_EXTENDER_PORT_REPLACE) { 1782 if ((*nh_index > soc_mem_index_max(unit, EGR_L3_NEXT_HOPm)) || 1783 (*nh_index < soc_mem_index_min(unit, EGR_L3_NEXT_HOPm))) { 1784 return BCM_E_PARAM; 1785 } 1786 } else { 1787 /* 1788 * Allocate a next-hop entry. By calling bcm_xgs3_nh_add() 1789 * with _BCM_L3_SHR_WRITE_DISABLE flag, a next-hop index is 1790 * allocated but nothing is written to hardware. The "nh_info" 1791 * in this case is not used, so just set to all zeros. 1792 */ 1793 bcm_l3_egress_t_init(&nh_info); 1794 1795 nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE; 1796 rv = bcm_xgs3_nh_add(unit, nh_flags, &nh_info, nh_index); 1797 BCM_IF_ERROR_RETURN(rv); 1798 } 1799 1800 /* Write EGR_L3_NEXT_HOP entry */ 1801 1802 if (extender_port->flags & BCM_EXTENDER_PORT_REPLACE) { 1803 /* Read the existing egress next_hop entry */ 1804 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 1805 *nh_index, &egr_nh); 1806 BCM_IF_ERROR_RETURN(rv); 1807 1808 /* Be sure that the existing entry is programmed to SD-tag */ 1809 egr_nh_entry_type = 1810 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, ent_type_f); 1811 if (egr_nh_entry_type != 0x2) { /* != SD-tag */ 1812 return BCM_E_PARAM; 1813 } 1814 1815 /* Get ETAG priority mapping profile pointer */ 1816 etag_dot1p_mapping_ptr = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 1817 &egr_nh, SD_TAG__ETAG_DOT1P_MAPPING_PTRf); 1818 } else { 1819 egr_nh_entry_type = 0x2; /* SD-tag */ 1820 etag_dot1p_mapping_ptr = 0; 1821 #ifdef BCM_TOMAHAWK_SUPPORT 1822 if (SOC_IS_TOMAHAWKX(unit)) { 1823 bcm_th_qos_egr_etag_id2profile(unit, extender_port->qos_map_id, 1824 &etag_dot1p_mapping_ptr); 1825 } 1826 #endif 1827 #ifdef BCM_TRIDENT2_SUPPORT 1828 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TRIDENT3X(unit)){ 1829 bcm_td2_qos_egr_etag_id2profile(unit, extender_port->qos_map_id, 1830 &etag_dot1p_mapping_ptr); 1831 } 1832 #endif 1833 } 1834 1835 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 1836 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1837 ent_type_f, egr_nh_entry_type); 1838 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1839 SD_TAG__DVPf, vp); 1840 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1841 SD_TAG__HG_HDR_SELf, 1); 1842 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1843 SD_TAG__VNTAG_DST_VIFf, extender_port->extended_port_vid); 1844 if (extender_port->pcp_de_select == BCM_EXTENDER_PCP_DE_SELECT_DEFAULT) { 1845 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1846 SD_TAG__ETAG_PCP_DE_SOURCEf, 2); 1847 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1848 SD_TAG__ETAG_PCPf, extender_port->pcp); 1849 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1850 SD_TAG__ETAG_DEf, extender_port->de); 1851 } else if (extender_port->pcp_de_select == BCM_EXTENDER_PCP_DE_SELECT_PHB) { 1852 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1853 SD_TAG__ETAG_PCP_DE_SOURCEf, 3); 1854 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1855 SD_TAG__ETAG_DOT1P_MAPPING_PTRf, etag_dot1p_mapping_ptr); 1856 } else { 1857 return BCM_E_PARAM; 1858 } 1859 /* For the transparent port, do not modify the ETAG. */ 1860 if ((extender_port->flags & BCM_EXTENDER_PORT_EGRESS_TRANSPARENT) == 0) { 1861 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1862 SD_TAG__VNTAG_ACTIONSf, 2); 1863 } 1864 1865 if (NULL != sd_tag) { 1866 sd_tag_add = sd_tag->flags & BCM_EXTENDER_EGRESS_SERVICE_VLAN_ADD; 1867 sd_tag_delete = sd_tag->flags & BCM_EXTENDER_EGRESS_SERVICE_VLAN_DELETE; 1868 sd_tag_replace_vlan = sd_tag->flags & BCM_EXTENDER_EGRESS_SERVICE_VLAN_REPLACE; 1869 sd_tag_replace_pri = sd_tag->flags & BCM_EXTENDER_EGRESS_SERVICE_PRI_REPLACE; 1870 sd_tag_replace_tpid = sd_tag->flags & BCM_EXTENDER_EGRESS_SERVICE_TPID_REPLACE; 1871 1872 /* Set SD-tag action for packets without an SD-tag */ 1873 if (sd_tag_add) { 1874 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1875 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf, 1); 1876 } 1877 1878 /* Set SD-tag action for packets with an SD-tag */ 1879 if (sd_tag_delete) { 1880 if (sd_tag_replace_vlan || sd_tag_replace_pri || sd_tag_replace_tpid) { 1881 return BCM_E_PARAM; 1882 } 1883 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1884 SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 3); /* DELETE SD-TAG */ 1885 } else { 1886 if (!sd_tag_replace_vlan && !sd_tag_replace_pri && !sd_tag_replace_tpid) { 1887 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1888 SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 0); /* NOOP */ 1889 } else if (sd_tag_replace_vlan && !sd_tag_replace_pri && sd_tag_replace_tpid) { 1890 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1891 SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 1); /* REPLACE_VID_TPID */ 1892 } else if (sd_tag_replace_vlan && !sd_tag_replace_pri && !sd_tag_replace_tpid) { 1893 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1894 SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 2); /* REPLACE_VID_ONLY */ 1895 } else if (sd_tag_replace_vlan && sd_tag_replace_pri && sd_tag_replace_tpid) { 1896 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1897 SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 4); /* REPLACE_VID_PRI_TPID */ 1898 } else if (sd_tag_replace_vlan && sd_tag_replace_pri && !sd_tag_replace_tpid) { 1899 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1900 SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 5); /* REPLACE_VID_PRI_ONLY */ 1901 } else if (!sd_tag_replace_vlan && sd_tag_replace_pri && !sd_tag_replace_tpid) { 1902 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1903 SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 6); /* REPLACE_PRI_ONLY */ 1904 } else if (!sd_tag_replace_vlan && !sd_tag_replace_pri && sd_tag_replace_tpid) { 1905 if (SOC_IS_TRIDENT(unit)) { 1906 /* REPLACE_TPID_ONLY action is not available on Trident. 1907 * It's available on Triumph3 and Trident2. 1908 */ 1909 return BCM_E_PARAM; 1910 } 1911 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1912 SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 7); /* REPLACE_TPID_ONLY */ 1913 } else { 1914 return BCM_E_PARAM; 1915 } 1916 } 1917 1918 /* Set SD-tag TPID */ 1919 if (sd_tag->service_tpid) { 1920 if (sd_tag_add || sd_tag_replace_tpid) { 1921 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_add(unit, 1922 sd_tag->service_tpid, &tpid_index)); 1923 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1924 SD_TAG__SD_TAG_TPID_INDEXf, tpid_index); 1925 } else { 1926 return BCM_E_PARAM; 1927 } 1928 } else { 1929 if (sd_tag_add || sd_tag_replace_tpid) { 1930 return BCM_E_PARAM; 1931 } 1932 } 1933 1934 /* Set SD-tag VLAN ID */ 1935 if (sd_tag->service_vlan) { 1936 if (sd_tag_add || sd_tag_replace_vlan) { 1937 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1938 SD_TAG__SD_TAG_VIDf, sd_tag->service_vlan); 1939 } else { 1940 return BCM_E_PARAM; 1941 } 1942 } else { 1943 if (sd_tag_add || sd_tag_replace_vlan) { 1944 return BCM_E_PARAM; 1945 } 1946 } 1947 1948 /* Set SD-tag Priority */ 1949 if (sd_tag->service_qos_map_id) { 1950 if (sd_tag_add || sd_tag_replace_pri) { 1951 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1952 SD_TAG__SD_TAG_DOT1P_PRI_SELECTf, 1); 1953 BCM_IF_ERROR_RETURN(_bcm_tr2_qos_id2idx(unit, 1954 sd_tag->service_qos_map_id, &mapping_ptr)); 1955 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1956 SD_TAG__SD_TAG_DOT1P_MAPPING_PTRf, mapping_ptr); 1957 } else { 1958 return BCM_E_PARAM; 1959 } 1960 } else { 1961 if (sd_tag_add || sd_tag_replace_pri) { 1962 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1963 SD_TAG__SD_TAG_DOT1P_PRI_SELECTf, 0); 1964 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1965 SD_TAG__NEW_PRIf, sd_tag->service_pri); 1966 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1967 SD_TAG__NEW_CFIf, sd_tag->service_cfi); 1968 } 1969 } 1970 } 1971 1972 /* The field SD_TAG_VID is not used for Port Extension. 1973 * Store match_vlan here for warm boot recovery. 1974 */ 1975 if (extender_port->match_vlan >= BCM_VLAN_INVALID) { 1976 return BCM_E_PARAM; 1977 } 1978 1979 if (NULL == sd_tag) { 1980 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1981 SD_TAG__SD_TAG_VIDf, extender_port->match_vlan); 1982 } else { 1983 /* Indicate this egress object is on shared VP */ 1984 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 1985 SD_TAG__RSVD_DVPf, 1); 1986 } 1987 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 1988 MEM_BLOCK_ALL, *nh_index, &egr_nh); 1989 if (rv < 0) { 1990 goto cleanup; 1991 } 1992 1993 /* Resolve gport */ 1994 1995 rv = _bcm_esw_gport_resolve(unit, extender_port->port, &mod_out, &port_out, &trunk_id, &id); 1996 if (rv < 0) { 1997 goto cleanup; 1998 } 1999 2000 ing_nh_port = -1; 2001 ing_nh_module = -1; 2002 ing_nh_trunk = -1; 2003 2004 if (BCM_GPORT_IS_TRUNK(extender_port->port)) { 2005 ing_nh_module = -1; 2006 ing_nh_port = -1; 2007 ing_nh_trunk = trunk_id; 2008 } else { 2009 ing_nh_module = mod_out; 2010 ing_nh_port = port_out; 2011 ing_nh_trunk = -1; 2012 } 2013 2014 /* Write ING_L3_NEXT_HOP entry */ 2015 2016 sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t)); 2017 2018 if (ing_nh_trunk == -1) { 2019 if (soc_feature(unit, soc_feature_generic_dest)) { 2020 soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 2021 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 2022 ing_nh_module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_port); 2023 } else { 2024 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 2025 &ing_nh, PORT_NUMf, ing_nh_port); 2026 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 2027 &ing_nh, MODULE_IDf, ing_nh_module); 2028 } 2029 } else { 2030 if (soc_feature(unit, soc_feature_generic_dest)) { 2031 soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 2032 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_trunk); 2033 } else { 2034 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 2035 &ing_nh, Tf, 1); 2036 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 2037 &ing_nh, TGIDf, ing_nh_trunk); 2038 } 2039 } 2040 2041 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, drop); 2042 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 2043 &ing_nh, ENTRY_TYPEf, 0x2); /* L2 DVP */ 2044 2045 if (soc_mem_field_valid(unit, ING_L3_NEXT_HOPm, DVP_ATTRIBUTE_1_INDEXf)) { 2046 uint32 mtu_profile_index; 2047 2048 rv = _bcm_tr3_mtu_profile_index_get(unit, 0x3fff, &mtu_profile_index); 2049 if (rv < 0) { 2050 goto cleanup; 2051 } 2052 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 2053 DVP_ATTRIBUTE_1_INDEXf, mtu_profile_index); 2054 } else if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) { 2055 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 2056 MTU_SIZEf, 0x3fff); 2057 } 2058 2059 rv = soc_mem_write (unit, ING_L3_NEXT_HOPm, 2060 MEM_BLOCK_ALL, *nh_index, &ing_nh); 2061 if (rv < 0) { 2062 goto cleanup; 2063 } 2064 2065 /* Write INITIAL_ING_L3_NEXT_HOP entry */ 2066 2067 sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t)); 2068 if (ing_nh_trunk == -1) { 2069 if (soc_feature(unit, soc_feature_generic_dest)) { 2070 soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, 2071 &initial_ing_nh, DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 2072 ing_nh_module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_port); 2073 } else { 2074 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 2075 &initial_ing_nh, PORT_NUMf, ing_nh_port); 2076 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 2077 &initial_ing_nh, MODULE_IDf, ing_nh_module); 2078 } 2079 } else { 2080 if (soc_feature(unit, soc_feature_generic_dest)) { 2081 soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, 2082 &initial_ing_nh, DESTINATIONf, SOC_MEM_FIF_DEST_LAG, 2083 ing_nh_trunk); 2084 } else { 2085 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 2086 &initial_ing_nh, Tf, 1); 2087 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 2088 &initial_ing_nh, TGIDf, ing_nh_trunk); 2089 } 2090 } 2091 rv = soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm, 2092 MEM_BLOCK_ALL, *nh_index, &initial_ing_nh); 2093 if (rv < 0) { 2094 goto cleanup; 2095 } 2096 2097 return rv; 2098 2099 cleanup: 2100 if (!(extender_port->flags & BCM_EXTENDER_PORT_REPLACE)) { 2101 (void) bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, *nh_index); 2102 } 2103 return rv; 2104 } 2105 2106 /* 2107 * Function: 2108 * _bcm_tr3_extender_nh_info_delete 2109 * Purpose: 2110 * Free next hop index and clear next hop tables. 2111 * Parameters: 2112 * unit - (IN) SOC unit number. 2113 * nh_index - (IN) Next hop index. 2114 * Returns: 2115 * BCM_X_XXX 2116 */ 2117 STATIC int 2118 _bcm_tr3_extender_nh_info_delete(int unit, int nh_index) 2119 { 2120 egr_l3_next_hop_entry_t egr_nh; 2121 ing_l3_next_hop_entry_t ing_nh; 2122 initial_ing_l3_next_hop_entry_t initial_ing_nh; 2123 int ref_count; 2124 int sd_tag_action_if_not_present; 2125 int sd_tag_action_if_present; 2126 int sd_tag_add; 2127 int sd_tag_replace_tpid; 2128 int tpid_index; 2129 uint32 entry_type = 0; 2130 soc_field_t etfld; 2131 2132 /* Read egress next hop entry before it's potentially deleted by 2133 * bcm_xgs3_nh_del. 2134 */ 2135 BCM_IF_ERROR_RETURN 2136 (READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &egr_nh)); 2137 /* Check next hop's reference count. If the count is zero, 2138 * the egress next hop entry was cleared by bcm_xgs3_nh_del. 2139 * In this case, the EGR_L3_NEXT_HOP.SD_TAG_TPID_INDEX's 2140 * reference count needs to be decremented. 2141 */ 2142 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_ref_count_get(unit, nh_index, &ref_count)); 2143 /* Check entry type */ 2144 etfld = SOC_IS_TRIDENT3X(unit) ? DATA_TYPEf : ENTRY_TYPEf; 2145 entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, etfld); 2146 2147 if (ref_count == 0 && entry_type == 2) { 2148 sd_tag_action_if_not_present = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 2149 &egr_nh, SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf); 2150 if (1 == sd_tag_action_if_not_present) { 2151 sd_tag_add = TRUE; 2152 } else { 2153 sd_tag_add = FALSE; 2154 } 2155 2156 sd_tag_action_if_present = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 2157 &egr_nh, SD_TAG__SD_TAG_ACTION_IF_PRESENTf); 2158 if ((1 == sd_tag_action_if_present) || 2159 (4 == sd_tag_action_if_present) || 2160 (7 == sd_tag_action_if_present)) { 2161 sd_tag_replace_tpid = TRUE; 2162 } else { 2163 sd_tag_replace_tpid = FALSE; 2164 } 2165 2166 if (sd_tag_add || sd_tag_replace_tpid) { 2167 tpid_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 2168 &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf); 2169 BCM_IF_ERROR_RETURN 2170 (_bcm_fb2_outer_tpid_entry_delete(unit, tpid_index)); 2171 } 2172 } 2173 2174 /* Clear EGR_L3_NEXT_HOP entry */ 2175 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 2176 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_NEXT_HOPm, 2177 MEM_BLOCK_ALL, nh_index, &egr_nh)); 2178 2179 /* Clear ING_L3_NEXT_HOP entry */ 2180 sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t)); 2181 BCM_IF_ERROR_RETURN(soc_mem_write (unit, ING_L3_NEXT_HOPm, 2182 MEM_BLOCK_ALL, nh_index, &ing_nh)); 2183 2184 /* Clear INITIAL_ING_L3_NEXT_HOP entry */ 2185 sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t)); 2186 BCM_IF_ERROR_RETURN(soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm, 2187 MEM_BLOCK_ALL, nh_index, &initial_ing_nh)); 2188 2189 /* Free the next-hop index. */ 2190 BCM_IF_ERROR_RETURN 2191 (bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, nh_index)); 2192 2193 return BCM_E_NONE; 2194 } 2195 2196 /* 2197 * Function: 2198 * _bcm_tr3_extender_port_nh_info_set 2199 * Purpose: 2200 * Get a next hop index and configure next hop tables. 2201 * Parameters: 2202 * unit - (IN) SOC unit number. 2203 * port - (IN) Physical GPORT ID. 2204 * extender_port_vid - (IN) extender port VID in ETAG. 2205 * pcp - - (IN) PCP field in ETAG. 2206 * de - - (IN) DE field in ETAG. 2207 * pcp_de_select - (IN) Selection of PCP and DE fields for egress ETAG. 2208 * qos_map_id- (IN) Qos map id for egress etag mapping profile. 2209 * sd_tag - (IN) SD-tag attributes. 2210 * vp - (IN) Virtual port number. 2211 * nh_index - (IN/OUT) Next hop index. 2212 * Returns: 2213 * BCM_X_XXX 2214 */ 2215 STATIC int 2216 _bcm_tr3_extender_port_nh_info_set(int unit, 2217 bcm_gport_t port, uint16 extended_port_vid, 2218 bcm_vlan_t match_vlan, uint8 pcp, uint8 de, 2219 uint32 pcp_de_select, int qos_map_id, 2220 _bcm_tr3_extender_sd_tag_t *sd_tag, 2221 int vp, int *nh_index) 2222 { 2223 int drop; 2224 bcm_extender_port_t extender_port; 2225 2226 bcm_extender_port_t_init(&extender_port); 2227 extender_port.flags = EXTENDER_PORT_INFO(unit, vp)->flags; 2228 extender_port.port = port; 2229 extender_port.match_vlan = match_vlan; 2230 extender_port.extended_port_vid = extended_port_vid; 2231 extender_port.pcp = pcp; 2232 extender_port.de = de; 2233 extender_port.pcp_de_select = pcp_de_select; 2234 extender_port.qos_map_id = qos_map_id; 2235 drop = (extender_port.flags & BCM_EXTENDER_PORT_DROP) ? 1 : 0; 2236 2237 return _bcm_tr3_extender_nh_info_set(unit, &extender_port, sd_tag, vp, drop, nh_index); 2238 } 2239 2240 /* 2241 * Function: 2242 * _bcm_tr3_extender_l3mc_nh_info_set 2243 * Purpose: 2244 * Configure next hop tables for L3MC. 2245 * Parameters: 2246 * unit - (IN) SOC unit number. 2247 * nh_index - (IN) Next hop index. 2248 * flags - (IN) EXTENDER multicast flag. 2249 * multicast_flags - (IN) EXTENDER multicast flag. 2250 * port - (IN) Physical GPORT ID. 2251 * extended_port_vid - (IN) extender port VID in Etag. 2252 * pcp_de_select - (IN) Selection of PCP and DE fields for egress ETAG. 2253 * qos_map_id- - (IN) Qos map id for egress etag mapping profile. 2254 * pcp - - (IN) PCP field in ETAG. 2255 * de - - (IN) DE field in ETAG. 2256 * vp - (IN) Virtual port number. 2257 * Returns: 2258 * BCM_X_XXX 2259 */ 2260 STATIC int 2261 _bcm_tr3_extender_l3mc_nh_info_set(int unit, int nh_index, uint32 flags, 2262 uint32 multicast_flags, bcm_gport_t port, bcm_if_t intf, 2263 uint16 extended_port_vid, int qos_map_id, 2264 uint32 pcp_de_select, uint8 pcp, uint8 de, int vp) 2265 { 2266 egr_l3_next_hop_entry_t egr_nh; 2267 bcm_module_t mod_out; 2268 bcm_port_t port_out; 2269 bcm_trunk_t trunk_id; 2270 int id; 2271 int ing_nh_port; 2272 int ing_nh_module; 2273 int ing_nh_trunk; 2274 ing_l3_next_hop_entry_t ing_nh; 2275 initial_ing_l3_next_hop_entry_t initial_ing_nh; 2276 int i; 2277 int flag_set; 2278 int etag_dot1p_mapping_ptr; 2279 int drop; 2280 soc_mem_t mem = EGR_L3_NEXT_HOPm; 2281 2282 uint32 flag_array[] = { 2283 BCM_L3_MULTICAST_L2_DEST_PRESERVE, 2284 BCM_L3_MULTICAST_L2_SRC_PRESERVE, 2285 BCM_L3_MULTICAST_L2_VLAN_PRESERVE, 2286 BCM_L3_MULTICAST_TTL_PRESERVE, 2287 BCM_L3_MULTICAST_DEST_PRESERVE, 2288 BCM_L3_MULTICAST_SRC_PRESERVE, 2289 BCM_L3_MULTICAST_VLAN_PRESERVE, 2290 BCM_L3_MULTICAST_L3_DROP, 2291 BCM_L3_MULTICAST_L2_DROP 2292 }; 2293 soc_field_t field_array[] = { 2294 L3MC__L2_MC_DA_DISABLEf, 2295 L3MC__L2_MC_SA_DISABLEf, 2296 L3MC__L2_MC_VLAN_DISABLEf, 2297 L3MC__L3_MC_TTL_DISABLEf, 2298 L3MC__L3_MC_DA_DISABLEf, 2299 L3MC__L3_MC_SA_DISABLEf, 2300 L3MC__L3_MC_VLAN_DISABLEf, 2301 L3MC__L3_DROPf, 2302 L3MC__L2_DROPf 2303 }; 2304 2305 if ((nh_index > soc_mem_index_max(unit, mem)) || 2306 (nh_index < soc_mem_index_min(unit, mem))) { 2307 return BCM_E_PARAM; 2308 } 2309 2310 etag_dot1p_mapping_ptr = 0; 2311 #ifdef BCM_TOMAHAWK_SUPPORT 2312 if (SOC_IS_TOMAHAWKX(unit)) { 2313 bcm_th_qos_egr_etag_id2profile(unit, qos_map_id, 2314 &etag_dot1p_mapping_ptr); 2315 } 2316 #endif 2317 #ifdef BCM_TRIDENT2_SUPPORT 2318 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TRIDENT3X(unit)){ 2319 bcm_td2_qos_egr_etag_id2profile(unit, qos_map_id, 2320 &etag_dot1p_mapping_ptr); 2321 } 2322 #endif 2323 2324 /*SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, 2325 MEM_BLOCK_ANY, nh_index, &egr_nh));*/ 2326 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 2327 2328 soc_mem_field32_set(unit, mem, &egr_nh, ENTRY_TYPEf, 7); /* L3MC view */ 2329 soc_mem_field32_set(unit, mem, &egr_nh, L3MC__INTF_NUMf, intf); 2330 2331 for (i = 0; i < COUNTOF(flag_array); i++) { 2332 if (multicast_flags & flag_array[i]) { 2333 flag_set = 1; 2334 } else { 2335 flag_set = 0; 2336 } 2337 if (soc_mem_field_valid(unit, mem, field_array[i])) { 2338 soc_mem_field32_set(unit, mem, &egr_nh, field_array[i], flag_set); 2339 } else { 2340 if (flag_set) { 2341 return BCM_E_PARAM; 2342 } 2343 } 2344 } 2345 /* Set up EGR_L3_NEXT_HOP entry */ 2346 /*soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 2347 L3MC__L3MC_USE_CONFIGURED_MACf, 0);*/ 2348 2349 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2350 if (soc_feature(unit, soc_feature_egr_l3_next_hop_next_ptr)) { 2351 soc_mem_field32_set(unit, mem, &egr_nh, L3MC__NEXT_PTR_TYPEf, 1); 2352 } else 2353 #endif 2354 { 2355 soc_mem_field32_set(unit, mem, &egr_nh, L3MC__DVP_VALIDf, 1); 2356 } 2357 soc_mem_field32_set(unit, mem, &egr_nh, 2358 L3MC__VNTAG_DST_VIFf, extended_port_vid); 2359 /* PPD2 header */ 2360 soc_mem_field32_set(unit, mem, &egr_nh, L3MC__HG_HDR_SELf, 1); 2361 2362 /* For the transparent port, do not modify the ETAG. */ 2363 if ((flags & BCM_EXTENDER_PORT_EGRESS_TRANSPARENT) == 0) { 2364 soc_mem_field32_set(unit, mem, &egr_nh, L3MC__VNTAG_ACTIONSf, 2); 2365 } 2366 2367 if (pcp_de_select == BCM_EXTENDER_PCP_DE_SELECT_DEFAULT) { 2368 soc_mem_field32_set(unit, mem, &egr_nh, L3MC__ETAG_PCP_DE_SOURCEf, 2); 2369 soc_mem_field32_set(unit, mem, &egr_nh, L3MC__ETAG_PCPf, pcp); 2370 soc_mem_field32_set(unit, mem, &egr_nh, L3MC__ETAG_DEf, de); 2371 } else if (pcp_de_select == BCM_EXTENDER_PCP_DE_SELECT_PHB) { 2372 soc_mem_field32_set(unit, mem, &egr_nh, L3MC__ETAG_PCP_DE_SOURCEf, 3); 2373 soc_mem_field32_set(unit, mem, &egr_nh, 2374 L3MC__ETAG_DOT1P_MAPPING_PTRf, etag_dot1p_mapping_ptr); 2375 } else { 2376 return BCM_E_PARAM; 2377 } 2378 2379 /* Indicate this egress object is on shared VP */ 2380 if (SOC_IS_TRIDENT3X(unit)) { 2381 int fld_len = soc_mem_field_length(unit, mem, L3MC__RESERVED_1f); 2382 soc_mem_field32_set(unit, mem, &egr_nh, L3MC__NEXT_PTRf, vp); 2383 if (fld_len > 0) { 2384 soc_mem_field32_set(unit, mem, &egr_nh, 2385 L3MC__RESERVED_1f, 1 << (fld_len - 1)); 2386 } 2387 } else { 2388 soc_mem_field32_set(unit, mem, &egr_nh, L3MC__RSVD_DVPf, 1); 2389 soc_mem_field32_set(unit, mem, &egr_nh, L3MC__DVPf, vp); 2390 } 2391 2392 /* Resolve gport */ 2393 BCM_IF_ERROR_RETURN( 2394 _bcm_esw_gport_resolve(unit, port, &mod_out, &port_out, 2395 &trunk_id, &id)); 2396 2397 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2398 if (soc_mem_field_valid(unit, mem, L3MC__HG_MC_DST_PORT_NUMf)) { 2399 if ((!BCM_GPORT_IS_TRUNK(port)) && 2400 (_bcm_xgs5_subport_coe_mod_port_local(unit, mod_out, port_out))) { 2401 soc_mem_field32_set(unit, mem, &egr_nh, 2402 L3MC__HG_MC_DST_PORT_NUMf, port_out); 2403 soc_mem_field32_set(unit, mem, &egr_nh, 2404 L3MC__HG_MC_DST_MODIDf, mod_out); 2405 } 2406 } 2407 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 2408 /* Write EGR_L3_NEXT_HOP entry */ 2409 SOC_IF_ERROR_RETURN( 2410 soc_mem_write(unit, mem, MEM_BLOCK_ALL, nh_index, &egr_nh)); 2411 2412 ing_nh_port = -1; 2413 ing_nh_module = -1; 2414 ing_nh_trunk = -1; 2415 if (BCM_GPORT_IS_TRUNK(port)) { 2416 ing_nh_module = -1; 2417 ing_nh_port = -1; 2418 ing_nh_trunk = trunk_id; 2419 } else { 2420 ing_nh_module = mod_out; 2421 ing_nh_port = port_out; 2422 ing_nh_trunk = -1; 2423 } 2424 2425 /* Write ING_L3_NEXT_HOP entry. It is not necessary and to be removed */ 2426 sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t)); 2427 if (ing_nh_trunk == -1) { 2428 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 2429 PORT_NUMf, ing_nh_port); 2430 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 2431 MODULE_IDf, ing_nh_module); 2432 } else { 2433 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 2434 Tf, 1); 2435 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 2436 TGIDf, ing_nh_trunk); 2437 } 2438 2439 drop = (flags & BCM_EXTENDER_PORT_DROP) ? 1 : 0; 2440 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, drop); 2441 2442 SOC_IF_ERROR_RETURN(soc_mem_write(unit, ING_L3_NEXT_HOPm, 2443 MEM_BLOCK_ALL, nh_index, &ing_nh)); 2444 2445 /* Write INITIAL_ING_L3_NEXT_HOP entry */ 2446 sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t)); 2447 if (ing_nh_trunk == -1) { 2448 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 2449 &initial_ing_nh, PORT_NUMf, ing_nh_port); 2450 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 2451 &initial_ing_nh, MODULE_IDf, ing_nh_module); 2452 } else { 2453 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 2454 &initial_ing_nh, Tf, 1); 2455 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 2456 &initial_ing_nh, TGIDf, ing_nh_trunk); 2457 } 2458 SOC_IF_ERROR_RETURN(soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm, 2459 MEM_BLOCK_ALL, nh_index, &initial_ing_nh)); 2460 2461 return BCM_E_NONE; 2462 } 2463 2464 /* 2465 * Function: 2466 * _bcm_tr3_extender_match_key_assemble 2467 * Purpose: 2468 * Constructs a vlan_xlate key for extender match 2469 * according to extender port. 2470 * Parameters: 2471 * unit - (IN) SOC unit number. 2472 * extender_port - (IN) Pointer to VLAN virtual port structure. 2473 * vent - (OUT) Pointer to a vlan_xlate entry. 2474 * Returns: 2475 * BCM_X_XXX 2476 */ 2477 STATIC int 2478 _bcm_tr3_extender_match_key_assemble( 2479 int unit, 2480 bcm_extender_port_t *extender_port, 2481 void *vent) 2482 { 2483 int key_type; 2484 bcm_module_t mod_out; 2485 bcm_port_t port_out; 2486 bcm_trunk_t trunk_out; 2487 int tmp_id; 2488 soc_mem_t mem = VLAN_XLATEm; 2489 2490 if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) { 2491 mem = VLAN_XLATE_1_DOUBLEm; 2492 sal_memset(vent, 0, sizeof(vlan_xlate_1_double_entry_t)); 2493 } else { 2494 sal_memset(vent, 0, sizeof(vlan_xlate_entry_t)); 2495 } 2496 2497 if (soc_feature(unit, soc_feature_base_valid)) { 2498 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 2499 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 2500 } else { 2501 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 2502 } 2503 2504 if (extender_port->match_vlan == BCM_VLAN_NONE) { 2505 BCM_IF_ERROR_RETURN( 2506 _bcm_esw_vlan_xlate_key_type_value_get( 2507 unit, VLXLT_HASH_KEY_TYPE_VIF,&key_type)); 2508 } else { 2509 if (!BCM_VLAN_VALID(extender_port->match_vlan)) { 2510 return BCM_E_PARAM; 2511 } 2512 BCM_IF_ERROR_RETURN( 2513 _bcm_esw_vlan_xlate_key_type_value_get( 2514 unit, VLXLT_HASH_KEY_TYPE_VIF_VLAN, &key_type)); 2515 soc_mem_field32_set(unit, mem, vent, VIF__VLANf, 2516 extender_port->match_vlan); 2517 } 2518 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, key_type); 2519 if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) { 2520 soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, key_type); 2521 } 2522 2523 if (extender_port->extended_port_vid >= 2524 (1 << soc_mem_field_length(unit, mem, VIF__SRC_VIFf))) { 2525 return BCM_E_PARAM; 2526 } 2527 soc_mem_field32_set(unit, mem, vent, VIF__SRC_VIFf, 2528 extender_port->extended_port_vid); 2529 2530 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT) 2531 if (soc_mem_field_valid(unit, mem, SOURCE_TYPEf)) { 2532 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1); 2533 } 2534 #endif /* BCM_TRIDENT2_SUPPORT || BCM_PE_SUPPORT */ 2535 BCM_IF_ERROR_RETURN 2536 (_bcm_esw_gport_resolve(unit, extender_port->port, 2537 &mod_out, &port_out, &trunk_out, &tmp_id)); 2538 if (BCM_GPORT_IS_TRUNK(extender_port->port)) { 2539 soc_mem_field32_set(unit, mem, vent, VIF__Tf, 1); 2540 soc_mem_field32_set(unit, mem, vent, VIF__TGIDf, trunk_out); 2541 } else { 2542 soc_mem_field32_set(unit, mem, vent, VIF__MODULE_IDf, mod_out); 2543 soc_mem_field32_set(unit, mem, vent, VIF__PORT_NUMf, port_out); 2544 } 2545 2546 return BCM_E_NONE; 2547 } 2548 2549 /* 2550 * Function: 2551 * bcm_tr3_extender_match_key_get 2552 * Purpose: 2553 * get a vlan_xlate key for extender match according to extender port id. 2554 * Parameters: 2555 * unit - (IN) SOC unit number. 2556 * extender_port_id - (IN) extender gport id. 2557 * vent - (OUT) Pointer to a vlan_xlate entry. 2558 * Returns: 2559 * BCM_X_XXX 2560 */ 2561 int 2562 bcm_tr3_extender_match_key_get( 2563 int unit, 2564 bcm_gport_t extender_port_id, 2565 void *vent) 2566 { 2567 bcm_extender_port_t extender_port; 2568 2569 bcm_extender_port_t_init(&extender_port); 2570 extender_port.extender_port_id = extender_port_id; 2571 BCM_IF_ERROR_RETURN( 2572 bcm_tr3_extender_port_get(unit, &extender_port)); 2573 return _bcm_tr3_extender_match_key_assemble(unit, &extender_port, vent); 2574 } 2575 2576 /* 2577 * Function: 2578 * _bcm_tr3_extender_match_add 2579 * Purpose: 2580 * Add match criteria for Extender VP. 2581 * Parameters: 2582 * unit - (IN) SOC unit number. 2583 * extender_port - (IN) Pointer to VLAN virtual port structure. 2584 * vp - (IN) Virtual port number. 2585 * Returns: 2586 * BCM_X_XXX 2587 */ 2588 STATIC int 2589 _bcm_tr3_extender_match_add(int unit, bcm_extender_port_t *extender_port, 2590 int vp) 2591 { 2592 uint32 vent[SOC_MAX_MEM_FIELD_WORDS]; 2593 uint32 old_vent[SOC_MAX_MEM_FIELD_WORDS]; 2594 int key_type; 2595 bcm_module_t mod_out; 2596 bcm_port_t port_out; 2597 bcm_trunk_t trunk_out; 2598 int tmp_id; 2599 bcm_vlan_action_set_t action; 2600 uint32 profile_idx; 2601 int rv; 2602 bcm_trunk_t trunk_id; 2603 int idx; 2604 int mod_local; 2605 int num_local_ports; 2606 bcm_port_t local_ports[SOC_MAX_NUM_PORTS]; 2607 int local_member_count; 2608 bcm_port_t local_member_array[SOC_MAX_NUM_PORTS]; 2609 int port_key_type_vif_vlan, port_key_type_vif; 2610 int port_key_type_a, port_key_type_b; 2611 int use_port_a, use_port_b; 2612 int vt_enable; 2613 soc_mem_t mem = VLAN_XLATEm; 2614 2615 if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) { 2616 mem = VLAN_XLATE_1_DOUBLEm; 2617 } 2618 sal_memset(vent, 0, sizeof(vent)); 2619 2620 if (soc_feature(unit, soc_feature_base_valid)) { 2621 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 2622 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 2623 } else { 2624 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 2625 } 2626 2627 if (extender_port->match_vlan == BCM_VLAN_NONE) { 2628 BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit, 2629 VLXLT_HASH_KEY_TYPE_VIF, &key_type)); 2630 } else { 2631 if (!BCM_VLAN_VALID(extender_port->match_vlan)) { 2632 return BCM_E_PARAM; 2633 } 2634 BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit, 2635 VLXLT_HASH_KEY_TYPE_VIF_VLAN, &key_type)); 2636 soc_mem_field32_set(unit, mem, vent, VIF__VLANf, 2637 extender_port->match_vlan); 2638 } 2639 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, key_type); 2640 if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) { 2641 soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, key_type); 2642 } 2643 2644 if (extender_port->extended_port_vid >= 2645 (1 << soc_mem_field_length(unit, mem, VIF__SRC_VIFf))) { 2646 return BCM_E_PARAM; 2647 } 2648 soc_mem_field32_set(unit, mem, vent, VIF__SRC_VIFf, 2649 extender_port->extended_port_vid); 2650 2651 #if defined( BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT) 2652 if (soc_mem_field_valid(unit, mem, SOURCE_TYPEf)) { 2653 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1); 2654 } 2655 #endif /* BCM_TRIDENT2_SUPPORT || BCM_PE_SUPPORT */ 2656 BCM_IF_ERROR_RETURN 2657 (_bcm_esw_gport_resolve(unit, extender_port->port, 2658 &mod_out, &port_out, &trunk_out, &tmp_id)); 2659 if (BCM_GPORT_IS_TRUNK(extender_port->port)) { 2660 soc_mem_field32_set(unit, mem, vent, VIF__Tf, 1); 2661 soc_mem_field32_set(unit, mem, vent, VIF__TGIDf, trunk_out); 2662 } else { 2663 soc_mem_field32_set(unit, mem, vent, VIF__MODULE_IDf, mod_out); 2664 soc_mem_field32_set(unit, mem, vent, VIF__PORT_NUMf, port_out); 2665 } 2666 2667 /* SVP */ 2668 soc_mem_field32_set(unit, mem, vent, VIF__MPLS_ACTIONf, 2669 ((extender_port->flags & BCM_EXTENDER_PORT_ID_ASSIGN_DISABLE) ? 0x0 : 0x1)); 2670 soc_mem_field32_set(unit, mem, vent, VIF__SOURCE_VPf, vp); 2671 2672 bcm_vlan_action_set_t_init(&action); 2673 if (BCM_VLAN_VALID(extender_port->match_vlan)) { 2674 soc_mem_field32_set(unit, mem, vent, VIF__NEW_OVIDf, 2675 extender_port->match_vlan); 2676 action.dt_outer = bcmVlanActionCopy; 2677 action.dt_inner = bcmVlanActionDelete; 2678 action.ot_outer = bcmVlanActionReplace; 2679 } else { 2680 action.ot_outer_prio = bcmVlanActionReplace; 2681 action.ut_outer = bcmVlanActionAdd; 2682 } 2683 BCM_IF_ERROR_RETURN 2684 (_bcm_trx_vlan_action_profile_entry_add(unit, &action, &profile_idx)); 2685 soc_mem_field32_set(unit, mem, vent, VIF__TAG_ACTION_PROFILE_PTRf, 2686 profile_idx); 2687 #if defined( BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT) 2688 if (soc_mem_field_valid(unit, mem, VIF__VLAN_ACTION_VALIDf)) { 2689 soc_mem_field32_set(unit, mem, vent, VIF__VLAN_ACTION_VALIDf, 1); 2690 } 2691 #endif /* BCM_TRIDENT2_SUPPORT || BCM_PE_SUPPORT */ 2692 2693 rv = soc_mem_insert_return_old(unit, mem, MEM_BLOCK_ALL, 2694 vent, old_vent); 2695 if (rv == SOC_E_EXISTS) { 2696 /* Delete the old vlan translate profile entry */ 2697 profile_idx = soc_mem_field32_get(unit, mem, old_vent, 2698 VIF__TAG_ACTION_PROFILE_PTRf); 2699 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx); 2700 } 2701 BCM_IF_ERROR_RETURN(rv); 2702 2703 num_local_ports = 0; 2704 if (BCM_GPORT_IS_TRUNK(extender_port->port)) { 2705 trunk_id = BCM_GPORT_TRUNK_GET(extender_port->port); 2706 rv = _bcm_trunk_id_validate(unit, trunk_id); 2707 if (BCM_FAILURE(rv)) { 2708 return BCM_E_PORT; 2709 } 2710 rv = _bcm_esw_trunk_local_members_get(unit, trunk_id, 2711 SOC_MAX_NUM_PORTS, local_member_array, &local_member_count); 2712 if (BCM_FAILURE(rv)) { 2713 return BCM_E_PORT; 2714 } 2715 for (idx = 0; idx < local_member_count; idx++) { 2716 local_ports[num_local_ports++] = local_member_array[idx]; 2717 } 2718 } else { 2719 BCM_IF_ERROR_RETURN 2720 (_bcm_esw_gport_resolve(unit, extender_port->port, &mod_out, &port_out, 2721 &trunk_id, &tmp_id)); 2722 if ((trunk_id != -1) || (tmp_id != -1)) { 2723 return BCM_E_PARAM; 2724 } 2725 BCM_IF_ERROR_RETURN 2726 (_bcm_esw_modid_is_local(unit, mod_out, &mod_local)); 2727 if (mod_local) { 2728 local_ports[num_local_ports++] = port_out; 2729 } 2730 } 2731 2732 BCM_IF_ERROR_RETURN(_bcm_esw_pt_vtkey_type_value_get(unit, 2733 VLXLT_HASH_KEY_TYPE_VIF_VLAN, &port_key_type_vif_vlan)); 2734 BCM_IF_ERROR_RETURN(_bcm_esw_pt_vtkey_type_value_get(unit, 2735 VLXLT_HASH_KEY_TYPE_VIF, &port_key_type_vif)); 2736 for (idx = 0; idx < num_local_ports; idx++) { 2737 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_get(unit, local_ports[idx], 2738 _bcmPortVTKeyTypeFirst, &port_key_type_a)); 2739 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_get(unit, local_ports[idx], 2740 _bcmPortVTKeyPortFirst, &use_port_a)); 2741 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_get(unit, local_ports[idx], 2742 _bcmPortVTKeyTypeSecond, &port_key_type_b)); 2743 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_get(unit, local_ports[idx], 2744 _bcmPortVTKeyPortSecond, &use_port_b)); 2745 2746 if (BCM_VLAN_VALID(extender_port->match_vlan)) { 2747 if ((port_key_type_a != port_key_type_vif_vlan) && 2748 (port_key_type_b != port_key_type_vif_vlan)) { 2749 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit, 2750 local_ports[idx], _bcmPortVTKeyTypeFirst, 2751 port_key_type_vif_vlan)); 2752 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit, 2753 local_ports[idx], _bcmPortVTKeyPortFirst, 1)); 2754 if (port_key_type_a == port_key_type_vif) { 2755 /* The first slot contained VIF key type, which 2756 * was just overwritten by VIF_VLAN key type. Hence, 2757 * the VIF key type needs to be moved to second slot. 2758 */ 2759 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit, 2760 local_ports[idx], _bcmPortVTKeyTypeSecond, 2761 port_key_type_a)); 2762 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit, 2763 local_ports[idx], _bcmPortVTKeyPortSecond, 2764 use_port_a)); 2765 } 2766 } 2767 } else { 2768 if ((port_key_type_a != port_key_type_vif) && 2769 (port_key_type_b != port_key_type_vif)) { 2770 if (port_key_type_a != port_key_type_vif_vlan) { 2771 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit, 2772 local_ports[idx], _bcmPortVTKeyTypeFirst, 2773 port_key_type_vif)); 2774 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit, 2775 local_ports[idx], _bcmPortVTKeyPortFirst, 1)); 2776 } else { 2777 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit, 2778 local_ports[idx], _bcmPortVTKeyTypeSecond, 2779 port_key_type_vif)); 2780 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit, 2781 local_ports[idx], _bcmPortVTKeyPortSecond, 1)); 2782 } 2783 } 2784 } 2785 2786 /* Enable ingress VLAN translation */ 2787 BCM_IF_ERROR_RETURN 2788 (_bcm_esw_port_config_get(unit, local_ports[idx], 2789 _bcmPortVlanTranslate, &vt_enable)); 2790 if (!vt_enable) { 2791 BCM_IF_ERROR_RETURN 2792 (_bcm_esw_port_config_set(unit, local_ports[idx], 2793 _bcmPortVlanTranslate, 1)); 2794 } 2795 2796 if (BCM_VLAN_VALID(extender_port->match_vlan)) { 2797 /* Enable egress VLAN translation */ 2798 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2799 if (soc_feature(unit, soc_feature_egr_vlan_control_is_memory)) { 2800 if (soc_feature(unit, soc_feature_egr_all_profile)) { 2801 BCM_IF_ERROR_RETURN(bcm_esw_port_egr_lport_field_set(unit, 2802 local_ports[idx], EGR_VLAN_CONTROL_1m, VT_ENABLEf, 1)); 2803 } else { 2804 SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, 2805 EGR_VLAN_CONTROL_1m, local_ports[idx], VT_ENABLEf, 1)); 2806 } 2807 } else 2808 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 2809 { 2810 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, 2811 EGR_VLAN_CONTROL_1r, local_ports[idx], VT_ENABLEf, 1)); 2812 } 2813 } 2814 } 2815 2816 return BCM_E_NONE; 2817 } 2818 2819 /* 2820 * Function: 2821 * _bcm_tr3_extender_match_delete 2822 * Purpose: 2823 * Delete match criteria for Extender VP. 2824 * Parameters: 2825 * unit - (IN) SOC unit number. 2826 * vp - (IN) Virtual port number. 2827 * old_vp - (OUT) Pointer to the old virtual port number of the entry. 2828 * Returns: 2829 * BCM_X_XXX 2830 */ 2831 STATIC int 2832 _bcm_tr3_extender_match_delete(int unit, int vp, int *old_vp) 2833 { 2834 uint32 vent[SOC_MAX_MEM_FIELD_WORDS]; 2835 uint32 old_vent[SOC_MAX_MEM_FIELD_WORDS]; 2836 int key_type; 2837 bcm_module_t mod_out; 2838 bcm_port_t port_out; 2839 bcm_trunk_t trunk_out; 2840 int tmp_id; 2841 uint32 profile_idx; 2842 int rv; 2843 soc_mem_t mem = VLAN_XLATEm; 2844 2845 if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) { 2846 mem = VLAN_XLATE_1_DOUBLEm; 2847 } 2848 sal_memset(vent, 0, sizeof(vent)); 2849 2850 if (BCM_VLAN_VALID(EXTENDER_PORT_INFO(unit, vp)->match_vlan)) { 2851 BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit, 2852 VLXLT_HASH_KEY_TYPE_VIF_VLAN, &key_type)); 2853 soc_mem_field32_set(unit, mem, vent, VIF__VLANf, 2854 EXTENDER_PORT_INFO(unit, vp)->match_vlan); 2855 } else { 2856 BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit, 2857 VLXLT_HASH_KEY_TYPE_VIF, &key_type)); 2858 } 2859 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, key_type); 2860 if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) { 2861 soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, key_type); 2862 } 2863 2864 soc_mem_field32_set(unit, mem, vent, VIF__SRC_VIFf, 2865 EXTENDER_PORT_INFO(unit, vp)->extended_port_vid); 2866 2867 #if defined( BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT) 2868 if (soc_mem_field_valid(unit, mem, SOURCE_TYPEf)) { 2869 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1); 2870 } 2871 #endif /* BCM_TRIDENT2_SUPPORT || BCM_PE_SUPPORT */ 2872 BCM_IF_ERROR_RETURN 2873 (_bcm_esw_gport_resolve(unit, EXTENDER_PORT_INFO(unit, vp)->port, 2874 &mod_out, &port_out, &trunk_out, &tmp_id)); 2875 if (BCM_GPORT_IS_TRUNK(EXTENDER_PORT_INFO(unit, vp)->port)) { 2876 soc_mem_field32_set(unit, mem, vent, VIF__Tf, 1); 2877 soc_mem_field32_set(unit, mem, vent, VIF__TGIDf, trunk_out); 2878 } else { 2879 soc_mem_field32_set(unit, mem, vent, VIF__MODULE_IDf, mod_out); 2880 soc_mem_field32_set(unit, mem, vent, VIF__PORT_NUMf, port_out); 2881 } 2882 2883 rv = soc_mem_delete_return_old(unit, mem, MEM_BLOCK_ALL, 2884 vent, old_vent); 2885 if (rv == SOC_E_NONE) { 2886 uint32 is_valid = 0; 2887 if (soc_feature(unit, soc_feature_base_valid)) { 2888 is_valid = 2889 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_0f) == 3 && 2890 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_1f) == 7; 2891 } else { 2892 is_valid = soc_mem_field32_get(unit, mem, old_vent, VALIDf); 2893 } 2894 if (is_valid) { 2895 if (old_vp != NULL) { 2896 *old_vp = soc_mem_field32_get(unit, mem, old_vent, 2897 VIF__SOURCE_VPf); 2898 } 2899 profile_idx = soc_mem_field32_get(unit, mem, old_vent, 2900 VIF__TAG_ACTION_PROFILE_PTRf); 2901 /* Delete the old vlan action profile entry */ 2902 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx); 2903 } 2904 } 2905 2906 return rv; 2907 } 2908 2909 2910 /* 2911 * Function: 2912 * _bcm_tr3_extender_port_match_add 2913 * Purpose: 2914 * Add a match to an existing port. 2915 * Parameters: 2916 * unit - (IN) SOC unit number. 2917 * port - (IN) port of match criteria. 2918 * extended_port_vid -(IN) extended_port_vid of match criteria. 2919 * vlan - (IN) vlan of match criteria. 2920 * vp - (IN) the vp of match destination. 2921 * Returns: 2922 * BCM_X_XXX 2923 */ 2924 int 2925 _bcm_tr3_extender_port_match_add(int unit, bcm_gport_t port, 2926 uint16 extended_port_vid, 2927 bcm_vlan_t vlan, int vp) 2928 { 2929 bcm_extender_port_t extender_port; 2930 2931 bcm_extender_port_t_init(&extender_port); 2932 extender_port.port = port; 2933 extender_port.match_vlan = vlan; 2934 extender_port.extended_port_vid = extended_port_vid; 2935 2936 return _bcm_tr3_extender_match_add(unit, &extender_port, vp); 2937 } 2938 2939 /* 2940 * Function: 2941 * _bcm_tr3_extender_port_match_delete 2942 * Purpose: 2943 * delete a match from an existing vp. 2944 * Parameters: 2945 * unit - (IN) SOC unit number. 2946 * port - (IN) port of match criteria. 2947 * extender_port_vid -(IN) extended_port_vid of match criteria. 2948 * vlan - (IN) vlan of match criteria. 2949 * vp - (IN) the vp of match destination. 2950 * Returns: 2951 * BCM_X_XXX 2952 */ 2953 int 2954 _bcm_tr3_extender_port_match_delete(int unit, bcm_gport_t port, 2955 uint16 extended_port_vid, 2956 bcm_vlan_t vlan, int vp) 2957 { 2958 uint32 vent[SOC_MAX_MEM_FIELD_WORDS]; 2959 uint32 old_vent[SOC_MAX_MEM_FIELD_WORDS]; 2960 int key_type; 2961 bcm_module_t mod_out; 2962 bcm_port_t port_out; 2963 bcm_trunk_t trunk_out; 2964 int tmp_id; 2965 uint32 profile_idx; 2966 int rv; 2967 int old_vp; 2968 int entry_index; 2969 soc_mem_t mem = VLAN_XLATEm; 2970 2971 if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) { 2972 mem = VLAN_XLATE_1_DOUBLEm; 2973 } 2974 sal_memset(vent, 0, sizeof(vent)); 2975 2976 if (BCM_VLAN_VALID(vlan)) { 2977 BCM_IF_ERROR_RETURN( 2978 _bcm_esw_vlan_xlate_key_type_value_get(unit, 2979 VLXLT_HASH_KEY_TYPE_VIF_VLAN, 2980 &key_type)); 2981 soc_mem_field32_set(unit, mem, vent, VIF__VLANf, vlan); 2982 } else { 2983 BCM_IF_ERROR_RETURN( 2984 _bcm_esw_vlan_xlate_key_type_value_get(unit, 2985 VLXLT_HASH_KEY_TYPE_VIF, 2986 &key_type)); 2987 } 2988 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, key_type); 2989 if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) { 2990 soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, key_type); 2991 } 2992 2993 soc_mem_field32_set(unit, mem, vent, VIF__SRC_VIFf, extended_port_vid); 2994 2995 #if defined( BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT) 2996 if (soc_mem_field_valid(unit, mem, SOURCE_TYPEf)) { 2997 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1); 2998 } 2999 #endif /* BCM_TRIDENT2_SUPPORT || BCM_PE_SUPPORT */ 3000 BCM_IF_ERROR_RETURN 3001 (_bcm_esw_gport_resolve(unit, port, &mod_out, 3002 &port_out, &trunk_out, &tmp_id)); 3003 if (BCM_GPORT_IS_TRUNK(port)) { 3004 soc_mem_field32_set(unit, mem, vent, VIF__Tf, 1); 3005 soc_mem_field32_set(unit, mem, vent, VIF__TGIDf, trunk_out); 3006 } else { 3007 soc_mem_field32_set(unit, mem, vent, VIF__MODULE_IDf, mod_out); 3008 soc_mem_field32_set(unit, mem, vent, VIF__PORT_NUMf, port_out); 3009 } 3010 3011 soc_mem_lock(unit, mem); 3012 rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL, &entry_index, 3013 vent, old_vent, 0); 3014 if (SOC_FAILURE(rv)) { 3015 soc_mem_unlock(unit, mem); 3016 return rv; 3017 } 3018 3019 old_vp = soc_mem_field32_get(unit, mem, old_vent, VIF__SOURCE_VPf); 3020 if (vp != old_vp) { 3021 soc_mem_unlock(unit, mem); 3022 return BCM_E_NOT_FOUND; 3023 } 3024 3025 rv = soc_mem_delete_return_old(unit, mem, 3026 MEM_BLOCK_ALL, vent, old_vent); 3027 soc_mem_unlock(unit, mem); 3028 if (rv == SOC_E_NONE) { 3029 uint32 is_valid = 0; 3030 if (soc_feature(unit, soc_feature_base_valid)) { 3031 is_valid = 3032 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_0f) == 3 && 3033 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_1f) == 7; 3034 } else { 3035 is_valid = soc_mem_field32_get(unit, mem, old_vent, VALIDf); 3036 } 3037 if (is_valid) { 3038 profile_idx = soc_mem_field32_get(unit, mem, old_vent, 3039 VIF__TAG_ACTION_PROFILE_PTRf); 3040 /* Delete the old vlan action profile entry */ 3041 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx); 3042 } 3043 } 3044 3045 return rv; 3046 } 3047 3048 /* 3049 * Function: 3050 * bcm_tr3_extender_port_add 3051 * Purpose: 3052 * Create an Extender port on Controlling Bridge. 3053 * Parameters: 3054 * unit - (IN) SOC unit number. 3055 * extender_port - (IN/OUT) Extender port information 3056 * Returns: 3057 * BCM_X_XXX 3058 */ 3059 int 3060 bcm_tr3_extender_port_add(int unit, 3061 bcm_extender_port_t *extender_port) 3062 { 3063 int mode; 3064 int vp, old_vp = 0, matched_vp; 3065 int rv = BCM_E_NONE; 3066 int num_vp; 3067 int nh_index = 0; 3068 bcm_if_t intf; 3069 ing_dvp_table_entry_t dvp_entry; 3070 source_vp_entry_t svp_entry; 3071 int cml_default_enable=0, cml_default_new=0, cml_default_move=0; 3072 int drop; 3073 _bcm_vp_info_t vp_info; 3074 3075 _bcm_vp_info_init(&vp_info); 3076 vp_info.vp_type = _bcmVpTypeExtender; 3077 3078 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_egress_mode_get(unit, &mode)); 3079 if (!mode) { 3080 LOG_INFO(BSL_LS_BCM_L3, 3081 (BSL_META_U(unit, 3082 "L3 egress mode must be set first\n"))); 3083 return BCM_E_DISABLED; 3084 } 3085 3086 if ((!soc_feature(unit, soc_feature_port_extender_vp_sharing)) && 3087 (extender_port->flags & BCM_EXTENDER_PORT_MATCH_NONE)) { 3088 return BCM_E_UNAVAIL; 3089 } 3090 3091 /* Check for invalid flag combinations */ 3092 if (extender_port->flags & BCM_EXTENDER_PORT_MATCH_NONE) { 3093 if ((extender_port->flags & BCM_EXTENDER_PORT_REPLACE) || 3094 (extender_port->flags & BCM_EXTENDER_PORT_MULTICAST)) { 3095 return BCM_E_PARAM; 3096 } 3097 } 3098 3099 if (!(extender_port->flags & BCM_EXTENDER_PORT_REPLACE)) { 3100 /* Create new Extender VP */ 3101 3102 if (extender_port->flags & BCM_EXTENDER_PORT_WITH_ID) { 3103 if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port->extender_port_id)) { 3104 return BCM_E_PARAM; 3105 } 3106 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port->extender_port_id); 3107 if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) { 3108 return BCM_E_PARAM; 3109 } 3110 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 3111 return BCM_E_EXISTS; 3112 } else { 3113 rv = _bcm_vp_used_set(unit, vp, vp_info); 3114 if (rv < 0) { 3115 return rv; 3116 } 3117 } 3118 } else { 3119 /* allocate a new VP index */ 3120 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 3121 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, 3122 vp_info, &vp); 3123 if (rv < 0) { 3124 return rv; 3125 } 3126 } 3127 3128 if (extender_port->flags & BCM_EXTENDER_PORT_MATCH_NONE) { 3129 /* For a EXTENDER port without any match criteria, an invalid 3130 * next hop index will be written to the ING_DVP_TABLE. 3131 */ 3132 nh_index = EXTENDER_INFO(unit)->invalid_next_hop_index; 3133 } else { 3134 /* Configure next hop tables */ 3135 drop = (extender_port->flags & BCM_EXTENDER_PORT_DROP) ? 1 : 0; 3136 rv = _bcm_tr3_extender_nh_info_set(unit, extender_port, NULL, vp, drop, 3137 &nh_index); 3138 if (rv < 0) { 3139 goto cleanup; 3140 } 3141 } 3142 3143 /* Configure DVP table */ 3144 intf = nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 3145 rv = _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigSet, vp, 3146 ING_DVP_CONFIG_INVALID_VP_TYPE, intf, 3147 ING_DVP_CONFIG_INVALID_PORT_TYPE); 3148 if (rv < 0) { 3149 goto cleanup; 3150 } 3151 3152 /* Configure SVP table */ 3153 sal_memset(&svp_entry, 0, sizeof(source_vp_entry_t)); 3154 soc_SOURCE_VPm_field32_set(unit, &svp_entry, ENTRY_TYPEf, 3); 3155 3156 /* Set the CML */ 3157 rv = _bcm_vp_default_cml_mode_get(unit, &cml_default_enable, 3158 &cml_default_new, &cml_default_move); 3159 if (rv < 0) { 3160 goto cleanup; 3161 } 3162 if (cml_default_enable) { 3163 /* Set the CML to default values */ 3164 soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_NEWf, 3165 cml_default_new); 3166 soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_MOVEf, 3167 cml_default_move); 3168 } else { 3169 /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */ 3170 soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_NEWf, 0x8); 3171 soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_MOVEf, 0x8); 3172 } 3173 3174 /* Set the TPID_SOURCE based on SGLP */ 3175 if (soc_mem_field_valid(unit, SOURCE_VPm, TPID_SOURCEf)) { 3176 soc_SOURCE_VPm_field32_set(unit, &svp_entry, TPID_SOURCEf, 2); 3177 } 3178 3179 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry); 3180 if (rv < 0) { 3181 goto cleanup; 3182 } 3183 3184 /* Configure SOURCE_VP_2 table */ 3185 #ifdef BCM_TRIDENT2_SUPPORT 3186 if (soc_mem_field_valid(unit, SOURCE_VP_2m, PARSE_USING_SGLP_TPIDf)) { 3187 source_vp_2_entry_t svp_2_entry; 3188 3189 sal_memset(&svp_2_entry, 0, sizeof(source_vp_2_entry_t)); 3190 soc_SOURCE_VP_2m_field32_set(unit, &svp_2_entry, PARSE_USING_SGLP_TPIDf, 1); 3191 rv = WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, vp, &svp_2_entry); 3192 if (rv < 0) { 3193 goto cleanup; 3194 } 3195 } 3196 #endif /* BCM_TRIDENT2_SUPPORT */ 3197 3198 if (!(extender_port->flags & BCM_EXTENDER_PORT_MULTICAST) 3199 && (!(extender_port->flags & BCM_EXTENDER_PORT_MATCH_NONE))) { 3200 /* Configure ingress VLAN translation table for unicast VPs */ 3201 rv = _bcm_tr3_extender_match_add(unit, extender_port, vp); 3202 if (rv < 0) { 3203 goto cleanup; 3204 } 3205 } 3206 3207 /* Configure the failover information */ 3208 if (BCM_SUCCESS(_bcm_esw_failover_extender_check(unit, 3209 extender_port))) { 3210 rv = _bcm_tr3_extender_failover_add(unit, extender_port, vp); 3211 if (rv < 0) { 3212 goto cleanup; 3213 } 3214 } 3215 3216 if (!(extender_port->flags & BCM_EXTENDER_PORT_MATCH_NONE)) { 3217 3218 /* Increment port's VP count */ 3219 rv = _bcm_tr3_extender_port_cnt_update(unit, extender_port->port, vp, TRUE); 3220 if (rv < 0) { 3221 goto cleanup; 3222 } 3223 } 3224 3225 } else { /* Replace properties of existing Extender VP */ 3226 3227 if (!(extender_port->flags & BCM_EXTENDER_PORT_WITH_ID)) { 3228 return BCM_E_PARAM; 3229 } 3230 if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port->extender_port_id)) { 3231 return BCM_E_PARAM; 3232 } 3233 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port->extender_port_id); 3234 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 3235 return BCM_E_PARAM; 3236 } 3237 3238 /* For existing Extender vp, NH entry already exists */ 3239 BCM_IF_ERROR_RETURN 3240 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 3241 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 3242 NEXT_HOP_INDEXf); 3243 3244 /* Update existing next hop entries */ 3245 drop = (extender_port->flags & BCM_EXTENDER_PORT_DROP) ? 1 : 0; 3246 BCM_IF_ERROR_RETURN 3247 (_bcm_tr3_extender_nh_info_set(unit, extender_port, NULL, vp, drop, 3248 &nh_index)); 3249 3250 /* Delete old ingress VLAN translation entry, 3251 * install new ingress VLAN translation entry 3252 */ 3253 if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MULTICAST) 3254 && (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE))) { 3255 BCM_IF_ERROR_RETURN( 3256 _bcm_tr3_extender_match_delete(unit, vp, &old_vp)); 3257 } 3258 if (!(extender_port->flags & BCM_EXTENDER_PORT_MULTICAST)) { 3259 #ifdef BCM_TRIDENT2_SUPPORT 3260 /* The extender port id may be one of members of a vplag. */ 3261 if (_bcm_vp_used_get(unit, old_vp, _bcmVpTypeVpLag)) { 3262 matched_vp = old_vp; 3263 } else 3264 #endif /* BCM_TRIDENT2_SUPPORT */ 3265 { 3266 matched_vp = vp; 3267 } 3268 BCM_IF_ERROR_RETURN 3269 (_bcm_tr3_extender_match_add(unit, extender_port, matched_vp)); 3270 } 3271 3272 /* Configure the failover information */ 3273 if (BCM_SUCCESS(_bcm_esw_failover_extender_check(unit, 3274 extender_port))) { 3275 BCM_IF_ERROR_RETURN 3276 (_bcm_tr3_extender_failover_add(unit, extender_port, vp)); 3277 } else { 3278 /* remove the failover configuration if found*/ 3279 bcm_gport_t gport = extender_port->extender_port_id; 3280 if (BCM_SUCCESS(_bcm_tr3_extender_failover_get(unit, gport, 3281 NULL, NULL, NULL))) { 3282 BCM_IF_ERROR_RETURN 3283 (_bcm_tr3_extender_failover_delete(unit, gport)); 3284 } 3285 } 3286 3287 /* Decrement old port's VP count, increment new port's VP count */ 3288 BCM_IF_ERROR_RETURN 3289 (_bcm_tr3_extender_port_cnt_update(unit, 3290 EXTENDER_PORT_INFO(unit, vp)->port, vp, FALSE)); 3291 BCM_IF_ERROR_RETURN 3292 (_bcm_tr3_extender_port_cnt_update(unit, 3293 EXTENDER_PORT_INFO(unit, vp)->port, vp, TRUE)); 3294 } 3295 3296 /* Set Extender VP software state */ 3297 EXTENDER_PORT_INFO(unit, vp)->flags = extender_port->flags; 3298 EXTENDER_PORT_INFO(unit, vp)->port = extender_port->port; 3299 EXTENDER_PORT_INFO(unit, vp)->extended_port_vid = 3300 extender_port->extended_port_vid; 3301 EXTENDER_PORT_INFO(unit, vp)->pcp_de_select = extender_port->pcp_de_select; 3302 EXTENDER_PORT_INFO(unit, vp)->qos_map_id = extender_port->qos_map_id; 3303 EXTENDER_PORT_INFO(unit, vp)->pcp = extender_port->pcp; 3304 EXTENDER_PORT_INFO(unit, vp)->de = extender_port->de; 3305 EXTENDER_PORT_INFO(unit, vp)->match_vlan = extender_port->match_vlan; 3306 3307 BCM_GPORT_EXTENDER_PORT_ID_SET(extender_port->extender_port_id, vp); 3308 3309 return rv; 3310 3311 cleanup: 3312 if (!(extender_port->flags & BCM_EXTENDER_PORT_REPLACE)) { 3313 (void) _bcm_vp_free(unit, _bcmVpTypeExtender, 1, vp); 3314 3315 if (!(extender_port->flags & BCM_EXTENDER_PORT_MATCH_NONE)) { 3316 _bcm_tr3_extender_nh_info_delete(unit, nh_index); 3317 } 3318 3319 (void)_bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigClear, vp, 3320 ING_DVP_CONFIG_INVALID_VP_TYPE, 3321 ING_DVP_CONFIG_INVALID_INTF_ID, 3322 ING_DVP_CONFIG_INVALID_PORT_TYPE); 3323 3324 sal_memset(&svp_entry, 0, sizeof(source_vp_entry_t)); 3325 (void)WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry); 3326 3327 #ifdef BCM_TRIDENT2_SUPPORT 3328 if (soc_mem_is_valid(unit, SOURCE_VP_2m)) { 3329 source_vp_2_entry_t svp_2_entry; 3330 3331 sal_memset(&svp_2_entry, 0, sizeof(source_vp_2_entry_t)); 3332 (void)WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, vp, &svp_2_entry); 3333 } 3334 #endif /* BCM_TRIDENT2_SUPPORT */ 3335 3336 if (!(extender_port->flags & BCM_EXTENDER_PORT_MULTICAST) 3337 && (!(extender_port->flags & BCM_EXTENDER_PORT_MATCH_NONE))) { 3338 (void) _bcm_tr3_extender_match_delete(unit, vp, NULL); 3339 } 3340 } 3341 3342 return rv; 3343 } 3344 3345 /* 3346 * Function: 3347 * bcm_tr3_extender_port_delete 3348 * Purpose: 3349 * Destroy a Extender virtual port. 3350 * Parameters: 3351 * unit - (IN) SOC unit number. 3352 * gport - (IN) Extender GPORT ID. 3353 * Returns: 3354 * BCM_X_XXX 3355 */ 3356 int 3357 bcm_tr3_extender_port_delete(int unit, bcm_gport_t gport) 3358 { 3359 int vp; 3360 source_vp_entry_t svp_entry; 3361 int nh_index; 3362 ing_dvp_table_entry_t dvp_entry; 3363 3364 if (!BCM_GPORT_IS_EXTENDER_PORT(gport)) { 3365 return BCM_E_PARAM; 3366 } 3367 3368 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport); 3369 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 3370 return BCM_E_NOT_FOUND; 3371 } 3372 if (EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE) { 3373 if (EXTENDER_PORT_INFO(unit, vp)->egress_list != NULL) { 3374 /* There are still EXTENDER egress objects attached to this 3375 * EXTENDER port. 3376 */ 3377 return BCM_E_BUSY; 3378 } 3379 } 3380 /* Delete failover information if found */ 3381 if (BCM_SUCCESS(_bcm_tr3_extender_failover_get(unit, gport, 3382 NULL, NULL, NULL))) { 3383 BCM_IF_ERROR_RETURN 3384 (_bcm_tr3_extender_failover_delete(unit, gport)); 3385 } 3386 3387 /* Delete ingress VLAN translation entry */ 3388 if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MULTICAST) 3389 && (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) 3390 ) { 3391 BCM_IF_ERROR_RETURN 3392 (_bcm_tr3_extender_match_delete(unit, vp, NULL)); 3393 } 3394 3395 /* Clear SVP entry */ 3396 sal_memset(&svp_entry, 0, sizeof(source_vp_entry_t)); 3397 BCM_IF_ERROR_RETURN 3398 (WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry)); 3399 3400 /* Clear SOURCE_VP_2 entry */ 3401 #ifdef BCM_TRIDENT2_SUPPORT 3402 if (soc_mem_is_valid(unit, SOURCE_VP_2m)) { 3403 source_vp_2_entry_t svp_2_entry; 3404 3405 sal_memset(&svp_2_entry, 0, sizeof(source_vp_2_entry_t)); 3406 BCM_IF_ERROR_RETURN 3407 (WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, vp, &svp_2_entry)); 3408 } 3409 #endif /* BCM_TRIDENT2_SUPPORT */ 3410 3411 /* Clear DVP entry */ 3412 BCM_IF_ERROR_RETURN 3413 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 3414 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, NEXT_HOP_INDEXf); 3415 BCM_IF_ERROR_RETURN( 3416 _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigClear, vp, 3417 ING_DVP_CONFIG_INVALID_VP_TYPE, 3418 ING_DVP_CONFIG_INVALID_INTF_ID, 3419 ING_DVP_CONFIG_INVALID_PORT_TYPE)); 3420 if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) { 3421 /* Clear next hop entries and free next hop index */ 3422 BCM_IF_ERROR_RETURN 3423 (_bcm_tr3_extender_nh_info_delete(unit, nh_index)); 3424 3425 /* Decrement port's VP count */ 3426 BCM_IF_ERROR_RETURN 3427 (_bcm_tr3_extender_port_cnt_update(unit, 3428 EXTENDER_PORT_INFO(unit, vp)->port, 3429 vp, FALSE)); 3430 } 3431 /* Free VP */ 3432 BCM_IF_ERROR_RETURN 3433 (_bcm_vp_free(unit, _bcmVpTypeExtender, 1, vp)); 3434 3435 /* Clear Extender VP software state */ 3436 sal_memset(EXTENDER_PORT_INFO(unit, vp), 0, 3437 sizeof(_bcm_tr3_extender_port_info_t)); 3438 3439 return BCM_E_NONE; 3440 } 3441 3442 /* 3443 * Function: 3444 * bcm_tr3_extender_port_delete_all 3445 * Purpose: 3446 * Destroy all Extender virtual ports. 3447 * Parameters: 3448 * unit - (IN) SOC unit number. 3449 * Returns: 3450 * BCM_X_XXX 3451 */ 3452 int 3453 bcm_tr3_extender_port_delete_all(int unit) 3454 { 3455 int i; 3456 bcm_gport_t extender_port_id; 3457 3458 for (i = soc_mem_index_min(unit, SOURCE_VPm); 3459 i <= soc_mem_index_max(unit, SOURCE_VPm); 3460 i++) { 3461 if (_bcm_vp_used_get(unit, i, _bcmVpTypeExtender)) { 3462 BCM_GPORT_EXTENDER_PORT_ID_SET(extender_port_id, i); 3463 BCM_IF_ERROR_RETURN 3464 (bcm_tr3_extender_port_delete(unit, extender_port_id)); 3465 } 3466 } 3467 3468 return BCM_E_NONE; 3469 } 3470 3471 /* 3472 * Function: 3473 * bcm_tr3_extender_port_get 3474 * Purpose: 3475 * Get Extender virtual port info. 3476 * Parameters: 3477 * unit - (IN) SOC unit number. 3478 * extender_port - (IN/OUT) Pointer to Extender virtual port structure. 3479 * Returns: 3480 * BCM_X_XXX 3481 */ 3482 int 3483 bcm_tr3_extender_port_get(int unit, bcm_extender_port_t *extender_port) 3484 { 3485 int rv, vp; 3486 3487 if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port->extender_port_id)) { 3488 return BCM_E_PARAM; 3489 } 3490 3491 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port->extender_port_id); 3492 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 3493 return BCM_E_NOT_FOUND; 3494 } 3495 3496 bcm_extender_port_t_init(extender_port); 3497 extender_port->flags = EXTENDER_PORT_INFO(unit, vp)->flags; 3498 BCM_GPORT_EXTENDER_PORT_ID_SET(extender_port->extender_port_id, vp); 3499 extender_port->port = EXTENDER_PORT_INFO(unit, vp)->port; 3500 extender_port->extended_port_vid = EXTENDER_PORT_INFO(unit, vp)-> 3501 extended_port_vid; 3502 extender_port->pcp_de_select = EXTENDER_PORT_INFO(unit, vp)->pcp_de_select; 3503 extender_port->qos_map_id = EXTENDER_PORT_INFO(unit, vp)->qos_map_id; 3504 extender_port->pcp = EXTENDER_PORT_INFO(unit, vp)->pcp; 3505 extender_port->de = EXTENDER_PORT_INFO(unit, vp)->de; 3506 extender_port->match_vlan = EXTENDER_PORT_INFO(unit, vp)->match_vlan; 3507 3508 rv = _bcm_tr3_extender_failover_get(unit, extender_port->extender_port_id, 3509 &extender_port->failover_port_id, 3510 &extender_port->failover_id, 3511 &extender_port->failover_mc_group); 3512 if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND && rv != BCM_E_UNAVAIL) { 3513 return rv; 3514 } 3515 3516 return BCM_E_NONE; 3517 } 3518 3519 /* 3520 * Function: 3521 * bcm_tr3_extender_port_traverse 3522 * Purpose: 3523 * Traverse all Extender ports and call supplied callback routine. 3524 * Parameters: 3525 * unit - (IN) Device Number 3526 * cb - (IN) User-provided callback 3527 * user_data - (IN/OUT) Cookie 3528 * Returns: 3529 * BCM_E_XXX 3530 */ 3531 int 3532 bcm_tr3_extender_port_traverse(int unit, bcm_extender_port_traverse_cb cb, 3533 void *user_data) 3534 { 3535 int i; 3536 bcm_extender_port_t extender_port; 3537 3538 for (i = soc_mem_index_min(unit, SOURCE_VPm); 3539 i <= soc_mem_index_max(unit, SOURCE_VPm); 3540 i++) { 3541 if (_bcm_vp_used_get(unit, i, _bcmVpTypeExtender)) { 3542 bcm_extender_port_t_init(&extender_port); 3543 BCM_GPORT_EXTENDER_PORT_ID_SET(extender_port.extender_port_id, i); 3544 BCM_IF_ERROR_RETURN(bcm_tr3_extender_port_get(unit, &extender_port)); 3545 BCM_IF_ERROR_RETURN(cb(unit, &extender_port, user_data)); 3546 } 3547 } 3548 3549 return BCM_E_NONE; 3550 } 3551 3552 /* 3553 * Function: 3554 * _bcm_tr3_extender_port_resolve 3555 * Purpose: 3556 * Get the modid, port, trunk values for a Extender virtual port 3557 * Parameters: 3558 * unit - (IN) BCM device number 3559 * gport - (IN) Global port identifier 3560 * modid - (OUT) Module ID 3561 * port - (OUT) Port number 3562 * trunk_id - (OUT) Trunk ID 3563 * id - (OUT) Virtual port ID 3564 * Returns: 3565 * BCM_E_XXX 3566 */ 3567 int 3568 _bcm_tr3_extender_port_resolve(int unit, bcm_gport_t extender_port_id, 3569 bcm_module_t *modid, bcm_port_t *port, 3570 bcm_trunk_t *trunk_id, int *id) 3571 3572 { 3573 int rv = BCM_E_NONE, nh_index, vp; 3574 ing_l3_next_hop_entry_t ing_nh; 3575 ing_dvp_table_entry_t dvp; 3576 uint32 dv, dt = SOC_MEM_FIF_DEST_INVALID; 3577 3578 if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port_id)) { 3579 return (BCM_E_BADID); 3580 } 3581 3582 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port_id); 3583 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 3584 return BCM_E_NOT_FOUND; 3585 } 3586 BCM_IF_ERROR_RETURN(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 3587 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 3588 NEXT_HOP_INDEXf); 3589 BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 3590 nh_index, &ing_nh)); 3591 3592 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf) != 0x2) { 3593 /* Entry type is not L2 DVP */ 3594 return BCM_E_NOT_FOUND; 3595 } 3596 3597 if (soc_feature(unit, soc_feature_generic_dest)) { 3598 dv = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, &ing_nh, 3599 DESTINATIONf, &dt); 3600 if (dt == SOC_MEM_FIF_DEST_LAG) { 3601 *trunk_id = dv; 3602 } else { 3603 *port = dv & SOC_MEM_FIF_DGPP_PORT_MASK; 3604 *modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >> 3605 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS; 3606 } 3607 } else { 3608 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 3609 *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf); 3610 } else { 3611 *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf); 3612 *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 3613 } 3614 } 3615 *id = vp; 3616 return rv; 3617 } 3618 3619 /* 3620 * Purpose: 3621 * Add a downstream forwarding entry 3622 * Parameters: 3623 * unit - (IN) Device Number 3624 * forward_entry - (IN) Forwarding entry 3625 */ 3626 int 3627 bcm_tr3_extender_forward_add(int unit, bcm_extender_forward_t *forward_entry) 3628 { 3629 int rv = BCM_E_NONE; 3630 bcm_module_t mod_out; 3631 bcm_port_t port_out; 3632 bcm_trunk_t tgid_out; 3633 int id_out; 3634 l2_entry_1_entry_t l2_entry; 3635 int lower_th, higher_th; 3636 3637 if (forward_entry->name_space > 0xfff) { 3638 return BCM_E_PARAM; 3639 } 3640 3641 BCM_IF_ERROR_RETURN( 3642 bcm_esw_switch_control_get(unit, 3643 bcmSwitchExtenderMulticastLowerThreshold, 3644 &lower_th)); 3645 BCM_IF_ERROR_RETURN( 3646 bcm_esw_switch_control_get(unit, 3647 bcmSwitchExtenderMulticastHigherThreshold, 3648 &higher_th)); 3649 3650 if ((forward_entry->extended_port_vid >= 3651 (1 << soc_mem_field_length(unit, L2_ENTRY_1m, PE_VID__ETAG_VIDf))) || 3652 (forward_entry->class_id >= 3653 (1 << soc_mem_field_length(unit, L2_ENTRY_1m, PE_VID__CLASS_IDf)))) { 3654 return BCM_E_PARAM; 3655 } 3656 3657 if (!(forward_entry->flags & BCM_EXTENDER_FORWARD_MULTICAST)) { 3658 if (forward_entry->extended_port_vid >= 3659 (1 << soc_mem_field_length(unit, L2_ENTRY_1m, 3660 PE_VID__ETAG_VIDf))) { 3661 return BCM_E_PARAM; 3662 } 3663 3664 if ((forward_entry->extended_port_vid >= lower_th) && 3665 (forward_entry->extended_port_vid <= higher_th)) { 3666 return BCM_E_PARAM; 3667 } 3668 3669 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, 3670 forward_entry->dest_port, 3671 &mod_out, &port_out, &tgid_out, &id_out)); 3672 if (-1 != id_out) { 3673 return BCM_E_PARAM; 3674 } 3675 3676 sal_memset(&l2_entry, 0, sizeof(l2_entry)); 3677 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VALIDf, 1); 3678 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, KEY_TYPEf, 3679 SOC_MEM_KEY_L2_ENTRY_1_PE_VID_PE_VID); 3680 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__NAMESPACEf, 3681 forward_entry->name_space); 3682 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__ETAG_VIDf, 3683 forward_entry->extended_port_vid); 3684 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__CLASS_IDf, 3685 forward_entry->class_id); 3686 if (-1 != tgid_out) { 3687 BCM_IF_ERROR_RETURN(_bcm_trunk_id_validate(unit, tgid_out)); 3688 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__DEST_TYPEf, 3689 1); 3690 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__TGIDf, 3691 tgid_out); 3692 } else { 3693 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__MODULE_IDf, 3694 mod_out); 3695 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__PORT_NUMf, 3696 port_out); 3697 } 3698 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, STATIC_BITf, 1); 3699 3700 } else { /* Multicast forward entry */ 3701 if ((forward_entry->extended_port_vid < lower_th) || 3702 (forward_entry->extended_port_vid > higher_th)) { 3703 return BCM_E_PARAM; 3704 } 3705 if (!_BCM_MULTICAST_IS_L2(forward_entry->dest_multicast)) { 3706 return BCM_E_PARAM; 3707 } 3708 3709 sal_memset(&l2_entry, 0, sizeof(l2_entry)); 3710 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VALIDf, 1); 3711 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, KEY_TYPEf, 3712 SOC_MEM_KEY_L2_ENTRY_1_PE_VID_PE_VID); 3713 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__NAMESPACEf, 3714 forward_entry->name_space); 3715 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__ETAG_VIDf, 3716 forward_entry->extended_port_vid); 3717 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__CLASS_IDf, 3718 forward_entry->class_id); 3719 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__L2MC_PTRf, 3720 _BCM_MULTICAST_ID_GET(forward_entry->dest_multicast)); 3721 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, STATIC_BITf, 1); 3722 } 3723 3724 if (forward_entry->flags & BCM_EXTENDER_FORWARD_COPY_TO_CPU) { 3725 if (SOC_MEM_FIELD_VALID(unit, L2_ENTRY_1m, PE_VID__DST_CPUf)) { 3726 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__DST_CPUf, 1); 3727 } 3728 } 3729 3730 soc_mem_lock(unit, L2_ENTRY_1m); 3731 3732 if (!(forward_entry->flags & BCM_EXTENDER_FORWARD_REPLACE)) { 3733 l2_entry_1_entry_t l2x_lookup; 3734 int l2_index; 3735 3736 /* See if the entry already exists */ 3737 rv = soc_mem_generic_lookup(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, 0, 3738 &l2_entry, &l2x_lookup, &l2_index); 3739 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 3740 soc_mem_unlock(unit, L2_ENTRY_1m); 3741 return rv; 3742 } 3743 if (BCM_SUCCESS(rv)) { 3744 soc_mem_unlock(unit, L2_ENTRY_1m); 3745 return BCM_E_EXISTS; 3746 } 3747 3748 rv = soc_mem_insert(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, &l2_entry); 3749 if (SOC_FAILURE(rv)) { 3750 soc_mem_unlock(unit, L2_ENTRY_1m); 3751 return rv; 3752 } 3753 } else { /* Replace existing entry */ 3754 rv = soc_mem_delete(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, &l2_entry); 3755 if (SOC_FAILURE(rv)) { 3756 soc_mem_unlock(unit, L2_ENTRY_1m); 3757 return rv; 3758 } 3759 rv = soc_mem_insert(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, &l2_entry); 3760 if (SOC_FAILURE(rv)) { 3761 soc_mem_unlock(unit, L2_ENTRY_1m); 3762 return rv; 3763 } 3764 } 3765 3766 soc_mem_unlock(unit, L2_ENTRY_1m); 3767 3768 return rv; 3769 } 3770 3771 /* 3772 * Purpose: 3773 * Delete a downstream forwarding entry 3774 * Parameters: 3775 * unit - (IN) Device Number 3776 * forward_entry - (IN) Forwarding entry 3777 */ 3778 int 3779 bcm_tr3_extender_forward_delete(int unit, 3780 bcm_extender_forward_t *forward_entry) 3781 { 3782 int rv = BCM_E_NONE; 3783 l2_entry_1_entry_t l2_entry; 3784 int lower_th, higher_th; 3785 3786 if (forward_entry->name_space > 0xfff) { 3787 return BCM_E_PARAM; 3788 } 3789 3790 BCM_IF_ERROR_RETURN( 3791 bcm_esw_switch_control_get(unit, 3792 bcmSwitchExtenderMulticastLowerThreshold, 3793 &lower_th)); 3794 BCM_IF_ERROR_RETURN( 3795 bcm_esw_switch_control_get(unit, 3796 bcmSwitchExtenderMulticastHigherThreshold, 3797 &higher_th)); 3798 3799 if (forward_entry->extended_port_vid >= 3800 (1 << soc_mem_field_length(unit, L2_ENTRY_1m, PE_VID__ETAG_VIDf))) { 3801 return BCM_E_PARAM; 3802 } 3803 3804 if (!(forward_entry->flags & BCM_EXTENDER_FORWARD_MULTICAST)) { 3805 if ((forward_entry->extended_port_vid >= lower_th) && 3806 (forward_entry->extended_port_vid <= higher_th)) { 3807 return BCM_E_PARAM; 3808 } 3809 } else { /* Multicast forward entry */ 3810 if ((forward_entry->extended_port_vid < lower_th) || 3811 (forward_entry->extended_port_vid > higher_th)) { 3812 return BCM_E_PARAM; 3813 } 3814 } 3815 3816 sal_memset(&l2_entry, 0, sizeof(l2_entry)); 3817 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, KEY_TYPEf, 3818 SOC_MEM_KEY_L2_ENTRY_1_PE_VID_PE_VID); 3819 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__NAMESPACEf, 3820 forward_entry->name_space); 3821 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__ETAG_VIDf, 3822 forward_entry->extended_port_vid); 3823 soc_mem_lock(unit, L2_ENTRY_1m); 3824 rv = soc_mem_delete(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, &l2_entry); 3825 soc_mem_unlock(unit, L2_ENTRY_1m); 3826 3827 return rv; 3828 } 3829 3830 /* 3831 * Purpose: 3832 * Delete all downstream forwarding entries 3833 * Parameters: 3834 * unit - Device Number 3835 */ 3836 int 3837 bcm_tr3_extender_forward_delete_all(int unit) 3838 { 3839 int rv = BCM_E_NONE; 3840 int seconds, enabled; 3841 l2_entry_1_entry_t match_mask; 3842 l2_entry_1_entry_t match_data; 3843 l2_bulk_entry_t l2_bulk; 3844 int match_mask_index, match_data_index; 3845 uint32 rval; 3846 int field_len; 3847 3848 SOC_IF_ERROR_RETURN 3849 (SOC_FUNCTIONS(unit)->soc_age_timer_get(unit, &seconds, &enabled)); 3850 if (enabled) { 3851 SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_stop(unit)); 3852 } 3853 3854 soc_mem_lock(unit, L2_ENTRY_1m); 3855 3856 /* Set match mask and data */ 3857 sal_memset(&match_mask, 0, sizeof(match_mask)); 3858 sal_memset(&match_data, 0, sizeof(match_data)); 3859 3860 soc_mem_field32_set(unit, L2_ENTRY_1m, &match_mask, VALIDf, 1); 3861 soc_mem_field32_set(unit, L2_ENTRY_1m, &match_data, VALIDf, 1); 3862 3863 soc_mem_field32_set(unit, L2_ENTRY_1m, &match_mask, WIDEf, 1); 3864 soc_mem_field32_set(unit, L2_ENTRY_1m, &match_data, WIDEf, 0); 3865 3866 field_len = soc_mem_field_length(unit, L2_ENTRY_1m, KEY_TYPEf); 3867 soc_mem_field32_set(unit, L2_ENTRY_1m, &match_mask, KEY_TYPEf, 3868 (1 << field_len) - 1); 3869 soc_mem_field32_set(unit, L2_ENTRY_1m, &match_data, KEY_TYPEf, 3870 SOC_MEM_KEY_L2_ENTRY_1_PE_VID_PE_VID); 3871 3872 sal_memset(&l2_bulk, 0, sizeof(l2_bulk)); 3873 sal_memcpy(&l2_bulk, &match_mask, sizeof(match_mask)); 3874 match_mask_index = 1; 3875 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, match_mask_index, &l2_bulk); 3876 if (BCM_SUCCESS(rv)) { 3877 sal_memset(&l2_bulk, 0, sizeof(l2_bulk)); 3878 sal_memcpy(&l2_bulk, &match_data, sizeof(match_data)); 3879 match_data_index = 0; 3880 rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, match_data_index, &l2_bulk); 3881 } 3882 3883 /* Set bulk control */ 3884 rval = 0; 3885 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0); 3886 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1); 3887 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 3888 _SOC_TR3_L2_BULK_BURST_MAX); 3889 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0); 3890 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 3891 soc_mem_index_count(unit, L2_ENTRY_1m)); 3892 soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 0); 3893 if (BCM_SUCCESS(rv)) { 3894 rv = WRITE_L2_BULK_CONTROLr(unit, rval); 3895 } 3896 if (BCM_SUCCESS(rv)) { 3897 rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr); 3898 } 3899 3900 soc_mem_unlock(unit, L2_ENTRY_1m); 3901 3902 if(enabled) { 3903 SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, seconds)); 3904 } 3905 3906 return rv; 3907 } 3908 3909 /* 3910 * Purpose: 3911 * Get a downstream forwarding entry 3912 * Parameters: 3913 * unit - (IN) Device Number 3914 * forward_entry - (IN/OUT) Forwarding entry 3915 */ 3916 int 3917 bcm_tr3_extender_forward_get(int unit, bcm_extender_forward_t *forward_entry) 3918 { 3919 int rv = BCM_E_NONE; 3920 l2_entry_1_entry_t l2_entry, l2_entry_out; 3921 int idx; 3922 _bcm_gport_dest_t dest; 3923 int l2mc_index; 3924 int lower_th, higher_th; 3925 3926 if (forward_entry->name_space > 0xfff) { 3927 return BCM_E_PARAM; 3928 } 3929 3930 BCM_IF_ERROR_RETURN( 3931 bcm_esw_switch_control_get(unit, 3932 bcmSwitchExtenderMulticastLowerThreshold, 3933 &lower_th)); 3934 BCM_IF_ERROR_RETURN( 3935 bcm_esw_switch_control_get(unit, 3936 bcmSwitchExtenderMulticastHigherThreshold, 3937 &higher_th)); 3938 3939 if (forward_entry->extended_port_vid >= 3940 (1 << soc_mem_field_length(unit, L2_ENTRY_1m, PE_VID__ETAG_VIDf))) { 3941 return BCM_E_PARAM; 3942 } 3943 3944 if (!(forward_entry->flags & BCM_EXTENDER_FORWARD_MULTICAST)) { 3945 if ((forward_entry->extended_port_vid >= lower_th) && 3946 (forward_entry->extended_port_vid <= higher_th)) { 3947 return BCM_E_PARAM; 3948 } 3949 } else { /* Multicast forward entry */ 3950 if ((forward_entry->extended_port_vid < lower_th) || 3951 (forward_entry->extended_port_vid > higher_th)) { 3952 return BCM_E_PARAM; 3953 } 3954 } 3955 3956 sal_memset(&l2_entry, 0, sizeof(l2_entry)); 3957 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, KEY_TYPEf, 3958 SOC_MEM_KEY_L2_ENTRY_1_PE_VID_PE_VID); 3959 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__NAMESPACEf, 3960 forward_entry->name_space); 3961 soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__ETAG_VIDf, 3962 forward_entry->extended_port_vid); 3963 soc_mem_lock(unit, L2_ENTRY_1m); 3964 rv = soc_mem_search(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, &idx, &l2_entry, 3965 &l2_entry_out, 0); 3966 soc_mem_unlock(unit, L2_ENTRY_1m); 3967 3968 if (SOC_SUCCESS(rv)) { 3969 if (!(forward_entry->flags & BCM_EXTENDER_FORWARD_MULTICAST)) { 3970 if (soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out, 3971 PE_VID__DEST_TYPEf)) { 3972 dest.tgid = soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out, 3973 PE_VID__TGIDf); 3974 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 3975 } else { 3976 dest.modid = soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out, 3977 PE_VID__MODULE_IDf); 3978 dest.port = soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out, 3979 PE_VID__PORT_NUMf); 3980 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 3981 } 3982 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, 3983 &(forward_entry->dest_port))); 3984 } else { 3985 l2mc_index = soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out, 3986 PE_VID__L2MC_PTRf); 3987 _BCM_MULTICAST_GROUP_SET(forward_entry->dest_multicast, 3988 _BCM_MULTICAST_TYPE_L2, l2mc_index); 3989 } 3990 forward_entry->class_id = soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out, 3991 PE_VID__CLASS_IDf); 3992 } 3993 3994 return rv; 3995 } 3996 3997 /* 3998 * Purpose: 3999 * Traverse all valid downstream forwarding entries and call the 4000 * supplied callback routine. 4001 * Parameters: 4002 * unit - Device Number 4003 * cb - User callback function, called once per forwarding entry. 4004 * user_data - cookie 4005 * Returns: 4006 * BCM_E_XXX 4007 */ 4008 int 4009 bcm_tr3_extender_forward_traverse(int unit, 4010 bcm_extender_forward_traverse_cb cb, 4011 void *user_data) 4012 { 4013 int rv = BCM_E_NONE; 4014 int chunk_entries, chunk_bytes; 4015 uint8 *l2_tbl_chunk = NULL; 4016 int chunk_idx_min, chunk_idx_max; 4017 int ent_idx; 4018 l2_entry_1_entry_t *l2_entry; 4019 bcm_extender_forward_t forward_entry; 4020 int l2mc_index; 4021 _bcm_gport_dest_t dest; 4022 int lower_th, higher_th; 4023 4024 /* Get ETAG VID multicast range */ 4025 BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit, 4026 bcmSwitchExtenderMulticastLowerThreshold, &lower_th)); 4027 BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit, 4028 bcmSwitchExtenderMulticastHigherThreshold, &higher_th)); 4029 4030 chunk_entries = soc_property_get(unit, spn_L2DELETE_CHUNKS, 4031 L2_MEM_CHUNKS_DEFAULT); 4032 chunk_bytes = 4 * SOC_MEM_WORDS(unit, L2_ENTRY_1m) * chunk_entries; 4033 l2_tbl_chunk = soc_cm_salloc(unit, chunk_bytes, "extender forward traverse"); 4034 if (NULL == l2_tbl_chunk) { 4035 return BCM_E_MEMORY; 4036 } 4037 for (chunk_idx_min = soc_mem_index_min(unit, L2_ENTRY_1m); 4038 chunk_idx_min <= soc_mem_index_max(unit, L2_ENTRY_1m); 4039 chunk_idx_min += chunk_entries) { 4040 4041 /* Read a chunk of L2 table */ 4042 sal_memset(l2_tbl_chunk, 0, chunk_bytes); 4043 chunk_idx_max = chunk_idx_min + chunk_entries - 1; 4044 if (chunk_idx_max > soc_mem_index_max(unit, L2_ENTRY_1m)) { 4045 chunk_idx_max = soc_mem_index_max(unit, L2_ENTRY_1m); 4046 } 4047 rv = soc_mem_read_range(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, 4048 chunk_idx_min, chunk_idx_max, l2_tbl_chunk); 4049 if (SOC_FAILURE(rv)) { 4050 break; 4051 } 4052 for (ent_idx = 0; 4053 ent_idx <= (chunk_idx_max - chunk_idx_min); 4054 ent_idx++) { 4055 l2_entry = soc_mem_table_idx_to_pointer(unit, L2_ENTRY_1m, 4056 l2_entry_1_entry_t *, l2_tbl_chunk, ent_idx); 4057 4058 if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry, VALIDf) == 0) { 4059 continue; 4060 } 4061 if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry, KEY_TYPEf) != 4062 SOC_MEM_KEY_L2_ENTRY_1_PE_VID_PE_VID) { 4063 continue; 4064 } 4065 4066 /* Get fields of forwarding entry */ 4067 bcm_extender_forward_t_init(&forward_entry); 4068 forward_entry.name_space = soc_L2_ENTRY_1m_field32_get(unit, 4069 l2_entry, PE_VID__NAMESPACEf); 4070 forward_entry.extended_port_vid = soc_L2_ENTRY_1m_field32_get(unit, 4071 l2_entry, PE_VID__ETAG_VIDf); 4072 forward_entry.class_id = soc_L2_ENTRY_1m_field32_get(unit, 4073 l2_entry, PE_VID__CLASS_IDf); 4074 if ((forward_entry.extended_port_vid >= lower_th) && 4075 (forward_entry.extended_port_vid <= higher_th)) { 4076 /* Multicast downstream forwarding entry */ 4077 forward_entry.flags |= BCM_EXTENDER_FORWARD_MULTICAST; 4078 l2mc_index = soc_L2_ENTRY_1m_field32_get(unit, l2_entry, 4079 PE_VID__L2MC_PTRf); 4080 _BCM_MULTICAST_GROUP_SET(forward_entry.dest_multicast, 4081 _BCM_MULTICAST_TYPE_L2, l2mc_index); 4082 } else { 4083 if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry, 4084 PE_VID__DEST_TYPEf)) { 4085 dest.tgid = soc_L2_ENTRY_1m_field32_get(unit, l2_entry, 4086 PE_VID__TGIDf); 4087 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 4088 } else { 4089 dest.modid = soc_L2_ENTRY_1m_field32_get(unit, l2_entry, 4090 PE_VID__MODULE_IDf); 4091 dest.port = soc_L2_ENTRY_1m_field32_get(unit, l2_entry, 4092 PE_VID__PORT_NUMf); 4093 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 4094 } 4095 rv = _bcm_esw_gport_construct(unit, &dest, 4096 &(forward_entry.dest_port)); 4097 if (BCM_FAILURE(rv)) { 4098 break; 4099 } 4100 } 4101 4102 if (SOC_MEM_FIELD_VALID(unit, L2_ENTRY_1m, PE_VID__DST_CPUf)) { 4103 if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry, 4104 PE_VID__DST_CPUf)) { 4105 forward_entry.flags |= BCM_EXTENDER_FORWARD_COPY_TO_CPU; 4106 } 4107 } 4108 4109 /* Invoke callback */ 4110 rv = cb(unit, &forward_entry, user_data); 4111 if (BCM_FAILURE(rv)) { 4112 break; 4113 } 4114 } 4115 if (BCM_FAILURE(rv)) { 4116 break; 4117 } 4118 } 4119 soc_cm_sfree(unit, l2_tbl_chunk); 4120 4121 return rv; 4122 } 4123 4124 /* 4125 * Function: 4126 * bcm_tr3_etag_ethertype_set 4127 * Purpose: 4128 * Set ETAG Ethertype. 4129 * Parameters: 4130 * unit - (IN) BCM device number 4131 * ethertype - (IN) Ethertype 4132 * Returns: 4133 * BCM_E_XXX 4134 */ 4135 int 4136 bcm_tr3_etag_ethertype_set(int unit, int ethertype) 4137 { 4138 4139 if (ethertype < 0 || ethertype > 0xffff) { 4140 return BCM_E_PARAM; 4141 } 4142 4143 if (soc_reg_field_valid(unit, PE_ETHERTYPEr, ETHERTYPEf)) { 4144 BCM_IF_ERROR_RETURN 4145 (soc_reg_field32_modify(unit, PE_ETHERTYPEr, 4146 REG_PORT_ANY, ETHERTYPEf, ethertype)); 4147 BCM_IF_ERROR_RETURN 4148 (soc_reg_field32_modify(unit, PE_ETHERTYPEr, 4149 REG_PORT_ANY, ENABLEf, ethertype ? 1 : 0)); 4150 } 4151 4152 if (soc_reg_field_valid(unit, EGR_PE_ETHERTYPEr, ETHERTYPEf)) { 4153 BCM_IF_ERROR_RETURN 4154 (soc_reg_field32_modify(unit, EGR_PE_ETHERTYPEr, 4155 REG_PORT_ANY, ETHERTYPEf, ethertype)); 4156 BCM_IF_ERROR_RETURN 4157 (soc_reg_field32_modify(unit, EGR_PE_ETHERTYPEr, 4158 REG_PORT_ANY, ENABLEf, ethertype ? 1 : 0)); 4159 } 4160 4161 if (soc_reg_field_valid(unit, EGR_PE_ETHERTYPE_2r, ETHERTYPEf)) { 4162 BCM_IF_ERROR_RETURN 4163 (soc_reg_field32_modify(unit, EGR_PE_ETHERTYPE_2r, 4164 REG_PORT_ANY, ETHERTYPEf, ethertype)); 4165 BCM_IF_ERROR_RETURN 4166 (soc_reg_field32_modify(unit, EGR_PE_ETHERTYPE_2r, 4167 REG_PORT_ANY, ENABLEf, ethertype ? 1 : 0)); 4168 } 4169 4170 if (soc_reg_field_valid(unit, IDB_OBM0_PE_ETHERTYPEr, ETHERTYPEf)) { 4171 BCM_IF_ERROR_RETURN 4172 (soc_reg_field32_modify(unit, IDB_OBM0_PE_ETHERTYPEr, 4173 REG_PORT_ANY, ETHERTYPEf, ethertype)); 4174 BCM_IF_ERROR_RETURN 4175 (soc_reg_field32_modify(unit, IDB_OBM0_PE_ETHERTYPEr, 4176 REG_PORT_ANY, ENABLEf, ethertype ? 1 : 0)); 4177 } 4178 4179 #ifdef BCM_TRIDENT3_SUPPORT 4180 if (SOC_IS_TRIDENT3X(unit)) { 4181 soc_td3_rx_etype_pe[unit] = ethertype; 4182 } 4183 #endif 4184 4185 return BCM_E_NONE; 4186 } 4187 4188 /* 4189 * Function: 4190 * bcm_tr3_etag_ethertype_get 4191 * Purpose: 4192 * Get ETAG Ethertype. 4193 * Parameters: 4194 * unit - (IN) BCM device number 4195 * ethertype - (OUT) Ethertype 4196 * Returns: 4197 * BCM_E_XXX 4198 */ 4199 int 4200 bcm_tr3_etag_ethertype_get(int unit, int *ethertype) 4201 { 4202 uint32 rval; 4203 4204 if (ethertype == NULL) { 4205 return BCM_E_PARAM; 4206 } 4207 4208 BCM_IF_ERROR_RETURN(READ_PE_ETHERTYPEr(unit, &rval)); 4209 if (soc_reg_field_get(unit, PE_ETHERTYPEr, rval, ENABLEf)) { 4210 *ethertype = soc_reg_field_get(unit, PE_ETHERTYPEr, rval, ETHERTYPEf); 4211 } else { 4212 *ethertype = 0; 4213 } 4214 4215 return BCM_E_NONE; 4216 } 4217 4218 /* 4219 * Function: 4220 * bcm_tr3_extender_untagged_add 4221 * Purpose: 4222 * Set Extender VP tagging/untagging status by adding 4223 * a (Extender VP, VLAN) egress VLAN translation entry. 4224 * Parameters: 4225 * unit - (IN) SOC unit number. 4226 * vlan - (IN) VLAN ID. 4227 * vp - (IN) Virtual port number. 4228 * flags - (IN) Untagging indication. 4229 * egr_vt_added - (OUT) Indicates if (VP, VLAN) added to egress VLAN 4230 * translation table. 4231 * Returns: 4232 * BCM_X_XXX 4233 */ 4234 int 4235 bcm_tr3_extender_untagged_add(int unit, bcm_vlan_t vlan, int vp, int flags, 4236 int *egr_vt_added) 4237 { 4238 uint32 vent[SOC_MAX_MEM_FIELD_WORDS]; 4239 uint32 old_vent[SOC_MAX_MEM_FIELD_WORDS]; 4240 bcm_vlan_action_set_t action; 4241 uint32 profile_idx; 4242 int rv = BCM_E_NONE; 4243 soc_mem_t mem = EGR_VLAN_XLATEm; 4244 if (soc_mem_is_valid(unit, EGR_VLAN_XLATE_1_DOUBLEm)) { 4245 mem = EGR_VLAN_XLATE_1_DOUBLEm; 4246 } 4247 4248 *egr_vt_added = FALSE; 4249 4250 sal_memset(vent, 0, sizeof(vent)); 4251 if (soc_feature(unit, soc_feature_base_valid)) { 4252 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3); 4253 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7); 4254 } else { 4255 soc_mem_field32_set(unit, mem, vent, VALIDf, 1); 4256 } 4257 if (soc_mem_field_valid(unit, mem, ENTRY_TYPEf)) { 4258 soc_mem_field32_set(unit, mem, vent, ENTRY_TYPEf, 1); 4259 } else if (soc_mem_field_valid(unit, mem, DATA_TYPEf)) { 4260 soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, 1); 4261 } 4262 4263 if (soc_mem_field_valid(unit, mem, KEY_TYPEf)) { 4264 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 1); 4265 } 4266 soc_mem_field32_set(unit, mem, vent, DVPf, vp); 4267 soc_mem_field32_set(unit, mem, vent, OVIDf, vlan); 4268 4269 if (!BCM_VLAN_VALID(EXTENDER_PORT_INFO(unit, vp)->match_vlan)) { 4270 if (!(flags & BCM_VLAN_PORT_UNTAGGED)) { 4271 /* No need to insert an egress vlan translation entry 4272 * to remove the outer tag. 4273 */ 4274 return BCM_E_NONE; 4275 } 4276 4277 #ifdef BCM_TRIDENT2_SUPPORT 4278 if (soc_mem_field_valid(unit, EGR_VP_VLAN_MEMBERSHIPm, UNTAGf)) { 4279 if (flags & BCM_VLAN_GPORT_ADD_VP_VLAN_MEMBERSHIP) { 4280 /* The UNTAG field of EGR_VP_VLAN_MEMBERSHIP table will 4281 * be configured with untagging status. It would be redundant 4282 * to insert an egress VLAN translation entry. 4283 */ 4284 return BCM_E_NONE; 4285 } 4286 } 4287 #endif /* BCM_TRIDENT2_SUPPORT */ 4288 4289 bcm_vlan_action_set_t_init(&action); 4290 action.dt_outer = bcmVlanActionDelete; 4291 action.ot_outer = bcmVlanActionDelete; 4292 } else { 4293 /* Extender port's match_vlan is valid. It needs to be inserted 4294 * into the packet using an egress vlan translation entry. 4295 */ 4296 soc_mem_field32_set(unit, mem, vent, NEW_OVIDf, 4297 EXTENDER_PORT_INFO(unit, vp)->match_vlan); 4298 bcm_vlan_action_set_t_init(&action); 4299 action.dt_outer = bcmVlanActionReplace; 4300 action.ot_outer = bcmVlanActionReplace; 4301 if (flags & BCM_VLAN_PORT_UNTAGGED) { 4302 action.dt_inner = bcmVlanActionNone; 4303 action.ot_inner = bcmVlanActionNone; 4304 } else { 4305 action.dt_inner = bcmVlanActionCopy; 4306 action.ot_inner = bcmVlanActionCopy; 4307 } 4308 } 4309 BCM_IF_ERROR_RETURN 4310 (_bcm_trx_egr_vlan_action_profile_entry_add(unit, &action, &profile_idx)); 4311 soc_mem_field32_set(unit, mem, vent, TAG_ACTION_PROFILE_PTRf, 4312 profile_idx); 4313 4314 rv = soc_mem_insert_return_old(unit, mem, MEM_BLOCK_ALL, 4315 vent, old_vent); 4316 if (rv == SOC_E_EXISTS) { 4317 /* Delete the old vlan translate profile entry */ 4318 profile_idx = soc_mem_field32_get(unit, mem, old_vent, 4319 TAG_ACTION_PROFILE_PTRf); 4320 rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, profile_idx); 4321 } 4322 4323 *egr_vt_added = TRUE; 4324 4325 return rv; 4326 } 4327 4328 /* 4329 * Function: 4330 * bcm_tr3_extender_untagged_delete 4331 * Purpose: 4332 * Delete (Extender VP, VLAN) egress VLAN translation entry. 4333 * Parameters: 4334 * unit - (IN) SOC unit number. 4335 * vlan - (IN) VLAN ID. 4336 * vp - (IN) Virtual port number. 4337 * Returns: 4338 * BCM_X_XXX 4339 */ 4340 int 4341 bcm_tr3_extender_untagged_delete(int unit, bcm_vlan_t vlan, int vp) 4342 { 4343 uint32 vent[SOC_MAX_MEM_FIELD_WORDS]; 4344 uint32 old_vent[SOC_MAX_MEM_FIELD_WORDS]; 4345 uint32 profile_idx; 4346 int rv; 4347 soc_mem_t mem = EGR_VLAN_XLATEm; 4348 if (soc_mem_is_valid(unit, EGR_VLAN_XLATE_1_DOUBLEm)) { 4349 mem = EGR_VLAN_XLATE_1_DOUBLEm; 4350 } 4351 4352 sal_memset(vent, 0, sizeof(vent)); 4353 if (soc_mem_field_valid(unit, mem, ENTRY_TYPEf)) { 4354 soc_mem_field32_set(unit, mem, vent, ENTRY_TYPEf, 1); 4355 } else if (soc_mem_field_valid(unit, mem, DATA_TYPEf)) { 4356 soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, 1); 4357 } 4358 4359 if (soc_mem_field_valid(unit, mem, KEY_TYPEf)) { 4360 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 1); 4361 } 4362 soc_mem_field32_set(unit, mem, vent, DVPf, vp); 4363 soc_mem_field32_set(unit, mem, vent, OVIDf, vlan); 4364 4365 rv = soc_mem_delete_return_old(unit, mem, MEM_BLOCK_ALL, 4366 vent, old_vent); 4367 if (rv == SOC_E_NONE) { 4368 uint32 is_valid = 0; 4369 if (soc_feature(unit, soc_feature_base_valid)) { 4370 is_valid = 4371 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_0f) == 3 && 4372 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_1f) == 7; 4373 } else { 4374 is_valid = soc_mem_field32_get(unit, mem, old_vent, VALIDf); 4375 } 4376 if (is_valid) { 4377 /* Delete the old vlan translate profile entry */ 4378 profile_idx = soc_mem_field32_get(unit, mem, old_vent, 4379 TAG_ACTION_PROFILE_PTRf); 4380 rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, profile_idx); 4381 } 4382 } 4383 4384 return rv; 4385 } 4386 4387 /* 4388 * Function: 4389 * bcm_tr3_extender_untagged_get 4390 * Purpose: 4391 * Get tagging/untagging status of a Extender virtual port by 4392 * reading the (Extender VP, VLAN) egress vlan translation entry. 4393 * Parameters: 4394 * unit - (IN) SOC unit number. 4395 * vlan - (IN) VLAN to remove virtual port from. 4396 * vp - (IN) Virtual port number. 4397 * flags - (OUT) Untagging status of the Extender virtual port. 4398 * Returns: 4399 * BCM_E_XXX 4400 */ 4401 int 4402 bcm_tr3_extender_untagged_get(int unit, bcm_vlan_t vlan, int vp, 4403 int *flags) 4404 { 4405 uint32 vent[SOC_MAX_MEM_FIELD_WORDS]; 4406 uint32 res_vent[SOC_MAX_MEM_FIELD_WORDS]; 4407 int idx; 4408 uint32 profile_idx; 4409 int rv; 4410 bcm_vlan_action_set_t action; 4411 soc_mem_t mem = EGR_VLAN_XLATEm; 4412 if (soc_mem_is_valid(unit, EGR_VLAN_XLATE_1_DOUBLEm)) { 4413 mem = EGR_VLAN_XLATE_1_DOUBLEm; 4414 } 4415 4416 *flags = 0; 4417 4418 sal_memset(vent, 0, sizeof(vent)); 4419 if (soc_mem_field_valid(unit, mem, ENTRY_TYPEf)) { 4420 soc_mem_field32_set(unit, mem, vent, ENTRY_TYPEf, 1); 4421 } else if (soc_mem_field_valid(unit, mem, DATA_TYPEf)) { 4422 soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, 1); 4423 } 4424 4425 if (soc_mem_field_valid(unit, mem, KEY_TYPEf)) { 4426 soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 1); 4427 } 4428 soc_mem_field32_set(unit, mem, vent, DVPf, vp); 4429 soc_mem_field32_set(unit, mem, vent, OVIDf, vlan); 4430 4431 rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL, &idx, vent, res_vent, 0); 4432 if (rv == SOC_E_NONE) { 4433 uint32 is_valid = 0; 4434 if (soc_feature(unit, soc_feature_base_valid)) { 4435 is_valid = 4436 soc_mem_field32_get(unit, mem, res_vent, BASE_VALID_0f) == 3 && 4437 soc_mem_field32_get(unit, mem, res_vent, BASE_VALID_1f) == 7; 4438 } else { 4439 is_valid = soc_mem_field32_get(unit, mem, res_vent, VALIDf); 4440 } 4441 if (is_valid) { 4442 profile_idx = soc_mem_field32_get(unit, mem, res_vent, 4443 TAG_ACTION_PROFILE_PTRf); 4444 _bcm_trx_egr_vlan_action_profile_entry_get(unit, &action, profile_idx); 4445 4446 if (!BCM_VLAN_VALID(EXTENDER_PORT_INFO(unit, vp)->match_vlan)) { 4447 if (bcmVlanActionDelete == action.ot_outer) { 4448 *flags = BCM_VLAN_PORT_UNTAGGED; 4449 } 4450 } else { 4451 if (bcmVlanActionNone == action.ot_inner) { 4452 *flags = BCM_VLAN_PORT_UNTAGGED; 4453 } 4454 } 4455 } 4456 } 4457 4458 return rv; 4459 } 4460 4461 /* 4462 * Function: 4463 * bcm_tr3_niv_port_untagged_vlan_set 4464 * Purpose: 4465 * Set the default VLAN ID for an Extender port. 4466 * Parameters: 4467 * unit - StrataSwitch unit number. 4468 * port - Extender gport. 4469 * vid - VLAN ID used for packets that ingress without a VLAN tag. 4470 * Returns: 4471 * BCM_E_xxx 4472 */ 4473 int 4474 bcm_tr3_extender_port_untagged_vlan_set(int unit, bcm_port_t port, 4475 bcm_vlan_t vid) 4476 { 4477 int rv = BCM_E_NONE; 4478 int vp; 4479 uint32 key_data[SOC_MAX_MEM_FIELD_WORDS]; 4480 uint32 entry_data[SOC_MAX_MEM_FIELD_WORDS]; 4481 int key_type; 4482 bcm_module_t mod_out; 4483 bcm_port_t port_out; 4484 bcm_trunk_t trunk_out; 4485 int tmp_id; 4486 int entry_index; 4487 soc_mem_t mem = VLAN_XLATEm; 4488 4489 if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) { 4490 mem = VLAN_XLATE_1_DOUBLEm; 4491 } 4492 4493 /* Get VP */ 4494 if (BCM_GPORT_IS_EXTENDER_PORT(port)) { 4495 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(port); 4496 } else { 4497 return BCM_E_PORT; 4498 } 4499 4500 /* Construct lookup key */ 4501 sal_memset(key_data, 0, sizeof(key_data)); 4502 4503 if (BCM_VLAN_VALID(EXTENDER_PORT_INFO(unit, vp)->match_vlan)) { 4504 BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit, 4505 VLXLT_HASH_KEY_TYPE_VIF_VLAN, &key_type)); 4506 soc_mem_field32_set(unit, mem, key_data, VIF__VLANf, 4507 EXTENDER_PORT_INFO(unit, vp)->match_vlan); 4508 } else { 4509 BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit, 4510 VLXLT_HASH_KEY_TYPE_VIF, &key_type)); 4511 } 4512 soc_mem_field32_set(unit, mem, key_data, KEY_TYPEf, key_type); 4513 if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) { 4514 soc_mem_field32_set(unit, mem, key_data, DATA_TYPEf, key_type); 4515 } 4516 4517 soc_mem_field32_set(unit, mem, key_data, VIF__SRC_VIFf, 4518 EXTENDER_PORT_INFO(unit, vp)->extended_port_vid); 4519 4520 if (soc_mem_field_valid(unit, mem, SOURCE_TYPEf)) { 4521 soc_mem_field32_set(unit, mem, key_data, SOURCE_TYPEf, 1); 4522 } 4523 BCM_IF_ERROR_RETURN 4524 (_bcm_esw_gport_resolve(unit, EXTENDER_PORT_INFO(unit, vp)->port, 4525 &mod_out, &port_out, &trunk_out, &tmp_id)); 4526 if (BCM_GPORT_IS_TRUNK(EXTENDER_PORT_INFO(unit, vp)->port)) { 4527 soc_mem_field32_set(unit, mem, key_data, VIF__Tf, 1); 4528 soc_mem_field32_set(unit, mem, key_data, VIF__TGIDf, trunk_out); 4529 } else { 4530 soc_mem_field32_set(unit, mem, key_data, VIF__MODULE_IDf, mod_out); 4531 soc_mem_field32_set(unit, mem, key_data, VIF__PORT_NUMf, port_out); 4532 } 4533 4534 /* Lookup existing entry */ 4535 SOC_IF_ERROR_RETURN(soc_mem_search(unit, mem, MEM_BLOCK_ALL, 4536 &entry_index, key_data, entry_data, 0)); 4537 4538 /* Replace entry's new VLAN */ 4539 soc_mem_field32_set(unit, mem, entry_data, VIF__NEW_OVIDf, vid); 4540 4541 /* Insert new entry */ 4542 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry_data); 4543 if (rv == SOC_E_EXISTS) { 4544 rv = BCM_E_NONE; 4545 } else { 4546 return BCM_E_INTERNAL; 4547 } 4548 4549 return rv; 4550 } 4551 4552 /* 4553 * Function: 4554 * bcm_tr3_extender_port_untagged_vlan_get 4555 * Purpose: 4556 * Get the default VLAN ID for an Extender port. 4557 * Parameters: 4558 * unit - StrataSwitch unit number. 4559 * port - Extender gport. 4560 * vid - (OUT) VLAN ID used for packets that ingress without a VLAN tag. 4561 * Returns: 4562 * BCM_E_xxx 4563 */ 4564 int 4565 bcm_tr3_extender_port_untagged_vlan_get(int unit, bcm_port_t port, 4566 bcm_vlan_t *vid) 4567 { 4568 int rv = BCM_E_NONE; 4569 int vp; 4570 uint32 key_data[SOC_MAX_MEM_FIELD_WORDS]; 4571 uint32 entry_data[SOC_MAX_MEM_FIELD_WORDS]; 4572 int key_type; 4573 bcm_module_t mod_out; 4574 bcm_port_t port_out; 4575 bcm_trunk_t trunk_out; 4576 int tmp_id; 4577 int entry_index; 4578 soc_mem_t mem = VLAN_XLATEm; 4579 4580 if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) { 4581 mem = VLAN_XLATE_1_DOUBLEm; 4582 } 4583 4584 /* Get VP */ 4585 if (BCM_GPORT_IS_EXTENDER_PORT(port)) { 4586 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(port); 4587 } else { 4588 return BCM_E_PORT; 4589 } 4590 4591 /* Construct lookup key */ 4592 sal_memset(key_data, 0, sizeof(key_data)); 4593 4594 if (BCM_VLAN_VALID(EXTENDER_PORT_INFO(unit, vp)->match_vlan)) { 4595 BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit, 4596 VLXLT_HASH_KEY_TYPE_VIF_VLAN, &key_type)); 4597 soc_mem_field32_set(unit, mem, key_data, VIF__VLANf, 4598 EXTENDER_PORT_INFO(unit, vp)->match_vlan); 4599 } else { 4600 BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit, 4601 VLXLT_HASH_KEY_TYPE_VIF, &key_type)); 4602 } 4603 soc_mem_field32_set(unit, mem, key_data, KEY_TYPEf, key_type); 4604 if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) { 4605 soc_mem_field32_set(unit, mem, key_data, DATA_TYPEf, key_type); 4606 } 4607 4608 soc_mem_field32_set(unit, mem, key_data, VIF__SRC_VIFf, 4609 EXTENDER_PORT_INFO(unit, vp)->extended_port_vid); 4610 4611 if (soc_mem_field_valid(unit, mem, SOURCE_TYPEf)) { 4612 soc_mem_field32_set(unit, mem, key_data, SOURCE_TYPEf, 1); 4613 } 4614 BCM_IF_ERROR_RETURN 4615 (_bcm_esw_gport_resolve(unit, EXTENDER_PORT_INFO(unit, vp)->port, 4616 &mod_out, &port_out, &trunk_out, &tmp_id)); 4617 if (BCM_GPORT_IS_TRUNK(EXTENDER_PORT_INFO(unit, vp)->port)) { 4618 soc_mem_field32_set(unit, mem, key_data, VIF__Tf, 1); 4619 soc_mem_field32_set(unit, mem, key_data, VIF__TGIDf, trunk_out); 4620 } else { 4621 soc_mem_field32_set(unit, mem, key_data, VIF__MODULE_IDf, mod_out); 4622 soc_mem_field32_set(unit, mem, key_data, VIF__PORT_NUMf, port_out); 4623 } 4624 4625 /* Lookup existing entry */ 4626 SOC_IF_ERROR_RETURN(soc_mem_search(unit, mem, MEM_BLOCK_ALL, 4627 &entry_index, key_data, entry_data, 0)); 4628 4629 /* Get entry's VLAN */ 4630 *vid = soc_mem_field32_get(unit, mem, entry_data, VIF__NEW_OVIDf); 4631 4632 return rv; 4633 } 4634 4635 /* 4636 * Function: 4637 * bcm_tr3_extender_port_learn_set 4638 * Purpose: 4639 * Set the CML bits for an extender port id. 4640 * Parameters: 4641 * unit - (IN) SOC unit number. 4642 * extender_port_id - (IN) Extender port id. 4643 * flags - (IN) Logical OR of BCM_PORT_LEARN_xxx flags 4644 * Returns: 4645 * BCM_E_XXX 4646 */ 4647 int 4648 bcm_tr3_extender_port_learn_set(int unit, bcm_gport_t extender_port_id, 4649 uint32 flags) 4650 { 4651 int vp = -1; 4652 int cml = 0; 4653 int rv = BCM_E_NONE; 4654 int entry_type; 4655 source_vp_entry_t svp; 4656 4657 cml = 0; 4658 if (!(flags & BCM_PORT_LEARN_FWD)) { 4659 cml |= (1 << 0); 4660 } 4661 if (flags & BCM_PORT_LEARN_CPU) { 4662 cml |= (1 << 1); 4663 } 4664 if (flags & BCM_PORT_LEARN_PENDING) { 4665 cml |= (1 << 2); 4666 } 4667 if (flags & BCM_PORT_LEARN_ARL) { 4668 cml |= (1 << 3); 4669 } 4670 4671 /* Get the VP index from the gport */ 4672 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port_id); 4673 if (vp == -1) { 4674 return BCM_E_PARAM; 4675 } 4676 4677 MEM_LOCK(unit, SOURCE_VPm); 4678 /* Be sure the entry is used and is set for Extender */ 4679 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 4680 MEM_UNLOCK(unit, SOURCE_VPm); 4681 return BCM_E_NOT_FOUND; 4682 } 4683 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 4684 if (SOC_FAILURE(rv)) { 4685 MEM_UNLOCK(unit, SOURCE_VPm); 4686 return rv; 4687 } 4688 4689 entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf); 4690 if (entry_type != 3) { 4691 MEM_UNLOCK(unit, SOURCE_VPm); 4692 return BCM_E_NOT_FOUND; 4693 } 4694 4695 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml); 4696 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml); 4697 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp); 4698 4699 MEM_UNLOCK(unit, SOURCE_VPm); 4700 return rv; 4701 } 4702 4703 /* 4704 * Function: 4705 * bcm_tr3_extender_port_learn_get 4706 * Purpose: 4707 * Get the CML bits for an extender port id 4708 * Parameters: 4709 * unit - (IN) SOC unit number. 4710 * extender_port_id - (IN) Extender port id. 4711 * flags - (OUT) Logical OR of BCM_PORT_LEARN_xxx flags 4712 * Returns: 4713 * BCM_E_XXX 4714 */ 4715 int 4716 bcm_tr3_extender_port_learn_get(int unit, bcm_gport_t extender_port_id, 4717 uint32 *flags) 4718 { 4719 int vp = -1; 4720 int cml = 0; 4721 int rv = BCM_E_NONE; 4722 int entry_type; 4723 source_vp_entry_t svp; 4724 4725 /* Get the VP index from the gport */ 4726 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port_id); 4727 if (vp == -1) { 4728 return BCM_E_PARAM; 4729 } 4730 4731 /* Be sure the entry is used and is set for EXTENDER */ 4732 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 4733 return BCM_E_NOT_FOUND; 4734 } 4735 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 4736 if (rv < 0) { 4737 return rv; 4738 } 4739 4740 entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf); 4741 if (entry_type != 3) { 4742 return BCM_E_NOT_FOUND; 4743 } 4744 4745 cml = soc_SOURCE_VPm_field32_get(unit, &svp, CML_FLAGS_NEWf); 4746 4747 *flags = 0; 4748 if (!(cml & (1 << 0))) { 4749 *flags |= BCM_PORT_LEARN_FWD; 4750 } 4751 if (cml & (1 << 1)) { 4752 *flags |= BCM_PORT_LEARN_CPU; 4753 } 4754 if (cml & (1 << 2)) { 4755 *flags |= BCM_PORT_LEARN_PENDING; 4756 } 4757 if (cml & (1 << 3)) { 4758 *flags |= BCM_PORT_LEARN_ARL; 4759 } 4760 return BCM_E_NONE; 4761 } 4762 4763 #ifdef BCM_TRIDENT2_SUPPORT 4764 4765 /* 4766 * Function: 4767 * _bcm_td2_extender_match_vp_replace 4768 * Purpose: 4769 * Replace VP value in Extender VP's match entry. 4770 * Parameters: 4771 * unit - (IN) SOC unit number. 4772 * vp - (IN) Extender VP whose match entry is being replaced. 4773 * new_vp - (IN) New VP value. 4774 * old_vp - (OUT) Old VP value. 4775 * Returns: 4776 * BCM_X_XXX 4777 */ 4778 STATIC int 4779 _bcm_td2_extender_match_vp_replace(int unit, int vp, int new_vp, int *old_vp) 4780 { 4781 int rv = BCM_E_NONE; 4782 uint32 key_data[SOC_MAX_MEM_FIELD_WORDS]; 4783 uint32 entry_data[SOC_MAX_MEM_FIELD_WORDS]; 4784 int key_type; 4785 bcm_module_t mod_out; 4786 bcm_port_t port_out; 4787 bcm_trunk_t trunk_out; 4788 int tmp_id; 4789 int entry_index; 4790 soc_mem_t vx_mem = VLAN_XLATEm; 4791 4792 if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) { 4793 vx_mem = VLAN_XLATE_1_DOUBLEm; 4794 } 4795 4796 /* Construct lookup key */ 4797 sal_memset(key_data, 0, sizeof(key_data)); 4798 4799 if (BCM_VLAN_VALID(EXTENDER_PORT_INFO(unit, vp)->match_vlan)) { 4800 BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit, 4801 VLXLT_HASH_KEY_TYPE_VIF_VLAN, &key_type)); 4802 soc_mem_field32_set(unit, vx_mem, key_data, VIF__VLANf, 4803 EXTENDER_PORT_INFO(unit, vp)->match_vlan); 4804 } else { 4805 BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit, 4806 VLXLT_HASH_KEY_TYPE_VIF, &key_type)); 4807 } 4808 soc_mem_field32_set(unit, vx_mem, key_data, KEY_TYPEf, key_type); 4809 if (SOC_MEM_FIELD_VALID(unit, vx_mem, DATA_TYPEf)) { 4810 soc_mem_field32_set(unit, vx_mem, key_data, DATA_TYPEf, key_type); 4811 } 4812 4813 soc_mem_field32_set(unit, vx_mem, key_data, VIF__SRC_VIFf, 4814 EXTENDER_PORT_INFO(unit, vp)->extended_port_vid); 4815 if (soc_mem_field_valid(unit, vx_mem, SOURCE_TYPEf)) { 4816 soc_mem_field32_set(unit, vx_mem, key_data, SOURCE_TYPEf, 1); 4817 } 4818 BCM_IF_ERROR_RETURN 4819 (_bcm_esw_gport_resolve(unit, EXTENDER_PORT_INFO(unit, vp)->port, 4820 &mod_out, &port_out, &trunk_out, &tmp_id)); 4821 if (BCM_GPORT_IS_TRUNK(EXTENDER_PORT_INFO(unit, vp)->port)) { 4822 soc_mem_field32_set(unit, vx_mem, key_data, VIF__Tf, 1); 4823 soc_mem_field32_set(unit, vx_mem, key_data, VIF__TGIDf, trunk_out); 4824 } else { 4825 soc_mem_field32_set(unit, vx_mem, key_data, VIF__MODULE_IDf, mod_out); 4826 soc_mem_field32_set(unit, vx_mem, key_data, VIF__PORT_NUMf, port_out); 4827 } 4828 4829 /* Lookup existing entry */ 4830 SOC_IF_ERROR_RETURN(soc_mem_search(unit, vx_mem, MEM_BLOCK_ALL, 4831 &entry_index, key_data, entry_data, 0)); 4832 4833 /* Replace entry's VP value */ 4834 *old_vp = soc_mem_field32_get(unit, vx_mem, entry_data, VIF__SOURCE_VPf); 4835 soc_mem_field32_set(unit, vx_mem, entry_data, VIF__SOURCE_VPf, new_vp); 4836 4837 /* Insert new entry */ 4838 rv = soc_mem_insert(unit, vx_mem, MEM_BLOCK_ALL, entry_data); 4839 if (rv == SOC_E_EXISTS) { 4840 rv = BCM_E_NONE; 4841 } else { 4842 return BCM_E_INTERNAL; 4843 } 4844 4845 return rv; 4846 } 4847 4848 /* 4849 * Function: 4850 * bcm_td2_extender_port_source_vp_lag_set 4851 * Purpose: 4852 * Set source VP LAG for an Extender virtual port. 4853 * Parameters: 4854 * unit - (IN) SOC unit number. 4855 * gport - (IN) Extender virtual port GPORT ID. 4856 * vp_lag_vp - (IN) VP representing the VP LAG. 4857 * Returns: 4858 * BCM_X_XXX 4859 */ 4860 int 4861 bcm_td2_extender_port_source_vp_lag_set(int unit, bcm_gport_t gport, 4862 int vp_lag_vp) 4863 { 4864 int vp, old_vp; 4865 4866 if (!BCM_GPORT_IS_EXTENDER_PORT(gport)) { 4867 return BCM_E_PARAM; 4868 } 4869 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport); 4870 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 4871 return BCM_E_PARAM; 4872 } 4873 4874 /* Set source VP LAG by replacing the SVP field in Extender VP's 4875 * match entry with the VP value representing the VP LAG. 4876 */ 4877 BCM_IF_ERROR_RETURN 4878 (_bcm_td2_extender_match_vp_replace(unit, vp, vp_lag_vp, &old_vp)); 4879 4880 return BCM_E_NONE; 4881 } 4882 4883 /* 4884 * Function: 4885 * bcm_td2_extender_port_source_vp_lag_clear 4886 * Purpose: 4887 * Clear source VP LAG for an Extender virtual port. 4888 * Parameters: 4889 * unit - (IN) SOC unit number. 4890 * gport - (IN) Extender virtual port GPORT ID. 4891 * vp_lag_vp - (IN) VP representing the VP LAG. 4892 * Returns: 4893 * BCM_X_XXX 4894 */ 4895 int 4896 bcm_td2_extender_port_source_vp_lag_clear(int unit, bcm_gport_t gport, 4897 int vp_lag_vp) 4898 { 4899 int vp, old_vp; 4900 4901 if (!BCM_GPORT_IS_EXTENDER_PORT(gport)) { 4902 return BCM_E_PARAM; 4903 } 4904 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport); 4905 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 4906 return BCM_E_PARAM; 4907 } 4908 4909 /* Clear source VP LAG by replacing the SVP field in Extender VP's 4910 * match entry with the VP value. 4911 */ 4912 BCM_IF_ERROR_RETURN 4913 (_bcm_td2_extender_match_vp_replace(unit, vp, vp, &old_vp)); 4914 4915 /* Check that the old VP value matches the VP value representing 4916 * the VP LAG or has been restored. 4917 */ 4918 if ((old_vp != vp_lag_vp) && (old_vp != vp)) { 4919 return BCM_E_INTERNAL; 4920 } 4921 4922 return BCM_E_NONE; 4923 } 4924 4925 /* 4926 * Function: 4927 * bcm_td2_extender_port_source_vp_lag_get 4928 * Purpose: 4929 * Set source VP LAG for an Extender virtual port. 4930 * Parameters: 4931 * unit - (IN) SOC unit number. 4932 * gport - (IN) Extender virtual port GPORT ID. 4933 * vp_lag_vp - (OUT) VP representing the VP LAG. 4934 * Returns: 4935 * BCM_X_XXX 4936 */ 4937 int 4938 bcm_td2_extender_port_source_vp_lag_get(int unit, bcm_gport_t gport, 4939 int *vp_lag_vp) 4940 { 4941 int vp; 4942 uint32 key_data[SOC_MAX_MEM_FIELD_WORDS]; 4943 uint32 entry_data[SOC_MAX_MEM_FIELD_WORDS]; 4944 int key_type; 4945 bcm_module_t mod_out; 4946 bcm_port_t port_out; 4947 bcm_trunk_t trunk_out; 4948 int tmp_id; 4949 int entry_index; 4950 soc_mem_t vx_mem = VLAN_XLATEm; 4951 4952 if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) { 4953 vx_mem = VLAN_XLATE_1_DOUBLEm; 4954 } 4955 4956 if (!BCM_GPORT_IS_EXTENDER_PORT(gport)) { 4957 return BCM_E_PARAM; 4958 } 4959 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport); 4960 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 4961 return BCM_E_PARAM; 4962 } 4963 4964 /* Construct match entry lookup key */ 4965 sal_memset(key_data, 0, sizeof(key_data)); 4966 4967 if (BCM_VLAN_VALID(EXTENDER_PORT_INFO(unit, vp)->match_vlan)) { 4968 BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit, 4969 VLXLT_HASH_KEY_TYPE_VIF_VLAN, &key_type)); 4970 soc_mem_field32_set(unit, vx_mem, key_data, VIF__VLANf, 4971 EXTENDER_PORT_INFO(unit, vp)->match_vlan); 4972 } else { 4973 BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit, 4974 VLXLT_HASH_KEY_TYPE_VIF, &key_type)); 4975 } 4976 soc_mem_field32_set(unit, vx_mem, key_data, KEY_TYPEf, key_type); 4977 if (SOC_MEM_FIELD_VALID(unit, vx_mem, DATA_TYPEf)) { 4978 soc_mem_field32_set(unit, vx_mem, key_data, DATA_TYPEf, key_type); 4979 } 4980 4981 soc_mem_field32_set(unit, vx_mem, key_data, VIF__SRC_VIFf, 4982 EXTENDER_PORT_INFO(unit, vp)->extended_port_vid); 4983 if (soc_mem_field_valid(unit, vx_mem, SOURCE_TYPEf)) { 4984 soc_mem_field32_set(unit, vx_mem, key_data, SOURCE_TYPEf, 1); 4985 } 4986 BCM_IF_ERROR_RETURN 4987 (_bcm_esw_gport_resolve(unit, EXTENDER_PORT_INFO(unit, vp)->port, 4988 &mod_out, &port_out, &trunk_out, &tmp_id)); 4989 if (BCM_GPORT_IS_TRUNK(EXTENDER_PORT_INFO(unit, vp)->port)) { 4990 soc_mem_field32_set(unit, vx_mem, key_data, VIF__Tf, 1); 4991 soc_mem_field32_set(unit, vx_mem, key_data, VIF__TGIDf, trunk_out); 4992 } else { 4993 soc_mem_field32_set(unit, vx_mem, key_data, VIF__MODULE_IDf, mod_out); 4994 soc_mem_field32_set(unit, vx_mem, key_data, VIF__PORT_NUMf, port_out); 4995 } 4996 4997 /* Lookup existing entry */ 4998 SOC_IF_ERROR_RETURN(soc_mem_search(unit, vx_mem, MEM_BLOCK_ALL, 4999 &entry_index, key_data, entry_data, 0)); 5000 5001 /* Get VP value representing VP LAG */ 5002 *vp_lag_vp = soc_mem_field32_get(unit, vx_mem, entry_data, VIF__SOURCE_VPf); 5003 if (!_bcm_vp_used_get(unit, *vp_lag_vp, _bcmVpTypeVpLag)) { 5004 return BCM_E_INTERNAL; 5005 } 5006 5007 return BCM_E_NONE; 5008 } 5009 5010 #endif /* BCM_TRIDENT2_SUPPORT */ 5011 5012 /* Function: 5013 * _bcm_tr3_extender_local_port_match 5014 * Purpose: 5015 * Determine if two gports represent the same local physical port(s). 5016 * Parameters: 5017 * unit - (IN) SOC unit Number 5018 * gport1 - (IN) GPORT ID 1 5019 * gport2 - (IN) GPORT ID 2 5020 * match - (OUT) Match indication 5021 * Returns: 5022 * BCM_E_XXX 5023 */ 5024 STATIC int 5025 _bcm_tr3_extender_local_port_match(int unit, bcm_gport_t gport1, 5026 bcm_gport_t gport2, int *match) 5027 { 5028 bcm_module_t mod1, mod2; 5029 bcm_port_t port1, port2; 5030 bcm_trunk_t tgid1, tgid2; 5031 int id1, id2; 5032 int mod_local; 5033 5034 *match = FALSE; 5035 5036 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, gport1, 5037 &mod1, &port1, &tgid1, &id1)); 5038 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, gport2, 5039 &mod2, &port2, &tgid2, &id2)); 5040 if (id1 != -1 || id2 != -1) { 5041 return BCM_E_PORT; 5042 } 5043 5044 if (BCM_TRUNK_INVALID != tgid1) { 5045 if (BCM_TRUNK_INVALID != tgid2) { 5046 if (tgid1 == tgid2) { 5047 *match = TRUE; 5048 } 5049 } 5050 } else { 5051 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, mod1, &mod_local)); 5052 if (!mod_local) { 5053 return BCM_E_PORT; 5054 } 5055 if (BCM_TRUNK_INVALID == tgid2) { 5056 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, mod2, &mod_local)); 5057 if (!mod_local) { 5058 return BCM_E_PORT; 5059 } 5060 if (mod1 == mod2 && port1 == port2) { 5061 *match = TRUE; 5062 } 5063 } 5064 } 5065 5066 return BCM_E_NONE; 5067 } 5068 5069 /* Function: 5070 * _bcm_tr3_extender_egress_match_ex_port 5071 * Purpose: 5072 * Determine if two Extender egress objects' attributes match, except for 5073 * port. 5074 * Parameters: 5075 * unit - (IN) SOC unit Number 5076 * extender_egress1 - (IN) Extender egress object 1, represented by 5077 * bcm_extender_egress_t. 5078 * extender_egress2 - (IN) Extender egress object 2, represented by 5079 * _bcm_tr3_extender_egress_t. 5080 * match - (OUT) Match indication 5081 * Returns: 5082 * BCM_E_XXX 5083 */ 5084 STATIC int 5085 _bcm_tr3_extender_egress_match_ex_port(int unit, 5086 bcm_extender_egress_t *extender_egress1, 5087 _bcm_tr3_extender_egress_t *extender_egress2, 5088 int *match) 5089 { 5090 int flags_match, vlan_match = 1, etag_vid_match ; 5091 int etag_pcp_match = 1, etag_de_match = 1; 5092 int pcp_de_select_match = 1, l3_intf_match = 1; 5093 int service_qos_map_id_match = 1, service_tpid_match = 1; 5094 int service_vlan_match = 1, service_pri_match = 1; 5095 int service_cfi_match = 1, qos_map_id_match = 1; 5096 5097 flags_match = (extender_egress1->flags == extender_egress2->flags); 5098 etag_vid_match = (extender_egress1->extended_port_vid == 5099 extender_egress2->extended_port_vid); 5100 etag_pcp_match = (extender_egress1->pcp == extender_egress2->pcp); 5101 etag_de_match = (extender_egress1->de == extender_egress2->de); 5102 pcp_de_select_match = (extender_egress1->pcp_de_select == 5103 extender_egress2->pcp_de_select); 5104 qos_map_id_match = (extender_egress1->qos_map_id == 5105 extender_egress2->qos_map_id); 5106 if (extender_egress1->flags & BCM_EXTENDER_EGRESS_L3) { 5107 l3_intf_match = (extender_egress1->intf == extender_egress2->intf); 5108 } else { 5109 vlan_match = (extender_egress1->match_vlan == extender_egress2->match_vlan); 5110 service_tpid_match = (extender_egress1->service_tpid == extender_egress2->service_tpid); 5111 service_vlan_match = (extender_egress1->service_vlan == extender_egress2->service_vlan); 5112 service_pri_match = (extender_egress1->service_pri == extender_egress2->service_pri); 5113 service_cfi_match = (extender_egress1->service_cfi == extender_egress2->service_cfi); 5114 service_qos_map_id_match = (extender_egress1->service_qos_map_id == 5115 extender_egress2->service_qos_map_id); 5116 } 5117 5118 if (flags_match && vlan_match && etag_vid_match && 5119 etag_pcp_match && etag_de_match && 5120 pcp_de_select_match && qos_map_id_match && 5121 service_vlan_match && service_tpid_match && 5122 service_pri_match && service_cfi_match && 5123 service_qos_map_id_match && l3_intf_match) { 5124 *match = TRUE; 5125 } else { 5126 *match = FALSE; 5127 } 5128 5129 return BCM_E_NONE; 5130 } 5131 5132 /* 5133 * Function: 5134 * _bcm_tr3_extender_egress_hash_calc 5135 * Purpose: 5136 * Calculate the hash value according to the egress object info. 5137 * Parameters: 5138 * unit - (IN) SOC unit number. 5139 * hash_key - (IN) hash key. 5140 * hash - (OUT) Hash(signature) calculated value. 5141 * Returns: 5142 * BCM_X_XXX 5143 */ 5144 STATIC int 5145 _bcm_tr3_extender_egress_hash_calc(int unit, void *hash_key, uint16 *hash) 5146 { 5147 uint32 sw_buf[8]; 5148 int size; 5149 int buf_idx = 0; 5150 bcm_extender_egress_t *extender_egress; 5151 5152 /* Input parameters check. */ 5153 if ((NULL == hash_key) || (NULL == hash)) { 5154 return (BCM_E_PARAM); 5155 } 5156 size = sizeof(sw_buf); 5157 sal_memset(sw_buf, 0, size); 5158 extender_egress = (bcm_extender_egress_t *)hash_key; 5159 5160 /* 5161 * Copy entry information to a temporary buffer, so we can 5162 * mask some fields we don't want to include in hash calculation. 5163 */ 5164 sw_buf[buf_idx++] = extender_egress->flags; 5165 sw_buf[buf_idx++] = extender_egress->intf; 5166 sw_buf[buf_idx++] = ((extender_egress->extended_port_vid << 16) | 5167 (extender_egress->pcp << 8) | extender_egress->de); 5168 sw_buf[buf_idx++] = extender_egress->qos_map_id; 5169 if (!(extender_egress->flags & BCM_EXTENDER_EGRESS_L3)) { 5170 sw_buf[buf_idx++] = ((extender_egress->service_tpid << 16) | 5171 extender_egress->service_vlan); 5172 sw_buf[buf_idx++] = ((extender_egress->service_pri << 16) | 5173 extender_egress->service_cfi); 5174 sw_buf[buf_idx++] = extender_egress->service_qos_map_id; 5175 } 5176 5177 size = sizeof(uint32) * buf_idx; 5178 *hash = _shr_crc16(0, (uint8 *)&sw_buf[0], size); 5179 5180 return BCM_E_NONE; 5181 } 5182 5183 5184 /* 5185 * Function: 5186 * _bcm_tr3_extender_egress_pbmp_get 5187 * Purpose: 5188 * Get the pbmp of the multicast egress objects 5189 * attaching to vp in the linked list. 5190 * Parameters: 5191 * unit - (IN) SOC unit Number 5192 * vp - (IN) Virtual port number. 5193 * pbmp - (OUT) pbmp of the multicast egress objects attaching to vp. 5194 * Returns: 5195 * BCM_E_XXX 5196 */ 5197 STATIC void 5198 _bcm_tr3_extender_egress_pbmp_get(int unit, int vp, bcm_pbmp_t *pbmp) 5199 { 5200 _bcm_tr3_extender_nh_info_t *nh_info; 5201 BCM_PBMP_CLEAR(*pbmp); 5202 5203 nh_info = EXTENDER_PORT_MC_NH_INFO(unit, vp); 5204 while (nh_info) { 5205 BCM_PBMP_PORT_ADD(*pbmp, nh_info->port); 5206 nh_info = nh_info->next; 5207 } 5208 5209 return; 5210 } 5211 5212 /* 5213 * Function: 5214 * _bcm_tr3_extender_egress_pbmp_delete 5215 * Purpose: 5216 * delete the pbmp of the multicast egress objects 5217 * attaching to vp from the linked list. 5218 * decrease the next hop ref_count of the port. 5219 * if next hop ref_count of the port is zero, 5220 * delete the node of the port from the list. 5221 * Parameters: 5222 * unit - (IN) SOC unit Number 5223 * vp - (IN) Virtual port number. 5224 * pbmp - (IN) pbmp of the multicast egress objects attaching to vp. 5225 * Returns: 5226 * BCM_E_XXX 5227 */ 5228 STATIC void 5229 _bcm_tr3_extender_egress_pbmp_delete(int unit, int vp, bcm_pbmp_t pbmp) 5230 { 5231 _bcm_tr3_extender_nh_info_t *ni_pre, *ni_cur, *ni_del; 5232 5233 ni_cur = EXTENDER_PORT_MC_NH_INFO(unit, vp); 5234 ni_pre = ni_cur; 5235 ni_del = NULL; 5236 while (ni_cur) { 5237 if (!BCM_PBMP_MEMBER(pbmp, ni_cur->port)) { 5238 ni_pre = ni_cur; 5239 ni_cur = ni_cur->next; 5240 continue; 5241 } 5242 5243 /* port match */ 5244 ni_cur->nh_ref_cnt--; 5245 if (ni_cur->nh_ref_cnt > 0) { 5246 ni_pre = ni_cur; 5247 ni_cur = ni_cur->next; 5248 continue; 5249 } 5250 5251 /* Next hop refence count is zero. */ 5252 if (ni_cur == EXTENDER_PORT_MC_NH_INFO(unit, vp)) { 5253 EXTENDER_PORT_MC_NH_INFO(unit, vp) = ni_cur->next; 5254 ni_del = ni_cur; 5255 ni_cur = ni_cur->next; 5256 ni_pre = ni_cur; 5257 } else { 5258 ni_del = ni_cur; 5259 ni_pre->next = ni_cur->next; 5260 ni_cur = ni_cur->next; 5261 } 5262 sal_free(ni_del); 5263 } 5264 5265 return; 5266 } 5267 5268 /* 5269 * Function: 5270 * _bcm_tr3_extender_egress_pbmp_add 5271 * Purpose: 5272 * add the pbmp of the multicast egress objects 5273 * attaching to vp to the linked list. 5274 * decrease the next hop ref_count of the port. 5275 * if next hop ref_count of the port is zero, 5276 * delete the node of the port from the list. 5277 * Parameters: 5278 * unit - (IN) SOC unit Number 5279 * vp - (IN) Virtual port number. 5280 * pbmp - (IN) pbmp of the multicast egress objects attaching to vp. 5281 * Returns: 5282 * BCM_E_XXX 5283 */ 5284 STATIC int 5285 _bcm_tr3_extender_egress_pbmp_add(int unit, int vp, bcm_pbmp_t pbmp) 5286 { 5287 bcm_port_t port; 5288 int alloc_size; 5289 _bcm_tr3_extender_nh_info_t *nh_info; 5290 bcm_pbmp_t sucess_pbmp; 5291 5292 nh_info = EXTENDER_PORT_MC_NH_INFO(unit, vp); 5293 while (nh_info) { 5294 if (BCM_PBMP_MEMBER(pbmp, nh_info->port)) { 5295 nh_info->nh_ref_cnt++; 5296 BCM_PBMP_PORT_REMOVE(pbmp, nh_info->port); 5297 } 5298 nh_info = nh_info->next; 5299 } 5300 5301 BCM_PBMP_CLEAR(sucess_pbmp); 5302 alloc_size = sizeof(_bcm_tr3_extender_nh_info_t); 5303 BCM_PBMP_ITER(pbmp, port) { 5304 nh_info = sal_alloc(alloc_size, "EXTENDER Egress Next Hop Info"); 5305 if (NULL == nh_info) { 5306 _bcm_tr3_extender_egress_pbmp_delete(unit, vp, sucess_pbmp); 5307 return BCM_E_MEMORY; 5308 } 5309 sal_memset(nh_info, 0, alloc_size); 5310 nh_info->port = port; 5311 nh_info->nh_ref_cnt = 1; 5312 nh_info->next = EXTENDER_PORT_MC_NH_INFO(unit, vp); 5313 EXTENDER_PORT_MC_NH_INFO(unit, vp) = nh_info; 5314 BCM_PBMP_PORT_ADD(sucess_pbmp, port); 5315 } 5316 5317 return BCM_E_NONE; 5318 } 5319 5320 /* 5321 * Function: 5322 * _bcm_tr3_extender_egress_pbmp_clear 5323 * Purpose: 5324 * clear the linked list which maintain the pbmp of 5325 * the multicast egress objects attaching to vp. 5326 * Parameters: 5327 * unit - (IN) SOC unit Number 5328 * vp - (IN) Virtual port number. 5329 * Returns: 5330 * BCM_E_XXX 5331 */ 5332 STATIC void 5333 _bcm_tr3_extender_egress_pbmp_clear(int unit, int vp) 5334 { 5335 _bcm_tr3_extender_nh_info_t *cur_node, *next_node; 5336 5337 next_node = NULL; 5338 cur_node = EXTENDER_PORT_MC_NH_INFO(unit, vp); 5339 while (cur_node) { 5340 next_node = cur_node->next; 5341 sal_free(cur_node); 5342 cur_node = next_node; 5343 } 5344 EXTENDER_PORT_MC_NH_INFO(unit, vp) = NULL; 5345 5346 return; 5347 } 5348 5349 /* Function: 5350 * bcm_tr3_extender_egress_add 5351 * Purpose: 5352 * Add a Extender egress object to a Extender Port 5353 * Parameters: 5354 * unit - (IN) SOC unit Number 5355 * extender_port - (IN) Extender Port 5356 * extender_egress - (IN/OUT) Extender egress object, the egress_if field is output. 5357 * Returns: 5358 * BCM_E_XXX 5359 */ 5360 int 5361 bcm_tr3_extender_egress_add( 5362 int unit, 5363 bcm_gport_t extender_port, 5364 bcm_extender_egress_t *extender_egress) 5365 { 5366 int vp; 5367 int match_ex_port; 5368 int local_port_match; 5369 int shared_nh_found; 5370 bcm_pbmp_t existing_pbmp, new_pbmp, update_pbmp; 5371 _bcm_tr3_extender_egress_t *curr_ptr = NULL, *temp_ptr = NULL; 5372 int nh_index; 5373 bcm_module_t mod_out; 5374 bcm_port_t port_out; 5375 bcm_trunk_t tgid_out; 5376 int id_out; 5377 bcm_port_t local_member_array[SOC_MAX_NUM_PORTS]; 5378 int local_member_count; 5379 int i; 5380 int mod_local = FALSE; 5381 bcm_port_t local_port; 5382 bcm_gport_t gport; 5383 _bcm_tr3_extender_sd_tag_t extender_sd_tag; 5384 bcm_if_t intf; 5385 int alloc_size; 5386 uint16 hash_val; 5387 int bkt_idx = 0; 5388 #ifdef BCM_TRIDENT2_SUPPORT 5389 int vp_routing = FALSE; 5390 bcm_l3_egress_t nh_info; 5391 uint32 nh_flags; 5392 #endif 5393 #if defined(BCM_HGPROXY_COE_SUPPORT) 5394 int is_local_subport = FALSE; 5395 #endif 5396 5397 /* Verify extender_port is a valid EXTENDER port with no match criteria */ 5398 if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port)) { 5399 return BCM_E_PARAM; 5400 } 5401 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port); 5402 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 5403 return BCM_E_NOT_FOUND; 5404 } 5405 if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) { 5406 return BCM_E_PARAM; 5407 } 5408 5409 if (extender_egress == NULL) { 5410 return BCM_E_PARAM; 5411 } 5412 5413 #ifdef BCM_TRIDENT2_SUPPORT 5414 if (soc_feature(unit, soc_feature_virtual_port_routing)) { 5415 vp_routing = TRUE; 5416 } 5417 #endif 5418 5419 if (!(extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST)) { 5420 /* When adding a unicast EXTENDER egress object to a EXTENDER port, 5421 * check that there are no other EXTENDER egress objects on the 5422 * EXTENDER port's egress_list. A EXTENDER port cannot be overloaded 5423 * with multiple unicast EXTENDER egress objects. 5424 */ 5425 if (NULL != EXTENDER_PORT_INFO(unit, vp)->egress_list) { 5426 return BCM_E_CONFIG; 5427 } 5428 /* BCM_EXTENDER_EGRESS_L3 must be with BCM_EXTENDER_EGRESS_MULTICAST */ 5429 if (extender_egress->flags & BCM_EXTENDER_EGRESS_L3) { 5430 return BCM_E_PARAM; 5431 } 5432 } else { 5433 /* For a multicast EXTENDER egress object, the field 5434 * match_vlan is not applicable. 5435 */ 5436 if (extender_egress->match_vlan) { 5437 return BCM_E_PARAM; 5438 } 5439 #ifdef BCM_TRIDENT2_SUPPORT 5440 if (vp_routing) { 5441 } else 5442 #endif 5443 { 5444 if (extender_egress->flags & BCM_EXTENDER_EGRESS_L3) { 5445 return BCM_E_UNAVAIL; 5446 } 5447 } 5448 } 5449 5450 BCM_PBMP_CLEAR(new_pbmp); 5451 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, extender_egress->port, 5452 &mod_out, &port_out, &tgid_out, &id_out)); 5453 if (BCM_TRUNK_INVALID != tgid_out) { 5454 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, 5455 tgid_out, SOC_MAX_NUM_PORTS, local_member_array, 5456 &local_member_count)); 5457 /* 5458 * For multicast, it will be unnecessary to create next hop 5459 * if there is no local port member. 5460 */ 5461 if (extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) { 5462 if (local_member_count <= 0) { 5463 return BCM_E_NONE; 5464 } 5465 } 5466 5467 for (i = 0; i < local_member_count; i++) { 5468 BCM_PBMP_PORT_ADD(new_pbmp, local_member_array[i]); 5469 } 5470 } else { 5471 #if defined(BCM_HGPROXY_COE_SUPPORT) 5472 BCM_IF_ERROR_RETURN( 5473 _bcm_esw_port_is_local_subport( 5474 unit, extender_egress->port, mod_out, port_out, 5475 &is_local_subport, &port_out)); 5476 if (is_local_subport) { 5477 mod_local = TRUE; 5478 } else 5479 #endif 5480 { 5481 BCM_IF_ERROR_RETURN( 5482 _bcm_esw_modid_is_local(unit, mod_out, &mod_local)); 5483 } 5484 5485 /* 5486 * For multicast, it will be unnecessary to create next hop 5487 * if there is no local port member. 5488 */ 5489 if (extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) { 5490 if (!mod_local) { 5491 return BCM_E_NONE; 5492 } 5493 } 5494 5495 if (mod_local) { 5496 BCM_PBMP_PORT_ADD(new_pbmp, port_out); 5497 } else { 5498 return BCM_E_PORT; 5499 } 5500 } 5501 5502 /* Traverse extender port's existing list of extender egress objects. 5503 * If an existing egress object has the same multicast flag, 5504 * extended_port_vid, match_vlan, PCP, and DE but different port, 5505 * its next hop index can be shared with the new extender egress object. 5506 * Also, create a bitmap of the physical ports on which the VP resides. 5507 */ 5508 BCM_PBMP_CLEAR(existing_pbmp); 5509 shared_nh_found = FALSE; 5510 curr_ptr = EXTENDER_PORT_INFO(unit, vp)->egress_list; 5511 if (extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) { 5512 BCM_IF_ERROR_RETURN( 5513 _bcm_tr3_extender_egress_hash_calc(unit, (void *)extender_egress, 5514 &hash_val)); 5515 bkt_idx = hash_val % TD_EXTENDER_PORT_HASH_BKT_SIZE; 5516 if (EXTENDER_PORT_INFO(unit, vp)->egress_list != NULL) { 5517 curr_ptr = EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next; 5518 } 5519 } 5520 while (NULL != curr_ptr) { 5521 /* Determine if the attributes of the current EXTENDER egress object match 5522 * those of the new EXTENDER egress object, except for the port attribute. 5523 */ 5524 BCM_IF_ERROR_RETURN(_bcm_tr3_extender_egress_match_ex_port(unit, 5525 extender_egress, curr_ptr, &match_ex_port)); 5526 if (match_ex_port) { 5527 /* Check if ports also match. If so, the EXTENDER egress object already exists. */ 5528 BCM_IF_ERROR_RETURN(_bcm_tr3_extender_local_port_match(unit, 5529 extender_egress->port, curr_ptr->port, &local_port_match)); 5530 if (local_port_match) { 5531 return BCM_E_EXISTS; 5532 } 5533 5534 /* If ports don't match, the next hop index can be shared. */ 5535 shared_nh_found = TRUE; 5536 nh_index = curr_ptr->next_hop_index; 5537 break; 5538 } 5539 /* Advance to next EXTENDER egress object */ 5540 curr_ptr = curr_ptr->next; 5541 } 5542 5543 if (!shared_nh_found) { 5544 /* If match not found, Configure next hop entry */ 5545 #ifdef BCM_TRIDENT2_SUPPORT 5546 if (extender_egress->flags & BCM_EXTENDER_EGRESS_L3) { 5547 bcm_l3_egress_t_init(&nh_info); 5548 nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE; 5549 BCM_IF_ERROR_RETURN 5550 (bcm_xgs3_nh_add(unit, nh_flags, &nh_info, &nh_index)); 5551 5552 /* Configure next hop entry for L3MC */ 5553 BCM_IF_ERROR_RETURN 5554 (_bcm_tr3_extender_l3mc_nh_info_set(unit, nh_index, 5555 EXTENDER_PORT_INFO(unit, vp)->flags, extender_egress->multicast_flags, 5556 extender_egress->port, extender_egress->intf, 5557 extender_egress->extended_port_vid, 5558 extender_egress->qos_map_id, extender_egress->pcp_de_select, 5559 extender_egress->pcp, extender_egress->de, vp)); 5560 } else 5561 #endif 5562 { 5563 sal_memset(&extender_sd_tag, 0, sizeof(extender_sd_tag)); 5564 extender_sd_tag.flags = extender_egress->flags; 5565 extender_sd_tag.service_tpid = extender_egress->service_tpid; 5566 extender_sd_tag.service_vlan = extender_egress->service_vlan; 5567 extender_sd_tag.service_pri = extender_egress->service_pri; 5568 extender_sd_tag.service_cfi = extender_egress->service_cfi; 5569 extender_sd_tag.service_qos_map_id = extender_egress->service_qos_map_id; 5570 5571 BCM_IF_ERROR_RETURN 5572 (_bcm_tr3_extender_port_nh_info_set(unit, 5573 extender_egress->port, extender_egress->extended_port_vid, 5574 extender_egress->match_vlan, extender_egress->pcp, 5575 extender_egress->de, extender_egress->pcp_de_select, 5576 extender_egress->qos_map_id, &extender_sd_tag, vp, &nh_index)); 5577 } 5578 } else { 5579 /* Increment next hop's reference count */ 5580 _bcm_xgs3_nh_ref_cnt_incr(unit, nh_index); 5581 } 5582 5583 /* Update next hop index in ING_DVP_TABLE */ 5584 intf = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_index; 5585 BCM_IF_ERROR_RETURN( 5586 _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigUpdate, vp, 5587 ING_DVP_CONFIG_INVALID_VP_TYPE, intf, 5588 ING_DVP_CONFIG_INVALID_PORT_TYPE)); 5589 5590 /* Configure ingress VLAN translation table for unicast 5591 * EXTENDER egress object. 5592 */ 5593 if (!(extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST)) { 5594 BCM_IF_ERROR_RETURN(_bcm_tr3_extender_port_match_add(unit, 5595 extender_egress->port, 5596 extender_egress->extended_port_vid, 5597 extender_egress->match_vlan, 5598 vp)); 5599 } 5600 5601 /* Increment the VP count on the new EXTENDER egress object's physical 5602 * port(s), unless the physical port(s) match those of VP's 5603 * other EXTENDER egress objects. 5604 */ 5605 if (extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) { 5606 _bcm_tr3_extender_egress_pbmp_get(unit, vp, &existing_pbmp); 5607 } 5608 BCM_PBMP_CLEAR(update_pbmp); 5609 BCM_PBMP_ASSIGN(update_pbmp, new_pbmp); 5610 BCM_PBMP_REMOVE(update_pbmp, existing_pbmp); 5611 BCM_PBMP_ITER(update_pbmp, local_port) { 5612 BCM_IF_ERROR_RETURN 5613 (bcm_esw_port_gport_get(unit, local_port, &gport)); 5614 BCM_IF_ERROR_RETURN 5615 (_bcm_tr3_extender_port_cnt_update(unit, gport, vp, TRUE)); 5616 } 5617 5618 if (extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) { 5619 BCM_IF_ERROR_RETURN( 5620 _bcm_tr3_extender_egress_pbmp_add(unit, vp, new_pbmp)); 5621 } 5622 5623 /* Insert the new EXTENDER egress object into VP's egress object list */ 5624 curr_ptr = sal_alloc(sizeof(_bcm_tr3_extender_egress_t), 5625 "EXTENDER egress object"); 5626 if (NULL == curr_ptr) { 5627 return BCM_E_MEMORY; 5628 } 5629 sal_memset(curr_ptr, 0, sizeof(_bcm_tr3_extender_egress_t)); 5630 curr_ptr->flags = extender_egress->flags; 5631 curr_ptr->port = extender_egress->port; 5632 curr_ptr->extended_port_vid = extender_egress->extended_port_vid; 5633 curr_ptr->qos_map_id = extender_egress->qos_map_id; 5634 curr_ptr->pcp_de_select = extender_egress->pcp_de_select; 5635 curr_ptr->pcp = extender_egress->pcp; 5636 curr_ptr->de = extender_egress->de; 5637 curr_ptr->match_vlan = extender_egress->match_vlan; 5638 curr_ptr->service_tpid = extender_egress->service_tpid; 5639 curr_ptr->service_vlan = extender_egress->service_vlan; 5640 curr_ptr->service_pri = extender_egress->service_pri; 5641 curr_ptr->service_cfi = extender_egress->service_cfi; 5642 curr_ptr->service_qos_map_id = extender_egress->service_qos_map_id; 5643 curr_ptr->next_hop_index = nh_index; 5644 curr_ptr->intf = extender_egress->intf; 5645 curr_ptr->multicast_flags = extender_egress->multicast_flags; 5646 if (!(extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST)) { 5647 curr_ptr->next = EXTENDER_PORT_INFO(unit, vp)->egress_list; 5648 EXTENDER_PORT_INFO(unit, vp)->egress_list = curr_ptr; 5649 } else { 5650 if ((EXTENDER_PORT_INFO(unit, vp)->egress_list == NULL)) { 5651 alloc_size = sizeof(_bcm_tr3_extender_egress_t) * 5652 TD_EXTENDER_PORT_HASH_BKT_SIZE; 5653 temp_ptr = sal_alloc(alloc_size, "EXTENDER egress object"); 5654 if (NULL == temp_ptr) { 5655 sal_free(curr_ptr); 5656 return BCM_E_MEMORY; 5657 } 5658 sal_memset(temp_ptr, 0, alloc_size); 5659 EXTENDER_PORT_INFO(unit, vp)->egress_list = temp_ptr; 5660 } 5661 curr_ptr->next = EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next; 5662 EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next = curr_ptr; 5663 } 5664 /* Set Extender egress object ID */ 5665 if (extender_egress->flags & BCM_EXTENDER_EGRESS_L3) { 5666 extender_egress->egress_if = nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 5667 } 5668 else { 5669 extender_egress->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 5670 } 5671 5672 return BCM_E_NONE; 5673 } 5674 5675 5676 /* Function: 5677 * bcm_tr3_extender_egress_delete 5678 * Purpose: 5679 * Delete a Extender egress object from a Extender port 5680 * Parameters: 5681 * unit - (IN) SOC unit Number 5682 * extender_port - (IN) Extender port 5683 * extender_egress - (IN) Extender egress object 5684 * Returns: 5685 * BCM_E_XXX 5686 */ 5687 int 5688 bcm_tr3_extender_egress_delete( 5689 int unit, 5690 bcm_gport_t extender_port, 5691 bcm_extender_egress_t *extender_egress) 5692 { 5693 int vp; 5694 int match_found; 5695 bcm_pbmp_t remaining_pbmp, pbmp; 5696 _bcm_tr3_extender_egress_t *curr_ptr, *prev_ptr, **head; 5697 _bcm_tr3_extender_egress_t *match_ptr = NULL; 5698 int local_port_match; 5699 int match_ex_port; 5700 bcm_module_t mod_out; 5701 bcm_port_t port_out; 5702 bcm_trunk_t tgid_out; 5703 int id_out; 5704 bcm_port_t local_member_array[SOC_MAX_NUM_PORTS]; 5705 int local_member_count; 5706 int i; 5707 int mod_local = FALSE; 5708 bcm_port_t local_port; 5709 bcm_gport_t gport; 5710 int nh_index; 5711 bcm_if_t intf; 5712 uint16 hash_val; 5713 int bkt_idx; 5714 #if defined(BCM_HGPROXY_COE_SUPPORT) 5715 int is_local_subport = FALSE; 5716 #endif 5717 5718 /* Verify extender_port is a valid EXTENDER port with no match criteria */ 5719 if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port)) { 5720 return BCM_E_PARAM; 5721 } 5722 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port); 5723 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 5724 return BCM_E_NOT_FOUND; 5725 } 5726 if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) { 5727 return BCM_E_PARAM; 5728 } 5729 5730 if (extender_egress == NULL) { 5731 return BCM_E_PARAM; 5732 } 5733 5734 /* Traverse EXTENDER port's list of EXTENDER egress objects to find the egress 5735 * object to be deleted. Also, among the remaining egress objects, 5736 * create a bitmap of the physical ports on which the VP resides. 5737 */ 5738 match_found = FALSE; 5739 BCM_PBMP_CLEAR(remaining_pbmp); 5740 prev_ptr = NULL; 5741 if (extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) { 5742 if ((EXTENDER_PORT_INFO(unit, vp)->egress_list == NULL)) { 5743 return BCM_E_NOT_FOUND; 5744 } 5745 BCM_IF_ERROR_RETURN( 5746 _bcm_tr3_extender_egress_hash_calc(unit, (void *)extender_egress, 5747 &hash_val)); 5748 bkt_idx = hash_val % TD_EXTENDER_PORT_HASH_BKT_SIZE; 5749 head = &(EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next); 5750 } else { 5751 head = &(EXTENDER_PORT_INFO(unit, vp)->egress_list); 5752 } 5753 curr_ptr = *head; 5754 while (NULL != curr_ptr) { 5755 BCM_IF_ERROR_RETURN(_bcm_tr3_extender_egress_match_ex_port(unit, 5756 extender_egress, curr_ptr, &match_ex_port)); 5757 BCM_IF_ERROR_RETURN(_bcm_tr3_extender_local_port_match(unit, 5758 extender_egress->port, curr_ptr->port, &local_port_match)); 5759 if (match_ex_port && local_port_match) { 5760 5761 match_found = TRUE; 5762 match_ptr = curr_ptr; 5763 if (curr_ptr == *head) { 5764 *head = curr_ptr->next; 5765 } else { 5766 /* 5767 * In the following line of code, Coverity thinks the 5768 * prev_ptr variable may still be NULL when dereferenced. 5769 * This situation will never occur because if curr_ptr 5770 * is not pointing to the head of the linked list, 5771 * prev_ptr would not be NULL. 5772 */ 5773 /* coverity[var_deref_op : FALSE] */ 5774 prev_ptr->next = curr_ptr->next; 5775 } 5776 break; 5777 } else { 5778 prev_ptr = curr_ptr; 5779 } 5780 5781 /* Advance to next EXTENDER egress object */ 5782 curr_ptr = curr_ptr->next; 5783 } 5784 if (!match_found) { 5785 return BCM_E_NOT_FOUND; 5786 } 5787 5788 /* Delete ingress VLAN translation entry */ 5789 if (!(match_ptr->flags & BCM_EXTENDER_EGRESS_MULTICAST)) { 5790 BCM_IF_ERROR_RETURN(_bcm_tr3_extender_port_match_delete(unit, 5791 match_ptr->port, match_ptr->extended_port_vid, 5792 match_ptr->match_vlan, vp)); 5793 } 5794 5795 /* If the VP's list of remaining egress objects is empty, modify VP's 5796 * next hop index to invalid next hop index. If not empty, 5797 * pick one of the next hop indices in the list. 5798 */ 5799 if (NULL == *head) { 5800 nh_index = EXTENDER_INFO(unit)->invalid_next_hop_index; 5801 } else { 5802 nh_index = (*head)->next_hop_index; 5803 } 5804 5805 /* Update next hop index in ING_DVP_TABLE */ 5806 intf = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_index; 5807 BCM_IF_ERROR_RETURN( 5808 _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigUpdate, vp, 5809 ING_DVP_CONFIG_INVALID_VP_TYPE, intf, 5810 ING_DVP_CONFIG_INVALID_PORT_TYPE)); 5811 5812 /* Decrement next hop's reference count. If count reaches zero, 5813 * free the next hop index and clear next hop table entries. 5814 */ 5815 BCM_IF_ERROR_RETURN 5816 (_bcm_tr3_extender_nh_info_delete(unit, match_ptr->next_hop_index)); 5817 5818 /* Decrement the VP count on the deleted EXTENDER egress object's physical 5819 * port(s), unless the physical port(s) are shared by the VP's remaining 5820 * EXTENDER egress objects. 5821 */ 5822 BCM_PBMP_CLEAR(pbmp); 5823 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, match_ptr->port, 5824 &mod_out, &port_out, &tgid_out, &id_out)); 5825 if (BCM_TRUNK_INVALID != tgid_out) { 5826 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, 5827 tgid_out, SOC_MAX_NUM_PORTS, local_member_array, 5828 &local_member_count)); 5829 for (i = 0; i < local_member_count; i++) { 5830 BCM_PBMP_PORT_ADD(pbmp, local_member_array[i]); 5831 } 5832 } else { 5833 #if defined(BCM_HGPROXY_COE_SUPPORT) 5834 BCM_IF_ERROR_RETURN( 5835 _bcm_esw_port_is_local_subport( 5836 unit, extender_egress->port, mod_out, port_out, 5837 &is_local_subport, &port_out)); 5838 if (is_local_subport) { 5839 mod_local = TRUE; 5840 } else 5841 #endif 5842 { 5843 BCM_IF_ERROR_RETURN( 5844 _bcm_esw_modid_is_local(unit, mod_out, &mod_local)); 5845 } 5846 if (mod_local) { 5847 BCM_PBMP_PORT_ADD(pbmp, port_out); 5848 } else { 5849 return BCM_E_INTERNAL; 5850 } 5851 } 5852 if (extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) { 5853 _bcm_tr3_extender_egress_pbmp_delete(unit, vp, pbmp); 5854 _bcm_tr3_extender_egress_pbmp_get(unit, vp, &remaining_pbmp); 5855 } 5856 BCM_PBMP_REMOVE(pbmp, remaining_pbmp); 5857 BCM_PBMP_ITER(pbmp, local_port) { 5858 BCM_IF_ERROR_RETURN 5859 (bcm_esw_port_gport_get(unit, local_port, &gport)); 5860 BCM_IF_ERROR_RETURN 5861 (_bcm_tr3_extender_port_cnt_update(unit, gport, vp, FALSE)); 5862 } 5863 if ((extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) && 5864 BCM_PBMP_IS_NULL(remaining_pbmp)) { 5865 sal_free(EXTENDER_PORT_INFO(unit, vp)->egress_list); 5866 EXTENDER_PORT_INFO(unit, vp)->egress_list = NULL; 5867 } 5868 /* Free the deleted EXTENDER egress object */ 5869 sal_free(match_ptr); 5870 5871 return BCM_E_NONE; 5872 } 5873 5874 /* Function: 5875 * bcm_tr3_extender_egress_set 5876 * Purpose: 5877 * Delete existing egress object for a Extender port and add 5878 * an array of Extender egress objects for the Extender port 5879 * Parameters: 5880 * unit - (IN) SOC unit Number 5881 * extender_port - (IN) Extender port 5882 * array_size - (IN) Number of Extender egress objects. 5883 * extender_egress_array - (IN/OUT) Array of Extender egress objects. 5884 * Returns: 5885 * BCM_E_XXX 5886 */ 5887 int 5888 bcm_tr3_extender_egress_set(int unit, bcm_gport_t extender_port, 5889 int array_size, bcm_extender_egress_t *extender_egress_array) 5890 { 5891 int vp; 5892 _bcm_tr3_extender_egress_t *curr_ptr, *next_ptr; 5893 bcm_pbmp_t pbmp; 5894 bcm_module_t mod_out; 5895 bcm_port_t port_out; 5896 bcm_trunk_t tgid_out; 5897 int id_out; 5898 bcm_port_t local_member_array[SOC_MAX_NUM_PORTS]; 5899 int local_member_count; 5900 int i; 5901 int mod_local = FALSE; 5902 bcm_gport_t gport; 5903 bcm_port_t local_port; 5904 bcm_if_t intf; 5905 int bkt_idx, bkt_size; 5906 int vp_mc = 0; 5907 #if defined(BCM_HGPROXY_COE_SUPPORT) 5908 int is_local_subport = FALSE; 5909 #endif 5910 5911 /* Verify extender_port is a valid EXTENDER port with no match criteria */ 5912 if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port)) { 5913 return BCM_E_PARAM; 5914 } 5915 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port); 5916 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 5917 return BCM_E_NOT_FOUND; 5918 } 5919 if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) { 5920 return BCM_E_PARAM; 5921 } 5922 if ((array_size > 0) && (extender_egress_array == NULL)) { 5923 return BCM_E_PARAM; 5924 } 5925 5926 /* Modify VP's next hop index to invalid next hop index */ 5927 intf = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + EXTENDER_INFO(unit)->invalid_next_hop_index; 5928 BCM_IF_ERROR_RETURN(_bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigUpdate, 5929 vp, ING_DVP_CONFIG_INVALID_VP_TYPE, intf, 5930 ING_DVP_CONFIG_INVALID_PORT_TYPE)); 5931 5932 /* Delete the existing EXTENDER egress objects attached to the given EXTENDER port */ 5933 if (EXTENDER_PORT_MC_NH_INFO(unit, vp) != NULL) { 5934 /* The shared vp associates with mulicast egress objects. */ 5935 if (EXTENDER_PORT_INFO(unit, vp)->egress_list == NULL) { 5936 return BCM_E_INTERNAL; 5937 } 5938 vp_mc = 1; 5939 } 5940 BCM_PBMP_CLEAR(pbmp); 5941 bkt_size = vp_mc ? TD_EXTENDER_PORT_HASH_BKT_SIZE : 1; 5942 for (bkt_idx = 0; bkt_idx < bkt_size; bkt_idx++) { 5943 if (vp_mc) { 5944 curr_ptr = EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next; 5945 } else { 5946 curr_ptr = EXTENDER_PORT_INFO(unit, vp)->egress_list; 5947 } 5948 while (NULL != curr_ptr) { 5949 /* Delete ingress VLAN translation entry */ 5950 if (!(curr_ptr->flags & BCM_EXTENDER_EGRESS_MULTICAST)) { 5951 BCM_IF_ERROR_RETURN(_bcm_tr3_extender_port_match_delete(unit, 5952 curr_ptr->port, curr_ptr->extended_port_vid, 5953 curr_ptr->match_vlan, vp)); 5954 } 5955 5956 /* Decrement next hop's reference count. If count reaches zero, 5957 * free the next hop index and clear next hop table entries. 5958 */ 5959 BCM_IF_ERROR_RETURN 5960 (_bcm_tr3_extender_nh_info_delete(unit, curr_ptr->next_hop_index)); 5961 5962 /* Add this EXTENDER egress object's port(s) to the bitmap of physical ports 5963 * on which the VP resides. 5964 */ 5965 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, curr_ptr->port, 5966 &mod_out, &port_out, &tgid_out, &id_out)); 5967 if (BCM_TRUNK_INVALID != tgid_out) { 5968 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, 5969 tgid_out, SOC_MAX_NUM_PORTS, local_member_array, 5970 &local_member_count)); 5971 for (i = 0; i < local_member_count; i++) { 5972 BCM_PBMP_PORT_ADD(pbmp, local_member_array[i]); 5973 } 5974 } else { 5975 #if defined(BCM_HGPROXY_COE_SUPPORT) 5976 BCM_IF_ERROR_RETURN( 5977 _bcm_esw_port_is_local_subport( 5978 unit, curr_ptr->port, mod_out, port_out, 5979 &is_local_subport, &port_out)); 5980 if (is_local_subport) { 5981 mod_local = TRUE; 5982 } else 5983 #endif 5984 { 5985 BCM_IF_ERROR_RETURN( 5986 _bcm_esw_modid_is_local(unit, mod_out, &mod_local)); 5987 } 5988 if (mod_local) { 5989 BCM_PBMP_PORT_ADD(pbmp, port_out); 5990 } else { 5991 return BCM_E_INTERNAL; 5992 } 5993 } 5994 5995 /* Free current EXTENDER egress object and advance to the next one */ 5996 next_ptr = curr_ptr->next; 5997 sal_free(curr_ptr); 5998 curr_ptr = next_ptr; 5999 } 6000 6001 if (vp_mc) { 6002 EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next = NULL; 6003 } else { 6004 EXTENDER_PORT_INFO(unit, vp)->egress_list = NULL; 6005 } 6006 } 6007 6008 if (vp_mc) { 6009 sal_free(EXTENDER_PORT_INFO(unit, vp)->egress_list); 6010 EXTENDER_PORT_INFO(unit, vp)->egress_list = NULL; 6011 _bcm_tr3_extender_egress_pbmp_clear(unit, vp); 6012 } 6013 6014 /* Decrement VP count on all the physical ports on which the VP resides */ 6015 BCM_PBMP_ITER(pbmp, local_port) { 6016 BCM_IF_ERROR_RETURN 6017 (bcm_esw_port_gport_get(unit, local_port, &gport)); 6018 BCM_IF_ERROR_RETURN 6019 (_bcm_tr3_extender_port_cnt_update(unit, gport, vp, FALSE)); 6020 } 6021 6022 /* Add new EXTENDER egress objects to EXTENDER port */ 6023 for (i = 0; i < array_size; i++) { 6024 BCM_IF_ERROR_RETURN 6025 (bcm_tr3_extender_egress_add(unit, extender_port, &extender_egress_array[i])); 6026 } 6027 6028 return BCM_E_NONE; 6029 } 6030 6031 /* Function: 6032 * bcm_esw_extender_egress_get 6033 * Purpose: 6034 * get an Extender egress object for Extender Port 6035 * Parameters: 6036 * unit - (IN) SOC unit Number 6037 * extender_port - (IN) Extender port 6038 * extender_egress - (IN/OUT) Extender egress object 6039 * Returns: 6040 * BCM_E_XXX 6041 */ 6042 int 6043 bcm_tr3_extender_egress_get(int unit, bcm_gport_t extender_port, 6044 bcm_extender_egress_t *extender_egress) 6045 { 6046 int vp; 6047 _bcm_tr3_extender_egress_t *curr_ptr; 6048 int bkt_idx, bkt_size; 6049 int vp_mc = 0; 6050 6051 /* Verify extender_port is a valid Extender port with no match criteria */ 6052 if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port)) { 6053 return BCM_E_PARAM; 6054 } 6055 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port); 6056 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 6057 return BCM_E_NOT_FOUND; 6058 } 6059 if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) { 6060 return BCM_E_PARAM; 6061 } 6062 if (extender_egress == NULL) { 6063 return BCM_E_PARAM; 6064 } 6065 6066 /* Traverse Extender port's existing list of Extender egress objects */ 6067 curr_ptr = EXTENDER_PORT_INFO(unit, vp)->egress_list; 6068 6069 if (EXTENDER_PORT_MC_NH_INFO(unit, vp) != NULL) { 6070 /* The shared vp associates with mulicast egress objects. */ 6071 if (EXTENDER_PORT_INFO(unit, vp)->egress_list == NULL) { 6072 return BCM_E_INTERNAL; 6073 } 6074 vp_mc = 1; 6075 } 6076 bkt_size = vp_mc ? TD_EXTENDER_PORT_HASH_BKT_SIZE : 1; 6077 for (bkt_idx = 0; bkt_idx < bkt_size; bkt_idx++) { 6078 if (vp_mc) { 6079 curr_ptr = EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next; 6080 } else { 6081 curr_ptr = EXTENDER_PORT_INFO(unit, vp)->egress_list; 6082 } 6083 while (NULL != curr_ptr) { 6084 if ((extender_egress->port == curr_ptr->port) && 6085 (extender_egress->extended_port_vid == 6086 curr_ptr->extended_port_vid) && 6087 (extender_egress->flags == curr_ptr->flags)) { 6088 6089 extender_egress->port = curr_ptr->port; 6090 extender_egress->extended_port_vid = 6091 curr_ptr->extended_port_vid; 6092 extender_egress->qos_map_id = curr_ptr->qos_map_id; 6093 extender_egress->pcp_de_select = 6094 curr_ptr->pcp_de_select; 6095 extender_egress->pcp = curr_ptr->pcp; 6096 extender_egress->de = curr_ptr->de; 6097 extender_egress->match_vlan = curr_ptr->match_vlan; 6098 extender_egress->service_tpid = curr_ptr->service_tpid; 6099 extender_egress->service_vlan = curr_ptr->service_vlan; 6100 extender_egress->service_pri = curr_ptr->service_pri; 6101 extender_egress->service_cfi = curr_ptr->service_cfi; 6102 extender_egress->service_qos_map_id = 6103 curr_ptr->service_qos_map_id; 6104 extender_egress->intf = curr_ptr->intf; 6105 extender_egress->multicast_flags = 6106 curr_ptr->multicast_flags; 6107 6108 extender_egress->egress_if = curr_ptr->next_hop_index + 6109 BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 6110 return BCM_E_NONE; 6111 } else { 6112 curr_ptr = curr_ptr->next; 6113 } 6114 } 6115 } 6116 return BCM_E_NOT_FOUND; 6117 } 6118 6119 /* Function: 6120 * bcm_tr3_extender_egress_get_all 6121 * Purpose: 6122 * get an Array of Extender egress objects for Extender Port 6123 * Parameters: 6124 * unit - (IN) SOC unit Number 6125 * extender_port - (IN) Extender port 6126 * array_size - (IN) Size of Extender egress objects array. 6127 * extender_egress_array - (OUT) Array of Extender egress objects. 6128 * count - (OUT) Number of Extender egress objects returned. 6129 * Returns: 6130 * BCM_E_XXX 6131 */ 6132 int 6133 bcm_tr3_extender_egress_get_all(int unit, bcm_gport_t extender_port, 6134 int array_size, bcm_extender_egress_t *extender_egress_array, int *count) 6135 { 6136 int vp; 6137 _bcm_tr3_extender_egress_t *curr_ptr; 6138 int bkt_idx, bkt_size; 6139 int vp_mc = 0; 6140 6141 /* Verify extender_port is a valid Extender port with no match criteria */ 6142 if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port)) { 6143 return BCM_E_PARAM; 6144 } 6145 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port); 6146 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 6147 return BCM_E_NOT_FOUND; 6148 } 6149 if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) { 6150 return BCM_E_PARAM; 6151 } 6152 if (array_size < 0) { 6153 return BCM_E_PARAM; 6154 } 6155 if ((array_size > 0) && (extender_egress_array == NULL)) { 6156 return BCM_E_PARAM; 6157 } 6158 if (count == NULL) { 6159 return BCM_E_PARAM; 6160 } 6161 6162 /* Traverse Extender port's existing list of Extender egress objects */ 6163 *count = 0; 6164 curr_ptr = EXTENDER_PORT_INFO(unit, vp)->egress_list; 6165 6166 if (EXTENDER_PORT_MC_NH_INFO(unit, vp) != NULL) { 6167 /* The shared vp associates with mulicast egress objects. */ 6168 if (EXTENDER_PORT_INFO(unit, vp)->egress_list == NULL) { 6169 return BCM_E_INTERNAL; 6170 } 6171 vp_mc = 1; 6172 } 6173 bkt_size = vp_mc ? TD_EXTENDER_PORT_HASH_BKT_SIZE : 1; 6174 6175 for (bkt_idx = 0; bkt_idx < bkt_size; bkt_idx++) { 6176 if (vp_mc) { 6177 curr_ptr = EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next; 6178 } else { 6179 curr_ptr = EXTENDER_PORT_INFO(unit, vp)->egress_list; 6180 } 6181 while (NULL != curr_ptr) { 6182 if (array_size > 0) { 6183 extender_egress_array[*count].flags = curr_ptr->flags; 6184 extender_egress_array[*count].port = curr_ptr->port; 6185 extender_egress_array[*count].extended_port_vid= 6186 curr_ptr->extended_port_vid; 6187 extender_egress_array[*count].match_vlan = curr_ptr->match_vlan; 6188 extender_egress_array[*count].pcp_de_select = 6189 curr_ptr->pcp_de_select; 6190 extender_egress_array[*count].qos_map_id = curr_ptr->qos_map_id; 6191 extender_egress_array[*count].pcp = curr_ptr->pcp; 6192 extender_egress_array[*count].de = curr_ptr->de; 6193 extender_egress_array[*count].service_tpid = curr_ptr->service_tpid; 6194 extender_egress_array[*count].service_vlan = curr_ptr->service_vlan; 6195 extender_egress_array[*count].service_pri = curr_ptr->service_pri; 6196 extender_egress_array[*count].service_cfi = curr_ptr->service_cfi; 6197 extender_egress_array[*count].service_qos_map_id = 6198 curr_ptr->service_qos_map_id; 6199 extender_egress_array[*count].intf = curr_ptr->intf; 6200 extender_egress_array[*count].multicast_flags = 6201 curr_ptr->multicast_flags; 6202 if (curr_ptr->flags & BCM_EXTENDER_EGRESS_L3) { 6203 extender_egress_array[*count].egress_if = 6204 curr_ptr->next_hop_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 6205 } else { 6206 extender_egress_array[*count].egress_if = 6207 curr_ptr->next_hop_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 6208 } 6209 } 6210 (*count)++; 6211 if (*count == array_size) { 6212 break; 6213 } 6214 curr_ptr = curr_ptr->next; 6215 } 6216 if ((array_size != 0) && (*count == array_size)) { 6217 break; 6218 } 6219 } 6220 return BCM_E_NONE; 6221 } 6222 6223 #ifndef BCM_SW_STATE_DUMP_DISABLE 6224 /* 6225 * Function: 6226 * _bcm_tr3_extender_sw_dump 6227 * Purpose: 6228 * Displays Extender module information maintained by software. 6229 * Parameters: 6230 * unit - Device unit number 6231 * Returns: 6232 * None 6233 */ 6234 void 6235 bcm_tr3_extender_sw_dump(int unit) 6236 { 6237 int i, num_vp; 6238 _bcm_tr3_extender_egress_t *curr_ptr; 6239 int egr_obj_index; 6240 char pfmt[SOC_PBMP_FMT_LEN]; 6241 int bkt_idx, bkt_size; 6242 int vp_mc = 0; 6243 bcm_pbmp_t pbmp; 6244 6245 LOG_CLI((BSL_META_U(unit, 6246 "\nSW Information Extender - Unit %d\n"), unit)); 6247 6248 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 6249 6250 LOG_CLI((BSL_META_U(unit, 6251 "\n Port Info : \n"))); 6252 for (i = 0; i < num_vp; i++) { 6253 if (!(EXTENDER_PORT_INFO(unit, i)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) { 6254 if (EXTENDER_PORT_INFO(unit, i)->port == 0) { 6255 continue; 6256 } 6257 LOG_CLI((BSL_META_U(unit, 6258 "\n Extender port vp = %d\n"), i)); 6259 LOG_CLI((BSL_META_U(unit, 6260 "Flags = 0x%x\n"), EXTENDER_PORT_INFO(unit, i)->flags)); 6261 LOG_CLI((BSL_META_U(unit, 6262 "Port = 0x%x\n"), EXTENDER_PORT_INFO(unit, i)->port)); 6263 LOG_CLI((BSL_META_U(unit, 6264 "ETAG VID = 0x%x\n"), 6265 EXTENDER_PORT_INFO(unit, i)->extended_port_vid)); 6266 LOG_CLI((BSL_META_U(unit, 6267 "PCP DE Select = 0x%x\n"), 6268 EXTENDER_PORT_INFO(unit, i)->pcp_de_select)); 6269 LOG_CLI((BSL_META_U(unit, 6270 "Default PCP = 0x%x\n"), EXTENDER_PORT_INFO(unit, i)->pcp)); 6271 LOG_CLI((BSL_META_U(unit, 6272 "Default DE = 0x%x\n"), EXTENDER_PORT_INFO(unit, i)->de)); 6273 LOG_CLI((BSL_META_U(unit, 6274 "Match VLAN = 0x%x\n"), EXTENDER_PORT_INFO(unit, i)->match_vlan)); 6275 }else { 6276 LOG_CLI((BSL_META_U(unit, 6277 "\n Extender port vp = %d\n"), i)); 6278 LOG_CLI((BSL_META_U(unit, 6279 " Flags = 0x%x\n"), EXTENDER_PORT_INFO(unit, i)->flags)); 6280 6281 egr_obj_index = 0; 6282 vp_mc = 0; 6283 if (EXTENDER_PORT_MC_NH_INFO(unit, i) != NULL) { 6284 if (EXTENDER_PORT_INFO(unit, i)->egress_list == NULL) { 6285 continue; 6286 } 6287 vp_mc = 1; 6288 } 6289 bkt_size = vp_mc ? TD_EXTENDER_PORT_HASH_BKT_SIZE : 1; 6290 for (bkt_idx = 0; bkt_idx < bkt_size; bkt_idx++) { 6291 /* The shared vp associates with mulicast egress objects. */ 6292 if (vp_mc) { 6293 curr_ptr = EXTENDER_PORT_HASH_BKT(unit, i, bkt_idx)->next; 6294 if (curr_ptr) { 6295 LOG_CLI((BSL_META_U(unit, 6296 "\n Bkt_idx = %d\n"), bkt_idx)); 6297 } 6298 } else { 6299 curr_ptr = EXTENDER_PORT_INFO(unit, i)->egress_list; 6300 } 6301 while (NULL != curr_ptr) { 6302 LOG_CLI((BSL_META_U(unit, 6303 " Egress object %d\n"), 6304 egr_obj_index)); 6305 LOG_CLI((BSL_META_U(unit, 6306 " Flags = 0x%x\n"), 6307 curr_ptr->flags)); 6308 LOG_CLI((BSL_META_U(unit, 6309 " Port = 0x%x\n"), 6310 curr_ptr->port)); 6311 LOG_CLI((BSL_META_U(unit, 6312 " ETAG VID = 0x%x\n"), 6313 curr_ptr->extended_port_vid)); 6314 LOG_CLI((BSL_META_U(unit, 6315 "PCP DE Select = 0x%x\n"), 6316 curr_ptr->pcp_de_select)); 6317 LOG_CLI((BSL_META_U(unit, 6318 "Default PCP = 0x%x\n"), curr_ptr->pcp)); 6319 LOG_CLI((BSL_META_U(unit, 6320 "Default DE = 0x%x\n"), curr_ptr->de)); 6321 6322 LOG_CLI((BSL_META_U(unit, 6323 " Match VLAN = 0x%x\n"), 6324 curr_ptr->match_vlan)); 6325 LOG_CLI((BSL_META_U(unit, 6326 " Service TPID = 0x%x\n"), 6327 curr_ptr->service_tpid)); 6328 LOG_CLI((BSL_META_U(unit, 6329 " Service VLAN = 0x%x\n"), 6330 curr_ptr->service_vlan)); 6331 LOG_CLI((BSL_META_U(unit, 6332 " Service PRI = 0x%x\n"), 6333 curr_ptr->service_pri)); 6334 LOG_CLI((BSL_META_U(unit, 6335 " Service CFI = 0x%x\n"), 6336 curr_ptr->service_cfi)); 6337 LOG_CLI((BSL_META_U(unit, 6338 " Service Qos Map ID = 0x%x\n"), 6339 curr_ptr->service_qos_map_id)); 6340 LOG_CLI((BSL_META_U(unit, 6341 " Next Hop Index = 0x%x\n"), 6342 curr_ptr->next_hop_index)); 6343 LOG_CLI((BSL_META_U(unit, 6344 " L3 Intf = 0x%x\n"), 6345 curr_ptr->intf)); 6346 LOG_CLI((BSL_META_U(unit, 6347 " Multicast_flags = 0x%x\n"), 6348 curr_ptr->multicast_flags)); 6349 egr_obj_index++; 6350 curr_ptr = curr_ptr->next; 6351 } 6352 } 6353 6354 if (vp_mc) { 6355 BCM_PBMP_CLEAR(pbmp); 6356 _bcm_tr3_extender_egress_pbmp_get(unit, i, &pbmp); 6357 LOG_CLI((BSL_META_U(unit, 6358 " pbmp = %s\n"), 6359 SOC_PBMP_FMT(pbmp, pfmt))); 6360 } 6361 6362 } 6363 } 6364 6365 return; 6366 } 6367 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 6368 6369 #ifdef BCM_TOMAHAWK_SUPPORT 6370 bcm_error_t 6371 _bcm_extender_gport_get(int unit, int is_trunk, int modid, 6372 int port, int etag_vid, bcm_gport_t *ext_gport) 6373 { 6374 int vp; 6375 bcm_trunk_t trunk_id = -1; 6376 bcm_port_t local_port_id; 6377 bcm_module_t local_modid; 6378 int id_out; 6379 6380 if (NULL == EXTENDER_INFO(unit)->port_info) { 6381 return BCM_E_INIT; 6382 } 6383 6384 if (NULL == ext_gport) { 6385 return BCM_E_PARAM; 6386 } 6387 for (vp = soc_mem_index_min(unit, SOURCE_VPm); 6388 vp <= soc_mem_index_max(unit, SOURCE_VPm); 6389 vp++) { 6390 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) { 6391 if (!(EXTENDER_PORT_INFO(unit, vp)->flags & 6392 BCM_EXTENDER_PORT_MULTICAST)) { 6393 BCM_IF_ERROR_RETURN 6394 (_bcm_esw_gport_resolve(unit, EXTENDER_PORT_INFO(unit, vp)->port, 6395 &local_modid, 6396 &local_port_id, 6397 &trunk_id, 6398 &id_out)); 6399 if (EXTENDER_PORT_INFO(unit, vp)->extended_port_vid == etag_vid) { 6400 if ((is_trunk == 1) && (trunk_id == port)) { 6401 BCM_GPORT_EXTENDER_PORT_ID_SET(*ext_gport, vp); 6402 return BCM_E_NONE; 6403 } else if ((is_trunk != 1) && (trunk_id == -1)) { 6404 if ((local_port_id == port) && 6405 (local_modid == modid )) { 6406 BCM_GPORT_EXTENDER_PORT_ID_SET(*ext_gport, vp); 6407 return BCM_E_NONE; 6408 } 6409 } 6410 } 6411 } 6412 } 6413 } 6414 return BCM_E_NOT_FOUND; 6415 } 6416 #endif /* BCM_TOMAHAWK_SUPPORT */ 6417 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */