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