vlan.c (85579B)
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 creation and deletion. 9 * Also manages addition and removal of virtual 10 * ports from VLAN. The types of virtual ports that 11 * can be added to or remove from VLAN can be VLAN 12 * VPs or NIV VPs. 13 */ 14 15 #include <soc/defs.h> 16 #include <sal/core/libc.h> 17 #include <shared/bsl.h> 18 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3) 19 20 #include <soc/mem.h> 21 #include <soc/hash.h> 22 23 #include <bcm/error.h> 24 25 #include <bcm_int/esw_dispatch.h> 26 #include <bcm_int/api_xlate_port.h> 27 28 #include <bcm_int/common/multicast.h> 29 #include <bcm_int/esw/multicast.h> 30 #include <bcm_int/esw/virtual.h> 31 #include <bcm_int/esw/vlan.h> 32 #include <bcm_int/esw/firebolt.h> 33 #include <bcm_int/esw/trx.h> 34 #include <bcm_int/esw/triumph2.h> 35 #include <bcm_int/esw/trident.h> 36 #include <bcm_int/esw/stack.h> 37 #include <bcm_int/esw/trunk.h> 38 #include <bcm_int/esw/ipmc.h> 39 #if defined(BCM_TRIUMPH3_SUPPORT) 40 #include <bcm_int/esw/triumph3.h> 41 #endif /* BCM_TRIUMPH3_SUPPORT*/ 42 43 /* -------------------------------------------------------- 44 * Software book keeping for virtual port group information 45 * -------------------------------------------------------- 46 */ 47 48 typedef struct _bcm_td_vp_group_s { 49 int vp_count; /* Number of VPs that belong to this VP group */ 50 SHR_BITDCL *vp_bitmap; /* Bitmap of VPs that belong to this VP group */ 51 SHR_BITDCL *vlan_bitmap; /* VLANs this VP group belongs to */ 52 } _bcm_td_vp_group_t; 53 54 typedef struct _bcm_td_vp_group_bk_s { 55 int vp_group_initialized; /* Flag to check initialized status */ 56 int num_ing_vp_group; /* Number of ingress VP groups */ 57 _bcm_td_vp_group_t *ing_vp_group_array; /* Ingress VP group array */ 58 int num_eg_vp_group; /* Number of egress VP groups */ 59 _bcm_td_vp_group_t *eg_vp_group_array; /* Egress VP group array */ 60 } _bcm_td_vp_group_bk_t; 61 62 typedef struct { 63 int ingress; 64 int egress; 65 } _bcm_td_vp_group_unmanaged_t; 66 67 STATIC _bcm_td_vp_group_bk_t _bcm_td_vp_group_bk[BCM_MAX_NUM_UNITS]; 68 69 STATIC _bcm_td_vp_group_unmanaged_t 70 _bcm_td_vp_group_unmanaged[BCM_MAX_NUM_UNITS]; 71 72 #define VP_GROUP_BK(unit) (&_bcm_td_vp_group_bk[unit]) 73 74 #define VP_GROUP_INIT(unit) \ 75 do { \ 76 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { \ 77 return BCM_E_UNIT; \ 78 } \ 79 if (!VP_GROUP_BK(unit)->vp_group_initialized) { \ 80 return BCM_E_INIT; \ 81 } \ 82 } while (0) 83 84 #define ING_VP_GROUP(unit, vp_group) \ 85 (&VP_GROUP_BK(unit)->ing_vp_group_array[vp_group]) 86 87 #define EG_VP_GROUP(unit, vp_group) \ 88 (&VP_GROUP_BK(unit)->eg_vp_group_array[vp_group]) 89 90 #define TD2_EGR_DVP_ATTRIBUTE_FIELD(_type,_sf) \ 91 (_type) == 1 ? TRILL__##_sf: \ 92 (_type) == 2 ? VXLAN__##_sf: \ 93 (_type) == 3 ? L2GRE__##_sf: \ 94 COMMON__##_sf; 95 96 /* 97 * Function: 98 * _bcm_td_vp_group_free_resources 99 * Purpose: 100 * Free VP group data structures. 101 * Parameters: 102 * unit - SOC unit number 103 * Returns: 104 * Nothing 105 */ 106 STATIC void 107 _bcm_td_vp_group_free_resources(int unit) 108 { 109 int num_vp_groups, i; 110 111 if (VP_GROUP_BK(unit)->ing_vp_group_array) { 112 num_vp_groups = soc_mem_field_length(unit, VLAN_TABLE(unit), VP_GROUP_BITMAPf); 113 for (i = 0; i < num_vp_groups; i++) { 114 if (ING_VP_GROUP(unit, i)->vp_bitmap) { 115 sal_free(ING_VP_GROUP(unit, i)->vp_bitmap); 116 ING_VP_GROUP(unit, i)->vp_bitmap = NULL; 117 } 118 if (ING_VP_GROUP(unit, i)->vlan_bitmap) { 119 sal_free(ING_VP_GROUP(unit, i)->vlan_bitmap); 120 ING_VP_GROUP(unit, i)->vlan_bitmap = NULL; 121 } 122 } 123 sal_free(VP_GROUP_BK(unit)->ing_vp_group_array); 124 VP_GROUP_BK(unit)->ing_vp_group_array = NULL; 125 } 126 127 if (VP_GROUP_BK(unit)->eg_vp_group_array) { 128 num_vp_groups = soc_mem_field_length(unit, EGR_VLANm, VP_GROUP_BITMAPf); 129 for (i = 0; i < num_vp_groups; i++) { 130 if (EG_VP_GROUP(unit, i)->vp_bitmap) { 131 sal_free(EG_VP_GROUP(unit, i)->vp_bitmap); 132 EG_VP_GROUP(unit, i)->vp_bitmap = NULL; 133 } 134 if (EG_VP_GROUP(unit, i)->vlan_bitmap) { 135 sal_free(EG_VP_GROUP(unit, i)->vlan_bitmap); 136 EG_VP_GROUP(unit, i)->vlan_bitmap = NULL; 137 } 138 } 139 sal_free(VP_GROUP_BK(unit)->eg_vp_group_array); 140 VP_GROUP_BK(unit)->eg_vp_group_array = NULL; 141 } 142 143 return; 144 } 145 146 /* 147 * Function: 148 * _td_egr_dvp_attribute_field_name_get 149 * Purpose: 150 * Retrieve the proper field name based the device and vp type. 151 * Parameters: 152 * unit - SOC unit number. 153 * Returns: 154 * BCM_E_XXX 155 */ 156 int 157 _td_egr_dvp_attribute_field_name_get(int unit, 158 egr_dvp_attribute_entry_t *dvp_entry, 159 soc_field_t legacy_name, 160 soc_field_t *result_name) 161 { 162 163 #ifdef BCM_TRIDENT2_SUPPORT 164 if (SOC_IS_TD2_TT2(unit)) { 165 int vp_type; 166 soc_field_t vp_type_f = VP_TYPEf; 167 168 if (SOC_MEM_FIELD_VALID(unit, EGR_DVP_ATTRIBUTEm, DATA_TYPEf)) { 169 vp_type_f = DATA_TYPEf; 170 } 171 vp_type = soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, dvp_entry, vp_type_f); 172 switch (legacy_name) { 173 case EN_EFILTERf: 174 *result_name = TD2_EGR_DVP_ATTRIBUTE_FIELD(vp_type, EN_EFILTERf); 175 break; 176 case VLAN_MEMBERSHIP_PROFILEf: 177 *result_name = TD2_EGR_DVP_ATTRIBUTE_FIELD(vp_type, 178 VLAN_MEMBERSHIP_PROFILEf); 179 break; 180 default: 181 return BCM_E_NOT_FOUND; 182 break; 183 } 184 } else 185 #endif 186 { 187 *result_name = legacy_name; 188 } 189 return BCM_E_NONE; 190 } 191 192 193 #ifdef BCM_WARM_BOOT_SUPPORT 194 /* 195 * Function: 196 * _bcm_td_vp_group_reinit 197 * Purpose: 198 * Recover the virtual port group data structures. 199 * Parameters: 200 * unit - SOC unit number. 201 * Returns: 202 * BCM_E_XXX 203 */ 204 STATIC int 205 _bcm_td_vp_group_reinit(int unit) 206 { 207 int rv = BCM_E_NONE; 208 uint8 *source_vp_buf = NULL; 209 uint8 *vlan_buf = NULL; 210 uint8* vlan_2_buf=NULL; 211 uint8 *egr_dvp_buf = NULL; 212 uint8 *egr_vlan_buf = NULL; 213 int index_min, index_max; 214 int i, k; 215 source_vp_entry_t *svp_entry; 216 int vp_group; 217 vlan_tab_entry_t *vlan_entry; 218 vlan_2_tab_entry_t *vlan_2_entry; 219 uint32 fldbuf[2]; 220 egr_dvp_attribute_entry_t *egr_dvp_entry; 221 egr_vlan_entry_t *egr_vlan_entry; 222 soc_field_t en_efilter_f; 223 soc_field_t vm_prof_f; 224 225 if (soc_feature(unit, soc_feature_vp_group_ingress_vlan_membership) && 226 (!bcm_td_ing_vp_group_unmanaged_get(unit))) { 227 228 /* Recover ingress VP group's virtual ports from SOURCE_VP table */ 229 230 source_vp_buf = soc_cm_salloc(unit, 231 SOC_MEM_TABLE_BYTES(unit, SOURCE_VPm), "SOURCE_VP buffer"); 232 if (NULL == source_vp_buf) { 233 rv = BCM_E_MEMORY; 234 goto cleanup; 235 } 236 237 index_min = soc_mem_index_min(unit, SOURCE_VPm); 238 index_max = soc_mem_index_max(unit, SOURCE_VPm); 239 rv = soc_mem_read_range(unit, SOURCE_VPm, MEM_BLOCK_ANY, 240 index_min, index_max, source_vp_buf); 241 if (SOC_FAILURE(rv)) { 242 goto cleanup; 243 } 244 245 for (i = index_min; i <= index_max; i++) { 246 svp_entry = soc_mem_table_idx_to_pointer 247 (unit, SOURCE_VPm, source_vp_entry_t *, source_vp_buf, i); 248 249 if (soc_SOURCE_VPm_field32_get(unit, svp_entry, 250 ENABLE_IFILTERf) == 0) { 251 continue; 252 } 253 254 vp_group = soc_SOURCE_VPm_field32_get(unit, svp_entry, 255 VLAN_MEMBERSHIP_PROFILEf); 256 SHR_BITSET(ING_VP_GROUP(unit, vp_group)->vp_bitmap, i); 257 ING_VP_GROUP(unit, vp_group)->vp_count++; 258 } 259 260 soc_cm_sfree(unit, source_vp_buf); 261 source_vp_buf= NULL; 262 263 /* Recover ingress VP group's vlans from VLAN table */ 264 265 vlan_buf = soc_cm_salloc(unit, 266 SOC_MEM_TABLE_BYTES(unit, VLAN_TABm), "VLAN_TAB buffer"); 267 if (NULL == vlan_buf) { 268 rv = BCM_E_MEMORY; 269 goto cleanup; 270 } 271 if (SOC_MEM_IS_VALID(unit,VLAN_2_TABm)) { 272 vlan_2_buf = soc_cm_salloc(unit, 273 SOC_MEM_TABLE_BYTES(unit, VLAN_2_TABm), "VLAN_2_TAB buffer"); 274 if (NULL == vlan_2_buf) { 275 rv = BCM_E_MEMORY; 276 goto cleanup; 277 } 278 } 279 index_min = soc_mem_index_min(unit, VLAN_TABm); 280 index_max = soc_mem_index_max(unit, VLAN_TABm); 281 rv = soc_mem_read_range(unit, VLAN_TABm, MEM_BLOCK_ANY, 282 index_min, index_max, vlan_buf); 283 if (SOC_FAILURE(rv)) { 284 goto cleanup; 285 } 286 if (SOC_MEM_IS_VALID(unit,VLAN_2_TABm)) { 287 rv = soc_mem_read_range(unit, VLAN_2_TABm, MEM_BLOCK_ANY, 288 index_min, index_max, vlan_2_buf); 289 if (SOC_FAILURE(rv)) { 290 goto cleanup; 291 } 292 } 293 for (i = index_min; i <= index_max; i++) { 294 vlan_entry = soc_mem_table_idx_to_pointer 295 (unit, VLAN_TABm, vlan_tab_entry_t *, vlan_buf, i); 296 297 if (soc_VLAN_TABm_field32_get(unit, vlan_entry, VALIDf) == 0) { 298 continue; 299 } 300 301 if (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) { 302 if (soc_VLAN_TABm_field32_get(unit, vlan_entry, 303 VIRTUAL_PORT_ENf) == 0) { 304 continue; 305 } 306 } 307 308 if (SOC_MEM_IS_VALID(unit, VLAN_2_TABm)) { 309 vlan_2_entry = soc_mem_table_idx_to_pointer 310 (unit, VLAN_2_TABm, vlan_2_tab_entry_t *, vlan_2_buf, i); 311 soc_VLAN_2_TABm_field_get(unit, vlan_2_entry, VP_GROUP_BITMAPf, fldbuf); 312 } else { 313 soc_VLAN_TABm_field_get(unit, vlan_entry, VP_GROUP_BITMAPf, fldbuf); 314 } 315 316 for (k = 0; k < VP_GROUP_BK(unit)->num_ing_vp_group; k++) { 317 if (fldbuf[k / 32] & (1 << (k % 32))) { 318 /* The bit in VP_GROUP_BITMAP that corresponds to 319 * VP group k is set. 320 */ 321 SHR_BITSET(ING_VP_GROUP(unit, k)->vlan_bitmap, i); 322 } 323 } 324 } 325 326 soc_cm_sfree(unit, vlan_buf); 327 vlan_buf = NULL; 328 if (SOC_MEM_IS_VALID(unit,VLAN_2_TABm)) { 329 soc_cm_sfree(unit, vlan_2_buf); 330 vlan_2_buf = NULL; 331 } 332 } 333 334 if (soc_feature(unit, soc_feature_vp_group_egress_vlan_membership) && 335 (!bcm_td_egr_vp_group_unmanaged_get(unit))) { 336 337 /* Recover egress VP group's virtual ports from 338 * EGR_DVP_ATTRIBUTE table 339 */ 340 341 egr_dvp_buf = soc_cm_salloc(unit, 342 SOC_MEM_TABLE_BYTES(unit, EGR_DVP_ATTRIBUTEm), 343 "EGR_DVP buffer"); 344 if (NULL == egr_dvp_buf) { 345 rv = BCM_E_MEMORY; 346 goto cleanup; 347 } 348 349 index_min = soc_mem_index_min(unit, EGR_DVP_ATTRIBUTEm); 350 index_max = soc_mem_index_max(unit, EGR_DVP_ATTRIBUTEm); 351 rv = soc_mem_read_range(unit, EGR_DVP_ATTRIBUTEm, MEM_BLOCK_ANY, 352 index_min, index_max, egr_dvp_buf); 353 if (SOC_FAILURE(rv)) { 354 goto cleanup; 355 } 356 357 for (i = index_min; i <= index_max; i++) { 358 egr_dvp_entry = soc_mem_table_idx_to_pointer 359 (unit, EGR_DVP_ATTRIBUTEm, egr_dvp_attribute_entry_t *, 360 egr_dvp_buf, i); 361 362 BCM_IF_ERROR_RETURN(_td_egr_dvp_attribute_field_name_get(unit, 363 egr_dvp_entry, EN_EFILTERf, &en_efilter_f)); 364 365 if (soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, egr_dvp_entry, 366 en_efilter_f) == 0) { 367 continue; 368 } 369 370 BCM_IF_ERROR_RETURN(_td_egr_dvp_attribute_field_name_get(unit, 371 egr_dvp_entry, VLAN_MEMBERSHIP_PROFILEf, 372 &vm_prof_f)); 373 374 vp_group = soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, egr_dvp_entry, 375 vm_prof_f); 376 SHR_BITSET(EG_VP_GROUP(unit, vp_group)->vp_bitmap, i); 377 EG_VP_GROUP(unit, vp_group)->vp_count++; 378 } 379 380 soc_cm_sfree(unit, egr_dvp_buf); 381 egr_dvp_buf = NULL; 382 383 /* Recover egress VP group's vlans from EGR_VLAN table */ 384 385 egr_vlan_buf = soc_cm_salloc(unit, 386 SOC_MEM_TABLE_BYTES(unit, EGR_VLANm), "EGR_VLAN buffer"); 387 if (NULL == egr_vlan_buf) { 388 rv = BCM_E_MEMORY; 389 goto cleanup; 390 } 391 392 index_min = soc_mem_index_min(unit, EGR_VLANm); 393 index_max = soc_mem_index_max(unit, EGR_VLANm); 394 rv = soc_mem_read_range(unit, EGR_VLANm, MEM_BLOCK_ANY, 395 index_min, index_max, egr_vlan_buf); 396 if (SOC_FAILURE(rv)) { 397 goto cleanup; 398 } 399 400 for (i = index_min; i <= index_max; i++) { 401 egr_vlan_entry = soc_mem_table_idx_to_pointer 402 (unit, EGR_VLANm, egr_vlan_entry_t *, egr_vlan_buf, i); 403 404 if (soc_EGR_VLANm_field32_get(unit, egr_vlan_entry, VALIDf) == 0) { 405 continue; 406 } 407 408 soc_EGR_VLANm_field_get(unit, egr_vlan_entry, VP_GROUP_BITMAPf, 409 fldbuf); 410 for (k = 0; k < VP_GROUP_BK(unit)->num_eg_vp_group; k++) { 411 if (fldbuf[k / 32] & (1 << (k % 32))) { 412 /* The bit in VP_GROUP_BITMAP that corresponds to 413 * VP group k is set. 414 */ 415 SHR_BITSET(EG_VP_GROUP(unit, k)->vlan_bitmap, i); 416 } 417 } 418 } 419 420 soc_cm_sfree(unit, egr_vlan_buf); 421 egr_vlan_buf = NULL; 422 } 423 424 cleanup: 425 if (source_vp_buf) { 426 soc_cm_sfree(unit, source_vp_buf); 427 } 428 if (vlan_buf) { 429 soc_cm_sfree(unit, vlan_buf); 430 } 431 if (vlan_2_buf) { 432 soc_cm_sfree(unit, vlan_2_buf); 433 } 434 if (egr_dvp_buf) { 435 soc_cm_sfree(unit, egr_dvp_buf); 436 } 437 if (egr_vlan_buf) { 438 soc_cm_sfree(unit, egr_vlan_buf); 439 } 440 441 return rv; 442 } 443 #endif /* BCM_WARM_BOOT_SUPPORT */ 444 445 #ifndef BCM_SW_STATE_DUMP_DISABLE 446 /* 447 * Function: 448 * bcm_td_vp_group_sw_dump 449 * Purpose: 450 * Displays VP group information maintained by software. 451 * Parameters: 452 * unit - Device unit number 453 * Returns: 454 * None 455 */ 456 void 457 bcm_td_vp_group_sw_dump(int unit) 458 { 459 int i, k; 460 int vp_bitmap_bit_size; 461 int num_vlan; 462 463 LOG_CLI((BSL_META_U(unit, 464 "\nSW Information Ingress VP Group - Unit %d\n"), unit)); 465 for (i = 0; i < VP_GROUP_BK(unit)->num_ing_vp_group; i++) { 466 LOG_CLI((BSL_META_U(unit, 467 "\n Ingress VP Group = %d\n"), i)); 468 LOG_CLI((BSL_META_U(unit, 469 " VP Count = %d\n"), ING_VP_GROUP(unit, i)->vp_count)); 470 471 LOG_CLI((BSL_META_U(unit, 472 " VP List ="))); 473 vp_bitmap_bit_size = soc_mem_index_count(unit, SOURCE_VPm); 474 for (k = 0; k < vp_bitmap_bit_size; k++) { 475 if (SHR_BITGET(ING_VP_GROUP(unit, i)->vp_bitmap, k)) { 476 LOG_CLI((BSL_META_U(unit, 477 " %d"), k)); 478 } 479 } 480 LOG_CLI((BSL_META_U(unit, 481 "\n"))); 482 483 LOG_CLI((BSL_META_U(unit, 484 " VLAN List ="))); 485 num_vlan = soc_mem_index_count(unit, VLAN_TABm); 486 for (k = 0; k < num_vlan; k++) { 487 if (SHR_BITGET(ING_VP_GROUP(unit, i)->vlan_bitmap, k)) { 488 LOG_CLI((BSL_META_U(unit, 489 " %d"), k)); 490 } 491 } 492 LOG_CLI((BSL_META_U(unit, 493 "\n"))); 494 } 495 496 LOG_CLI((BSL_META_U(unit, 497 "\nSW Information Egress VP Group - Unit %d\n"), unit)); 498 for (i = 0; i < VP_GROUP_BK(unit)->num_eg_vp_group; i++) { 499 LOG_CLI((BSL_META_U(unit, 500 "\n Egress VP Group = %d\n"), i)); 501 LOG_CLI((BSL_META_U(unit, 502 " VP Count = %d\n"), EG_VP_GROUP(unit, i)->vp_count)); 503 504 LOG_CLI((BSL_META_U(unit, 505 " VP List ="))); 506 vp_bitmap_bit_size = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm); 507 for (k = 0; k < vp_bitmap_bit_size; k++) { 508 if (SHR_BITGET(EG_VP_GROUP(unit, i)->vp_bitmap, k)) { 509 LOG_CLI((BSL_META_U(unit, 510 " %d"), k)); 511 } 512 } 513 LOG_CLI((BSL_META_U(unit, 514 "\n"))); 515 516 LOG_CLI((BSL_META_U(unit, 517 " VLAN List ="))); 518 num_vlan = soc_mem_index_count(unit, EGR_VLANm); 519 for (k = 0; k < num_vlan; k++) { 520 if (SHR_BITGET(EG_VP_GROUP(unit, i)->vlan_bitmap, k)) { 521 LOG_CLI((BSL_META_U(unit, 522 " %d"), k)); 523 } 524 } 525 LOG_CLI((BSL_META_U(unit, 526 "\n"))); 527 } 528 529 return; 530 } 531 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 532 533 /* 534 * Function: 535 * bcm_td_vp_group_init 536 * Purpose: 537 * Initialize the virtual port group data structures. 538 * Parameters: 539 * unit - SOC unit number. 540 * Returns: 541 * BCM_E_XXX 542 */ 543 int 544 bcm_td_vp_group_init(int unit) 545 { 546 int num_vp_groups, num_vp, num_vlan, i; 547 int rv = BCM_E_NONE; 548 549 _bcm_td_vp_group_free_resources(unit); 550 551 #ifdef BCM_WARM_BOOT_SUPPORT 552 if (SOC_WARM_BOOT(unit)) { 553 } else 554 #endif 555 { 556 _bcm_td_vp_group_unmanaged[unit].ingress = FALSE; 557 _bcm_td_vp_group_unmanaged[unit].egress = FALSE; 558 } 559 sal_memset(VP_GROUP_BK(unit), 0, sizeof(_bcm_td_vp_group_bk_t)); 560 561 if (SOC_MEM_FIELD_VALID(unit, VLAN_TABLE(unit), VP_GROUP_BITMAPf)) { 562 num_vp_groups = soc_mem_field_length(unit, VLAN_TABLE(unit), VP_GROUP_BITMAPf); 563 VP_GROUP_BK(unit)->num_ing_vp_group = num_vp_groups; 564 565 if (NULL == VP_GROUP_BK(unit)->ing_vp_group_array) { 566 VP_GROUP_BK(unit)->ing_vp_group_array = 567 sal_alloc(sizeof(_bcm_td_vp_group_t) * num_vp_groups, 568 "ingress vp group array"); 569 if (NULL == VP_GROUP_BK(unit)->ing_vp_group_array) { 570 _bcm_td_vp_group_free_resources(unit); 571 return BCM_E_MEMORY; 572 } 573 } 574 sal_memset(VP_GROUP_BK(unit)->ing_vp_group_array, 0, 575 sizeof(_bcm_td_vp_group_t) * num_vp_groups); 576 577 for (i = 0; i < num_vp_groups; i++) { 578 num_vp = soc_mem_index_count(unit, SOURCE_VPm); 579 if (NULL == ING_VP_GROUP(unit, i)->vp_bitmap) { 580 ING_VP_GROUP(unit, i)->vp_bitmap = sal_alloc 581 (SHR_BITALLOCSIZE(num_vp), "ingress vp group vp bitmap"); 582 if (NULL == ING_VP_GROUP(unit, i)->vp_bitmap) { 583 _bcm_td_vp_group_free_resources(unit); 584 return BCM_E_MEMORY; 585 } 586 } 587 sal_memset(ING_VP_GROUP(unit, i)->vp_bitmap, 0, 588 SHR_BITALLOCSIZE(num_vp)); 589 590 num_vlan = soc_mem_index_count(unit, VLAN_TABLE(unit)); 591 if (NULL == ING_VP_GROUP(unit, i)->vlan_bitmap) { 592 ING_VP_GROUP(unit, i)->vlan_bitmap = sal_alloc 593 (SHR_BITALLOCSIZE(num_vlan), "ingress vp group vlan bitmap"); 594 if (NULL == ING_VP_GROUP(unit, i)->vlan_bitmap) { 595 _bcm_td_vp_group_free_resources(unit); 596 return BCM_E_MEMORY; 597 } 598 } 599 sal_memset(ING_VP_GROUP(unit, i)->vlan_bitmap, 0, 600 SHR_BITALLOCSIZE(num_vlan)); 601 } 602 } 603 604 if (SOC_MEM_FIELD_VALID(unit, EGR_VLANm, VP_GROUP_BITMAPf)) { 605 num_vp_groups = soc_mem_field_length(unit, EGR_VLANm, VP_GROUP_BITMAPf); 606 VP_GROUP_BK(unit)->num_eg_vp_group = num_vp_groups; 607 608 if (NULL == VP_GROUP_BK(unit)->eg_vp_group_array) { 609 VP_GROUP_BK(unit)->eg_vp_group_array = 610 sal_alloc(sizeof(_bcm_td_vp_group_t) * num_vp_groups, 611 "egress vp group array"); 612 if (NULL == VP_GROUP_BK(unit)->eg_vp_group_array) { 613 _bcm_td_vp_group_free_resources(unit); 614 return BCM_E_MEMORY; 615 } 616 } 617 sal_memset(VP_GROUP_BK(unit)->eg_vp_group_array, 0, 618 sizeof(_bcm_td_vp_group_t) * num_vp_groups); 619 620 for (i = 0; i < num_vp_groups; i++) { 621 num_vp = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm); 622 if (NULL == EG_VP_GROUP(unit, i)->vp_bitmap) { 623 EG_VP_GROUP(unit, i)->vp_bitmap = sal_alloc 624 (SHR_BITALLOCSIZE(num_vp), "egress vp group vp bitmap"); 625 if (NULL == EG_VP_GROUP(unit, i)->vp_bitmap) { 626 _bcm_td_vp_group_free_resources(unit); 627 return BCM_E_MEMORY; 628 } 629 } 630 sal_memset(EG_VP_GROUP(unit, i)->vp_bitmap, 0, 631 SHR_BITALLOCSIZE(num_vp)); 632 633 num_vlan = soc_mem_index_count(unit, EGR_VLANm); 634 if (NULL == EG_VP_GROUP(unit, i)->vlan_bitmap) { 635 EG_VP_GROUP(unit, i)->vlan_bitmap = sal_alloc 636 (SHR_BITALLOCSIZE(num_vlan), "egress vp group vlan bitmap"); 637 if (NULL == EG_VP_GROUP(unit, i)->vlan_bitmap) { 638 _bcm_td_vp_group_free_resources(unit); 639 return BCM_E_MEMORY; 640 } 641 } 642 sal_memset(EG_VP_GROUP(unit, i)->vlan_bitmap, 0, 643 SHR_BITALLOCSIZE(num_vlan)); 644 } 645 } 646 647 VP_GROUP_BK(unit)->vp_group_initialized = 1; 648 649 #ifdef BCM_WARM_BOOT_SUPPORT 650 if (SOC_WARM_BOOT(unit)) { 651 rv = _bcm_td_vp_group_reinit(unit); 652 if (BCM_FAILURE(rv)) { 653 _bcm_td_vp_group_free_resources(unit); 654 } 655 } 656 #endif /* BCM_WARM_BOOT_SUPPORT */ 657 658 return rv; 659 } 660 661 /* 662 * Function: 663 * bcm_td_vp_group_detach 664 * Purpose: 665 * De-initialize the virtual port group data structures. 666 * Parameters: 667 * unit - SOC unit number. 668 * Returns: 669 * BCM_E_XXX 670 */ 671 int 672 bcm_td_vp_group_detach(int unit) 673 { 674 _bcm_td_vp_group_free_resources(unit); 675 676 VP_GROUP_BK(unit)->vp_group_initialized = 0; 677 678 return BCM_E_NONE; 679 } 680 681 /* 682 * Function: 683 * _bcm_td_phy_port_trunk_is_local 684 * Purpose: 685 * Determine if the given physical port or trunk is local. 686 * Parameters: 687 * unit - (IN) SOC unit number. 688 * gport - (IN) Physical port or trunk GPORT ID. 689 * is_local - (OUT) Indicates if gport is local. 690 * Returns: 691 * BCM_X_XXX 692 */ 693 STATIC int 694 _bcm_td_phy_port_trunk_is_local(int unit, bcm_gport_t gport, int *is_local) 695 { 696 bcm_trunk_t trunk_id; 697 int rv = BCM_E_NONE; 698 int local_member_count; 699 bcm_module_t mod_out; 700 bcm_port_t port_out; 701 int id; 702 int modid_local; 703 704 *is_local = 0; 705 706 if (BCM_GPORT_IS_TRUNK(gport)) { 707 trunk_id = BCM_GPORT_TRUNK_GET(gport); 708 rv = _bcm_trunk_id_validate(unit, trunk_id); 709 if (BCM_FAILURE(rv)) { 710 return (BCM_E_PORT); 711 } 712 rv = _bcm_esw_trunk_local_members_get(unit, trunk_id, 713 0, NULL, &local_member_count); 714 if (BCM_FAILURE(rv)) { 715 return (BCM_E_PORT); 716 } 717 if (local_member_count > 0) { 718 *is_local = 1; 719 } 720 } else { 721 BCM_IF_ERROR_RETURN 722 (_bcm_esw_gport_resolve(unit, gport, &mod_out, &port_out, 723 &trunk_id, &id)); 724 /* In case of extended queuing on KTX, trunk_id gets updated with 725 * extended queue value. So set it to invalid value. 726 */ 727 #ifdef BCM_KATANA_SUPPORT 728 if (soc_feature(unit, soc_feature_extended_queueing)) { 729 if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) || 730 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) || 731 (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport))) { 732 trunk_id = BCM_TRUNK_INVALID; 733 } 734 } 735 #endif 736 if ((trunk_id != -1) || (id != -1)) { 737 return BCM_E_PARAM; 738 } 739 740 BCM_IF_ERROR_RETURN 741 (_bcm_esw_modid_is_local(unit, mod_out, &modid_local)); 742 743 *is_local = modid_local; 744 } 745 746 return BCM_E_NONE; 747 } 748 749 750 /* 751 * Function: 752 * bcm_td_vlan_vp_group_set 753 * Purpose: 754 * set/clear the specified VP group in the vlan's vp group bitmap. 755 * Parameters: 756 * unit - (IN) Device Number 757 * vlan_mem - (IN) VLAN_TABm or EGR_VLANm 758 * vlan - (IN) vlan mem entry index 759 * vp_group - (IN) the specified VP group 760 * enable - (IN) TRUE to set, FALSE to clear 761 * Returns: 762 * BCM_E_XXX 763 * Notes: 764 * If vp_group == -1 and enable == false, clear the vp_group bitmap 765 */ 766 767 int 768 bcm_td_vlan_vp_group_set( 769 int unit, /* unit number */ 770 soc_mem_t vlan_mem, /* either VLAN_TABm or EGR_VLANm */ 771 int vlan, /* index to the above memory table */ 772 int vp_group, /* the VP group number */ 773 int enable /* TRUE to set, FALSE to clear the VP group */ 774 ) 775 { 776 int field_len; 777 vlan_tab_entry_t vtab; /* both egr_vlan and vlan_tab is same size*/ 778 uint32 vp_group_bitmap[2]; 779 int i; 780 int rv; 781 782 /* safety check */ 783 field_len = soc_mem_field_length(unit,vlan_mem, 784 VP_GROUP_BITMAPf); 785 if (vp_group >= 0) { 786 if (vp_group >= field_len) { 787 return BCM_E_PARAM; 788 } 789 } else if (enable) { 790 return BCM_E_PARAM; 791 } 792 793 if (field_len > sizeof(vp_group_bitmap) * 8) { 794 return BCM_E_INTERNAL; 795 } 796 797 sal_memset(&vtab, 0, sizeof(vlan_tab_entry_t)); 798 799 soc_mem_lock(unit, vlan_mem); 800 801 if ((rv = soc_mem_read(unit, vlan_mem, MEM_BLOCK_ANY, vlan, 802 &vtab)) != BCM_E_NONE) { 803 soc_mem_unlock(unit, vlan_mem); 804 return rv; 805 } 806 807 if (vp_group >= 0) { 808 soc_mem_field_get(unit, vlan_mem, (uint32 *)&vtab, 809 VP_GROUP_BITMAPf, vp_group_bitmap); 810 if (enable) { 811 vp_group_bitmap[vp_group/32] |= 1 << (vp_group%32); 812 } else { 813 /* clear the vp_group */ 814 vp_group_bitmap[vp_group/32] &= ~(1 << (vp_group%32)); 815 } 816 } else { 817 /* clear the VP group bitmap for this vlan */ 818 for (i = 0; i < COUNTOF(vp_group_bitmap); i++) { 819 vp_group_bitmap[i] = 0; 820 } 821 } 822 soc_mem_field_set(unit, vlan_mem, (uint32 *)&vtab, 823 VP_GROUP_BITMAPf, vp_group_bitmap); 824 if ((rv = soc_mem_write(unit, vlan_mem, 825 MEM_BLOCK_ALL, vlan, &vtab)) != BCM_E_NONE) { 826 soc_mem_unlock(unit, vlan_mem); 827 return rv; 828 } 829 soc_mem_unlock(unit, vlan_mem); 830 return BCM_E_NONE; 831 } 832 833 /* 834 * Function: 835 * bcm_td_vlan_vp_group_get 836 * Purpose: 837 * get the flags indicating the given vp group is set for 838 * ingress or/and egress. 839 * Parameters: 840 * unit - (IN) Device Number 841 * vlan_mem - (IN) VLAN_TABm or EGR_VLANm 842 * vlan - (IN) vlan mem entry index 843 * vp_group - (IN) the specified VP group 844 * enable - (OUT) usage flag 845 * Returns: 846 * BCM_E_XXX 847 */ 848 849 int 850 bcm_td_vlan_vp_group_get( 851 int unit, /* unit number */ 852 soc_mem_t vlan_mem, /* either VLAN_TABm or EGR_VLANm */ 853 int vlan, /* index to the above memory table */ 854 int vp_group, /* the VP group number */ 855 int *enable /* TRUE: the given group is set */ 856 ) 857 { 858 int field_len; 859 vlan_tab_entry_t vtab; /* both egr_vlan and vlan_tab is same size*/ 860 uint32 vp_group_bitmap[2]; 861 int rv; 862 863 /* safety check */ 864 field_len = soc_mem_field_length(unit,vlan_mem, 865 VP_GROUP_BITMAPf); 866 if (vp_group >= field_len) { 867 return BCM_E_PARAM; 868 } 869 870 if (field_len > sizeof(vp_group_bitmap) * 8) { 871 return BCM_E_INTERNAL; 872 } 873 874 *enable = 0; 875 sal_memset(&vtab, 0, sizeof(vlan_tab_entry_t)); 876 877 if ((rv = soc_mem_read(unit, vlan_mem, MEM_BLOCK_ANY, vlan, 878 &vtab)) != BCM_E_NONE) { 879 return rv; 880 } 881 882 soc_mem_field_get(unit, vlan_mem, (uint32 *)&vtab, 883 VP_GROUP_BITMAPf, vp_group_bitmap); 884 if (vp_group_bitmap[vp_group/32] & (1 << (vp_group%32))) { 885 *enable = TRUE; 886 } 887 888 return BCM_E_NONE; 889 } 890 891 /* 892 * Function: 893 * _bcm_td_vp_local_ports_get 894 * Purpose: 895 * Get the local ports on which the given VP resides. 896 * Parameters: 897 * unit - (IN) Device Number 898 * vp - (IN) Virtual port number 899 * local_port_max - (OUT) Size of local_port_array 900 * local_port_array - (OUT) Array of local ports 901 * local_port_count - (OUT) Number of local ports 902 * Returns: 903 * BCM_E_XXX 904 * Notes: 905 * If local_port_max = 0 and local_port_array == NULL, 906 * the number of local ports will still be returned in 907 * local_port_count. 908 */ 909 910 STATIC int 911 _bcm_td_vp_local_ports_get(int unit, int vp, int local_port_max, 912 bcm_port_t *local_port_array, int *local_port_count) 913 { 914 ing_dvp_table_entry_t dvp_entry; 915 ing_l3_next_hop_entry_t ing_nh; 916 uint32 nh_index; 917 bcm_trunk_t trunk_id; 918 bcm_module_t modid; 919 bcm_port_t port; 920 int modid_local; 921 922 if (local_port_max < 0) { 923 return BCM_E_PARAM; 924 } 925 926 if ((local_port_max == 0) && (NULL != local_port_array)) { 927 return BCM_E_PARAM; 928 } 929 930 if ((local_port_max > 0) && (NULL == local_port_array)) { 931 return BCM_E_PARAM; 932 } 933 934 if (NULL == local_port_count) { 935 return BCM_E_PARAM; 936 } 937 938 *local_port_count = 0; 939 940 BCM_IF_ERROR_RETURN 941 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 942 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 943 NEXT_HOP_INDEXf); 944 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 945 nh_index, &ing_nh)); 946 947 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) { 948 trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf); 949 950 BCM_IF_ERROR_RETURN 951 (_bcm_esw_trunk_local_members_get(unit, 952 trunk_id, 953 local_port_max, 954 local_port_array, 955 local_port_count)); 956 } else { 957 modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf); 958 port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf); 959 960 BCM_IF_ERROR_RETURN 961 (_bcm_esw_modid_is_local(unit, modid, &modid_local)); 962 if (TRUE != modid_local) { 963 *local_port_count = 0; 964 return BCM_E_NONE; 965 } 966 967 *local_port_count = 1; 968 if (NULL != local_port_array) { 969 local_port_array[0] = port; 970 } 971 } 972 973 return BCM_E_NONE; 974 } 975 976 /* 977 * Function: 978 * bcm_td_vlan_vp_group_get_all 979 * Purpose: 980 * get the array of gports and flags related to the gport. 981 * Parameters: 982 * unit - (IN) Device Number 983 * vlan - (IN) vlan mem entry index 984 * array_max - (IN) max size of the array 985 * bcm_gport_t *gport_array - (IN) gport array 986 * flags_array -(IN) flags array related to gports 987 * port_cnt - (IN/OUT) point to the first available array entry 988 * Returns: 989 * BCM_E_XXX 990 */ 991 992 int 993 bcm_td_vlan_vp_group_get_all( 994 int unit, /* unit number */ 995 int vlan, /* index to the vlan memory table */ 996 int array_max, /* max size of the array */ 997 bcm_gport_t *gport_array, /* gport array */ 998 int *flags_array, /* flags array related to gports */ 999 int *port_cnt) /* point to the first available array entry */ 1000 { 1001 int num_vp_groups; 1002 int vpg; 1003 int ing_enable; 1004 int egr_enable; 1005 int rv; 1006 1007 num_vp_groups = soc_mem_field_length(unit, VLAN_TABLE(unit), 1008 VP_GROUP_BITMAPf); 1009 1010 for (vpg = 0; vpg < num_vp_groups; vpg++) { 1011 ing_enable = 0; 1012 egr_enable = 0; 1013 if ((*port_cnt == array_max) && (gport_array || flags_array)) { 1014 break; 1015 } 1016 if (flags_array) { 1017 flags_array[*port_cnt] = 0; 1018 } 1019 if (soc_feature(unit, 1020 soc_feature_vp_group_ingress_vlan_membership) && 1021 bcm_td_ing_vp_group_unmanaged_get(unit)) { 1022 rv = bcm_td_vlan_vp_group_get(unit,VLAN_TABLE(unit),vlan, 1023 vpg,&ing_enable); 1024 BCM_IF_ERROR_RETURN(rv); 1025 if (ing_enable) { 1026 if (gport_array) { 1027 BCM_GPORT_VP_GROUP_SET(gport_array[*port_cnt],vpg); 1028 } 1029 if (flags_array) { 1030 flags_array[*port_cnt] = BCM_VLAN_PORT_INGRESS_ONLY; 1031 } 1032 } 1033 } 1034 if (soc_feature(unit, 1035 soc_feature_vp_group_egress_vlan_membership) && 1036 bcm_td_egr_vp_group_unmanaged_get(unit)) { 1037 rv = bcm_td_vlan_vp_group_get(unit,EGR_VLANm,vlan, 1038 vpg,&egr_enable); 1039 BCM_IF_ERROR_RETURN(rv); 1040 if (egr_enable) { 1041 if (gport_array) { 1042 BCM_GPORT_VP_GROUP_SET(gport_array[*port_cnt],vpg); 1043 } 1044 if (flags_array) { 1045 flags_array[*port_cnt] |= BCM_VLAN_PORT_EGRESS_ONLY; 1046 } 1047 } 1048 } 1049 if (ing_enable || egr_enable) { 1050 (*port_cnt)++; 1051 } 1052 } 1053 return BCM_E_NONE; 1054 } 1055 1056 /* 1057 * Function: 1058 * _bcm_td_vp_vlan_bitmap_get 1059 * Purpose: 1060 * Get a bitmap of all the VLANs the given VP belongs to. 1061 * Parameters: 1062 * unit - (IN) BCM device number 1063 * vp_gport - (IN) VP gport ID 1064 * vlan_bitmap - (OUT) Bitmap of VLANs 1065 * Returns: 1066 * BCM_E_XXX 1067 */ 1068 STATIC int 1069 _bcm_td_vp_vlan_bitmap_get(int unit, bcm_gport_t vp_gport, SHR_BITDCL *vlan_bitmap) 1070 { 1071 int rv; 1072 int vp; 1073 int mc_type; 1074 source_vp_entry_t svp_entry; 1075 int vp_group; 1076 int num_vlan; 1077 egr_dvp_attribute_entry_t egr_dvp_entry; 1078 bcm_port_t local_port; 1079 int local_port_count; 1080 uint8 *vlan_tab_buf = NULL; 1081 int index_min, index_max; 1082 int if_max, if_count; 1083 bcm_if_t *if_array = NULL; 1084 int i, j, k; 1085 vlan_tab_entry_t *vlan_tab_entry; 1086 int mc_index_array[3]; 1087 int match_prev_mc_index = FALSE; 1088 bcm_multicast_t group; 1089 bcm_gport_t local_gport; 1090 bcm_if_t encap_id; 1091 int match = FALSE; 1092 1093 if (BCM_GPORT_IS_VLAN_PORT(vp_gport)) { 1094 vp = BCM_GPORT_VLAN_PORT_ID_GET(vp_gport); 1095 mc_type = _BCM_MULTICAST_TYPE_VLAN; 1096 } else if (BCM_GPORT_IS_NIV_PORT(vp_gport)) { 1097 vp = BCM_GPORT_NIV_PORT_ID_GET(vp_gport); 1098 mc_type = _BCM_MULTICAST_TYPE_NIV; 1099 } else if (BCM_GPORT_IS_EXTENDER_PORT(vp_gport)) { 1100 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(vp_gport); 1101 mc_type = _BCM_MULTICAST_TYPE_EXTENDER; 1102 } else if (BCM_GPORT_IS_TRUNK(vp_gport)) { 1103 BCM_IF_ERROR_RETURN( 1104 _bcm_esw_trunk_tid_to_vp_lag_vp( 1105 unit, BCM_GPORT_TRUNK_GET(vp_gport), &vp)); 1106 /* there is no need to set mc_type for vplag */ 1107 mc_type = 0; 1108 } else { 1109 return BCM_E_PARAM; 1110 } 1111 1112 /* Check if VP already belongs to a VP group. 1113 * If so, just return the VP group's VLAN bitmap. 1114 */ 1115 1116 if (soc_feature(unit, soc_feature_vp_group_ingress_vlan_membership)) { 1117 SOC_IF_ERROR_RETURN 1118 (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp_entry)); 1119 if (soc_SOURCE_VPm_field32_get( 1120 unit, &svp_entry, ENABLE_IFILTERf) == 1) { 1121 vp_group = soc_SOURCE_VPm_field32_get(unit, &svp_entry, 1122 VLAN_MEMBERSHIP_PROFILEf); 1123 num_vlan = soc_mem_index_count(unit, VLAN_TABm); 1124 sal_memcpy(vlan_bitmap, ING_VP_GROUP(unit, vp_group)->vlan_bitmap, 1125 SHR_BITALLOCSIZE(num_vlan)); 1126 return BCM_E_NONE; 1127 } 1128 } 1129 1130 if (soc_feature(unit, soc_feature_vp_group_egress_vlan_membership)) { 1131 soc_field_t en_efilter_f; 1132 soc_field_t vm_prof_f; 1133 1134 SOC_IF_ERROR_RETURN 1135 (READ_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ANY, vp, &egr_dvp_entry)); 1136 1137 BCM_IF_ERROR_RETURN(_td_egr_dvp_attribute_field_name_get(unit, 1138 &egr_dvp_entry, EN_EFILTERf, &en_efilter_f)); 1139 1140 if (soc_EGR_DVP_ATTRIBUTEm_field32_get( 1141 unit, &egr_dvp_entry, en_efilter_f) == 1) { 1142 BCM_IF_ERROR_RETURN(_td_egr_dvp_attribute_field_name_get(unit, 1143 &egr_dvp_entry, VLAN_MEMBERSHIP_PROFILEf, &vm_prof_f)); 1144 vp_group = soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, &egr_dvp_entry, 1145 vm_prof_f); 1146 num_vlan = soc_mem_index_count(unit, EGR_VLANm); 1147 sal_memcpy(vlan_bitmap, EG_VP_GROUP(unit, vp_group)->vlan_bitmap, 1148 SHR_BITALLOCSIZE(num_vlan)); 1149 return BCM_E_NONE; 1150 } 1151 } 1152 1153 #if defined(BCM_TRIDENT2_SUPPORT) 1154 /* need a special process for vp-lag */ 1155 if (BCM_GPORT_IS_TRUNK(vp_gport)) { 1156 bcm_trunk_member_t *member_array; 1157 int member_count, member_max; 1158 bcm_trunk_chip_info_t trunk_chip_info; 1159 SHR_BITDCL *vlan_bitmap_tmp = NULL; 1160 1161 /* 1 get vp-lag member count max */ 1162 rv = bcm_esw_trunk_chip_info_get(unit, &trunk_chip_info); 1163 if (BCM_FAILURE(rv)) { 1164 goto cleanup; 1165 } 1166 1167 member_max = trunk_chip_info.vp_ports_max; 1168 /* 2 alloc member array according to the member count */ 1169 member_array = sal_alloc(member_max * sizeof(bcm_trunk_member_t), 1170 "member array"); 1171 if (NULL == member_array) { 1172 rv = BCM_E_MEMORY; 1173 goto cleanup; 1174 } 1175 /* 3 get member array */ 1176 rv = bcm_esw_trunk_get(unit, BCM_GPORT_TRUNK_GET(vp_gport), NULL, 1177 member_max, member_array, &member_count); 1178 if (BCM_FAILURE(rv)) { 1179 sal_free (member_array); 1180 goto cleanup; 1181 } 1182 /* 4 alloc vlan bitmap tmp */ 1183 num_vlan = soc_mem_index_count(unit, VLAN_TABm); 1184 vlan_bitmap_tmp = sal_alloc(SHR_BITALLOCSIZE(num_vlan), 1185 "vlan bitmap tmp"); 1186 if (NULL == vlan_bitmap_tmp) { 1187 sal_free (member_array); 1188 goto cleanup; 1189 } 1190 /* 5 get each member vlan bitmap, then or them together */ 1191 for (i = 0; i < member_count; i++) { 1192 sal_memset(vlan_bitmap_tmp, 0, SHR_BITALLOCSIZE(num_vlan)); 1193 rv = _bcm_td_vp_vlan_bitmap_get( 1194 unit, member_array[i].gport, vlan_bitmap_tmp); 1195 if (BCM_FAILURE(rv)) { 1196 sal_free (vlan_bitmap_tmp); 1197 sal_free (member_array); 1198 goto cleanup; 1199 } 1200 1201 SHR_BITOR_RANGE( 1202 vlan_bitmap_tmp, vlan_bitmap, 0, num_vlan, vlan_bitmap); 1203 } 1204 1205 sal_free (vlan_bitmap_tmp); 1206 sal_free (member_array); 1207 return BCM_E_NONE; 1208 } 1209 #endif/*BCM_TRIDENT2_SUPPORT*/ 1210 /* VP does not belong to any VP group. Need to derive VLAN bitmap by 1211 * searching through each VLAN table entry's BC_IDX/UMC_IDX/UUC_IDX 1212 * multicast groups to see if VP belongs to their VP replication lists. 1213 */ 1214 1215 /* Get one local port on which the VP resides. 1216 * Even if the VP resides on a trunk group, only one trunk 1217 * member is needed since all members of a trunk group 1218 * have the same VP replication list. 1219 */ 1220 BCM_IF_ERROR_RETURN 1221 (_bcm_td_vp_local_ports_get(unit, 1222 vp, 1, &local_port, &local_port_count)); 1223 if (local_port_count == 0) { 1224 return BCM_E_PORT; 1225 } 1226 1227 vlan_tab_buf = soc_cm_salloc(unit, 1228 SOC_MEM_TABLE_BYTES(unit, VLAN_TABm), "VLAN_TAB buffer"); 1229 if (NULL == vlan_tab_buf) { 1230 rv = BCM_E_MEMORY; 1231 goto cleanup; 1232 } 1233 1234 index_min = soc_mem_index_min(unit, VLAN_TABm); 1235 index_max = soc_mem_index_max(unit, VLAN_TABm); 1236 rv = soc_mem_read_range(unit, VLAN_TABm, MEM_BLOCK_ANY, 1237 index_min, index_max, vlan_tab_buf); 1238 if (SOC_FAILURE(rv)) { 1239 goto cleanup; 1240 } 1241 1242 if_max = soc_mem_index_count(unit, ING_L3_NEXT_HOPm); 1243 if_array = sal_alloc(sizeof(bcm_if_t) * if_max, "if_array"); 1244 if (NULL == if_array) { 1245 rv = BCM_E_MEMORY; 1246 goto cleanup; 1247 } 1248 sal_memset(if_array, 0, sizeof(bcm_if_t) * if_max); 1249 1250 SHR_BITCLR_RANGE(vlan_bitmap, 0, soc_mem_index_count(unit, VLAN_TABm)); 1251 1252 for (i = index_min; i <= index_max; i++) { 1253 vlan_tab_entry = soc_mem_table_idx_to_pointer 1254 (unit, VLAN_TABm, vlan_tab_entry_t *, vlan_tab_buf, i); 1255 1256 if (0 == soc_VLAN_TABm_field32_get(unit, vlan_tab_entry, 1257 VALIDf)) { 1258 continue; 1259 } 1260 1261 if (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) { 1262 if (0 == soc_VLAN_TABm_field32_get(unit, vlan_tab_entry, 1263 VIRTUAL_PORT_ENf)) { 1264 continue; 1265 } 1266 } 1267 1268 mc_index_array[0] = soc_VLAN_TABm_field32_get(unit, vlan_tab_entry, 1269 BC_IDXf); 1270 mc_index_array[1] = soc_VLAN_TABm_field32_get(unit, vlan_tab_entry, 1271 UMC_IDXf); 1272 mc_index_array[2] = soc_VLAN_TABm_field32_get(unit, vlan_tab_entry, 1273 UUC_IDXf); 1274 1275 for (j = 0; j < 3; j++) { 1276 1277 /* Check if the same mc_index was already searched */ 1278 match_prev_mc_index = FALSE; 1279 for (k = j - 1; k >= 0; k--) { 1280 if (mc_index_array[j] == mc_index_array[k]) { 1281 match_prev_mc_index = TRUE; 1282 break; 1283 } 1284 } 1285 if (match_prev_mc_index) { 1286 /* continue to next mc_index */ 1287 continue; 1288 } 1289 1290 /* Get VP replication list for (mc_index, local_port) */ 1291 rv = bcm_esw_ipmc_egress_intf_get(unit, mc_index_array[j], 1292 local_port, if_max, if_array, &if_count); 1293 if (SOC_FAILURE(rv)) { 1294 goto cleanup; 1295 } 1296 1297 /* Get VP's encap_id */ 1298 _BCM_MULTICAST_GROUP_SET(group, mc_type, mc_index_array[j]); 1299 rv = bcm_esw_port_gport_get(unit, local_port, &local_gport); 1300 if (SOC_FAILURE(rv)) { 1301 goto cleanup; 1302 } 1303 if (BCM_GPORT_IS_VLAN_PORT(vp_gport)) { 1304 rv = bcm_esw_multicast_vlan_encap_get(unit, group, local_gport, 1305 vp_gport, &encap_id); 1306 } else if (BCM_GPORT_IS_NIV_PORT(vp_gport)) { 1307 rv = bcm_esw_multicast_niv_encap_get(unit, group, local_gport, 1308 vp_gport, &encap_id); 1309 } else if (BCM_GPORT_IS_EXTENDER_PORT(vp_gport)) { 1310 rv = bcm_esw_multicast_extender_encap_get(unit, group, local_gport, 1311 vp_gport, &encap_id); 1312 } 1313 1314 1315 if (SOC_FAILURE(rv)) { 1316 goto cleanup; 1317 } 1318 1319 /* Search for VP's encap_id in if_array */ 1320 match = FALSE; 1321 for (k = 0; k < if_count; k++) { 1322 if (encap_id == if_array[k]) { 1323 match = TRUE; 1324 break; 1325 } 1326 } 1327 if (match) { 1328 break; 1329 } 1330 } 1331 1332 if (match) { 1333 /* VP belongs to this VLAN */ 1334 SHR_BITSET(vlan_bitmap, i); 1335 } 1336 } 1337 1338 cleanup: 1339 if (vlan_tab_buf) { 1340 soc_cm_sfree(unit, vlan_tab_buf); 1341 } 1342 1343 if (if_array) { 1344 sal_free(if_array); 1345 } 1346 1347 return rv; 1348 } 1349 1350 /* 1351 * Function: 1352 * _bcm_td_ing_vp_group_join 1353 * Purpose: 1354 * Assign VP to an ingress VP group. 1355 * Parameters: 1356 * unit - (IN) BCM device number 1357 * vp - (IN) VP number 1358 * vlan_bitmap - (IN) Bitmap of VLANs the VP belongs to. 1359 * vp_group - (OUT) Assigned VP group. 1360 * Returns: 1361 * BCM_E_XXX 1362 */ 1363 STATIC int 1364 _bcm_td_ing_vp_group_join(int unit, int vp, 1365 SHR_BITDCL *vlan_bitmap, int *vp_group) 1366 { 1367 int i; 1368 int num_vlan, vid; 1369 vlan_tab_entry_t vlan_entry; 1370 uint32 fldbuf[2]; 1371 1372 num_vlan = soc_mem_index_count(unit, VLAN_TABLE(unit)); 1373 1374 /* First, check if VP's vlan_bitmap matches any existing ingress 1375 * VP group's vlan_bitmap. If so, assign the VP to the VP group 1376 * with the matching vlan_bitmap. 1377 */ 1378 for (i = 0; i < VP_GROUP_BK(unit)->num_ing_vp_group; i++) { 1379 if ((ING_VP_GROUP(unit, i)->vp_count > 0) && 1380 SHR_BITEQ_RANGE(vlan_bitmap, ING_VP_GROUP(unit, i)->vlan_bitmap, 1381 0, num_vlan)) { 1382 *vp_group = i; 1383 SHR_BITSET(ING_VP_GROUP(unit, i)->vp_bitmap, vp); 1384 ING_VP_GROUP(unit, i)->vp_count++; 1385 return BCM_E_NONE; 1386 } 1387 } 1388 1389 /* VP's vlan_bitmap does not match any existing VP group's 1390 * vlan_bitmap. Allocate a new ingress VP group for the VP. 1391 */ 1392 for (i = 0; i < VP_GROUP_BK(unit)->num_ing_vp_group; i++) { 1393 if (0 == ING_VP_GROUP(unit, i)->vp_count) { 1394 *vp_group = i; 1395 SHR_BITSET(ING_VP_GROUP(unit, i)->vp_bitmap, vp); 1396 ING_VP_GROUP(unit, i)->vp_count++; 1397 sal_memcpy(ING_VP_GROUP(unit, i)->vlan_bitmap, vlan_bitmap, 1398 SHR_BITALLOCSIZE(num_vlan)); 1399 1400 /* Update VLAN table's VP_GROUP_BITMAP field */ 1401 for (vid = 0; vid < num_vlan; vid++) { 1402 if (SHR_BITGET(ING_VP_GROUP(unit, i)->vlan_bitmap, vid)) { 1403 SOC_IF_ERROR_RETURN 1404 (soc_mem_read(unit, VLAN_TABLE(unit), MEM_BLOCK_ANY, vid, &vlan_entry)); 1405 soc_mem_field_get(unit, VLAN_TABLE(unit), (uint32 *)&vlan_entry, 1406 VP_GROUP_BITMAPf, fldbuf); 1407 fldbuf[i / 32] |= (1 << (i % 32)); 1408 soc_mem_field_set(unit, VLAN_TABLE(unit), (uint32 *)&vlan_entry, 1409 VP_GROUP_BITMAPf, fldbuf); 1410 SOC_IF_ERROR_RETURN 1411 (soc_mem_write(unit, VLAN_TABLE(unit), MEM_BLOCK_ALL, vid, &vlan_entry)); 1412 } 1413 } 1414 1415 return BCM_E_NONE; 1416 } 1417 } 1418 1419 /* An empty VP group is not available. */ 1420 return BCM_E_RESOURCE; 1421 } 1422 1423 /* 1424 * Function: 1425 * _bcm_td_eg_vp_group_join 1426 * Purpose: 1427 * Assign VP to an egress VP group. 1428 * Parameters: 1429 * unit - (IN) BCM device number 1430 * vp - (IN) VP number 1431 * vlan_bitmap - (IN) Bitmap of VLANs the VP belongs to. 1432 * vp_group - (OUT) Assigned VP group. 1433 * Returns: 1434 * BCM_E_XXX 1435 */ 1436 STATIC int 1437 _bcm_td_eg_vp_group_join(int unit, int vp, 1438 SHR_BITDCL *vlan_bitmap, int *vp_group) 1439 { 1440 int i; 1441 int num_vlan, vid; 1442 egr_vlan_entry_t egr_vlan_entry; 1443 uint32 fldbuf[2]; 1444 1445 num_vlan = soc_mem_index_count(unit, EGR_VLANm); 1446 1447 /* First, check if VP's vlan_bitmap matches any existing egress 1448 * VP group's vlan_bitmap. If so, assign the VP to the VP group 1449 * with the matching vlan_bitmap. 1450 */ 1451 for (i = 0; i < VP_GROUP_BK(unit)->num_eg_vp_group; i++) { 1452 if ((EG_VP_GROUP(unit, i)->vp_count > 0) && 1453 SHR_BITEQ_RANGE(vlan_bitmap, EG_VP_GROUP(unit, i)->vlan_bitmap, 1454 0, num_vlan)) { 1455 *vp_group = i; 1456 SHR_BITSET(EG_VP_GROUP(unit, i)->vp_bitmap, vp); 1457 EG_VP_GROUP(unit, i)->vp_count++; 1458 return BCM_E_NONE; 1459 } 1460 } 1461 1462 /* VP's vlan_bitmap does not match any existing VP group's 1463 * vlan_bitmap. Allocate a new egress VP group for the VP. 1464 */ 1465 for (i = 0; i < VP_GROUP_BK(unit)->num_eg_vp_group; i++) { 1466 if (0 == EG_VP_GROUP(unit, i)->vp_count) { 1467 *vp_group = i; 1468 SHR_BITSET(EG_VP_GROUP(unit, i)->vp_bitmap, vp); 1469 EG_VP_GROUP(unit, i)->vp_count++; 1470 sal_memcpy(EG_VP_GROUP(unit, i)->vlan_bitmap, vlan_bitmap, 1471 SHR_BITALLOCSIZE(num_vlan)); 1472 1473 /* Update EGR_VLAN table's VP_GROUP_BITMAP field */ 1474 for (vid = 0; vid < num_vlan; vid++) { 1475 if (SHR_BITGET(EG_VP_GROUP(unit, i)->vlan_bitmap, vid)) { 1476 SOC_IF_ERROR_RETURN 1477 (READ_EGR_VLANm(unit, MEM_BLOCK_ANY, vid, 1478 &egr_vlan_entry)); 1479 soc_EGR_VLANm_field_get(unit, &egr_vlan_entry, 1480 VP_GROUP_BITMAPf, fldbuf); 1481 fldbuf[i / 32] |= (1 << (i % 32)); 1482 soc_EGR_VLANm_field_set(unit, &egr_vlan_entry, 1483 VP_GROUP_BITMAPf, fldbuf); 1484 SOC_IF_ERROR_RETURN 1485 (WRITE_EGR_VLANm(unit, MEM_BLOCK_ALL, vid, 1486 &egr_vlan_entry)); 1487 } 1488 } 1489 1490 return BCM_E_NONE; 1491 } 1492 } 1493 1494 /* An empty VP group is not available. */ 1495 return BCM_E_RESOURCE; 1496 } 1497 1498 /* 1499 * Function: 1500 * _bcm_td_ing_vp_group_leave 1501 * Purpose: 1502 * Remove VP from an ingress VP group. 1503 * Parameters: 1504 * unit - (IN) BCM device number 1505 * vp - (IN) VP number 1506 * vp_group - (IN) VP group. 1507 * Returns: 1508 * BCM_E_XXX 1509 */ 1510 STATIC int 1511 _bcm_td_ing_vp_group_leave(int unit, int vp, int vp_group) 1512 { 1513 int num_vlan, vid; 1514 vlan_tab_entry_t vlan_entry; 1515 uint32 fldbuf[2]; 1516 1517 SHR_BITCLR(ING_VP_GROUP(unit, vp_group)->vp_bitmap, vp); 1518 ING_VP_GROUP(unit, vp_group)->vp_count--; 1519 1520 if (0 == ING_VP_GROUP(unit, vp_group)->vp_count) { 1521 1522 /* Clear the bit corresponding to the given VP group in 1523 * VLAN table's VP_GROUP_BITMAP field 1524 */ 1525 num_vlan = soc_mem_index_count(unit, VLAN_TABLE(unit)); 1526 for (vid = 0; vid < num_vlan; vid++) { 1527 if (SHR_BITGET(ING_VP_GROUP(unit, vp_group)->vlan_bitmap, vid)) { 1528 SOC_IF_ERROR_RETURN 1529 (soc_mem_read(unit, VLAN_TABLE(unit), MEM_BLOCK_ANY, vid, &vlan_entry)); 1530 soc_mem_field_get(unit, VLAN_TABLE(unit), (uint32 *)&vlan_entry, 1531 VP_GROUP_BITMAPf, fldbuf); 1532 fldbuf[vp_group / 32] &= ~(1 << (vp_group % 32)); 1533 soc_mem_field_set(unit, VLAN_TABLE(unit), (uint32 *)&vlan_entry, 1534 VP_GROUP_BITMAPf, fldbuf); 1535 SOC_IF_ERROR_RETURN 1536 (soc_mem_write(unit, VLAN_TABLE(unit), MEM_BLOCK_ALL, vid, &vlan_entry)); 1537 } 1538 } 1539 1540 SHR_BITCLR_RANGE(ING_VP_GROUP(unit, vp_group)->vlan_bitmap, 0, num_vlan); 1541 } 1542 1543 return BCM_E_NONE; 1544 } 1545 1546 /* 1547 * Function: 1548 * _bcm_td_eg_vp_group_leave 1549 * Purpose: 1550 * Remove VP from an egress VP group. 1551 * Parameters: 1552 * unit - (IN) BCM device number 1553 * vp - (IN) VP number 1554 * vp_group - (IN) VP group. 1555 * Returns: 1556 * BCM_E_XXX 1557 */ 1558 STATIC int 1559 _bcm_td_eg_vp_group_leave(int unit, int vp, int vp_group) 1560 { 1561 int num_vlan, vid; 1562 egr_vlan_entry_t egr_vlan_entry; 1563 uint32 fldbuf[2]; 1564 1565 SHR_BITCLR(EG_VP_GROUP(unit, vp_group)->vp_bitmap, vp); 1566 EG_VP_GROUP(unit, vp_group)->vp_count--; 1567 1568 if (0 == EG_VP_GROUP(unit, vp_group)->vp_count) { 1569 1570 /* Clear the bit corresponding to the given VP group in 1571 * EGR_VLAN table's VP_GROUP_BITMAP field 1572 */ 1573 num_vlan = soc_mem_index_count(unit, EGR_VLANm); 1574 for (vid = 0; vid < num_vlan; vid++) { 1575 if (SHR_BITGET(EG_VP_GROUP(unit, vp_group)->vlan_bitmap, vid)) { 1576 SOC_IF_ERROR_RETURN 1577 (READ_EGR_VLANm(unit, MEM_BLOCK_ANY, vid, &egr_vlan_entry)); 1578 soc_EGR_VLANm_field_get(unit, &egr_vlan_entry, 1579 VP_GROUP_BITMAPf, fldbuf); 1580 fldbuf[vp_group / 32] &= ~(1 << (vp_group % 32)); 1581 soc_EGR_VLANm_field_set(unit, &egr_vlan_entry, 1582 VP_GROUP_BITMAPf, fldbuf); 1583 SOC_IF_ERROR_RETURN 1584 (WRITE_EGR_VLANm(unit, MEM_BLOCK_ALL, vid, &egr_vlan_entry)); 1585 } 1586 } 1587 1588 SHR_BITCLR_RANGE(EG_VP_GROUP(unit, vp_group)->vlan_bitmap, 0, num_vlan); 1589 } 1590 1591 return BCM_E_NONE; 1592 } 1593 1594 /* 1595 * Function: 1596 * bcm_td_ing_vp_group_move 1597 * Purpose: 1598 * Move VP from one ingress VP group to another due to add/remove VP 1599 * to/from VLAN. 1600 * Parameters: 1601 * unit - (IN) BCM device number 1602 * vp - (IN) VP number 1603 * vlan - (IN) VLAN to/from which VP is added or removed 1604 * add - (IN) If TRUE, VP is added to VLAN, else removed from VLAN. 1605 * Returns: 1606 * BCM_E_XXX 1607 */ 1608 int 1609 bcm_td_ing_vp_group_move(int unit, int vp, bcm_vlan_t vlan, int add) 1610 { 1611 int rv = BCM_E_NONE; 1612 source_vp_entry_t svp_entry; 1613 int ifilter_en; 1614 int old_vp_group, new_vp_group; 1615 int num_vlan; 1616 SHR_BITDCL *new_vlan_bitmap = NULL; 1617 1618 SOC_IF_ERROR_RETURN 1619 (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp_entry)); 1620 ifilter_en = soc_SOURCE_VPm_field32_get(unit, &svp_entry, 1621 ENABLE_IFILTERf); 1622 if (1 != ifilter_en) { 1623 return BCM_E_DISABLED; 1624 } 1625 1626 old_vp_group = soc_SOURCE_VPm_field32_get(unit, &svp_entry, 1627 VLAN_MEMBERSHIP_PROFILEf); 1628 1629 /* Derive VP's new VLAN bitmap by adding/removing VLAN 1630 * to/from VP group's VLAN bitmap 1631 */ 1632 num_vlan = soc_mem_index_count(unit, VLAN_TABm); 1633 new_vlan_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vlan), 1634 "vlan bitmap"); 1635 if (NULL == new_vlan_bitmap) { 1636 return BCM_E_MEMORY; 1637 } 1638 sal_memset(new_vlan_bitmap, 0, SHR_BITALLOCSIZE(num_vlan)); 1639 1640 sal_memcpy(new_vlan_bitmap, 1641 ING_VP_GROUP(unit, old_vp_group)->vlan_bitmap, 1642 SHR_BITALLOCSIZE(num_vlan)); 1643 if (add) { 1644 SHR_BITSET(new_vlan_bitmap, vlan); 1645 } else { 1646 SHR_BITCLR(new_vlan_bitmap, vlan); 1647 } 1648 1649 /* If VP's new VLAN bitmap is not the same as the VP group's 1650 * VLAN bitmap, move the VP to another VP group 1651 */ 1652 if (!SHR_BITEQ_RANGE(new_vlan_bitmap, 1653 ING_VP_GROUP(unit, old_vp_group)->vlan_bitmap, 1654 0, num_vlan)) { 1655 1656 /* Join a new VP group */ 1657 rv = _bcm_td_ing_vp_group_join(unit, vp, new_vlan_bitmap, 1658 &new_vp_group); 1659 if (BCM_FAILURE(rv)) { 1660 goto cleanup; 1661 } 1662 1663 /* Update vp group field */ 1664 soc_SOURCE_VPm_field32_set(unit, &svp_entry, 1665 VLAN_MEMBERSHIP_PROFILEf, new_vp_group); 1666 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry); 1667 if (BCM_FAILURE(rv)) { 1668 goto cleanup; 1669 } 1670 1671 /* Leave the old VP group */ 1672 rv = _bcm_td_ing_vp_group_leave(unit, vp, old_vp_group); 1673 if (BCM_FAILURE(rv)) { 1674 goto cleanup; 1675 } 1676 } 1677 1678 cleanup: 1679 if (new_vlan_bitmap) { 1680 sal_free(new_vlan_bitmap); 1681 } 1682 1683 return rv; 1684 } 1685 1686 /* 1687 * Function: 1688 * bcm_td_eg_vp_group_move 1689 * Purpose: 1690 * Move VP from one egress VP group to another due to add/remove VP 1691 * to/from VLAN. 1692 * Parameters: 1693 * unit - (IN) BCM device number 1694 * vp - (IN) VP number 1695 * vlan - (IN) VLAN to/from which VP is added or removed 1696 * add - (IN) If TRUE, VP is added to VLAN, else removed from VLAN. 1697 * Returns: 1698 * BCM_E_XXX 1699 */ 1700 int 1701 bcm_td_eg_vp_group_move(int unit, int vp, bcm_vlan_t vlan, int add) 1702 { 1703 int rv = BCM_E_NONE; 1704 egr_dvp_attribute_entry_t dvp_entry; 1705 int efilter_en; 1706 int old_vp_group, new_vp_group; 1707 int num_vlan; 1708 SHR_BITDCL *new_vlan_bitmap = NULL; 1709 soc_field_t en_efilter_f; 1710 soc_field_t vm_prof_f; 1711 1712 SOC_IF_ERROR_RETURN 1713 (READ_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 1714 BCM_IF_ERROR_RETURN(_td_egr_dvp_attribute_field_name_get(unit, 1715 &dvp_entry, EN_EFILTERf, &en_efilter_f)); 1716 efilter_en = soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, &dvp_entry, 1717 en_efilter_f); 1718 if (1 != efilter_en) { 1719 return BCM_E_DISABLED; 1720 } 1721 1722 BCM_IF_ERROR_RETURN(_td_egr_dvp_attribute_field_name_get(unit, 1723 &dvp_entry, VLAN_MEMBERSHIP_PROFILEf, &vm_prof_f)); 1724 old_vp_group = soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, &dvp_entry, 1725 vm_prof_f); 1726 1727 /* Derive VP's new VLAN bitmap by adding/removing VLAN 1728 * to/from VP group's VLAN bitmap 1729 */ 1730 num_vlan = soc_mem_index_count(unit, EGR_VLANm); 1731 new_vlan_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vlan), 1732 "vlan bitmap"); 1733 if (NULL == new_vlan_bitmap) { 1734 return BCM_E_MEMORY; 1735 } 1736 sal_memset(new_vlan_bitmap, 0, SHR_BITALLOCSIZE(num_vlan)); 1737 1738 sal_memcpy(new_vlan_bitmap, 1739 EG_VP_GROUP(unit, old_vp_group)->vlan_bitmap, 1740 SHR_BITALLOCSIZE(num_vlan)); 1741 if (add) { 1742 SHR_BITSET(new_vlan_bitmap, vlan); 1743 } else { 1744 SHR_BITCLR(new_vlan_bitmap, vlan); 1745 } 1746 1747 /* If VP's new VLAN bitmap is not the same as the VP group's 1748 * VLAN bitmap, move the VP to another VP group 1749 */ 1750 if (!SHR_BITEQ_RANGE(new_vlan_bitmap, 1751 EG_VP_GROUP(unit, old_vp_group)->vlan_bitmap, 1752 0, num_vlan)) { 1753 1754 /* Join a new VP group */ 1755 rv = _bcm_td_eg_vp_group_join(unit, vp, new_vlan_bitmap, 1756 &new_vp_group); 1757 if (BCM_FAILURE(rv)) { 1758 goto cleanup; 1759 } 1760 1761 /* Update vp group field */ 1762 soc_EGR_DVP_ATTRIBUTEm_field32_set(unit, &dvp_entry, 1763 vm_prof_f, new_vp_group); 1764 rv = WRITE_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ALL, vp, &dvp_entry); 1765 if (BCM_FAILURE(rv)) { 1766 goto cleanup; 1767 } 1768 1769 /* Leave the old VP group */ 1770 rv = _bcm_td_eg_vp_group_leave(unit, vp, old_vp_group); 1771 if (BCM_FAILURE(rv)) { 1772 goto cleanup; 1773 } 1774 } 1775 1776 cleanup: 1777 if (new_vlan_bitmap) { 1778 sal_free(new_vlan_bitmap); 1779 } 1780 1781 return rv; 1782 } 1783 1784 /* 1785 * Function: 1786 * bcm_td_ing_vp_group_vlan_get_all 1787 * Purpose: 1788 * Get all VPs from the VP groups belonging to the given VLAN. 1789 * Parameters: 1790 * unit - (IN) BCM device number 1791 * vlan - (IN) VLAN ID 1792 * vp_bitmap - (OUT) Bitmap of VPs. 1793 * Returns: 1794 * BCM_E_XXX 1795 */ 1796 int 1797 bcm_td_ing_vp_group_vlan_get_all(int unit, bcm_vlan_t vlan, 1798 SHR_BITDCL *vp_bitmap) 1799 { 1800 vlan_tab_entry_t vlan_entry; 1801 uint32 fldbuf[2]; 1802 int i; 1803 1804 SOC_IF_ERROR_RETURN 1805 (soc_mem_read(unit, VLAN_TABLE(unit), MEM_BLOCK_ANY, vlan, &vlan_entry)); 1806 soc_mem_field_get(unit, VLAN_TABLE(unit), (uint32 *)&vlan_entry, VP_GROUP_BITMAPf, fldbuf); 1807 1808 for (i = 0; i < VP_GROUP_BK(unit)->num_ing_vp_group; i++) { 1809 if (fldbuf[i / 32] & (1 << (i % 32))) { 1810 /* The bit in VP_GROUP_BITMAP that corresponds to 1811 * VP group i is set. Get all VPs in VP group i. 1812 */ 1813 SHR_BITOR_RANGE(vp_bitmap, ING_VP_GROUP(unit, i)->vp_bitmap, 1814 0, soc_mem_index_count(unit, SOURCE_VPm), vp_bitmap); 1815 } 1816 } 1817 1818 return BCM_E_NONE; 1819 } 1820 1821 /* 1822 * Function: 1823 * bcm_td_eg_vp_group_vlan_get_all 1824 * Purpose: 1825 * Get all VPs from the VP groups belonging to the given VLAN. 1826 * Parameters: 1827 * unit - (IN) BCM device number 1828 * vlan - (IN) VLAN ID 1829 * vp_bitmap - (OUT) Bitmap of VPs. 1830 * Returns: 1831 * BCM_E_XXX 1832 */ 1833 int 1834 bcm_td_eg_vp_group_vlan_get_all(int unit, bcm_vlan_t vlan, 1835 SHR_BITDCL *vp_bitmap) 1836 { 1837 egr_vlan_entry_t egr_vlan_entry; 1838 uint32 fldbuf[2]; 1839 int i; 1840 1841 SOC_IF_ERROR_RETURN 1842 (READ_EGR_VLANm(unit, MEM_BLOCK_ANY, vlan, &egr_vlan_entry)); 1843 soc_EGR_VLANm_field_get(unit, &egr_vlan_entry, VP_GROUP_BITMAPf, fldbuf); 1844 1845 for (i = 0; i < VP_GROUP_BK(unit)->num_eg_vp_group; i++) { 1846 if (fldbuf[i / 32] & (1 << (i % 32))) { 1847 /* The bit in VP_GROUP_BITMAP that corresponds to 1848 * VP group i is set. Get all VPs in VP group i. 1849 */ 1850 SHR_BITOR_RANGE(vp_bitmap, EG_VP_GROUP(unit, i)->vp_bitmap, 1851 0, soc_mem_index_count(unit, SOURCE_VPm), vp_bitmap); 1852 } 1853 } 1854 1855 return BCM_E_NONE; 1856 } 1857 1858 /* 1859 * Function: 1860 * bcm_td_ing_vp_group_vlan_delete_all 1861 * Purpose: 1862 * Delete all VP groups from the given VLAN. 1863 * Parameters: 1864 * unit - (IN) BCM device number 1865 * vlan - (IN) VLAN ID 1866 * Returns: 1867 * BCM_E_XXX 1868 */ 1869 int 1870 bcm_td_ing_vp_group_vlan_delete_all(int unit, bcm_vlan_t vlan) 1871 { 1872 vlan_tab_entry_t vlan_entry; 1873 uint32 fldbuf[2]; 1874 int i, k; 1875 int vp_bitmap_bit_size; 1876 1877 SOC_IF_ERROR_RETURN 1878 (soc_mem_read(unit, VLAN_TABLE(unit), MEM_BLOCK_ANY, vlan, &vlan_entry)); 1879 soc_mem_field_get(unit, VLAN_TABLE(unit), (uint32 *)&vlan_entry, VP_GROUP_BITMAPf, fldbuf); 1880 1881 for (i = 0; i < VP_GROUP_BK(unit)->num_ing_vp_group; i++) { 1882 if (fldbuf[i / 32] & (1 << (i % 32))) { 1883 /* The bit in VP_GROUP_BITMAP that corresponds to 1884 * VP group i is set. Then remove all VPs in VP group i 1885 * from VLAN. 1886 */ 1887 vp_bitmap_bit_size = soc_mem_index_count(unit, SOURCE_VPm); 1888 for (k = 0; k < vp_bitmap_bit_size; k++) { 1889 if (SHR_BITGET(ING_VP_GROUP(unit, i)->vp_bitmap, k)) { 1890 /* VP k belongs to VP group i */ 1891 BCM_IF_ERROR_RETURN 1892 (bcm_td_ing_vp_group_move(unit, k, vlan, FALSE)); 1893 } 1894 } 1895 } 1896 } 1897 1898 return BCM_E_NONE; 1899 } 1900 1901 /* 1902 * Function: 1903 * bcm_td_eg_vp_group_vlan_delete_all 1904 * Purpose: 1905 * Delete all VP groups from the given VLAN. 1906 * Parameters: 1907 * unit - (IN) BCM device number 1908 * vlan - (IN) VLAN ID 1909 * Returns: 1910 * BCM_E_XXX 1911 */ 1912 int 1913 bcm_td_eg_vp_group_vlan_delete_all(int unit, bcm_vlan_t vlan) 1914 { 1915 egr_vlan_entry_t egr_vlan_entry; 1916 uint32 fldbuf[2]; 1917 int i, k; 1918 int vp_bitmap_bit_size; 1919 1920 SOC_IF_ERROR_RETURN 1921 (READ_EGR_VLANm(unit, MEM_BLOCK_ANY, vlan, &egr_vlan_entry)); 1922 soc_EGR_VLANm_field_get(unit, &egr_vlan_entry, VP_GROUP_BITMAPf, fldbuf); 1923 1924 for (i = 0; i < VP_GROUP_BK(unit)->num_eg_vp_group; i++) { 1925 if (fldbuf[i / 32] & (1 << (i % 32))) { 1926 /* The bit in VP_GROUP_BITMAP that corresponds to 1927 * VP group i is set. Then remove all VPs in VP group i 1928 * from VLAN. 1929 */ 1930 vp_bitmap_bit_size = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm); 1931 for (k = 0; k < vp_bitmap_bit_size; k++) { 1932 if (SHR_BITGET(EG_VP_GROUP(unit, i)->vp_bitmap, k)) { 1933 /* VP k belongs to VP group i */ 1934 BCM_IF_ERROR_RETURN 1935 (bcm_td_eg_vp_group_move(unit, k, vlan, FALSE)); 1936 } 1937 } 1938 } 1939 } 1940 1941 return BCM_E_NONE; 1942 } 1943 1944 /* 1945 * Function: 1946 * bcm_td_vp_vlan_member_set 1947 * Purpose: 1948 * Set virtual port ingress and egress filter modes. 1949 * Parameters: 1950 * unit - (IN) BCM device number 1951 * gport - (IN) VP gport ID 1952 * flags - (IN) Ingress and egress filter modes. 1953 * Returns: 1954 * BCM_E_XXX 1955 */ 1956 int 1957 bcm_td_vp_vlan_member_set(int unit, bcm_gport_t gport, uint32 flags) 1958 { 1959 int rv = BCM_E_NONE; 1960 int vp; 1961 bcm_vlan_port_t vlan_vp; 1962 bcm_gport_t phy_port_trunk; 1963 int is_local; 1964 source_vp_entry_t svp_entry; 1965 egr_dvp_attribute_entry_t dvp_entry; 1966 int old_ifilter_en, old_efilter_en; 1967 int old_vp_group, vp_group; 1968 int num_vlan; 1969 SHR_BITDCL *vlan_bitmap = NULL; 1970 soc_field_t en_efilter_f; 1971 soc_field_t vm_prof_f; 1972 1973 if (flags & BCM_PORT_VLAN_MEMBER_INGRESS) { 1974 if (!soc_feature(unit, soc_feature_vp_group_ingress_vlan_membership)) { 1975 return BCM_E_UNAVAIL; 1976 } 1977 } 1978 1979 if (flags & BCM_PORT_VLAN_MEMBER_EGRESS) { 1980 if (!soc_feature(unit, soc_feature_vp_group_egress_vlan_membership)) { 1981 return BCM_E_UNAVAIL; 1982 } 1983 } 1984 1985 if (BCM_GPORT_IS_VLAN_PORT(gport)) { 1986 vp = BCM_GPORT_VLAN_PORT_ID_GET(gport); 1987 1988 /* Get the physical port or trunk the VP resides on */ 1989 bcm_vlan_port_t_init(&vlan_vp); 1990 BCM_GPORT_VLAN_PORT_ID_SET(vlan_vp.vlan_port_id, vp); 1991 BCM_IF_ERROR_RETURN(bcm_tr2_vlan_vp_find(unit, &vlan_vp)); 1992 phy_port_trunk = vlan_vp.port; 1993 1994 } else if (BCM_GPORT_IS_NIV_PORT(gport)) { 1995 bcm_niv_port_t niv_port; 1996 bcm_niv_egress_t niv_egress; 1997 int count; 1998 1999 vp = BCM_GPORT_NIV_PORT_ID_GET(gport); 2000 2001 /* Get the physical port or trunk the VP resides on */ 2002 bcm_niv_port_t_init(&niv_port); 2003 BCM_GPORT_NIV_PORT_ID_SET(niv_port.niv_port_id, vp); 2004 BCM_IF_ERROR_RETURN(bcm_trident_niv_port_get(unit, &niv_port)); 2005 if (niv_port.flags & BCM_NIV_PORT_MATCH_NONE) { 2006 phy_port_trunk = BCM_GPORT_INVALID; 2007 bcm_niv_egress_t_init(&niv_egress); 2008 rv = bcm_trident_niv_egress_get(unit, niv_port.niv_port_id, 2009 1, &niv_egress, &count); 2010 if (BCM_SUCCESS(rv)) { 2011 if (!(niv_egress.flags & BCM_NIV_EGRESS_MULTICAST)) { 2012 phy_port_trunk = niv_egress.port; 2013 } 2014 } 2015 } else { 2016 phy_port_trunk = niv_port.port; 2017 } 2018 #ifdef BCM_TRIUMPH3_SUPPORT 2019 } else if (BCM_GPORT_IS_EXTENDER_PORT(gport)) { 2020 bcm_extender_port_t extender_port; 2021 bcm_extender_egress_t extender_egress; 2022 int count; 2023 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport); 2024 2025 /* Get the physical port or trunk the VP resides on */ 2026 bcm_extender_port_t_init(&extender_port); 2027 BCM_GPORT_EXTENDER_PORT_ID_SET(extender_port.extender_port_id, vp); 2028 BCM_IF_ERROR_RETURN(bcm_tr3_extender_port_get(unit, &extender_port)); 2029 if (extender_port.flags & BCM_EXTENDER_PORT_MATCH_NONE) { 2030 phy_port_trunk = BCM_GPORT_INVALID; 2031 bcm_extender_egress_t_init(&extender_egress); 2032 rv = bcm_tr3_extender_egress_get_all(unit, 2033 extender_port.extender_port_id, 1, &extender_egress, &count); 2034 if (count == 0) { 2035 /* No Extender egress object has been added to VP yet. */ 2036 return BCM_E_CONFIG; 2037 } 2038 if (BCM_SUCCESS(rv)) { 2039 if (!extender_egress.flags & BCM_EXTENDER_EGRESS_MULTICAST) { 2040 phy_port_trunk = extender_egress.port; 2041 } 2042 } 2043 } else { 2044 phy_port_trunk = extender_port.port; 2045 } 2046 #endif /* BCM_TRIUMPH3_SUPPORT */ 2047 } else if (BCM_GPORT_IS_MPLS_PORT(gport)) { 2048 vp = BCM_GPORT_MPLS_PORT_ID_GET(gport); 2049 phy_port_trunk = BCM_GPORT_INVALID; 2050 } else if (BCM_GPORT_IS_VXLAN_PORT(gport)) { 2051 vp = BCM_GPORT_VXLAN_PORT_ID_GET(gport); 2052 phy_port_trunk = BCM_GPORT_INVALID; 2053 } else if (BCM_GPORT_IS_TRUNK(gport)) { 2054 BCM_IF_ERROR_RETURN( 2055 _bcm_esw_trunk_tid_to_vp_lag_vp(unit, 2056 BCM_GPORT_TRUNK_GET(gport), &vp)); 2057 phy_port_trunk = BCM_GPORT_INVALID; 2058 } else { 2059 return BCM_E_PARAM; 2060 } 2061 2062 /* If gport is invalid or cleanning-up the vp membership, 2063 ignore is_local check */ 2064 if (phy_port_trunk != BCM_GPORT_INVALID 2065 && (flags & (BCM_PORT_VLAN_MEMBER_INGRESS | 2066 BCM_PORT_VLAN_MEMBER_EGRESS))) { 2067 BCM_IF_ERROR_RETURN 2068 (_bcm_td_phy_port_trunk_is_local(unit, phy_port_trunk, &is_local)); 2069 if (!is_local) { 2070 /* Ingress and egress filter modes can be set only on local VPs */ 2071 return BCM_E_PORT; 2072 } 2073 } 2074 2075 /* Set ingress filter mode */ 2076 2077 #ifdef BCM_TRIDENT2_SUPPORT 2078 if (soc_feature(unit, soc_feature_ing_vp_vlan_membership) && 2079 (flags & BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP)) { 2080 SOC_IF_ERROR_RETURN 2081 (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp_entry)); 2082 old_ifilter_en = soc_SOURCE_VPm_field32_get(unit, &svp_entry, 2083 ENABLE_IFILTERf); 2084 if (flags & BCM_PORT_VLAN_MEMBER_INGRESS) { 2085 /* td2 hash table */ 2086 if (0 == old_ifilter_en) { 2087 /* enable hash table */ 2088 soc_SOURCE_VPm_field32_set(unit, &svp_entry, 2089 ENABLE_IFILTERf, 2); 2090 SOC_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, 2091 MEM_BLOCK_ALL, vp, &svp_entry)); 2092 } 2093 2094 if (soc_feature(unit, soc_feature_vp_group_ingress_vlan_membership) 2095 && (1 == old_ifilter_en)) { 2096 /* Update ingress filter enable and vp group fields */ 2097 old_vp_group = soc_SOURCE_VPm_field32_get( 2098 unit, &svp_entry, VLAN_MEMBERSHIP_PROFILEf); 2099 soc_SOURCE_VPm_field32_set(unit, &svp_entry, 2100 ENABLE_IFILTERf, 2); 2101 if (!bcm_td_ing_vp_group_unmanaged_get(unit)) { 2102 soc_SOURCE_VPm_field32_set(unit, &svp_entry, 2103 VLAN_MEMBERSHIP_PROFILEf, 0); 2104 } 2105 BCM_IF_ERROR_RETURN( 2106 WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry)); 2107 if (!bcm_td_ing_vp_group_unmanaged_get(unit)) { 2108 /* Remove VP from VP group */ 2109 BCM_IF_ERROR_RETURN( 2110 _bcm_td_ing_vp_group_leave(unit, vp, old_vp_group)); 2111 } 2112 } 2113 } else { 2114 if (2 == old_ifilter_en) { 2115 soc_SOURCE_VPm_field32_set(unit, &svp_entry, 2116 ENABLE_IFILTERf, 0); 2117 BCM_IF_ERROR_RETURN 2118 (WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry)); 2119 } 2120 } 2121 } else 2122 #endif 2123 if (soc_feature(unit, soc_feature_vp_group_ingress_vlan_membership)) { 2124 2125 SOC_IF_ERROR_RETURN 2126 (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp_entry)); 2127 old_ifilter_en = soc_SOURCE_VPm_field32_get(unit, &svp_entry, 2128 ENABLE_IFILTERf); 2129 old_vp_group = soc_SOURCE_VPm_field32_get(unit, &svp_entry, 2130 VLAN_MEMBERSHIP_PROFILEf); 2131 2132 if (flags & BCM_PORT_VLAN_MEMBER_INGRESS) { 2133 if (0 == old_ifilter_en 2134 #ifdef BCM_TRIDENT2_SUPPORT 2135 || (soc_feature(unit, soc_feature_ing_vp_vlan_membership) 2136 && (2 == old_ifilter_en)) 2137 #endif 2138 ) { 2139 /* Enable ingress filtering */ 2140 if (!bcm_td_ing_vp_group_unmanaged_get(unit)) { 2141 /* Get all the VLANs this VP belongs to */ 2142 num_vlan = soc_mem_index_count(unit, VLAN_TABm); 2143 vlan_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vlan), 2144 "vlan bitmap"); 2145 if (NULL == vlan_bitmap) { 2146 return BCM_E_MEMORY; 2147 } 2148 sal_memset(vlan_bitmap, 0, SHR_BITALLOCSIZE(num_vlan)); 2149 rv = _bcm_td_vp_vlan_bitmap_get(unit, gport, vlan_bitmap); 2150 if (BCM_FAILURE(rv)) { 2151 goto cleanup; 2152 } 2153 2154 /* Assign VP to an ingress VP group */ 2155 rv = _bcm_td_ing_vp_group_join(unit, vp, vlan_bitmap, 2156 &vp_group); 2157 if (BCM_FAILURE(rv)) { 2158 goto cleanup; 2159 } 2160 2161 soc_SOURCE_VPm_field32_set(unit, &svp_entry, 2162 VLAN_MEMBERSHIP_PROFILEf, vp_group); 2163 } 2164 /* Update ingress filter enable and vp group fields */ 2165 soc_SOURCE_VPm_field32_set(unit, &svp_entry, 2166 ENABLE_IFILTERf, 1); 2167 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry); 2168 if (BCM_FAILURE(rv)) { 2169 goto cleanup; 2170 } 2171 2172 if (vlan_bitmap) { 2173 sal_free(vlan_bitmap); 2174 vlan_bitmap = NULL; 2175 } 2176 } 2177 } else { 2178 if (1 == old_ifilter_en) { 2179 /* Disable ingress filtering */ 2180 2181 /* Update ingress filter enable and vp group fields */ 2182 soc_SOURCE_VPm_field32_set(unit, &svp_entry, 2183 ENABLE_IFILTERf, 0); 2184 if (!bcm_td_ing_vp_group_unmanaged_get(unit)) { 2185 soc_SOURCE_VPm_field32_set(unit, &svp_entry, 2186 VLAN_MEMBERSHIP_PROFILEf, 0); 2187 } 2188 BCM_IF_ERROR_RETURN 2189 (WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry)); 2190 if (!bcm_td_ing_vp_group_unmanaged_get(unit)) { 2191 /* Remove VP from VP group */ 2192 BCM_IF_ERROR_RETURN 2193 (_bcm_td_ing_vp_group_leave(unit, vp, old_vp_group)); 2194 } 2195 } 2196 } 2197 } 2198 2199 SOC_IF_ERROR_RETURN 2200 (READ_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 2201 BCM_IF_ERROR_RETURN(_td_egr_dvp_attribute_field_name_get(unit, 2202 &dvp_entry, EN_EFILTERf, &en_efilter_f)); 2203 BCM_IF_ERROR_RETURN(_td_egr_dvp_attribute_field_name_get(unit, 2204 &dvp_entry, VLAN_MEMBERSHIP_PROFILEf, &vm_prof_f)); 2205 2206 /* Set egress filter mode */ 2207 2208 #ifdef BCM_TRIDENT2_SUPPORT 2209 if (soc_feature(unit, soc_feature_egr_vp_vlan_membership) && 2210 (flags & BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP)) { 2211 old_efilter_en = soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, 2212 &dvp_entry, en_efilter_f); 2213 /* td2 hash table */ 2214 if (flags & BCM_PORT_VLAN_MEMBER_EGRESS) { 2215 if (0 == old_efilter_en) { 2216 /* enable hash table */ 2217 soc_EGR_DVP_ATTRIBUTEm_field32_set(unit, &dvp_entry, 2218 en_efilter_f, 2); 2219 BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit, 2220 MEM_BLOCK_ALL, vp, &dvp_entry)); 2221 } 2222 2223 if (soc_feature(unit, soc_feature_vp_group_egress_vlan_membership) 2224 && (1 == old_efilter_en)) { 2225 /* Update egress filter enable and vp group fields */ 2226 old_vp_group = soc_EGR_DVP_ATTRIBUTEm_field32_get( 2227 unit, &dvp_entry, vm_prof_f); 2228 soc_EGR_DVP_ATTRIBUTEm_field32_set(unit, &dvp_entry, 2229 en_efilter_f, 2); 2230 if (!bcm_td_egr_vp_group_unmanaged_get(unit)) { 2231 soc_EGR_DVP_ATTRIBUTEm_field32_set(unit, &dvp_entry, 2232 vm_prof_f, 0); 2233 } 2234 BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm( 2235 unit, MEM_BLOCK_ALL, vp, &dvp_entry)); 2236 if (!bcm_td_egr_vp_group_unmanaged_get(unit)) { 2237 /* Remove VP from VP group */ 2238 BCM_IF_ERROR_RETURN( 2239 _bcm_td_eg_vp_group_leave(unit, vp, old_vp_group)); 2240 } 2241 } 2242 } else { 2243 if (2 == old_efilter_en) { 2244 soc_EGR_DVP_ATTRIBUTEm_field32_set(unit, &dvp_entry, 2245 en_efilter_f, 0); 2246 BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit, 2247 MEM_BLOCK_ALL, vp, &dvp_entry)); 2248 } 2249 } 2250 } else 2251 #endif 2252 if (soc_feature(unit, soc_feature_vp_group_egress_vlan_membership)) { 2253 old_efilter_en = soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, &dvp_entry, 2254 en_efilter_f); 2255 old_vp_group = soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, &dvp_entry, 2256 vm_prof_f); 2257 if (flags & BCM_PORT_VLAN_MEMBER_EGRESS) { 2258 if (0 == old_efilter_en 2259 #ifdef BCM_TRIDENT2_SUPPORT 2260 || (soc_feature(unit, soc_feature_egr_vp_vlan_membership) 2261 && (2 == old_efilter_en)) 2262 #endif 2263 ) { 2264 /* Enable egress filtering */ 2265 if (!bcm_td_egr_vp_group_unmanaged_get(unit)) { 2266 /* Get all the VLANs this VP belongs to */ 2267 num_vlan = soc_mem_index_count(unit, EGR_VLANm); 2268 vlan_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vlan), 2269 "vlan bitmap"); 2270 if (NULL == vlan_bitmap) { 2271 return BCM_E_MEMORY; 2272 } 2273 sal_memset(vlan_bitmap, 0, SHR_BITALLOCSIZE(num_vlan)); 2274 rv = _bcm_td_vp_vlan_bitmap_get(unit, gport, vlan_bitmap); 2275 if (BCM_FAILURE(rv)) { 2276 goto cleanup; 2277 } 2278 2279 /* Assign VP to an egress VP group */ 2280 rv = _bcm_td_eg_vp_group_join(unit, vp, vlan_bitmap, 2281 &vp_group); 2282 if (BCM_FAILURE(rv)) { 2283 goto cleanup; 2284 } 2285 2286 soc_EGR_DVP_ATTRIBUTEm_field32_set(unit, &dvp_entry, 2287 vm_prof_f, vp_group); 2288 } 2289 /* Update egress filter enable and vp group fields */ 2290 soc_EGR_DVP_ATTRIBUTEm_field32_set(unit, &dvp_entry, 2291 en_efilter_f, 1); 2292 rv = WRITE_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ALL, vp, &dvp_entry); 2293 if (BCM_FAILURE(rv)) { 2294 goto cleanup; 2295 } 2296 2297 if (vlan_bitmap) { 2298 sal_free(vlan_bitmap); 2299 vlan_bitmap = NULL; 2300 } 2301 } 2302 } else { 2303 if (1 == old_efilter_en) { 2304 /* Disable egress filtering */ 2305 2306 /* Update egress filter enable and vp group fields */ 2307 soc_EGR_DVP_ATTRIBUTEm_field32_set(unit, &dvp_entry, 2308 en_efilter_f, 0); 2309 if (!bcm_td_egr_vp_group_unmanaged_get(unit)) { 2310 soc_EGR_DVP_ATTRIBUTEm_field32_set(unit, &dvp_entry, 2311 vm_prof_f, 0); 2312 } 2313 BCM_IF_ERROR_RETURN 2314 (WRITE_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ALL, vp, &dvp_entry)); 2315 2316 if (!bcm_td_egr_vp_group_unmanaged_get(unit)) { 2317 /* Remove VP from VP group */ 2318 BCM_IF_ERROR_RETURN 2319 (_bcm_td_eg_vp_group_leave(unit, vp, old_vp_group)); 2320 } 2321 } 2322 } 2323 } 2324 2325 cleanup: 2326 if (vlan_bitmap) { 2327 sal_free(vlan_bitmap); 2328 } 2329 2330 return rv; 2331 } 2332 2333 /* 2334 * Function: 2335 * bcm_td_vp_vlan_member_get 2336 * Purpose: 2337 * Get virtual port ingress and egress filter modes. 2338 * Parameters: 2339 * unit - (IN) BCM device number 2340 * gport - (IN) VP gport id 2341 * flags - (OUT) Ingress and egress filter modes. 2342 * Returns: 2343 * BCM_E_XXX 2344 */ 2345 int 2346 bcm_td_vp_vlan_member_get(int unit, bcm_gport_t gport, uint32 *flags) 2347 { 2348 int vp; 2349 source_vp_entry_t svp_entry; 2350 int ifilter_en; 2351 egr_dvp_attribute_entry_t dvp_entry; 2352 int efilter_en; 2353 soc_field_t en_efilter_f; 2354 2355 if (BCM_GPORT_IS_VLAN_PORT(gport)) { 2356 vp = BCM_GPORT_VLAN_PORT_ID_GET(gport); 2357 } else if (BCM_GPORT_IS_NIV_PORT(gport)) { 2358 vp = BCM_GPORT_NIV_PORT_ID_GET(gport); 2359 } else if (BCM_GPORT_IS_EXTENDER_PORT(gport)) { 2360 vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport); 2361 } else if (BCM_GPORT_IS_MPLS_PORT(gport)) { 2362 vp = BCM_GPORT_MPLS_PORT_ID_GET(gport); 2363 } else if (BCM_GPORT_IS_VXLAN_PORT(gport)) { 2364 vp = BCM_GPORT_VXLAN_PORT_ID_GET(gport); 2365 } else if (BCM_GPORT_IS_TRUNK(gport)) { 2366 BCM_IF_ERROR_RETURN( 2367 _bcm_esw_trunk_tid_to_vp_lag_vp(unit, 2368 BCM_GPORT_TRUNK_GET(gport), &vp)); 2369 } else { 2370 return BCM_E_PARAM; 2371 } 2372 2373 *flags = 0; 2374 2375 if (soc_feature(unit, soc_feature_vp_group_ingress_vlan_membership)) { 2376 SOC_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp_entry)); 2377 ifilter_en = soc_SOURCE_VPm_field32_get(unit, &svp_entry, ENABLE_IFILTERf); 2378 if (ifilter_en == 1) { 2379 *flags |= BCM_PORT_VLAN_MEMBER_INGRESS; 2380 } 2381 } 2382 2383 #ifdef BCM_TRIDENT2_SUPPORT 2384 if (soc_feature(unit, soc_feature_ing_vp_vlan_membership)) { 2385 SOC_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp_entry)); 2386 ifilter_en = soc_SOURCE_VPm_field32_get(unit, &svp_entry, ENABLE_IFILTERf); 2387 if (ifilter_en == 2) { 2388 *flags |= BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP | 2389 BCM_PORT_VLAN_MEMBER_INGRESS; 2390 } 2391 } 2392 #endif 2393 2394 2395 if (soc_feature(unit, soc_feature_vp_group_egress_vlan_membership)) { 2396 SOC_IF_ERROR_RETURN 2397 (READ_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 2398 BCM_IF_ERROR_RETURN(_td_egr_dvp_attribute_field_name_get(unit, 2399 &dvp_entry, EN_EFILTERf, &en_efilter_f)); 2400 efilter_en = soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, &dvp_entry, 2401 en_efilter_f); 2402 if (efilter_en == 1) { 2403 *flags |= BCM_PORT_VLAN_MEMBER_EGRESS; 2404 } 2405 } 2406 #ifdef BCM_TRIDENT2_SUPPORT 2407 if (soc_feature(unit, soc_feature_egr_vp_vlan_membership)) { 2408 SOC_IF_ERROR_RETURN 2409 (READ_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry)); 2410 BCM_IF_ERROR_RETURN(_td_egr_dvp_attribute_field_name_get(unit, 2411 &dvp_entry, EN_EFILTERf, &en_efilter_f)); 2412 efilter_en = soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, &dvp_entry, 2413 en_efilter_f); 2414 if (efilter_en == 2) { 2415 *flags |= BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP | 2416 BCM_PORT_VLAN_MEMBER_EGRESS; 2417 } 2418 } 2419 #endif 2420 2421 return BCM_E_NONE; 2422 } 2423 2424 /* 2425 * Function: 2426 * bcm_td_ing_vp_group_unmanaged_get 2427 * Purpose: 2428 * Check if VP group resource is managed by user. If so, user will be 2429 * resposible to assign a VP group to a VP and add the VP group to the 2430 * vlan's VP group bitmap in order to establish the vlan membership. 2431 * Parameters: 2432 * unit - (IN) BCM device number 2433 * Returns: 2434 * TRUE/FALSE 2435 */ 2436 int 2437 bcm_td_ing_vp_group_unmanaged_get(int unit) 2438 { 2439 return _bcm_td_vp_group_unmanaged[unit].ingress; 2440 } 2441 2442 int 2443 bcm_td_egr_vp_group_unmanaged_get(int unit) 2444 { 2445 return _bcm_td_vp_group_unmanaged[unit].egress; 2446 } 2447 2448 /* 2449 * Function: 2450 * bcm_td_ing_vp_group_unmanaged_set 2451 * Purpose: 2452 * Set whether the VP group resource is managed by user. 2453 * Parameters: 2454 * unit - (IN) BCM device number 2455 unmanaged - (IN) TRUE/FALSE 2456 * Returns: BCM_E_XXX 2457 */ 2458 int 2459 bcm_td_ing_vp_group_unmanaged_set(int unit, int flag) 2460 { 2461 int num_vp_groups; 2462 int vp_count; 2463 int i; 2464 2465 /* check if to set the same value */ 2466 if (_bcm_td_vp_group_unmanaged[unit].ingress == flag) { 2467 return BCM_E_NONE; 2468 } 2469 2470 /* make sure auto method hasn't kicked in yet */ 2471 if (VP_GROUP_BK(unit)->vp_group_initialized) { 2472 num_vp_groups = soc_mem_field_length(unit, VLAN_TABLE(unit), VP_GROUP_BITMAPf); 2473 2474 for (vp_count = 0,i = 0; i < VP_GROUP_BK(unit)->num_ing_vp_group; i++) { 2475 if (0 == ING_VP_GROUP(unit, i)->vp_count) { 2476 vp_count++; 2477 } 2478 } 2479 2480 if (vp_count != num_vp_groups) { 2481 LOG_WARN(BSL_LS_BCM_VLAN, 2482 (BSL_META_U(unit, 2483 "Unmanaged mode set fails: VP group auto method already started\n"))); 2484 return BCM_E_EXISTS; 2485 } 2486 } 2487 _bcm_td_vp_group_unmanaged[unit].ingress = flag; 2488 return BCM_E_NONE; 2489 } 2490 2491 int 2492 bcm_td_egr_vp_group_unmanaged_set(int unit, int flag) 2493 { 2494 int num_vp_groups; 2495 int vp_count; 2496 int i; 2497 2498 /* check if to set the same value */ 2499 if (_bcm_td_vp_group_unmanaged[unit].egress == flag) { 2500 return BCM_E_NONE; 2501 } 2502 2503 /* make sure auto method hasn't kicked in yet */ 2504 if (VP_GROUP_BK(unit)->vp_group_initialized) { 2505 num_vp_groups = soc_mem_field_length(unit, EGR_VLANm, VP_GROUP_BITMAPf); 2506 2507 for (vp_count = 0,i = 0; i < VP_GROUP_BK(unit)->num_eg_vp_group; i++) { 2508 if (0 == EG_VP_GROUP(unit, i)->vp_count) { 2509 vp_count++; 2510 } 2511 } 2512 2513 if (vp_count != num_vp_groups) { 2514 LOG_WARN(BSL_LS_BCM_VLAN, 2515 (BSL_META_U(unit, 2516 "Unmanaged mode set fails: VP group auto method already started\n"))); 2517 2518 return BCM_E_EXISTS; 2519 } 2520 } 2521 _bcm_td_vp_group_unmanaged[unit].egress = flag; 2522 return BCM_E_NONE; 2523 } 2524 2525 2526 2527 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */