vlan.c (83778B)
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: vlan.c 8 * Purpose: Manages VLAN virtual port functions 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <soc/defs.h> 14 #include <sal/core/libc.h> 15 #if defined(BCM_ENDURO_SUPPORT) && defined(INCLUDE_L3) 16 17 #include <soc/drv.h> 18 #include <soc/scache.h> 19 #include <soc/hash.h> 20 21 #include <bcm/error.h> 22 23 #include <bcm_int/esw_dispatch.h> 24 #include <bcm_int/api_xlate_port.h> 25 26 #include <bcm_int/common/multicast.h> 27 #include <bcm_int/esw/multicast.h> 28 #include <bcm_int/esw/virtual.h> 29 #include <bcm_int/esw/vlan.h> 30 #include <bcm_int/esw/firebolt.h> 31 #include <bcm_int/esw/trx.h> 32 #include <bcm_int/esw/triumph2.h> 33 #include <bcm_int/esw/enduro.h> 34 #include <bcm_int/esw/stack.h> 35 #include <bcm_int/esw/ipmc.h> 36 37 typedef struct _bcm_enduro_vlan_vp_info_s { 38 bcm_vlan_port_match_t criteria; 39 uint32 flags; 40 bcm_vlan_t match_vlan; 41 bcm_vlan_t match_inner_vlan; 42 bcm_vlan_t egress_vlan; 43 bcm_gport_t port; 44 } _bcm_enduro_vlan_vp_info_t; 45 46 /* 47 * Software book keeping for VLAN virtual related information 48 */ 49 typedef struct _bcm_enduro_vlan_virtual_bookkeeping_s { 50 int vlan_virtual_initialized; /* Flag to check initialized status */ 51 sal_mutex_t vlan_virtual_mutex; /* VLAN virtual module lock */ 52 _bcm_enduro_vlan_vp_info_t *port_info; /* VP state */ 53 } _bcm_enduro_vlan_virtual_bookkeeping_t; 54 55 STATIC _bcm_enduro_vlan_virtual_bookkeeping_t _bcm_enduro_vlan_virtual_bk_info[BCM_MAX_NUM_UNITS]; 56 57 #define VLAN_VIRTUAL_INFO(unit) (&_bcm_enduro_vlan_virtual_bk_info[unit]) 58 59 #define VLAN_VIRTUAL_INIT(unit) \ 60 do { \ 61 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { \ 62 return BCM_E_UNIT; \ 63 } \ 64 if (!VLAN_VIRTUAL_INFO(unit)->vlan_virtual_initialized) { \ 65 return BCM_E_INIT; \ 66 } \ 67 } while (0) 68 69 #define VLAN_VIRTUAL_LOCK(unit) \ 70 sal_mutex_take(VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex, sal_mutex_FOREVER); 71 72 #define VLAN_VIRTUAL_UNLOCK(unit) \ 73 sal_mutex_give(VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex); 74 75 #define VLAN_VP_INFO(unit, vp) (&VLAN_VIRTUAL_INFO(unit)->port_info[vp]) 76 77 /* 78 * Function: 79 * _bcm_enduro_vlan_vp_port_cnt_update 80 * Purpose: 81 * Update port's VP count. 82 * Parameters: 83 * unit - (IN) SOC unit number. 84 * gport - (IN) GPORT ID. 85 * vp - (IN) Virtual port number. 86 * incr - (IN) If TRUE, increment VP count, else decrease VP count. 87 * Returns: 88 * BCM_X_XXX 89 */ 90 STATIC int 91 _bcm_enduro_vlan_vp_port_cnt_update(int unit, bcm_gport_t gport, 92 int vp, int incr) 93 { 94 int mod_out, port_out, tgid_out, id_out; 95 int idx; 96 int mod_local; 97 _bcm_port_info_t *port_info; 98 int local_member_count; 99 bcm_port_t local_member_array[SOC_MAX_NUM_PORTS]; 100 uint32 port_flags; 101 102 BCM_IF_ERROR_RETURN 103 (_bcm_esw_gport_resolve(unit, gport, &mod_out, 104 &port_out, &tgid_out, &id_out)); 105 if (-1 != id_out) { 106 return BCM_E_PARAM; 107 } 108 109 /* Update the physical port's SW state. If associated with a trunk, 110 * update each local physical port's SW state. 111 */ 112 113 if (BCM_TRUNK_INVALID != tgid_out) { 114 115 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid_out, 116 SOC_MAX_NUM_PORTS, local_member_array, &local_member_count)); 117 118 for (idx = 0; idx < local_member_count; idx++) { 119 _bcm_port_info_access(unit, local_member_array[idx], &port_info); 120 if (incr) { 121 port_info->vp_count++; 122 } else { 123 port_info->vp_count--; 124 } 125 BCM_IF_ERROR_RETURN( 126 bcm_esw_port_vlan_member_get( 127 unit, local_member_array[idx], &port_flags)); 128 BCM_IF_ERROR_RETURN( 129 bcm_esw_port_vlan_member_set( 130 unit, local_member_array[idx], port_flags)); 131 } 132 } else { 133 BCM_IF_ERROR_RETURN 134 (_bcm_esw_modid_is_local(unit, mod_out, &mod_local)); 135 if (mod_local) { 136 if (soc_feature(unit, soc_feature_sysport_remap)) { 137 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 138 } 139 _bcm_port_info_access(unit, port_out, &port_info); 140 if (incr) { 141 port_info->vp_count++; 142 } else { 143 port_info->vp_count--; 144 } 145 BCM_IF_ERROR_RETURN( 146 bcm_esw_port_vlan_member_get( 147 unit, port_out, &port_flags)); 148 BCM_IF_ERROR_RETURN( 149 bcm_esw_port_vlan_member_set( 150 unit, port_out, port_flags)); 151 } 152 } 153 154 return BCM_E_NONE; 155 } 156 157 /* 158 * Function: 159 * _bcm_enduro_vlan_virtual_free_resources 160 * Purpose: 161 * Free all allocated tables and memory 162 * Parameters: 163 * unit - SOC unit number 164 * Returns: 165 * Nothing 166 */ 167 STATIC void 168 _bcm_enduro_vlan_virtual_free_resources(int unit) 169 { 170 if (VLAN_VIRTUAL_INFO(unit)->port_info) { 171 sal_free(VLAN_VIRTUAL_INFO(unit)->port_info); 172 VLAN_VIRTUAL_INFO(unit)->port_info = NULL; 173 } 174 if (VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex) { 175 sal_mutex_destroy(VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex); 176 VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex = NULL; 177 } 178 } 179 180 #ifdef BCM_WARM_BOOT_SUPPORT 181 /* 182 * Function: 183 * bcm_enduro_vlan_virtual_reinit 184 * Purpose: 185 * Warm boot recovery for the VLAN virtual software module 186 * Parameters: 187 * unit - Device Number 188 * Returns: 189 * BCM_E_XXX 190 */ 191 int 192 bcm_enduro_vlan_virtual_reinit(int unit) 193 { 194 int rv = BCM_E_NONE; 195 int stable_size; 196 uint8 *vlan_xlate_buf = NULL; 197 vlan_xlate_entry_t *vt_entry; 198 int i, index_min, index_max; 199 uint32 key_type, vp, nh_index, trunk_bit; 200 source_vp_entry_t svp_entry; 201 ing_dvp_table_entry_t dvp_entry; 202 ing_l3_next_hop_entry_t ing_nh_entry; 203 wlan_svp_table_entry_t wlan_svp_entry; 204 bcm_trunk_t tgid; 205 bcm_module_t modid, mod_out; 206 bcm_port_t port_num, port_out; 207 uint32 profile_idx; 208 ing_vlan_tag_action_profile_entry_t ing_profile_entry; 209 _bcm_vp_info_t vp_info; 210 211 _bcm_vp_info_init(&vp_info); 212 vp_info.vp_type = _bcmVpTypeVlan; 213 214 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 215 216 /* Recover VLAN virtual ports from VLAN_XLATE table */ 217 218 vlan_xlate_buf = soc_cm_salloc(unit, 219 SOC_MEM_TABLE_BYTES(unit, VLAN_XLATEm), "VLAN_XLATE buffer"); 220 if (NULL == vlan_xlate_buf) { 221 rv = BCM_E_MEMORY; 222 goto cleanup; 223 } 224 225 index_min = soc_mem_index_min(unit, VLAN_XLATEm); 226 index_max = soc_mem_index_max(unit, VLAN_XLATEm); 227 rv = soc_mem_read_range(unit, VLAN_XLATEm, MEM_BLOCK_ANY, 228 index_min, index_max, vlan_xlate_buf); 229 if (SOC_FAILURE(rv)) { 230 goto cleanup; 231 } 232 233 for (i = index_min; i <= index_max; i++) { 234 vt_entry = soc_mem_table_idx_to_pointer 235 (unit, VLAN_XLATEm, vlan_xlate_entry_t *, 236 vlan_xlate_buf, i); 237 238 if (soc_VLAN_XLATEm_field32_get(unit, vt_entry, VALIDf) == 0) { 239 continue; 240 } 241 242 key_type = soc_VLAN_XLATEm_field32_get(unit, vt_entry, KEY_TYPEf); 243 if ((key_type != TR_VLXLT_HASH_KEY_TYPE_OVID) && 244 (key_type != TR_VLXLT_HASH_KEY_TYPE_IVID_OVID) && 245 (key_type != TR_VLXLT_HASH_KEY_TYPE_OTAG)) { 246 continue; 247 } 248 249 if (soc_VLAN_XLATEm_field32_get(unit, vt_entry, MPLS_ACTIONf) != 1) { 250 continue; 251 } 252 253 vp = soc_VLAN_XLATEm_field32_get(unit, vt_entry, SOURCE_VPf); 254 if ((stable_size == 0) || SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 255 /* Determine if VP is a VLAN VP by process of elimination. 256 * Can rule out NIV VP since NIV VPs have different VIF key 257 * types in VLAN_XLATEm. 258 */ 259 260 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp_entry); 261 if (BCM_FAILURE(rv)) { 262 goto cleanup; 263 } 264 /* Rule out MPLS and MiM VPs, for which ENTRY_TYPE = 1 */ 265 if (soc_SOURCE_VPm_field32_get(unit, &svp_entry, ENTRY_TYPEf) != 3) { 266 continue; 267 } 268 269 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry); 270 if (BCM_FAILURE(rv)) { 271 goto cleanup; 272 } 273 274 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 275 NEXT_HOP_INDEXf); 276 rv = READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, 277 &ing_nh_entry); 278 if (BCM_FAILURE(rv)) { 279 goto cleanup; 280 } 281 /* Rule out Subport VPs, for which ENTRY_TYPE = 3 */ 282 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh_entry, 283 ENTRY_TYPEf) != 2) { 284 continue; 285 } 286 287 /* Rule out WLAN vp */ 288 if (SOC_MEM_IS_VALID(unit, WLAN_SVP_TABLEm)) { 289 if (vp > soc_mem_index_max(unit, WLAN_SVP_TABLEm)) { 290 continue; 291 } 292 rv = READ_WLAN_SVP_TABLEm(unit, MEM_BLOCK_ANY, vp, 293 &wlan_svp_entry); 294 if (BCM_FAILURE(rv)) { 295 goto cleanup; 296 } 297 if (soc_WLAN_SVP_TABLEm_field32_get(unit, &wlan_svp_entry, 298 VALIDf) == 1) { 299 continue; 300 } 301 } 302 303 /* At this point, we are sure VP is a VLAN VP. */ 304 305 rv = _bcm_vp_used_set(unit, vp, vp_info); 306 if (BCM_FAILURE(rv)) { 307 goto cleanup; 308 } 309 } else { 310 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 311 /* VP bitmap is recovered by virtual_init */ 312 continue; 313 } 314 } 315 316 /* Recover VLAN_VP_INFO(unit, vp)->criteria, match_vlan, and 317 * match_inner_vlan. 318 */ 319 switch (key_type) { 320 case TR_VLXLT_HASH_KEY_TYPE_OVID: 321 VLAN_VP_INFO(unit, vp)->criteria = 322 BCM_VLAN_PORT_MATCH_PORT_VLAN; 323 VLAN_VP_INFO(unit, vp)->match_vlan = 324 soc_VLAN_XLATEm_field32_get(unit, vt_entry, OVIDf); 325 break; 326 case TR_VLXLT_HASH_KEY_TYPE_IVID_OVID: 327 VLAN_VP_INFO(unit, vp)->criteria = 328 BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED; 329 VLAN_VP_INFO(unit, vp)->match_vlan = 330 soc_VLAN_XLATEm_field32_get(unit, vt_entry, OVIDf); 331 VLAN_VP_INFO(unit, vp)->match_inner_vlan = 332 soc_VLAN_XLATEm_field32_get(unit, vt_entry, IVIDf); 333 break; 334 case TR_VLXLT_HASH_KEY_TYPE_OTAG: 335 VLAN_VP_INFO(unit, vp)->criteria = 336 BCM_VLAN_PORT_MATCH_PORT_VLAN16; 337 VLAN_VP_INFO(unit, vp)->match_vlan = 338 soc_VLAN_XLATEm_field32_get(unit, vt_entry, OTAGf); 339 break; 340 /* coverity[dead_error_begin] */ 341 default: 342 continue; 343 } 344 345 /* Recover VLAN_VP_INFO(unit, vp)->port */ 346 trunk_bit = soc_VLAN_XLATEm_field32_get(unit, vt_entry, Tf); 347 if (trunk_bit) { 348 tgid = soc_VLAN_XLATEm_field32_get(unit, vt_entry, TGIDf); 349 BCM_GPORT_TRUNK_SET(VLAN_VP_INFO(unit, vp)->port, tgid); 350 } else { 351 modid = soc_VLAN_XLATEm_field32_get(unit, vt_entry, MODULE_IDf); 352 port_num = soc_VLAN_XLATEm_field32_get(unit, vt_entry, PORT_NUMf); 353 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 354 modid, port_num, &mod_out, &port_out); 355 if (BCM_FAILURE(rv)) { 356 goto cleanup; 357 } 358 BCM_GPORT_MODPORT_SET(VLAN_VP_INFO(unit, vp)->port, 359 mod_out, port_out); 360 } 361 362 /* Recover VLAN_VP_INFO(unit, vp)->flags */ 363 profile_idx = soc_VLAN_XLATEm_field32_get(unit, vt_entry, 364 TAG_ACTION_PROFILE_PTRf); 365 rv = READ_ING_VLAN_TAG_ACTION_PROFILEm(unit, MEM_BLOCK_ANY, 366 profile_idx, &ing_profile_entry); 367 if (BCM_FAILURE(rv)) { 368 goto cleanup; 369 } 370 if ((soc_ING_VLAN_TAG_ACTION_PROFILEm_field32_get(unit, 371 &ing_profile_entry, DT_OTAG_ACTIONf) == 372 bcmVlanActionReplace) && 373 (soc_ING_VLAN_TAG_ACTION_PROFILEm_field32_get(unit, 374 &ing_profile_entry, DT_ITAG_ACTIONf) == 375 bcmVlanActionNone)) { 376 VLAN_VP_INFO(unit, vp)->flags |= BCM_VLAN_PORT_INNER_VLAN_PRESERVE; 377 } 378 if (VLAN_VP_INFO(unit, vp)->criteria == 379 BCM_VLAN_PORT_MATCH_PORT_VLAN16) { 380 VLAN_VP_INFO(unit, vp)->flags |= BCM_VLAN_PORT_EGRESS_VLAN16; 381 } 382 383 if (stable_size == 0) { 384 /* In the Port module, a port's VP count is not recovered in 385 * level 1 Warm Boot. 386 */ 387 rv = _bcm_enduro_vlan_vp_port_cnt_update(unit, 388 VLAN_VP_INFO(unit, vp)->port, vp, TRUE); 389 if (BCM_FAILURE(rv)) { 390 goto cleanup; 391 } 392 } 393 } 394 395 cleanup: 396 if (vlan_xlate_buf) { 397 soc_cm_sfree(unit, vlan_xlate_buf); 398 } 399 400 if (BCM_FAILURE(rv)) { 401 _bcm_enduro_vlan_virtual_free_resources(unit); 402 } 403 404 return rv; 405 } 406 #endif /* BCM_WARM_BOOT_SUPPORT */ 407 408 #ifndef BCM_SW_STATE_DUMP_DISABLE 409 /* 410 * Function: 411 * _bcm_enduro_vlan_vp_sw_dump 412 * Purpose: 413 * Displays VLAN VP information maintained by software. 414 * Parameters: 415 * unit - Device unit number 416 * Returns: 417 * None 418 */ 419 void 420 bcm_enduro_vlan_vp_sw_dump(int unit) 421 { 422 int i, num_vp; 423 424 LOG_CLI((BSL_META_U(unit, 425 "\nSW Information VLAN VP - Unit %d\n"), unit)); 426 427 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 428 429 for (i = 0; i < num_vp; i++) { 430 if (VLAN_VP_INFO(unit, i)->port == 0) { 431 continue; 432 } 433 LOG_CLI((BSL_META_U(unit, 434 "\n VLAN vp = %d\n"), i)); 435 LOG_CLI((BSL_META_U(unit, 436 " Criteria = 0x%x,"), VLAN_VP_INFO(unit, i)->criteria)); 437 switch (VLAN_VP_INFO(unit, i)->criteria) { 438 case BCM_VLAN_PORT_MATCH_PORT_VLAN: 439 LOG_CLI((BSL_META_U(unit, 440 " port plus outer VLAN ID\n"))); 441 break; 442 case BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED: 443 LOG_CLI((BSL_META_U(unit, 444 " port plus outer and inner VLAN IDs\n"))); 445 break; 446 case BCM_VLAN_PORT_MATCH_PORT_VLAN16: 447 LOG_CLI((BSL_META_U(unit, 448 " port plus outer VLAN tag\n"))); 449 break; 450 default: 451 LOG_CLI((BSL_META_U(unit, 452 " \n"))); 453 } 454 LOG_CLI((BSL_META_U(unit, 455 " Flags = 0x%x\n"), VLAN_VP_INFO(unit, i)->flags)); 456 LOG_CLI((BSL_META_U(unit, 457 " Match VLAN = 0x%x\n"), VLAN_VP_INFO(unit, i)->match_vlan)); 458 LOG_CLI((BSL_META_U(unit, 459 " Match Inner VLAN = 0x%x\n"), 460 VLAN_VP_INFO(unit, i)->match_inner_vlan)); 461 LOG_CLI((BSL_META_U(unit, 462 " Port = 0x%x\n"), VLAN_VP_INFO(unit, i)->port)); 463 } 464 465 return; 466 } 467 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 468 469 /* 470 * Function: 471 * bcm_enduro_vlan_virtual_init 472 * Purpose: 473 * Initialize the VLAN virtual port module. 474 * Parameters: 475 * unit - SOC unit number. 476 * Returns: 477 * BCM_E_XXX 478 */ 479 int 480 bcm_enduro_vlan_virtual_init(int unit) 481 { 482 int num_vp; 483 484 if (VLAN_VIRTUAL_INFO(unit)->vlan_virtual_initialized) { 485 bcm_enduro_vlan_virtual_detach(unit); 486 } 487 488 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 489 if (NULL == VLAN_VIRTUAL_INFO(unit)->port_info) { 490 VLAN_VIRTUAL_INFO(unit)->port_info = 491 sal_alloc(sizeof(_bcm_enduro_vlan_vp_info_t) * num_vp, "vlan_vp_info"); 492 if (NULL == VLAN_VIRTUAL_INFO(unit)->port_info) { 493 _bcm_enduro_vlan_virtual_free_resources(unit); 494 return BCM_E_MEMORY; 495 } 496 } 497 sal_memset(VLAN_VIRTUAL_INFO(unit)->port_info, 0, 498 sizeof(_bcm_enduro_vlan_vp_info_t) * num_vp); 499 500 if (NULL == VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex) { 501 VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex = 502 sal_mutex_create("vlan virtual mutex"); 503 if (NULL == VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex) { 504 _bcm_enduro_vlan_virtual_free_resources(unit); 505 return BCM_E_MEMORY; 506 } 507 } 508 509 VLAN_VIRTUAL_INFO(unit)->vlan_virtual_initialized = 1; 510 511 /* Warm boot recovery of VLAN_VP_INFO depends on the completion 512 * of _bcm_virtual_init, but _bcm_virtual_init is after the 513 * VLAN module in the init sequence. Hence, warm boot recovery 514 * of VLAN_VP_INFO is moved to end of _bcm_virtual_init. 515 */ 516 517 return BCM_E_NONE; 518 } 519 520 /* 521 * Function: 522 * bcm_enduro_vlan_virtual_detach 523 * Purpose: 524 * Detach the VLAN virtual port module. 525 * Parameters: 526 * unit - SOC unit number. 527 * Returns: 528 * BCM_E_XXX 529 */ 530 int 531 bcm_enduro_vlan_virtual_detach(int unit) 532 { 533 _bcm_enduro_vlan_virtual_free_resources(unit); 534 535 VLAN_VIRTUAL_INFO(unit)->vlan_virtual_initialized = 0; 536 537 return BCM_E_NONE; 538 } 539 540 /* 541 * Function: 542 * _bcm_enduro_vlan_vp_nh_info_set 543 * Purpose: 544 * Get a next hop index and configure next hop tables. 545 * Parameters: 546 * unit - (IN) SOC unit number. 547 * vlan_vp - (IN) Pointer to VLAN virtual port structure. 548 * vp - (IN) Virtual port number. 549 * drop - (IN) Drop indication. 550 * nh_index - (IN/OUT) Next hop index. 551 * Returns: 552 * BCM_X_XXX 553 */ 554 STATIC int 555 _bcm_enduro_vlan_vp_nh_info_set(int unit, bcm_vlan_port_t *vlan_vp, int vp, 556 int drop, int *nh_index) 557 { 558 int rv; 559 uint32 nh_flags; 560 bcm_l3_egress_t nh_info; 561 egr_l3_next_hop_entry_t egr_nh; 562 uint8 egr_nh_entry_type; 563 bcm_module_t mod_out; 564 bcm_port_t port_out; 565 bcm_trunk_t trunk_id; 566 int id; 567 int ing_nh_port; 568 int ing_nh_module; 569 int ing_nh_trunk; 570 ing_l3_next_hop_entry_t ing_nh; 571 initial_ing_l3_next_hop_entry_t initial_ing_nh; 572 573 /* Get a next hop index */ 574 575 if (vlan_vp->flags & BCM_VLAN_PORT_REPLACE) { 576 if ((*nh_index > soc_mem_index_max(unit, EGR_L3_NEXT_HOPm)) || 577 (*nh_index < soc_mem_index_min(unit, EGR_L3_NEXT_HOPm))) { 578 return BCM_E_PARAM; 579 } 580 } else { 581 /* 582 * Allocate a next-hop entry. By calling bcm_xgs3_nh_add() 583 * with _BCM_L3_SHR_WRITE_DISABLE flag, a next-hop index is 584 * allocated but nothing is written to hardware. The "nh_info" 585 * in this case is not used, so just set to all zeros. 586 */ 587 bcm_l3_egress_t_init(&nh_info); 588 589 nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE; 590 rv = bcm_xgs3_nh_add(unit, nh_flags, &nh_info, nh_index); 591 BCM_IF_ERROR_RETURN(rv); 592 } 593 594 /* Write EGR_L3_NEXT_HOP entry */ 595 596 if (vlan_vp->flags & BCM_VLAN_PORT_REPLACE) { 597 /* Read the existing egress next_hop entry */ 598 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 599 *nh_index, &egr_nh); 600 BCM_IF_ERROR_RETURN(rv); 601 602 /* Be sure that the existing entry is programmed to SD-tag */ 603 egr_nh_entry_type = 604 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, ENTRY_TYPEf); 605 if (egr_nh_entry_type != 0x2) { /* != SD-tag */ 606 return BCM_E_PARAM; 607 } 608 } else { 609 egr_nh_entry_type = 0x2; /* SD-tag */ 610 } 611 612 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 613 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 614 ENTRY_TYPEf, egr_nh_entry_type); 615 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 616 SD_TAG__DVPf, vp); 617 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 618 SD_TAG__HG_HDR_SELf, 1); 619 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, 620 MEM_BLOCK_ALL, *nh_index, &egr_nh); 621 if (rv < 0) { 622 goto cleanup; 623 } 624 625 /* Resolve gport */ 626 627 rv = _bcm_esw_gport_resolve(unit, vlan_vp->port, &mod_out, 628 &port_out, &trunk_id, &id); 629 if (rv < 0) { 630 goto cleanup; 631 } 632 633 ing_nh_port = -1; 634 ing_nh_module = -1; 635 ing_nh_trunk = -1; 636 637 if (BCM_GPORT_IS_TRUNK(vlan_vp->port)) { 638 ing_nh_module = -1; 639 ing_nh_port = -1; 640 ing_nh_trunk = trunk_id; 641 } else { 642 ing_nh_module = mod_out; 643 ing_nh_port = port_out; 644 ing_nh_trunk = -1; 645 } 646 647 /* Write ING_L3_NEXT_HOP entry */ 648 649 sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t)); 650 651 if (ing_nh_trunk == -1) { 652 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 653 &ing_nh, PORT_NUMf, ing_nh_port); 654 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 655 &ing_nh, MODULE_IDf, ing_nh_module); 656 } else { 657 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 658 &ing_nh, Tf, 1); 659 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 660 &ing_nh, TGIDf, ing_nh_trunk); 661 } 662 663 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, drop); 664 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 665 &ing_nh, ENTRY_TYPEf, 0x2); /* L2 DVP */ 666 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, 667 &ing_nh, MTU_SIZEf, 0x3fff); 668 rv = soc_mem_write (unit, ING_L3_NEXT_HOPm, 669 MEM_BLOCK_ALL, *nh_index, &ing_nh); 670 if (rv < 0) { 671 goto cleanup; 672 } 673 674 /* Write INITIAL_ING_L3_NEXT_HOP entry */ 675 676 sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t)); 677 if (ing_nh_trunk == -1) { 678 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 679 &initial_ing_nh, PORT_NUMf, ing_nh_port); 680 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 681 &initial_ing_nh, MODULE_IDf, ing_nh_module); 682 } else { 683 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 684 &initial_ing_nh, Tf, 1); 685 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm, 686 &initial_ing_nh, TGIDf, ing_nh_trunk); 687 } 688 rv = soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm, 689 MEM_BLOCK_ALL, *nh_index, &initial_ing_nh); 690 if (rv < 0) { 691 goto cleanup; 692 } 693 694 return rv; 695 696 cleanup: 697 if (!(vlan_vp->flags & BCM_VLAN_PORT_REPLACE)) { 698 (void) bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, *nh_index); 699 } 700 return rv; 701 } 702 703 /* 704 * Function: 705 * _bcm_enduro_vlan_vp_nh_info_delete 706 * Purpose: 707 * Free next hop index and clear next hop tables. 708 * Parameters: 709 * unit - (IN) SOC unit number. 710 * nh_index - (IN) Next hop index. 711 * Returns: 712 * BCM_X_XXX 713 */ 714 STATIC int 715 _bcm_enduro_vlan_vp_nh_info_delete(int unit, int nh_index) 716 { 717 egr_l3_next_hop_entry_t egr_nh; 718 ing_l3_next_hop_entry_t ing_nh; 719 initial_ing_l3_next_hop_entry_t initial_ing_nh; 720 721 /* Clear EGR_L3_NEXT_HOP entry */ 722 sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t)); 723 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_NEXT_HOPm, 724 MEM_BLOCK_ALL, nh_index, &egr_nh)); 725 726 /* Clear ING_L3_NEXT_HOP entry */ 727 sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t)); 728 BCM_IF_ERROR_RETURN(soc_mem_write (unit, ING_L3_NEXT_HOPm, 729 MEM_BLOCK_ALL, nh_index, &ing_nh)); 730 731 /* Clear INITIAL_ING_L3_NEXT_HOP entry */ 732 sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t)); 733 BCM_IF_ERROR_RETURN(soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm, 734 MEM_BLOCK_ALL, nh_index, &initial_ing_nh)); 735 736 /* Free the next-hop index. */ 737 BCM_IF_ERROR_RETURN 738 (bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, nh_index)); 739 740 return BCM_E_NONE; 741 } 742 743 /* 744 * Function: 745 * _bcm_enduro_vlan_vp_match_add 746 * Purpose: 747 * Add match criteria for VLAN VP. 748 * Parameters: 749 * unit - (IN) SOC unit number. 750 * vlan_vp - (IN) Pointer to VLAN virtual port structure. 751 * vp - (IN) Virtual port number. 752 * Returns: 753 * BCM_X_XXX 754 */ 755 STATIC int 756 _bcm_enduro_vlan_vp_match_add(int unit, bcm_vlan_port_t *vlan_vp, int vp) 757 { 758 vlan_xlate_entry_t vent, old_vent; 759 int key_type = 0; 760 bcm_vlan_action_set_t action; 761 uint32 profile_idx; 762 int rv; 763 764 if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_NONE) { 765 return BCM_E_NONE; 766 } 767 768 if (!((vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN) || 769 (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED) || 770 (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN16))) { 771 return BCM_E_PARAM; 772 } 773 774 if ((vlan_vp->egress_vlan > BCM_VLAN_MAX) || 775 (vlan_vp->egress_inner_vlan > BCM_VLAN_MAX)) { 776 return BCM_E_PARAM; 777 } 778 779 sal_memset(&vent, 0, sizeof(vlan_xlate_entry_t)); 780 781 soc_VLAN_XLATEm_field32_set(unit, &vent, VALIDf, 1); 782 783 if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN) { 784 key_type = bcmVlanTranslateKeyPortOuter; 785 } else if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED) { 786 key_type = bcmVlanTranslateKeyPortDouble; 787 } else if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN16) { 788 key_type = bcmVlanTranslateKeyPortOuterTag; 789 } 790 BCM_IF_ERROR_RETURN 791 (_bcm_trx_vlan_translate_entry_assemble(unit, &vent, 792 vlan_vp->port, 793 key_type, 794 vlan_vp->match_inner_vlan, 795 vlan_vp->match_vlan)); 796 797 soc_VLAN_XLATEm_field32_set(unit, &vent, MPLS_ACTIONf, 0x1); /* SVP */ 798 soc_VLAN_XLATEm_field32_set(unit, &vent, SOURCE_VPf, vp); 799 soc_VLAN_XLATEm_field32_set(unit, &vent, NEW_OVIDf, 800 vlan_vp->egress_vlan); 801 soc_VLAN_XLATEm_field32_set(unit, &vent, NEW_IVIDf, 802 vlan_vp->egress_inner_vlan); 803 804 bcm_vlan_action_set_t_init(&action); 805 806 /* For double tagged packets */ 807 if (vlan_vp->flags & BCM_VLAN_PORT_INNER_VLAN_PRESERVE) { 808 action.dt_outer = bcmVlanActionReplace; 809 action.dt_outer_prio = bcmVlanActionReplace; 810 action.dt_inner = bcmVlanActionNone; 811 action.dt_inner_prio = bcmVlanActionNone; 812 } else { 813 /* Strip inner VLAN */ 814 action.dt_outer = bcmVlanActionReplace; 815 action.dt_outer_prio = bcmVlanActionReplace; 816 action.dt_inner = bcmVlanActionDelete; 817 action.dt_inner_prio = bcmVlanActionDelete; 818 } 819 820 if (vlan_vp->flags & BCM_VLAN_PORT_INNER_VLAN_ADD) { 821 action.ot_inner = bcmVlanActionAdd; 822 } else { 823 action.ot_inner = bcmVlanActionNone; 824 } 825 826 action.ot_outer = bcmVlanActionReplace; 827 action.ot_outer_prio = bcmVlanActionReplace; 828 829 BCM_IF_ERROR_RETURN 830 (_bcm_trx_vlan_action_profile_entry_add(unit, &action, &profile_idx)); 831 832 soc_VLAN_XLATEm_field32_set(unit, &vent, TAG_ACTION_PROFILE_PTRf, 833 profile_idx); 834 835 rv = soc_mem_insert_return_old(unit, VLAN_XLATEm, MEM_BLOCK_ALL, 836 &vent, &old_vent); 837 if (rv == SOC_E_EXISTS) { 838 /* Delete the old vlan translate profile entry */ 839 profile_idx = soc_VLAN_XLATEm_field32_get(unit, &old_vent, 840 TAG_ACTION_PROFILE_PTRf); 841 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx); 842 } 843 return rv; 844 } 845 846 /* 847 * Function: 848 * _bcm_enduro_vlan_vp_match_delete 849 * Purpose: 850 * Delete match criteria for VLAN VP. 851 * Parameters: 852 * unit - (IN) SOC unit number. 853 * vp - (IN) Virtual port number. 854 * Returns: 855 * BCM_X_XXX 856 */ 857 STATIC int 858 _bcm_enduro_vlan_vp_match_delete(int unit, int vp) 859 { 860 vlan_xlate_entry_t vent, old_vent; 861 int key_type = 0; 862 uint32 profile_idx; 863 int rv; 864 865 if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_NONE) { 866 return BCM_E_NONE; 867 } 868 869 if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN) { 870 key_type = bcmVlanTranslateKeyPortOuter; 871 } else if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED) { 872 key_type = bcmVlanTranslateKeyPortDouble; 873 } else if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN16) { 874 key_type = bcmVlanTranslateKeyPortOuterTag; 875 } else { 876 return BCM_E_INTERNAL; 877 } 878 879 sal_memset(&vent, 0, sizeof(vlan_xlate_entry_t)); 880 BCM_IF_ERROR_RETURN 881 (_bcm_trx_vlan_translate_entry_assemble(unit, &vent, 882 VLAN_VP_INFO(unit, vp)->port, 883 key_type, 884 VLAN_VP_INFO(unit, vp)->match_inner_vlan, 885 VLAN_VP_INFO(unit, vp)->match_vlan)); 886 887 rv = soc_mem_delete_return_old(unit, VLAN_XLATEm, MEM_BLOCK_ALL, &vent, &old_vent); 888 if ((rv == SOC_E_NONE) && soc_VLAN_XLATEm_field32_get(unit, &old_vent, VALIDf)) { 889 profile_idx = soc_VLAN_XLATEm_field32_get(unit, &old_vent, 890 TAG_ACTION_PROFILE_PTRf); 891 /* Delete the old vlan action profile entry */ 892 rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx); 893 } 894 return rv; 895 } 896 897 /* 898 * Function: 899 * _bcm_enduro_vlan_vp_match_get 900 * Purpose: 901 * Get match criteria for VLAN VP. 902 * Parameters: 903 * unit - (IN) SOC unit number. 904 * vp - (IN) Virtual port number. 905 * vlan_vp - (OUT) Pointer to VLAN virtual port structure. 906 * Returns: 907 * BCM_X_XXX 908 */ 909 STATIC int 910 _bcm_enduro_vlan_vp_match_get(int unit, int vp, bcm_vlan_port_t *vlan_vp) 911 { 912 vlan_xlate_entry_t vent, vent_out; 913 int key_type = 0; 914 int idx; 915 916 vlan_vp->criteria = VLAN_VP_INFO(unit, vp)->criteria; 917 vlan_vp->match_vlan = VLAN_VP_INFO(unit, vp)->match_vlan; 918 vlan_vp->match_inner_vlan = VLAN_VP_INFO(unit, vp)->match_inner_vlan; 919 vlan_vp->port = VLAN_VP_INFO(unit, vp)->port; 920 921 if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_NONE) { 922 return BCM_E_NONE; 923 } 924 925 if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN) { 926 key_type = bcmVlanTranslateKeyPortOuter; 927 } else if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED) { 928 key_type = bcmVlanTranslateKeyPortDouble; 929 } else if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN16) { 930 key_type = bcmVlanTranslateKeyPortOuterTag; 931 } else { 932 return BCM_E_INTERNAL; 933 } 934 935 sal_memset(&vent, 0, sizeof(vlan_xlate_entry_t)); 936 BCM_IF_ERROR_RETURN 937 (_bcm_trx_vlan_translate_entry_assemble(unit, &vent, 938 VLAN_VP_INFO(unit, vp)->port, 939 key_type, 940 VLAN_VP_INFO(unit, vp)->match_inner_vlan, 941 VLAN_VP_INFO(unit, vp)->match_vlan)); 942 943 BCM_IF_ERROR_RETURN 944 (soc_mem_search(unit, VLAN_XLATEm, MEM_BLOCK_ALL, 945 &idx, &vent, &vent_out, 0)); 946 vlan_vp->egress_vlan = soc_VLAN_XLATEm_field32_get(unit, &vent_out, 947 NEW_OVIDf); 948 vlan_vp->egress_inner_vlan = soc_VLAN_XLATEm_field32_get(unit, &vent_out, 949 NEW_IVIDf); 950 951 return BCM_E_NONE; 952 } 953 954 /* 955 * Function: 956 * _bcm_enduro_vlan_vp_create 957 * Purpose: 958 * Create a VLAN virtual port. 959 * Parameters: 960 * unit - (IN) SOC unit number. 961 * vlan_vp - (IN/OUT) Pointer to VLAN virtual port structure. 962 * Returns: 963 * BCM_X_XXX 964 */ 965 STATIC int 966 _bcm_enduro_vlan_vp_create(int unit, 967 bcm_vlan_port_t *vlan_vp) 968 { 969 int mode; 970 int vp; 971 int rv = BCM_E_NONE; 972 int num_vp; 973 int nh_index = 0; 974 ing_dvp_table_entry_t dvp_entry; 975 source_vp_entry_t svp_entry; 976 int cml_default_enable=0, cml_default_new=0, cml_default_move=0; 977 _bcm_vp_info_t vp_info; 978 979 _bcm_vp_info_init(&vp_info); 980 vp_info.vp_type = _bcmVpTypeVlan; 981 982 BCM_IF_ERROR_RETURN(bcm_xgs3_l3_egress_mode_get(unit, &mode)); 983 if (!mode) { 984 LOG_INFO(BSL_LS_BCM_L3, 985 (BSL_META_U(unit, 986 "L3 egress mode must be set first\n"))); 987 return BCM_E_DISABLED; 988 } 989 990 if (!(vlan_vp->flags & BCM_VLAN_PORT_REPLACE)) { /* Create new VLAN VP */ 991 992 if (vlan_vp->flags & BCM_VLAN_PORT_WITH_ID) { 993 if (!BCM_GPORT_IS_VLAN_PORT(vlan_vp->vlan_port_id)) { 994 return BCM_E_PARAM; 995 } 996 vp = BCM_GPORT_VLAN_PORT_ID_GET(vlan_vp->vlan_port_id); 997 if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) { 998 return BCM_E_PARAM; 999 } 1000 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 1001 return BCM_E_EXISTS; 1002 } else { 1003 rv = _bcm_vp_used_set(unit, vp, vp_info); 1004 if (rv < 0) { 1005 return rv; 1006 } 1007 } 1008 } else { 1009 /* allocate a new VP index */ 1010 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 1011 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, 1012 vp_info, &vp); 1013 if (rv < 0) { 1014 return rv; 1015 } 1016 } 1017 1018 /* Configure next hop tables */ 1019 rv = _bcm_enduro_vlan_vp_nh_info_set(unit, vlan_vp, vp, 0, 1020 &nh_index); 1021 if (rv < 0) { 1022 goto cleanup; 1023 } 1024 1025 /* Configure DVP table */ 1026 sal_memset(&dvp_entry, 0, sizeof(ing_dvp_table_entry_t)); 1027 soc_ING_DVP_TABLEm_field32_set(unit, &dvp_entry, NEXT_HOP_INDEXf, 1028 nh_index); 1029 rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp_entry); 1030 if (rv < 0) { 1031 goto cleanup; 1032 } 1033 1034 /* Configure SVP table */ 1035 sal_memset(&svp_entry, 0, sizeof(source_vp_entry_t)); 1036 soc_SOURCE_VPm_field32_set(unit, &svp_entry, ENTRY_TYPEf, 3); 1037 1038 /* Set the CML */ 1039 rv = _bcm_vp_default_cml_mode_get (unit, 1040 &cml_default_enable, &cml_default_new, 1041 &cml_default_move); 1042 if (rv < 0) { 1043 goto cleanup; 1044 } 1045 1046 if (cml_default_enable) { 1047 /* Set the CML to default values */ 1048 soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_NEWf, cml_default_new); 1049 soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_MOVEf, cml_default_move); 1050 } else { 1051 /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */ 1052 soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_NEWf, 0x8); 1053 soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_MOVEf, 0x8); 1054 } 1055 1056 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry); 1057 if (rv < 0) { 1058 goto cleanup; 1059 } 1060 1061 /* Configure ingress VLAN translation table */ 1062 rv = _bcm_enduro_vlan_vp_match_add(unit, vlan_vp, vp); 1063 if (rv < 0) { 1064 goto cleanup; 1065 } 1066 1067 /* Increment port's VP count */ 1068 rv = _bcm_enduro_vlan_vp_port_cnt_update(unit, vlan_vp->port, vp, TRUE); 1069 if (rv < 0) { 1070 goto cleanup; 1071 } 1072 1073 } else { /* Replace properties of existing VLAN VP */ 1074 1075 if (!(vlan_vp->flags & BCM_VLAN_PORT_WITH_ID)) { 1076 return BCM_E_PARAM; 1077 } 1078 if (!BCM_GPORT_IS_VLAN_PORT(vlan_vp->vlan_port_id)) { 1079 return BCM_E_PARAM; 1080 } 1081 vp = BCM_GPORT_VLAN_PORT_ID_GET(vlan_vp->vlan_port_id); 1082 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 1083 return BCM_E_PARAM; 1084 } 1085 1086 /* For existing vlan vp, NH entry already exists */ 1087 BCM_IF_ERROR_RETURN 1088 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 1089 1090 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 1091 NEXT_HOP_INDEXf); 1092 1093 /* Update existing next hop entries */ 1094 BCM_IF_ERROR_RETURN 1095 (_bcm_enduro_vlan_vp_nh_info_set(unit, vlan_vp, vp, 0, 1096 &nh_index)); 1097 1098 /* Delete old ingress VLAN translation entry, 1099 * install new ingress VLAN translation entry 1100 */ 1101 BCM_IF_ERROR_RETURN 1102 (_bcm_enduro_vlan_vp_match_delete(unit, vp)); 1103 1104 BCM_IF_ERROR_RETURN 1105 (_bcm_enduro_vlan_vp_match_add(unit, vlan_vp, vp)); 1106 1107 /* Decrement old port's VP count, increment new port's VP count */ 1108 BCM_IF_ERROR_RETURN 1109 (_bcm_enduro_vlan_vp_port_cnt_update(unit, 1110 VLAN_VP_INFO(unit, vp)->port, vp, FALSE)); 1111 1112 BCM_IF_ERROR_RETURN 1113 (_bcm_enduro_vlan_vp_port_cnt_update(unit, 1114 vlan_vp->port, vp, TRUE)); 1115 } 1116 1117 /* Set VLAN VP software state */ 1118 VLAN_VP_INFO(unit, vp)->criteria = vlan_vp->criteria; 1119 VLAN_VP_INFO(unit, vp)->flags = vlan_vp->flags; 1120 VLAN_VP_INFO(unit, vp)->match_vlan = vlan_vp->match_vlan; 1121 VLAN_VP_INFO(unit, vp)->match_inner_vlan = vlan_vp->match_inner_vlan; 1122 VLAN_VP_INFO(unit, vp)->egress_vlan = vlan_vp->egress_vlan; 1123 VLAN_VP_INFO(unit, vp)->port = vlan_vp->port; 1124 1125 BCM_GPORT_VLAN_PORT_ID_SET(vlan_vp->vlan_port_id, vp); 1126 vlan_vp->encap_id = nh_index; 1127 1128 return rv; 1129 1130 cleanup: 1131 if (!(vlan_vp->flags & BCM_VLAN_PORT_REPLACE)) { 1132 (void) _bcm_vp_free(unit, _bcmVpTypeVlan, 1, vp); 1133 _bcm_enduro_vlan_vp_nh_info_delete(unit, nh_index); 1134 1135 sal_memset(&dvp_entry, 0, sizeof(ing_dvp_table_entry_t)); 1136 (void)WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp_entry); 1137 1138 sal_memset(&svp_entry, 0, sizeof(source_vp_entry_t)); 1139 (void)WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry); 1140 1141 (void) _bcm_enduro_vlan_vp_match_delete(unit, vp); 1142 } 1143 1144 return rv; 1145 } 1146 1147 /* 1148 * Function: 1149 * bcm_enduro_vlan_vp_create 1150 * Purpose: 1151 * Create a VLAN virtual port. 1152 * Parameters: 1153 * unit - (IN) SOC unit number. 1154 * vlan_vp - (IN/OUT) Pointer to VLAN virtual port structure. 1155 * Returns: 1156 * BCM_X_XXX 1157 */ 1158 int 1159 bcm_enduro_vlan_vp_create(int unit, 1160 bcm_vlan_port_t *vlan_vp) 1161 { 1162 int rv; 1163 1164 VLAN_VIRTUAL_INIT(unit); 1165 1166 VLAN_VIRTUAL_LOCK(unit); 1167 1168 rv = _bcm_enduro_vlan_vp_create(unit, vlan_vp); 1169 1170 VLAN_VIRTUAL_UNLOCK(unit); 1171 1172 return rv; 1173 } 1174 1175 /* 1176 * Function: 1177 * _bcm_enduro_vlan_vp_destroy 1178 * Purpose: 1179 * Destroy a VLAN virtual port. 1180 * Parameters: 1181 * unit - (IN) SOC unit number. 1182 * gport - (IN) VLAN VP GPORT ID. 1183 * Returns: 1184 * BCM_X_XXX 1185 */ 1186 STATIC int 1187 _bcm_enduro_vlan_vp_destroy(int unit, bcm_gport_t gport) 1188 { 1189 int vp; 1190 source_vp_entry_t svp_entry; 1191 int nh_index; 1192 ing_dvp_table_entry_t dvp_entry; 1193 1194 if (!BCM_GPORT_IS_VLAN_PORT(gport)) { 1195 return BCM_E_PARAM; 1196 } 1197 1198 vp = BCM_GPORT_VLAN_PORT_ID_GET(gport); 1199 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 1200 return BCM_E_NOT_FOUND; 1201 } 1202 1203 /* Delete ingress VLAN translation entry */ 1204 BCM_IF_ERROR_RETURN 1205 (_bcm_enduro_vlan_vp_match_delete(unit, vp)); 1206 1207 /* Clear SVP entry */ 1208 sal_memset(&svp_entry, 0, sizeof(source_vp_entry_t)); 1209 BCM_IF_ERROR_RETURN 1210 (WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry)); 1211 1212 /* Clear DVP entry */ 1213 BCM_IF_ERROR_RETURN 1214 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 1215 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, NEXT_HOP_INDEXf); 1216 1217 sal_memset(&dvp_entry, 0, sizeof(ing_dvp_table_entry_t)); 1218 BCM_IF_ERROR_RETURN 1219 (WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp_entry)); 1220 1221 /* Clear next hop entries and free next hop index */ 1222 BCM_IF_ERROR_RETURN 1223 (_bcm_enduro_vlan_vp_nh_info_delete(unit, nh_index)); 1224 1225 /* Decrement port's VP count */ 1226 BCM_IF_ERROR_RETURN 1227 (_bcm_enduro_vlan_vp_port_cnt_update(unit, 1228 VLAN_VP_INFO(unit, vp)->port, 1229 vp, FALSE)); 1230 /* Free VP */ 1231 BCM_IF_ERROR_RETURN 1232 (_bcm_vp_free(unit, _bcmVpTypeVlan, 1, vp)); 1233 1234 /* Clear VLAN VP software state */ 1235 sal_memset(VLAN_VP_INFO(unit, vp), 0, sizeof(_bcm_enduro_vlan_vp_info_t)); 1236 1237 return BCM_E_NONE; 1238 } 1239 1240 /* 1241 * Function: 1242 * bcm_enduro_vlan_vp_destroy 1243 * Purpose: 1244 * Destroy a VLAN virtual port. 1245 * Parameters: 1246 * unit - (IN) SOC unit number. 1247 * gport - (IN) VLAN VP GPORT ID. 1248 * Returns: 1249 * BCM_X_XXX 1250 */ 1251 int 1252 bcm_enduro_vlan_vp_destroy(int unit, bcm_gport_t gport) 1253 { 1254 int rv; 1255 1256 VLAN_VIRTUAL_INIT(unit); 1257 1258 VLAN_VIRTUAL_LOCK(unit); 1259 1260 rv = _bcm_enduro_vlan_vp_destroy(unit, gport); 1261 1262 VLAN_VIRTUAL_UNLOCK(unit); 1263 1264 return rv; 1265 } 1266 1267 /* 1268 * Function: 1269 * _bcm_enduro_vlan_vp_find 1270 * Purpose: 1271 * Get VLAN virtual port info. 1272 * Parameters: 1273 * unit - (IN) SOC unit number. 1274 * vlan_vp - (IN/OUT) Pointer to VLAN virtual port structure. 1275 * Returns: 1276 * BCM_X_XXX 1277 */ 1278 STATIC int 1279 _bcm_enduro_vlan_vp_find(int unit, bcm_vlan_port_t *vlan_vp) 1280 { 1281 int vp; 1282 ing_dvp_table_entry_t dvp_entry; 1283 int nh_index; 1284 1285 if (!BCM_GPORT_IS_VLAN_PORT(vlan_vp->vlan_port_id)) { 1286 return BCM_E_PARAM; 1287 } 1288 1289 vp = BCM_GPORT_VLAN_PORT_ID_GET(vlan_vp->vlan_port_id); 1290 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 1291 return BCM_E_NOT_FOUND; 1292 } 1293 1294 bcm_vlan_port_t_init(vlan_vp); 1295 1296 BCM_IF_ERROR_RETURN(_bcm_enduro_vlan_vp_match_get(unit, vp, vlan_vp)); 1297 1298 vlan_vp->flags = VLAN_VP_INFO(unit, vp)->flags; 1299 1300 BCM_IF_ERROR_RETURN 1301 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 1302 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, NEXT_HOP_INDEXf); 1303 vlan_vp->encap_id = nh_index; 1304 1305 BCM_GPORT_VLAN_PORT_ID_SET(vlan_vp->vlan_port_id, vp); 1306 1307 return BCM_E_NONE; 1308 } 1309 1310 /* 1311 * Function: 1312 * bcm_enduro_vlan_vp_find 1313 * Purpose: 1314 * Get VLAN virtual port info. 1315 * Parameters: 1316 * unit - (IN) SOC unit number. 1317 * vlan_vp - (IN/OUT) Pointer to VLAN virtual port structure. 1318 * Returns: 1319 * BCM_X_XXX 1320 */ 1321 int 1322 bcm_enduro_vlan_vp_find(int unit, bcm_vlan_port_t *vlan_vp) 1323 { 1324 VLAN_VIRTUAL_INIT(unit); 1325 return _bcm_enduro_vlan_vp_find(unit, vlan_vp); 1326 } 1327 1328 /* 1329 * Function: 1330 * _bcm_enduro_vlan_vp_is_local 1331 * Purpose: 1332 * Determine if VLAN VP resides on a local port. 1333 * Parameters: 1334 * unit - (IN) SOC unit number. 1335 * vp - (IN) Virtual port number. 1336 * vp_is_local - (OUT) Indicates if VLAN VP is local. 1337 * Returns: 1338 * BCM_X_XXX 1339 */ 1340 STATIC int 1341 _bcm_enduro_vlan_vp_is_local(int unit, int vp, int *vp_is_local) 1342 { 1343 bcm_gport_t gport; 1344 bcm_trunk_t trunk_id; 1345 int rv = BCM_E_NONE; 1346 bcm_module_t mod_out; 1347 bcm_port_t port_out; 1348 int id; 1349 int modid_local; 1350 int local_member_count; 1351 1352 *vp_is_local = 0; 1353 1354 if (vp < 0) { 1355 return BCM_E_PARAM; 1356 } 1357 1358 gport = VLAN_VP_INFO(unit, vp)->port; 1359 1360 if (BCM_GPORT_IS_TRUNK(gport)) { 1361 trunk_id = BCM_GPORT_TRUNK_GET(gport); 1362 rv = _bcm_trunk_id_validate(unit, trunk_id); 1363 if (BCM_FAILURE(rv)) { 1364 return (BCM_E_PORT); 1365 } 1366 rv = _bcm_esw_trunk_local_members_get(unit, trunk_id, 0, NULL, 1367 &local_member_count); 1368 if (BCM_FAILURE(rv)) { 1369 return (BCM_E_PORT); 1370 } 1371 1372 if (local_member_count > 0) { 1373 *vp_is_local = 1; 1374 } 1375 } else { 1376 BCM_IF_ERROR_RETURN 1377 (_bcm_esw_gport_resolve(unit, gport, &mod_out, &port_out, 1378 &trunk_id, &id)); 1379 1380 BCM_IF_ERROR_RETURN 1381 (_bcm_esw_modid_is_local(unit, mod_out, &modid_local)); 1382 1383 *vp_is_local = modid_local; 1384 } 1385 1386 return BCM_E_NONE; 1387 } 1388 1389 /* 1390 * Function: 1391 * _bcm_enduro_vlan_vp_untagged_add 1392 * Purpose: 1393 * Set VLAN VP tagging/untagging status by adding 1394 * a (VLAN VP, VLAN) egress VLAN translation entry. 1395 * Parameters: 1396 * unit - (IN) SOC unit number. 1397 * vlan - (IN) VLAN ID. 1398 * vp - (IN) Virtual port number. 1399 * flags - (IN) Untagging indication. 1400 * Returns: 1401 * BCM_X_XXX 1402 */ 1403 STATIC int 1404 _bcm_enduro_vlan_vp_untagged_add(int unit, bcm_vlan_t vlan, int vp, 1405 int flags) 1406 { 1407 egr_vlan_xlate_entry_t vent, old_vent; 1408 bcm_vlan_action_set_t action; 1409 uint32 profile_idx; 1410 int rv; 1411 1412 sal_memset(&vent, 0, sizeof(egr_vlan_xlate_entry_t)); 1413 1414 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, VALIDf, 1); 1415 1416 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, ENTRY_TYPEf, 1); 1417 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, DVPf, vp); 1418 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, OVIDf, vlan); 1419 1420 if (VLAN_VP_INFO(unit, vp)->flags & BCM_VLAN_PORT_EGRESS_VLAN16) { 1421 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, NEW_OTAG_VPTAG_SELf, 1); 1422 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, NEW_OTAG_VPTAGf, 1423 VLAN_VP_INFO(unit, vp)->match_vlan); 1424 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, NEW_IVIDf, 1425 VLAN_VP_INFO(unit, vp)->egress_vlan & 0xfff); 1426 } else { 1427 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, NEW_OTAG_VPTAG_SELf, 0); 1428 /* egress_vlan in vlan_vp structure is used as switching vlan */ 1429 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, NEW_OVIDf, 1430 VLAN_VP_INFO(unit, vp)->match_vlan & 0xfff); 1431 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, NEW_IVIDf, 1432 VLAN_VP_INFO(unit, vp)->egress_vlan & 0xfff); 1433 } 1434 1435 bcm_vlan_action_set_t_init(&action); 1436 1437 action.dt_outer = bcmVlanActionReplace; 1438 action.ot_outer = bcmVlanActionReplace; 1439 1440 if (flags & BCM_VLAN_PORT_UNTAGGED) { 1441 action.dt_inner = bcmVlanActionNone; 1442 action.ot_inner = bcmVlanActionNone; 1443 } else { 1444 action.dt_inner = bcmVlanActionReplace; 1445 action.ot_inner = bcmVlanActionAdd; 1446 } 1447 1448 BCM_IF_ERROR_RETURN 1449 (_bcm_trx_egr_vlan_action_profile_entry_add(unit, &action, &profile_idx)); 1450 1451 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, TAG_ACTION_PROFILE_PTRf, 1452 profile_idx); 1453 1454 rv = soc_mem_insert_return_old(unit, EGR_VLAN_XLATEm, MEM_BLOCK_ALL, 1455 &vent, &old_vent); 1456 if (rv == SOC_E_EXISTS) { 1457 /* Delete the old vlan translate profile entry */ 1458 profile_idx = soc_EGR_VLAN_XLATEm_field32_get(unit, &old_vent, 1459 TAG_ACTION_PROFILE_PTRf); 1460 rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, profile_idx); 1461 } 1462 1463 return rv; 1464 } 1465 1466 /* 1467 * Function: 1468 * _bcm_enduro_vlan_vp_untagged_delete 1469 * Purpose: 1470 * Delete (VLAN VP, VLAN) egress VLAN translation entry. 1471 * Parameters: 1472 * unit - (IN) SOC unit number. 1473 * vlan - (IN) VLAN ID. 1474 * vp - (IN) Virtual port number. 1475 * Returns: 1476 * BCM_X_XXX 1477 */ 1478 STATIC int 1479 _bcm_enduro_vlan_vp_untagged_delete(int unit, bcm_vlan_t vlan, int vp) 1480 { 1481 egr_vlan_xlate_entry_t vent, old_vent; 1482 uint32 profile_idx; 1483 int rv; 1484 1485 sal_memset(&vent, 0, sizeof(egr_vlan_xlate_entry_t)); 1486 1487 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, ENTRY_TYPEf, 1); 1488 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, DVPf, vp); 1489 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, OVIDf, vlan); 1490 1491 rv = soc_mem_delete_return_old(unit, EGR_VLAN_XLATEm, MEM_BLOCK_ALL, 1492 &vent, &old_vent); 1493 if ((rv == SOC_E_NONE) && 1494 soc_EGR_VLAN_XLATEm_field32_get(unit, &old_vent, VALIDf)) { 1495 /* Delete the old vlan translate profile entry */ 1496 profile_idx = soc_EGR_VLAN_XLATEm_field32_get(unit, &old_vent, 1497 TAG_ACTION_PROFILE_PTRf); 1498 rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, profile_idx); 1499 } 1500 1501 return rv; 1502 } 1503 1504 /* 1505 * Function: 1506 * _bcm_enduro_vlan_vp_untagged_delete_all 1507 * Purpose: 1508 * Delete all (VLAN VP, VLAN) egress VLAN translation entries for a 1509 * given VLAN. 1510 * Parameters: 1511 * unit - (IN) SOC unit number. 1512 * vlan - (IN) VLAN ID. 1513 * array_size - (IN) Number of elements in the virtual port array. 1514 * gport_array - (IN) Array of VLAN VP GPORT IDs. 1515 * Returns: 1516 * BCM_X_XXX 1517 */ 1518 STATIC int 1519 _bcm_enduro_vlan_vp_untagged_delete_all(int unit, bcm_vlan_t vlan, 1520 int array_size, bcm_gport_t *gport_array) 1521 { 1522 int i; 1523 egr_vlan_xlate_entry_t vent, old_vent; 1524 int vp; 1525 uint32 profile_idx; 1526 int rv = BCM_E_NONE; 1527 1528 for (i = 0; i < array_size; i++) { 1529 1530 sal_memset(&vent, 0, sizeof(egr_vlan_xlate_entry_t)); 1531 1532 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, ENTRY_TYPEf, 1); 1533 vp = BCM_GPORT_VLAN_PORT_ID_GET(gport_array[i]); 1534 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, DVPf, vp); 1535 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, OVIDf, vlan); 1536 1537 rv = soc_mem_delete_return_old(unit, EGR_VLAN_XLATEm, MEM_BLOCK_ALL, 1538 &vent, &old_vent); 1539 BCM_IF_ERROR_RETURN(rv); 1540 1541 if (soc_EGR_VLAN_XLATEm_field32_get(unit, &old_vent, VALIDf)) { 1542 /* Delete the old vlan translate profile entry */ 1543 profile_idx = soc_EGR_VLAN_XLATEm_field32_get(unit, &old_vent, 1544 TAG_ACTION_PROFILE_PTRf); 1545 rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, profile_idx); 1546 } 1547 } 1548 1549 return rv; 1550 } 1551 1552 /* 1553 * Function: 1554 * _bcm_enduro_vlan_vp_untagged_get 1555 * Purpose: 1556 * Get tagging/untagging status of a VLAN virtual port by 1557 * reading the (VLAN VP, VLAN) egress vlan translation entry. 1558 * Parameters: 1559 * unit - (IN) SOC unit number. 1560 * vlan - (IN) VLAN to remove virtual port from. 1561 * vp - (IN) Virtual port number. 1562 * flags - (OUT) Untagging status of the VLAN virtual port. 1563 * Returns: 1564 * BCM_E_XXX 1565 */ 1566 STATIC int 1567 _bcm_enduro_vlan_vp_untagged_get(int unit, bcm_vlan_t vlan, int vp, 1568 int *flags) 1569 { 1570 egr_vlan_xlate_entry_t vent, res_vent; 1571 int idx; 1572 uint32 profile_idx; 1573 int rv; 1574 bcm_vlan_action_set_t action; 1575 1576 sal_memset(&vent, 0, sizeof(egr_vlan_xlate_entry_t)); 1577 1578 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, ENTRY_TYPEf, 1); 1579 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, DVPf, vp); 1580 soc_EGR_VLAN_XLATEm_field32_set(unit, &vent, OVIDf, vlan); 1581 1582 rv = soc_mem_search(unit, EGR_VLAN_XLATEm, MEM_BLOCK_ALL, &idx, 1583 &vent, &res_vent, 0); 1584 if ((rv == SOC_E_NONE) && 1585 soc_EGR_VLAN_XLATEm_field32_get(unit, &res_vent, VALIDf)) { 1586 profile_idx = soc_EGR_VLAN_XLATEm_field32_get(unit, &res_vent, 1587 TAG_ACTION_PROFILE_PTRf); 1588 _bcm_trx_egr_vlan_action_profile_entry_get(unit, &action, profile_idx); 1589 1590 if (bcmVlanActionNone == action.ot_inner) { 1591 *flags = BCM_VLAN_PORT_UNTAGGED; 1592 } else { 1593 *flags = 0; 1594 } 1595 } 1596 1597 return rv; 1598 } 1599 1600 /* 1601 * Function: 1602 * bcm_enduro_vlan_vp_update_vlan_pbmp 1603 * Purpose: 1604 * Update VLAN table's port bitmap. 1605 * Parameters: 1606 * unit - (IN) SOC unit number. 1607 * vlan - (IN) VLAN ID. 1608 * pbmp - (IN) VLAN port bitmap. 1609 * Returns: 1610 * BCM_E_XXX 1611 */ 1612 int 1613 bcm_enduro_vlan_vp_update_vlan_pbmp(int unit, bcm_vlan_t vlan, 1614 bcm_pbmp_t *pbmp) 1615 { 1616 int rv = BCM_E_NONE; 1617 vlan_tab_entry_t vtab; 1618 egr_vlan_entry_t egr_vtab; 1619 1620 soc_mem_lock(unit, VLAN_TABm); 1621 1622 rv = soc_mem_read(unit, VLAN_TABm, MEM_BLOCK_ANY, vlan, &vtab); 1623 if (rv < 0) { 1624 soc_mem_unlock(unit, VLAN_TABm); 1625 return rv; 1626 } 1627 1628 soc_mem_pbmp_field_set(unit, VLAN_TABm, &vtab, PORT_BITMAPf, pbmp); 1629 rv = soc_mem_write(unit, VLAN_TABm, MEM_BLOCK_ALL, vlan, &vtab); 1630 if (rv < 0) { 1631 soc_mem_unlock(unit, VLAN_TABm); 1632 return rv; 1633 } 1634 1635 soc_mem_unlock(unit, VLAN_TABm); 1636 1637 soc_mem_lock(unit, EGR_VLANm); 1638 1639 rv = soc_mem_read(unit, EGR_VLANm, MEM_BLOCK_ANY, vlan, &egr_vtab); 1640 if (rv < 0) { 1641 soc_mem_unlock(unit, EGR_VLANm); 1642 return rv; 1643 } 1644 1645 soc_mem_pbmp_field_set(unit, EGR_VLANm, &egr_vtab, PORT_BITMAPf, pbmp); 1646 rv = soc_mem_write(unit, EGR_VLANm, MEM_BLOCK_ALL, vlan, &egr_vtab); 1647 if (rv < 0) { 1648 soc_mem_unlock(unit, EGR_VLANm); 1649 return rv; 1650 } 1651 1652 soc_mem_unlock(unit, EGR_VLANm); 1653 1654 return rv; 1655 } 1656 1657 /* 1658 * Function: 1659 * bcm_enduro_vlan_vp_add 1660 * Purpose: 1661 * Add a VLAN virtual port to the specified vlan. 1662 * Parameters: 1663 * unit - (IN) SOC unit number. 1664 * vlan - (IN) VLAN ID to add virtual port to as a member. 1665 * gport - (IN) VLAN VP Gport ID 1666 * flags - (IN) Indicates if packet should egress out of the given 1667 * VLAN virtual port untagged. 1668 * Returns: 1669 * BCM_E_XXX 1670 */ 1671 int 1672 bcm_enduro_vlan_vp_add(int unit, bcm_vlan_t vlan, bcm_gport_t gport, 1673 int flags) 1674 { 1675 int rv = BCM_E_NONE; 1676 int vp; 1677 int vp_is_local; 1678 vlan_tab_entry_t vtab; 1679 bcm_pbmp_t vlan_pbmp, vlan_ubmp, l2_pbmp, l3_pbmp, l2_l3_pbmp; 1680 int i, mc_idx; 1681 bcm_vlan_port_t vlan_vp; 1682 bcm_module_t mod_out; 1683 bcm_port_t port_out; 1684 bcm_trunk_t trunk_id; 1685 int id; 1686 int mod_local; 1687 bcm_gport_t local_gport; 1688 bcm_if_t encap_id; 1689 bcm_multicast_t group; 1690 int bc_idx, umc_idx, uuc_idx; 1691 soc_field_t group_type[3] = {BC_IDXf, UMC_IDXf, UUC_IDXf}; 1692 int bc_do_not_add = 0, umc_do_not_add = 0, uuc_do_not_add = 0; 1693 1694 VLAN_VIRTUAL_INIT(unit); 1695 1696 vp = BCM_GPORT_VLAN_PORT_ID_GET(gport); 1697 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 1698 return BCM_E_NOT_FOUND; 1699 } 1700 1701 BCM_IF_ERROR_RETURN 1702 (_bcm_enduro_vlan_vp_is_local(unit, vp, &vp_is_local)); 1703 if (!vp_is_local) { 1704 return BCM_E_PORT; 1705 } 1706 1707 if (flags & ~(BCM_VLAN_PORT_UNTAGGED | 1708 BCM_VLAN_GPORT_ADD_UNKNOWN_UCAST_DO_NOT_ADD | 1709 BCM_VLAN_GPORT_ADD_UNKNOWN_MCAST_DO_NOT_ADD | 1710 BCM_VLAN_GPORT_ADD_BCAST_DO_NOT_ADD)) { 1711 return BCM_E_PARAM; 1712 } 1713 1714 sal_memset(&vtab, 0, sizeof(vlan_tab_entry_t)); 1715 1716 soc_mem_lock(unit, VLAN_TABm); 1717 1718 rv = soc_mem_read(unit, VLAN_TABm, MEM_BLOCK_ANY, vlan, &vtab); 1719 if (rv < 0) { 1720 soc_mem_unlock(unit, VLAN_TABm); 1721 return rv; 1722 } 1723 1724 if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VALIDf)) { 1725 soc_mem_unlock(unit, VLAN_TABm); 1726 return BCM_E_NOT_FOUND; 1727 } 1728 1729 /* Enable VP switching on the VLAN */ 1730 if (!SHR_BITGET(vlan_info[unit].vp_mode, vlan) && 1731 SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) { 1732 if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VIRTUAL_PORT_ENf)) { 1733 soc_mem_field32_set(unit, VLAN_TABm, &vtab, VIRTUAL_PORT_ENf, 1); 1734 rv = soc_mem_write(unit, VLAN_TABm, MEM_BLOCK_ALL, vlan, &vtab); 1735 if (rv < 0) { 1736 soc_mem_unlock(unit, VLAN_TABm); 1737 return rv; 1738 } 1739 soc_mem_unlock(unit, VLAN_TABm); 1740 1741 /* Also need to copy the physical port members to the L2_BITMAP of 1742 * the IPMC entry for each group once we've gone virtual */ 1743 rv = mbcm_driver[unit]->mbcm_vlan_port_get 1744 (unit, vlan, &vlan_pbmp, &vlan_ubmp, NULL); 1745 if (rv < 0) { 1746 return rv; 1747 } 1748 1749 /* Deal with each group */ 1750 for (i = 0; i < 3; i++) { 1751 mc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, group_type[i]); 1752 rv = _bcm_esw_multicast_ipmc_read(unit, mc_idx, &l2_pbmp, &l3_pbmp); 1753 if (rv < 0) { 1754 return rv; 1755 } 1756 rv = _bcm_esw_multicast_ipmc_write(unit, mc_idx, vlan_pbmp, 1757 l3_pbmp, TRUE); 1758 if (rv < 0) { 1759 return rv; 1760 } 1761 } 1762 } 1763 } else { 1764 soc_mem_unlock(unit, VLAN_TABm); 1765 } 1766 1767 bc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, BC_IDXf); 1768 umc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, UMC_IDXf); 1769 uuc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, UUC_IDXf); 1770 1771 if (flags & BCM_VLAN_GPORT_ADD_BCAST_DO_NOT_ADD) { 1772 bc_do_not_add = 1; 1773 } else { 1774 bc_do_not_add = 0; 1775 } 1776 if (flags & BCM_VLAN_GPORT_ADD_UNKNOWN_MCAST_DO_NOT_ADD) { 1777 umc_do_not_add = 1; 1778 } else { 1779 umc_do_not_add = 0; 1780 } 1781 if (flags & BCM_VLAN_GPORT_ADD_UNKNOWN_UCAST_DO_NOT_ADD) { 1782 uuc_do_not_add = 1; 1783 } else { 1784 uuc_do_not_add = 0; 1785 } 1786 1787 if ((bc_idx == umc_idx) && (bc_do_not_add != umc_do_not_add)) { 1788 return BCM_E_PARAM; 1789 } 1790 if ((bc_idx == uuc_idx) && (bc_do_not_add != uuc_do_not_add)) { 1791 return BCM_E_PARAM; 1792 } 1793 if ((umc_idx == uuc_idx) && (umc_do_not_add != uuc_do_not_add)) { 1794 return BCM_E_PARAM; 1795 } 1796 1797 /* Get the VP attributes (need physical port) */ 1798 bcm_vlan_port_t_init(&vlan_vp); 1799 vlan_vp.vlan_port_id = gport; 1800 rv = _bcm_enduro_vlan_vp_find(unit, &vlan_vp); 1801 if (rv < 0) { 1802 return rv; 1803 } 1804 1805 /* Check if vlan_vp.port is a local port or trunk */ 1806 if (BCM_GPORT_IS_TRUNK(vlan_vp.port)) { 1807 trunk_id = BCM_GPORT_TRUNK_GET(vlan_vp.port); 1808 rv = _bcm_trunk_id_validate(unit, trunk_id); 1809 if (BCM_FAILURE(rv)) { 1810 return BCM_E_PORT; 1811 } 1812 local_gport = vlan_vp.port; 1813 } else { 1814 rv = _bcm_esw_gport_resolve(unit, vlan_vp.port, &mod_out, &port_out, 1815 &trunk_id, &id); 1816 if (BCM_FAILURE(rv)) { 1817 return (BCM_E_PORT); 1818 } 1819 rv = _bcm_esw_modid_is_local(unit, mod_out, &mod_local); 1820 if (BCM_FAILURE(rv)) { 1821 return rv; 1822 } 1823 if (TRUE != mod_local) { 1824 /* Only add this to replication set if destination is local */ 1825 return BCM_E_PORT; 1826 } 1827 /* Convert system local_port to physical local_port */ 1828 if (soc_feature(unit, soc_feature_sysport_remap)) { 1829 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 1830 } 1831 rv = bcm_esw_port_gport_get(unit, port_out, &local_gport); 1832 if (BCM_FAILURE(rv)) { 1833 return rv; 1834 } 1835 } 1836 1837 /* Add the VP to the BC group */ 1838 if (!bc_do_not_add) { 1839 _BCM_MULTICAST_GROUP_SET(group, _BCM_MULTICAST_TYPE_VLAN, bc_idx); 1840 rv = bcm_esw_multicast_vlan_encap_get(unit, group, local_gport, 1841 gport, &encap_id); 1842 if (BCM_FAILURE(rv)) { 1843 return rv; 1844 } 1845 rv = bcm_esw_multicast_egress_add(unit, group, local_gport, encap_id); 1846 if (rv < 0) { 1847 return rv; 1848 } 1849 1850 } 1851 1852 /* Add the VP to the UMC group, if UMC group is different from BC group */ 1853 if (!umc_do_not_add) { 1854 if (umc_idx != bc_idx) { 1855 _BCM_MULTICAST_GROUP_SET(group, _BCM_MULTICAST_TYPE_VLAN, umc_idx); 1856 rv = bcm_esw_multicast_vlan_encap_get(unit, group, local_gport, 1857 gport, &encap_id); 1858 if (BCM_FAILURE(rv)) { 1859 return rv; 1860 } 1861 rv = bcm_esw_multicast_egress_add(unit, group, local_gport, encap_id); 1862 if (rv < 0) { 1863 return rv; 1864 } 1865 } 1866 } 1867 1868 /* Add the VP to the UUC group, if UUC group is different from BC/UMC group */ 1869 if (!uuc_do_not_add) { 1870 if ((uuc_idx != bc_idx) && (uuc_idx != umc_idx)) { 1871 _BCM_MULTICAST_GROUP_SET(group, _BCM_MULTICAST_TYPE_VLAN, uuc_idx); 1872 rv = bcm_esw_multicast_vlan_encap_get(unit, group, local_gport, 1873 gport, &encap_id); 1874 if (BCM_FAILURE(rv)) { 1875 return rv; 1876 } 1877 rv = bcm_esw_multicast_egress_add(unit, group, local_gport, encap_id); 1878 if (rv < 0) { 1879 return rv; 1880 } 1881 } 1882 } 1883 1884 /* Update the VLAN table's port bitmap to contain the BC/UMC/UUC groups' 1885 * L2 and L3 bitmaps, since the VLAN table's port bitmap is used for 1886 * ingress and egress VLAN membership checks. 1887 */ 1888 1889 BCM_PBMP_CLEAR(l2_l3_pbmp); 1890 for (i = 0; i < 3; i++) { 1891 mc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, group_type[i]); 1892 rv = _bcm_esw_multicast_ipmc_read(unit, mc_idx, &l2_pbmp, &l3_pbmp); 1893 if (rv < 0) { 1894 return rv; 1895 } 1896 BCM_PBMP_OR(l2_l3_pbmp, l2_pbmp); 1897 BCM_PBMP_OR(l2_l3_pbmp, l3_pbmp); 1898 } 1899 1900 rv = bcm_enduro_vlan_vp_update_vlan_pbmp(unit, vlan, &l2_l3_pbmp); 1901 if (rv < 0) { 1902 return rv; 1903 } 1904 1905 VLAN_VIRTUAL_LOCK(unit); 1906 rv = _bcm_enduro_vlan_vp_untagged_add(unit, vlan, vp, flags); 1907 VLAN_VIRTUAL_UNLOCK(unit); 1908 1909 return rv; 1910 } 1911 1912 /* 1913 * Function: 1914 * bcm_enduro_vlan_vp_delete 1915 * Purpose: 1916 * Remove a VLAN virtual port from the specified vlan. 1917 * Parameters: 1918 * unit - (IN) SOC unit number. 1919 * vlan - (IN) VLAN to remove virtual port from. 1920 * gport - (IN) VLAN VP Gport ID 1921 * Returns: 1922 * BCM_E_XXX 1923 */ 1924 int 1925 bcm_enduro_vlan_vp_delete(int unit, bcm_vlan_t vlan, bcm_gport_t gport) 1926 { 1927 int rv = BCM_E_NONE; 1928 int vp; 1929 int vp_is_local; 1930 vlan_tab_entry_t vtab; 1931 bcm_vlan_port_t vlan_vp; 1932 bcm_module_t mod_out; 1933 bcm_port_t port_out; 1934 bcm_trunk_t trunk_id; 1935 int id; 1936 int mod_local; 1937 bcm_gport_t local_gport; 1938 int bc_idx, umc_idx, uuc_idx; 1939 bcm_multicast_t group; 1940 bcm_if_t encap_id; 1941 int i, mc_idx; 1942 soc_field_t group_type[3] = {BC_IDXf, UMC_IDXf, UUC_IDXf}; 1943 bcm_pbmp_t l2_pbmp, l3_pbmp, l2_l3_pbmp; 1944 1945 VLAN_VIRTUAL_INIT(unit); 1946 1947 vp = BCM_GPORT_VLAN_PORT_ID_GET(gport); 1948 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 1949 return BCM_E_NOT_FOUND; 1950 } 1951 1952 BCM_IF_ERROR_RETURN 1953 (_bcm_enduro_vlan_vp_is_local(unit, vp, &vp_is_local)); 1954 if (!vp_is_local) { 1955 return BCM_E_PORT; 1956 } 1957 1958 sal_memset(&vtab, 0, sizeof(vlan_tab_entry_t)); 1959 1960 rv = soc_mem_read(unit, VLAN_TABm, MEM_BLOCK_ANY, vlan, &vtab); 1961 if (rv < 0) { 1962 return rv; 1963 } 1964 1965 if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VALIDf)) { 1966 return BCM_E_NOT_FOUND; 1967 } 1968 1969 if (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) { 1970 if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VIRTUAL_PORT_ENf)) { 1971 /* VP switching is not enabled on the VLAN */ 1972 return BCM_E_PORT; 1973 } 1974 } 1975 1976 /* Get the VP attributes (need physical port) */ 1977 bcm_vlan_port_t_init(&vlan_vp); 1978 vlan_vp.vlan_port_id = gport; 1979 rv = _bcm_enduro_vlan_vp_find(unit, &vlan_vp); 1980 if (rv < 0) { 1981 return rv; 1982 } 1983 1984 /* Check if vlan_vp.port is a local port or trunk */ 1985 if (BCM_GPORT_IS_TRUNK(vlan_vp.port)) { 1986 trunk_id = BCM_GPORT_TRUNK_GET(vlan_vp.port); 1987 rv = _bcm_trunk_id_validate(unit, trunk_id); 1988 if (BCM_FAILURE(rv)) { 1989 return BCM_E_PORT; 1990 } 1991 local_gport = vlan_vp.port; 1992 } else { 1993 rv = _bcm_esw_gport_resolve(unit, vlan_vp.port, &mod_out, &port_out, 1994 &trunk_id, &id); 1995 if (BCM_FAILURE(rv)) { 1996 return (BCM_E_PORT); 1997 } 1998 rv = _bcm_esw_modid_is_local(unit, mod_out, &mod_local); 1999 if (BCM_FAILURE(rv)) { 2000 return rv; 2001 } 2002 if (TRUE != mod_local) { 2003 /* Only add this to replication set if destination is local */ 2004 return BCM_E_PORT; 2005 } 2006 /* Convert system local_port to physical local_port */ 2007 if (soc_feature(unit, soc_feature_sysport_remap)) { 2008 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 2009 } 2010 rv = bcm_esw_port_gport_get(unit, port_out, &local_gport); 2011 if (BCM_FAILURE(rv)) { 2012 return rv; 2013 } 2014 } 2015 2016 /* Delete the VP from the BC group */ 2017 bc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, BC_IDXf); 2018 _BCM_MULTICAST_GROUP_SET(group, _BCM_MULTICAST_TYPE_VLAN, bc_idx); 2019 rv = bcm_esw_multicast_vlan_encap_get(unit, group, local_gport, 2020 gport, &encap_id); 2021 if (BCM_FAILURE(rv)) { 2022 return rv; 2023 } 2024 rv = bcm_esw_multicast_egress_delete(unit, group, local_gport, encap_id); 2025 if (rv < 0) { 2026 return rv; 2027 } 2028 2029 /* Delete the VP from the UMC group, if UMC group is different 2030 * from BC group. 2031 */ 2032 umc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, UMC_IDXf); 2033 if (umc_idx != bc_idx) { 2034 _BCM_MULTICAST_GROUP_SET(group, _BCM_MULTICAST_TYPE_VLAN, umc_idx); 2035 rv = bcm_esw_multicast_vlan_encap_get(unit, group, local_gport, 2036 gport, &encap_id); 2037 if (BCM_FAILURE(rv)) { 2038 return rv; 2039 } 2040 rv = bcm_esw_multicast_egress_delete(unit, group, local_gport, encap_id); 2041 if (rv < 0) { 2042 return rv; 2043 } 2044 } 2045 2046 /* Delete the VP from the UUC group, if UUC group is different 2047 * from BC and UMC groups. 2048 */ 2049 uuc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, UUC_IDXf); 2050 if ((uuc_idx != bc_idx) && (uuc_idx != umc_idx)) { 2051 _BCM_MULTICAST_GROUP_SET(group, _BCM_MULTICAST_TYPE_VLAN, uuc_idx); 2052 rv = bcm_esw_multicast_vlan_encap_get(unit, group, local_gport, 2053 gport, &encap_id); 2054 if (BCM_FAILURE(rv)) { 2055 return rv; 2056 } 2057 rv = bcm_esw_multicast_egress_delete(unit, group, local_gport, encap_id); 2058 if (rv < 0) { 2059 return rv; 2060 } 2061 } 2062 2063 /* Update the VLAN table's port bitmap to contain the BC/UMC/UUC groups' 2064 * L2 and L3 bitmaps, since the VLAN table's port bitmap is used for 2065 * ingress and egress VLAN membership checks. 2066 */ 2067 2068 BCM_PBMP_CLEAR(l2_l3_pbmp); 2069 for (i = 0; i < 3; i++) { 2070 mc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, group_type[i]); 2071 rv = _bcm_esw_multicast_ipmc_read(unit, mc_idx, &l2_pbmp, &l3_pbmp); 2072 if (rv < 0) { 2073 return rv; 2074 } 2075 BCM_PBMP_OR(l2_l3_pbmp, l2_pbmp); 2076 BCM_PBMP_OR(l2_l3_pbmp, l3_pbmp); 2077 } 2078 2079 rv = bcm_enduro_vlan_vp_update_vlan_pbmp(unit, vlan, &l2_l3_pbmp); 2080 if (rv < 0) { 2081 return rv; 2082 } 2083 2084 VLAN_VIRTUAL_LOCK(unit); 2085 rv = _bcm_enduro_vlan_vp_untagged_delete(unit, vlan, vp); 2086 VLAN_VIRTUAL_UNLOCK(unit); 2087 2088 return rv; 2089 } 2090 2091 STATIC int 2092 _bcm_enduro_vlan_mc_group_gport_is_member(int unit, bcm_multicast_t group, 2093 bcm_gport_t gport, bcm_gport_t vp, int *is_member) 2094 { 2095 int rv = BCM_E_NONE; 2096 bcm_if_t encap_id; 2097 int if_max; 2098 bcm_if_t *if_array; 2099 int if_count, if_cur; 2100 int mc_idx; 2101 2102 if (NULL == is_member) { 2103 return BCM_E_PARAM; 2104 } 2105 *is_member = FALSE; 2106 2107 /* Get VP's multicast encap id */ 2108 if (BCM_GPORT_IS_VLAN_PORT(gport)) { 2109 BCM_IF_ERROR_RETURN(bcm_esw_multicast_vlan_encap_get(unit, group, 2110 vp, gport, &encap_id)); 2111 } else { 2112 return BCM_E_PARAM; 2113 } 2114 2115 /* Find out if VP is a member of the multicast group */ 2116 if_max = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 2117 if_array = sal_alloc(if_max * sizeof(bcm_if_t), 2118 "temp repl interface array"); 2119 if (if_array == NULL) { 2120 return BCM_E_MEMORY; 2121 } 2122 2123 mc_idx = _BCM_MULTICAST_ID_GET(group); 2124 { 2125 rv = bcm_esw_ipmc_egress_intf_get(unit, mc_idx, 2126 vp, if_max, if_array, &if_count); 2127 if (BCM_FAILURE(rv)) { 2128 sal_free(if_array); 2129 return rv; 2130 } 2131 for (if_cur = 0; if_cur < if_count; if_cur++) { 2132 if (if_array[if_cur] == encap_id) { 2133 *is_member = TRUE; 2134 sal_free(if_array); 2135 return BCM_E_NONE; 2136 } 2137 } 2138 } 2139 2140 sal_free(if_array); 2141 return BCM_E_NONE; 2142 } 2143 2144 2145 /* 2146 * Function: 2147 * bcm_enduro_vlan_vp_get 2148 * Purpose: 2149 * Get untagging status of a VLAN virtual port. 2150 * Parameters: 2151 * unit - (IN) SOC unit number. 2152 * vlan - (IN) VLAN to remove virtual port from. 2153 * gport - (IN) VLAN VP Gport ID 2154 * flags - (OUT) Untagging status of the VLAN virtual port. 2155 * Returns: 2156 * BCM_E_XXX 2157 */ 2158 int 2159 bcm_enduro_vlan_vp_get(int unit, bcm_vlan_t vlan, bcm_gport_t gport, 2160 int *flags) 2161 { 2162 int rv = BCM_E_NONE; 2163 int vp; 2164 bcm_vlan_port_t vlan_vp; 2165 bcm_gport_t phy_port_trunk = BCM_GPORT_INVALID; 2166 int vp_is_local; 2167 vlan_tab_entry_t vtab; 2168 int bc_idx, umc_idx, uuc_idx; 2169 bcm_multicast_t group; 2170 int is_bc_member = FALSE; 2171 int is_umc_member = FALSE; 2172 int is_uuc_member = FALSE; 2173 int untagged_flag = 0; 2174 2175 VLAN_VIRTUAL_INIT(unit); 2176 2177 vp = BCM_GPORT_VLAN_PORT_ID_GET(gport); 2178 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 2179 return BCM_E_NOT_FOUND; 2180 } 2181 2182 /* Get the physical port or trunk the VP resides on */ 2183 bcm_vlan_port_t_init(&vlan_vp); 2184 vlan_vp.vlan_port_id = gport; 2185 BCM_IF_ERROR_RETURN(bcm_enduro_vlan_vp_find(unit, &vlan_vp)); 2186 phy_port_trunk = vlan_vp.port; 2187 BCM_IF_ERROR_RETURN 2188 (_bcm_enduro_vlan_vp_is_local(unit, vp, &vp_is_local)); 2189 if (!vp_is_local) { 2190 return BCM_E_PORT; 2191 } 2192 2193 *flags = 0; 2194 2195 sal_memset(&vtab, 0, sizeof(vlan_tab_entry_t)); 2196 SOC_IF_ERROR_RETURN 2197 (soc_mem_read(unit, VLAN_TABm, MEM_BLOCK_ANY, vlan, &vtab)); 2198 if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VALIDf)) { 2199 return BCM_E_NOT_FOUND; 2200 } 2201 2202 if (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) { 2203 if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VIRTUAL_PORT_ENf)) { 2204 /* No virtual port exists for this VLAN */ 2205 return BCM_E_NOT_FOUND; 2206 } 2207 } 2208 2209 if (phy_port_trunk != BCM_GPORT_INVALID) { 2210 2211 bc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, BC_IDXf); 2212 _BCM_MULTICAST_GROUP_SET(group, _BCM_MULTICAST_TYPE_VLAN, bc_idx); 2213 BCM_IF_ERROR_RETURN(_bcm_enduro_vlan_mc_group_gport_is_member(unit, group, 2214 gport, phy_port_trunk, &is_bc_member)); 2215 2216 umc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, UMC_IDXf); 2217 if (umc_idx != bc_idx) { 2218 BCM_IF_ERROR_RETURN(_bcm_tr_multicast_ipmc_group_type_get(unit, umc_idx, 2219 &group)); 2220 BCM_IF_ERROR_RETURN(_bcm_enduro_vlan_mc_group_gport_is_member(unit, group, 2221 gport, phy_port_trunk, &is_umc_member)); 2222 } else { 2223 is_umc_member = is_bc_member; 2224 } 2225 2226 uuc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, UUC_IDXf); 2227 if (uuc_idx != bc_idx && uuc_idx != umc_idx) { 2228 BCM_IF_ERROR_RETURN(_bcm_tr_multicast_ipmc_group_type_get(unit, uuc_idx, 2229 &group)); 2230 BCM_IF_ERROR_RETURN(_bcm_enduro_vlan_mc_group_gport_is_member(unit, group, 2231 gport, phy_port_trunk, &is_uuc_member)); 2232 } else if (uuc_idx == bc_idx) { 2233 is_uuc_member = is_bc_member; 2234 } else { 2235 is_uuc_member = is_umc_member; 2236 } 2237 2238 } 2239 if (!is_bc_member) { 2240 *flags |= BCM_VLAN_GPORT_ADD_BCAST_DO_NOT_ADD; 2241 } 2242 if (!is_umc_member) { 2243 *flags |= BCM_VLAN_GPORT_ADD_UNKNOWN_MCAST_DO_NOT_ADD; 2244 } 2245 if (!is_uuc_member) { 2246 *flags |= BCM_VLAN_GPORT_ADD_UNKNOWN_UCAST_DO_NOT_ADD; 2247 } 2248 2249 rv = _bcm_enduro_vlan_vp_untagged_get(unit, vlan, vp, &untagged_flag); 2250 2251 *flags |= untagged_flag; 2252 2253 return rv; 2254 2255 } 2256 2257 /* 2258 * Function: 2259 * _bcm_enduro_vlan_vp_mc_group_get_all 2260 * Purpose: 2261 * Get all the next hop indices of the given multicast group. 2262 * Parameters: 2263 * unit - (IN) SOC unit number. 2264 * mc_idx - (IN) Multicast group index. 2265 * nh_bitmap - (IN/OUT) Bitmap of next hop indices. 2266 * Returns: 2267 * BCM_E_XXX 2268 */ 2269 STATIC int 2270 _bcm_enduro_vlan_vp_mc_group_get_all(int unit, int mc_idx, 2271 SHR_BITDCL *nh_bitmap) 2272 { 2273 bcm_multicast_t mc_group; 2274 int rv; 2275 int num_encap_id; 2276 bcm_if_t *encap_id_array = NULL; 2277 int i; 2278 int nh_index; 2279 2280 _BCM_MULTICAST_GROUP_SET(mc_group, _BCM_MULTICAST_TYPE_VLAN, mc_idx); 2281 2282 /* Get the number of encap IDs of the multicast group */ 2283 rv = bcm_esw_multicast_egress_get(unit, mc_group, 0, 2284 NULL, NULL, &num_encap_id); 2285 if (rv < 0) { 2286 return rv; 2287 } 2288 2289 /* Get all the encap IDs of the multicast group */ 2290 2291 encap_id_array = sal_alloc(sizeof(bcm_if_t) * num_encap_id, 2292 "encap_id_array"); 2293 if (NULL == encap_id_array) { 2294 return BCM_E_MEMORY; 2295 } 2296 sal_memset(encap_id_array, 0, sizeof(bcm_if_t) * num_encap_id); 2297 2298 rv = bcm_esw_multicast_egress_get(unit, mc_group, num_encap_id, 2299 NULL, encap_id_array, &num_encap_id); 2300 if (rv < 0) { 2301 sal_free(encap_id_array); 2302 return rv; 2303 } 2304 2305 /* Convert encap IDs to next hop indices */ 2306 2307 for (i = 0; i < num_encap_id; i++) { 2308 if (BCM_IF_INVALID != (uint32)encap_id_array[i]) { 2309 nh_index = encap_id_array[i]; 2310 SHR_BITSET(nh_bitmap, nh_index); 2311 } 2312 } 2313 2314 sal_free(encap_id_array); 2315 return rv; 2316 } 2317 2318 /* 2319 * Function: 2320 * bcm_enduro_vlan_vp_get_all 2321 * Purpose: 2322 * Get virtual ports of the given VLAN. 2323 * Parameters: 2324 * unit - (IN) SOC unit number. 2325 * vlan - (IN) VLAN ID. 2326 * array_max - (IN) Max number of elements in the array. 2327 * gport_array - (OUT) Array of virtual ports in GPORT format. 2328 * flags_array - (OUT) Array of untagging status. 2329 * array_size - (OUT) Actual number of elements in the array. 2330 * Returns: 2331 * BCM_E_XXX 2332 * Notes: If array_max == 0 and gport_array == NULL, actual number of 2333 * virtual ports in the VLAN will be returned in array_size. 2334 */ 2335 int 2336 bcm_enduro_vlan_vp_get_all(int unit, bcm_vlan_t vlan, int array_max, 2337 bcm_gport_t *gport_array, int *flags_array, int *array_size) 2338 { 2339 vlan_tab_entry_t vtab; 2340 int nh_tbl_size; 2341 SHR_BITDCL *nh_bitmap = NULL; 2342 int bc_idx, umc_idx, uuc_idx; 2343 int rv; 2344 int i; 2345 egr_l3_next_hop_entry_t egr_nh; 2346 int dvp; 2347 2348 if (array_max < 0) { 2349 return BCM_E_PARAM; 2350 } 2351 2352 if ((array_max > 0) && (NULL == gport_array)) { 2353 return BCM_E_PARAM; 2354 } 2355 2356 if (NULL == array_size) { 2357 return BCM_E_PARAM; 2358 } 2359 2360 *array_size = 0; 2361 2362 VLAN_VIRTUAL_INIT(unit); 2363 2364 BCM_IF_ERROR_RETURN 2365 (soc_mem_read(unit, VLAN_TABm, MEM_BLOCK_ANY, (int)vlan, &vtab)); 2366 2367 if (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) { 2368 if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VIRTUAL_PORT_ENf)) { 2369 /* This vlan has no virtual port members. */ 2370 return BCM_E_NONE; 2371 } 2372 } 2373 2374 nh_tbl_size = soc_mem_index_count(unit, ING_L3_NEXT_HOPm); 2375 nh_bitmap = sal_alloc(SHR_BITALLOCSIZE(nh_tbl_size), "nh_bitmap"); 2376 if (NULL == nh_bitmap) { 2377 return BCM_E_MEMORY; 2378 } 2379 sal_memset(nh_bitmap, 0, SHR_BITALLOCSIZE(nh_tbl_size)); 2380 2381 /* Get VPs from BC group */ 2382 bc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, BC_IDXf); 2383 rv = _bcm_enduro_vlan_vp_mc_group_get_all(unit, bc_idx, nh_bitmap); 2384 if (rv < 0) { 2385 goto cleanup; 2386 } 2387 2388 /* Get VPs from UMC group, if different from BC group */ 2389 umc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, UMC_IDXf); 2390 if (umc_idx != bc_idx) { 2391 rv = _bcm_enduro_vlan_vp_mc_group_get_all(unit, umc_idx, nh_bitmap); 2392 if (rv < 0) { 2393 goto cleanup; 2394 } 2395 } 2396 2397 /* Get VPs from UUC group, if different from BC and UMC group */ 2398 uuc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, UUC_IDXf); 2399 if ((uuc_idx != bc_idx) && (uuc_idx != umc_idx)) { 2400 rv = _bcm_enduro_vlan_vp_mc_group_get_all(unit, uuc_idx, nh_bitmap); 2401 if (rv < 0) { 2402 goto cleanup; 2403 } 2404 } 2405 2406 /* Convert next hop indices to VLAN VP gports */ 2407 for (i = 0; i < nh_tbl_size; i++) { 2408 if (SHR_BITGET(nh_bitmap, i)) { 2409 if (0 == array_max) { 2410 (*array_size)++; 2411 } else { 2412 rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, i, &egr_nh); 2413 if (rv < 0) { 2414 goto cleanup; 2415 } 2416 dvp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, SD_TAG__DVPf); 2417 BCM_GPORT_VLAN_PORT_ID_SET(gport_array[*array_size], dvp); 2418 if (NULL != flags_array) { 2419 rv = _bcm_enduro_vlan_vp_untagged_get(unit, vlan, dvp, 2420 &flags_array[*array_size]); 2421 if (rv < 0) { 2422 goto cleanup; 2423 } 2424 } 2425 (*array_size)++; 2426 if (*array_size == array_max) { 2427 break; 2428 } 2429 } 2430 } 2431 } 2432 2433 cleanup: 2434 if (NULL != nh_bitmap) { 2435 sal_free(nh_bitmap); 2436 } 2437 2438 return rv; 2439 } 2440 2441 /* 2442 * Function: 2443 * bcm_enduro_vlan_vp_delete_all 2444 * Purpose: 2445 * Remove all VLAN virtual ports from the specified vlan. 2446 * Parameters: 2447 * unit - (IN) SOC unit number. 2448 * vlan - (IN) VLAN to remove virtual ports from. 2449 * Returns: 2450 * BCM_E_XXX 2451 */ 2452 int 2453 bcm_enduro_vlan_vp_delete_all(int unit, bcm_vlan_t vlan) 2454 { 2455 vlan_tab_entry_t vtab; 2456 int num_vp; 2457 bcm_gport_t *gport_array = NULL; 2458 int rv = BCM_E_NONE; 2459 int bc_idx, umc_idx, uuc_idx; 2460 bcm_multicast_t group; 2461 2462 VLAN_VIRTUAL_INIT(unit); 2463 2464 sal_memset(&vtab, 0, sizeof(vlan_tab_entry_t)); 2465 2466 BCM_IF_ERROR_RETURN 2467 (soc_mem_read(unit, VLAN_TABm, MEM_BLOCK_ANY, vlan, &vtab)); 2468 2469 if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VALIDf)) { 2470 return BCM_E_NOT_FOUND; 2471 } 2472 2473 if (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) { 2474 if (soc_mem_field32_get(unit, VLAN_TABm, &vtab, VIRTUAL_PORT_ENf)) { 2475 2476 /* Get all VPs from the VLAN before deletion */ 2477 2478 BCM_IF_ERROR_RETURN 2479 (bcm_enduro_vlan_vp_get_all(unit, vlan, 0, NULL, NULL, &num_vp)); 2480 2481 gport_array = sal_alloc(sizeof(bcm_gport_t) * num_vp, 2482 "vlan vp gport array"); 2483 if (NULL == gport_array) { 2484 return BCM_E_MEMORY; 2485 } 2486 sal_memset(gport_array, 0, sizeof(bcm_gport_t) * num_vp); 2487 2488 rv = bcm_enduro_vlan_vp_get_all(unit, vlan, num_vp, 2489 gport_array, NULL, &num_vp); 2490 if (rv < 0) { 2491 goto cleanup; 2492 } 2493 2494 /* Delete all VPs from the BC group */ 2495 2496 bc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, BC_IDXf); 2497 _BCM_MULTICAST_GROUP_SET(group, _BCM_MULTICAST_TYPE_VLAN, bc_idx); 2498 rv = bcm_esw_multicast_egress_delete_all(unit, group); 2499 if (rv < 0) { 2500 goto cleanup; 2501 } 2502 rv = bcm_esw_multicast_destroy(unit, group); 2503 if (rv < 0) { 2504 goto cleanup; 2505 } 2506 2507 /* Delete all VPs from the UMC group, if UMC group is different 2508 * from BC group. 2509 */ 2510 2511 umc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, UMC_IDXf); 2512 if (umc_idx != bc_idx) { 2513 _BCM_MULTICAST_GROUP_SET(group, _BCM_MULTICAST_TYPE_VLAN, umc_idx); 2514 rv = bcm_esw_multicast_egress_delete_all(unit, group); 2515 if (rv < 0) { 2516 goto cleanup; 2517 } 2518 rv = bcm_esw_multicast_destroy(unit, group); 2519 if (rv < 0) { 2520 goto cleanup; 2521 } 2522 } 2523 2524 /* Delete all VPs from the UUC group, if UUC group is different 2525 * from BC and UMC groups. 2526 */ 2527 uuc_idx = soc_mem_field32_get(unit, VLAN_TABm, &vtab, UUC_IDXf); 2528 if ((uuc_idx != bc_idx) && (uuc_idx != umc_idx)) { 2529 _BCM_MULTICAST_GROUP_SET(group, _BCM_MULTICAST_TYPE_VLAN, uuc_idx); 2530 rv = bcm_esw_multicast_egress_delete_all(unit, group); 2531 if (rv < 0) { 2532 goto cleanup; 2533 } 2534 rv = bcm_esw_multicast_destroy(unit, group); 2535 if (rv < 0) { 2536 goto cleanup; 2537 } 2538 } 2539 2540 if (!SHR_BITGET(vlan_info[unit].vp_mode, vlan) && 2541 SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) { 2542 soc_mem_field32_set(unit, VLAN_TABm, &vtab, VIRTUAL_PORT_ENf, 0); 2543 } 2544 soc_mem_field32_set(unit, VLAN_TABm, &vtab, BC_IDXf, 0); 2545 soc_mem_field32_set(unit, VLAN_TABm, &vtab, UMC_IDXf, 0); 2546 soc_mem_field32_set(unit, VLAN_TABm, &vtab, UUC_IDXf, 0); 2547 rv = soc_mem_write(unit, VLAN_TABm, MEM_BLOCK_ALL, (int)vlan, &vtab); 2548 if (rv < 0) { 2549 goto cleanup; 2550 } 2551 2552 /* Delete all DVP tagging/untagging entries */ 2553 VLAN_VIRTUAL_LOCK(unit); 2554 rv = _bcm_enduro_vlan_vp_untagged_delete_all(unit, vlan, 2555 num_vp, gport_array); 2556 VLAN_VIRTUAL_UNLOCK(unit); 2557 if (rv < 0) { 2558 goto cleanup; 2559 } 2560 } 2561 } 2562 2563 cleanup: 2564 if (NULL != gport_array) { 2565 sal_free(gport_array); 2566 } 2567 return rv; 2568 } 2569 2570 /* 2571 * Function: 2572 * _bcm_enduro_vlan_port_resolve 2573 * Purpose: 2574 * Get the modid, port, trunk values for a VLAN virtual port 2575 * Parameters: 2576 * unit - (IN) BCM device number 2577 * gport - (IN) Global port identifier 2578 * modid - (OUT) Module ID 2579 * port - (OUT) Port number 2580 * trunk_id - (OUT) Trunk ID 2581 * id - (OUT) Virtual port ID 2582 * Returns: 2583 * BCM_E_XXX 2584 */ 2585 int 2586 _bcm_enduro_vlan_port_resolve(int unit, bcm_gport_t vlan_port_id, 2587 bcm_module_t *modid, bcm_port_t *port, 2588 bcm_trunk_t *trunk_id, int *id) 2589 2590 { 2591 int rv = BCM_E_NONE, nh_index, vp; 2592 ing_l3_next_hop_entry_t ing_nh; 2593 ing_dvp_table_entry_t dvp; 2594 2595 VLAN_VIRTUAL_INIT(unit); 2596 2597 if (!BCM_GPORT_IS_VLAN_PORT(vlan_port_id)) { 2598 return (BCM_E_BADID); 2599 } 2600 2601 vp = BCM_GPORT_VLAN_PORT_ID_GET(vlan_port_id); 2602 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) { 2603 return BCM_E_NOT_FOUND; 2604 } 2605 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 2606 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 2607 NEXT_HOP_INDEXf); 2608 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 2609 nh_index, &ing_nh)); 2610 2611 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf) != 0x2) { 2612 /* Entry type is not L2 DVP */ 2613 return BCM_E_NOT_FOUND; 2614 } 2615 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 2616 *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf); 2617 } else { 2618 /* Only add this to replication set if destination is local */ 2619 *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf); 2620 *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 2621 } 2622 *id = vp; 2623 return rv; 2624 } 2625 2626 2627 #endif /* BCM_ENDURO_SUPPORT && INCLUDE_L3 */