openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

vlan.c (187173B)


      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: Handle trident2plus specific vlan features:
      9  *             Manages VFI VLAN membership tables.
     10  */
     11 
     12 #include <soc/defs.h>
     13 #include <soc/field.h>
     14 #include <sal/core/libc.h>
     15 #include <shared/bsl.h>
     16 
     17 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
     18 
     19 #include <soc/mem.h>
     20 #include <soc/hash.h>
     21 #include <soc/ptable.h>
     22 #include <soc/drv.h>
     23 #include <soc/td2_td2p.h>
     24 #include <soc/mcm/memacc.h>
     25 #include <bcm/error.h>
     26 #include <bcm/port.h>
     27 
     28 #include <bcm_int/api_xlate_port.h>
     29 #include <bcm_int/esw/trident2plus.h>
     30 #include <bcm_int/esw/trident.h>
     31 #include <bcm_int/esw/trx.h>
     32 #include <bcm_int/esw/triumph3.h>
     33 #include <bcm_int/esw/triumph2.h>
     34 #include <bcm_int/common/multicast.h>
     35 #include <bcm_int/esw/trunk.h>
     36 #include <bcm_int/esw/port.h>
     37 #include <bcm_int/esw/ipmc.h>
     38 #include <bcm_int/esw/virtual.h>
     39 #if defined(BCM_TRIDENT3_SUPPORT)
     40 #include <bcm_int/esw/trident3.h>
     41 #endif
     42 
     43 #define BCMI_MAX_COE_MODULE_ID         255
     44 #define BCMI_NUM_PORTS_PER_COE_MODULE  128
     45 
     46 #define BCMI_VP_GROUP_VP_OFFSET    ((BCMI_MAX_COE_MODULE_ID * \
     47                                       BCMI_NUM_PORTS_PER_COE_MODULE) - 1)
     48 
     49 #define BCMI_VP_GROUP_GLP_COUNT    ((BCMI_MAX_COE_MODULE_ID * \
     50                                       BCMI_NUM_PORTS_PER_COE_MODULE))
     51 
     52 #define BCMI_VP_GROUP_GLP_MODID_SHIFT    7
     53 #define BCMI_VP_GROUP_GLP_MODID_MASK     0xff
     54 #define BCMI_VP_GROUP_GLP_PORT_SHIFT     0
     55 #define BCMI_VP_GROUP_GLP_PORT_MASK      0x7f
     56 
     57 #define BCMI_VP_GROUP_SUBPORT_MODID_GET(_gport)    \
     58         (((_gport) >> BCMI_VP_GROUP_GLP_MODID_SHIFT) & \
     59                     BCMI_VP_GROUP_GLP_MODID_MASK)
     60 
     61 #define BCMI_VP_GROUP_SUBPORT_PORT_GET(_gport)     \
     62         (((_gport) >> BCMI_VP_GROUP_GLP_PORT_SHIFT) & \
     63                     BCMI_VP_GROUP_GLP_PORT_MASK)
     64 
     65 #define VP_FILTER_DISABLE      0
     66 #define VP_FILTER_VP_GRP_BMAP  1
     67 #define VP_FILTER_HASH         2
     68 #define VP_DO_NOT_CHECK        3
     69 
     70 #define GPP_FILTER_DISABLE      0
     71 #define GPP_FILTER_ING_PORT     1
     72 #define GPP_FILTER_HASH         2
     73 #define GPP_FILTER_VP_GRP_BMAP  3
     74 
     75 #define _BCM_DEFAULT_STP_STATE        0 /* Disabled */
     76 #define _BCM_DEFAULT_UNTAGGED_STATE   0
     77 
     78 #define _BCM_INVALID_STG            -1
     79 #define _BCM_INVALID_VP_GROUP       -1
     80 #define _BCM_INVALID_VFI_PROFILE    -1
     81 
     82 #define BCM_MN_VPN_MAX             2047
     83 #define BCM_MN_VPN_COUNT           (BCM_MN_VPN_MAX - BCM_VPN_MIN + 1)
     84 
     85 STATIC soc_field_t _bcm_vp_group_stp_field[64] = {
     86     SP_TREE_VP_GRP0f,
     87     SP_TREE_VP_GRP1f,
     88     SP_TREE_VP_GRP2f,
     89     SP_TREE_VP_GRP3f,
     90     SP_TREE_VP_GRP4f,
     91     SP_TREE_VP_GRP5f,
     92     SP_TREE_VP_GRP6f,
     93     SP_TREE_VP_GRP7f,
     94     SP_TREE_VP_GRP8f,
     95     SP_TREE_VP_GRP9f,
     96     SP_TREE_VP_GRP10f,
     97     SP_TREE_VP_GRP11f,
     98     SP_TREE_VP_GRP12f,
     99     SP_TREE_VP_GRP13f,
    100     SP_TREE_VP_GRP14f,
    101     SP_TREE_VP_GRP15f,
    102     SP_TREE_VP_GRP16f,
    103     SP_TREE_VP_GRP17f,
    104     SP_TREE_VP_GRP18f,
    105     SP_TREE_VP_GRP19f,
    106     SP_TREE_VP_GRP20f,
    107     SP_TREE_VP_GRP21f,
    108     SP_TREE_VP_GRP22f,
    109     SP_TREE_VP_GRP23f,
    110     SP_TREE_VP_GRP24f,
    111     SP_TREE_VP_GRP25f,
    112     SP_TREE_VP_GRP26f,
    113     SP_TREE_VP_GRP27f,
    114     SP_TREE_VP_GRP28f,
    115     SP_TREE_VP_GRP29f,
    116     SP_TREE_VP_GRP30f,
    117     SP_TREE_VP_GRP31f,
    118     SP_TREE_VP_GRP32f,
    119     SP_TREE_VP_GRP33f,
    120     SP_TREE_VP_GRP34f,
    121     SP_TREE_VP_GRP35f,
    122     SP_TREE_VP_GRP36f,
    123     SP_TREE_VP_GRP37f,
    124     SP_TREE_VP_GRP38f,
    125     SP_TREE_VP_GRP39f,
    126     SP_TREE_VP_GRP40f,
    127     SP_TREE_VP_GRP41f,
    128     SP_TREE_VP_GRP42f,
    129     SP_TREE_VP_GRP43f,
    130     SP_TREE_VP_GRP44f,
    131     SP_TREE_VP_GRP45f,
    132     SP_TREE_VP_GRP46f,
    133     SP_TREE_VP_GRP47f,
    134     SP_TREE_VP_GRP48f,
    135     SP_TREE_VP_GRP49f,
    136     SP_TREE_VP_GRP50f,
    137     SP_TREE_VP_GRP51f,
    138     SP_TREE_VP_GRP52f,
    139     SP_TREE_VP_GRP53f,
    140     SP_TREE_VP_GRP54f,
    141     SP_TREE_VP_GRP55f,
    142     SP_TREE_VP_GRP56f,
    143     SP_TREE_VP_GRP57f,
    144     SP_TREE_VP_GRP58f,
    145     SP_TREE_VP_GRP59f,
    146     SP_TREE_VP_GRP60f,
    147     SP_TREE_VP_GRP61f,
    148     SP_TREE_VP_GRP62f,
    149     SP_TREE_VP_GRP63f
    150 };
    151 
    152 /* Internal functions */
    153 STATIC int _bcm_td2p_vlan_vfi_mbrship_profile_entry_set(int unit,
    154                                               bcm_vlan_t vlan_vpn,
    155                                               int egress,
    156                                               void *entry_data);
    157 STATIC int _bcm_td2p_vlan_vpn_mbrship_profile_get(int unit,
    158                                             bcm_vlan_t vlan_vpn,
    159                                             int egress, 
    160                                             uint32 *prof_index);
    161 STATIC int _bcm_td2p_vlan_vpn_mbrship_profile_set(int unit,
    162                                             bcm_vlan_t vlan_vpn,
    163                                             int egress, 
    164                                             int prof_index);
    165 
    166 STATIC int bcm_td2p_vp_group_port_filter_get(int unit, int port,
    167                                             int egress, int *vp_group, int *filter);
    168 STATIC int _bcm_td2p_gpp_hw_index_get(int unit, int port, int *hw_index);
    169 STATIC int _bcm_td2p_vp_group_resolve_port_num(int unit, int port, int *port_offset);
    170 
    171 
    172 /* --------------------------------------------------------
    173  * Software book keeping for virtual port group information
    174  * --------------------------------------------------------
    175  */
    176 
    177 typedef struct _bcm_td2p_vp_group_s {
    178     int gpp_vp_count;          /* Number of VPs and GPPs that belong to this VP group */
    179     int stp_state;
    180     int ut_state;
    181 
    182     SHR_BITDCL *gpp_vp_bitmap; /* Bitmap of VPs and GPPs that belong to this VP group */
    183     SHR_BITDCL *vlan_vfi_bitmap;  /* VLANs and VFIs this VP group belongs to */
    184 } _bcm_td2p_vp_group_t;
    185 
    186 
    187 typedef struct _bcm_td2p_vp_group_bk_s {
    188     int vp_group_initialized; /* Flag to check initialized status */
    189     int num_ing_vp_group;     /* Number of ingress VP groups */
    190     _bcm_td2p_vp_group_t *ing_vp_group_array; /* Ingress VP group array */
    191     int num_eg_vp_group;      /* Number of egress VP groups */
    192     _bcm_td2p_vp_group_t *eg_vp_group_array; /* Egress VP group array */
    193 } _bcm_td2p_vp_group_bk_t;
    194 
    195 typedef struct {
    196     int ingress;
    197     int egress;
    198 } _bcm_td2p_vp_group_unmanaged_t;
    199 
    200 STATIC _bcm_td2p_vp_group_bk_t _bcm_td2p_vp_group_bk[BCM_MAX_NUM_UNITS];
    201 
    202 STATIC _bcm_td2p_vp_group_unmanaged_t 
    203         _bcm_td2p_vp_group_unmanaged[BCM_MAX_NUM_UNITS];
    204 
    205 STATIC sal_mutex_t _bcm_vp_group_ing_mutex[BCM_MAX_NUM_UNITS] = {NULL};
    206 STATIC sal_mutex_t _bcm_vp_group_egr_mutex[BCM_MAX_NUM_UNITS] = {NULL};
    207 
    208 
    209 /* 
    210  * VP Group resource lock
    211  */
    212 #define VP_GROUP_ING_LOCK(unit) \
    213         sal_mutex_take(_bcm_vp_group_ing_mutex[unit], sal_mutex_FOREVER); 
    214 
    215 #define VP_GROUP_EGR_LOCK(unit) \
    216         sal_mutex_take(_bcm_vp_group_egr_mutex[unit], sal_mutex_FOREVER); 
    217 
    218 #define VP_GROUP_ING_UNLOCK(unit) \
    219         sal_mutex_give(_bcm_vp_group_ing_mutex[unit]); 
    220 
    221 #define VP_GROUP_EGR_UNLOCK(unit) \
    222         sal_mutex_give(_bcm_vp_group_egr_mutex[unit]); 
    223 
    224 #define VP_GROUP_LOCK_MEMS(unit, egress) \
    225         if(!egress) { \
    226             VP_GROUP_ING_LOCK(unit); \
    227         } else { \
    228             VP_GROUP_EGR_LOCK(unit); \
    229         }
    230 
    231 #define VP_GROUP_UNLOCK_MEMS(unit, egress) \
    232         if(!egress) { \
    233             VP_GROUP_ING_UNLOCK(unit); \
    234         } else { \
    235             VP_GROUP_EGR_UNLOCK(unit); \
    236         }
    237 
    238 const char * _bcm_vp_group_access_type_strs[] = {
    239     "GLP",
    240     "VP",
    241     "STG"
    242 };
    243 
    244 const char * _bcm_vp_group_port_type_strs[] = {
    245     "Front-Panel",
    246     "GLP",
    247     "VP"
    248 };
    249 
    250 #define VP_GROUP_BK(unit) (&_bcm_td2p_vp_group_bk[unit])
    251 
    252 #define VP_GROUP_INIT(unit)                              \
    253     do {                                                 \
    254         if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { \
    255             return BCM_E_UNIT;                           \
    256         }                                                \
    257         if (!VP_GROUP_BK(unit)->vp_group_initialized) {  \
    258             return BCM_E_INIT;                           \
    259         }                                                \
    260     } while (0)
    261 
    262 #define ING_VP_GROUP(unit, vp_group) \
    263     (&VP_GROUP_BK(unit)->ing_vp_group_array[vp_group])
    264 
    265 #define EG_VP_GROUP(unit, vp_group) \
    266     (&VP_GROUP_BK(unit)->eg_vp_group_array[vp_group])
    267 
    268 #define ING_STG_GROUP_DATA(unit, stg) \
    269     (&VP_GROUP_BK(unit)->ing_vp_group_array[vp_group])
    270 
    271 #define TD2P_EGR_DVP_ATTRIBUTE_FIELD(_type,_sf) \
    272         (_type) == 1 ? TRILL__##_sf: \
    273         (_type) == 2 ? VXLAN__##_sf: \
    274         (_type) == 3 ? L2GRE__##_sf: \
    275         COMMON__##_sf;
    276 
    277 #define VP_GROUP_SP_TREE_FIELD(_vp_group) \
    278         SP_TREE_VP_GRP##_vp_group##f
    279 
    280 #define VP_GROUP_CLEANUP(op) \
    281     do { int __rv__; if ((__rv__ = (op)) < 0) { goto cleanup; } } while(0)
    282 
    283 /*
    284  * Function:
    285  *      _bcm_td2p_vp_group_free_resources
    286  * Purpose:
    287  *      Free VP group data structures. 
    288  * Parameters:
    289  *      unit - SOC unit number
    290  * Returns:
    291  *      Nothing
    292  */
    293 STATIC void
    294 _bcm_td2p_vp_group_free_resources(int unit)
    295 {
    296     int num_vp_groups, i;
    297 
    298     if (VP_GROUP_BK(unit)->ing_vp_group_array) {
    299         num_vp_groups = soc_mem_field_length(unit, ING_VLAN_VFI_MEMBERSHIPm,
    300                 VP_GROUP_BITMAPf);
    301         for (i = 0; i < num_vp_groups; i++) {
    302             if (ING_VP_GROUP(unit, i)->gpp_vp_bitmap) {
    303                 sal_free(ING_VP_GROUP(unit, i)->gpp_vp_bitmap);
    304                 ING_VP_GROUP(unit, i)->gpp_vp_bitmap = NULL;
    305             }
    306             if (ING_VP_GROUP(unit, i)->vlan_vfi_bitmap) {
    307                 sal_free(ING_VP_GROUP(unit, i)->vlan_vfi_bitmap);
    308                 ING_VP_GROUP(unit, i)->vlan_vfi_bitmap = NULL;
    309             }
    310         }
    311         sal_free(VP_GROUP_BK(unit)->ing_vp_group_array);
    312         VP_GROUP_BK(unit)->ing_vp_group_array = NULL;
    313     }
    314 
    315     if (_bcm_vp_group_ing_mutex[unit]) {
    316         sal_mutex_destroy(_bcm_vp_group_ing_mutex[unit]);
    317         _bcm_vp_group_ing_mutex[unit] = NULL;
    318     }
    319 
    320     if (VP_GROUP_BK(unit)->eg_vp_group_array) {
    321         num_vp_groups = soc_mem_field_length(unit, EGR_VLAN_VFI_MEMBERSHIPm,
    322                 VP_GROUP_BITMAPf);
    323         for (i = 0; i < num_vp_groups; i++) {
    324             if (EG_VP_GROUP(unit, i)->gpp_vp_bitmap) {
    325                 sal_free(EG_VP_GROUP(unit, i)->gpp_vp_bitmap);
    326                 EG_VP_GROUP(unit, i)->gpp_vp_bitmap = NULL;
    327             }
    328             if (EG_VP_GROUP(unit, i)->vlan_vfi_bitmap) {
    329                 sal_free(EG_VP_GROUP(unit, i)->vlan_vfi_bitmap);
    330                 EG_VP_GROUP(unit, i)->vlan_vfi_bitmap = NULL;
    331             }
    332         }
    333         sal_free(VP_GROUP_BK(unit)->eg_vp_group_array);
    334         VP_GROUP_BK(unit)->eg_vp_group_array = NULL;
    335     }
    336 
    337     if (_bcm_vp_group_egr_mutex[unit]) {
    338         sal_mutex_destroy(_bcm_vp_group_egr_mutex[unit]);
    339         _bcm_vp_group_egr_mutex[unit] = NULL;
    340     }
    341 
    342     return;
    343 }
    344 
    345 /*
    346  * Function:
    347  *      _td2p_egr_dvp_attribute_field_name_get
    348  * Purpose:
    349  *      Retrieve the proper field name based the device and vp type.
    350  * Parameters:
    351  *      unit - SOC unit number.
    352  * Returns:
    353  *      BCM_E_XXX
    354  */
    355 STATIC int
    356 _td2p_egr_dvp_attribute_field_name_get(int unit,
    357                          void *dvp_entry,
    358                          soc_field_t legacy_name,
    359                          soc_field_t *result_name)
    360 {
    361     int vp_type;
    362     soc_field_t vpt_fld = DATA_TYPEf;
    363 
    364     if (soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, VP_TYPEf)) {
    365         vpt_fld = VP_TYPEf;
    366     }
    367 
    368     vp_type = soc_EGR_DVP_ATTRIBUTEm_field32_get(unit,
    369                 (egr_dvp_attribute_entry_t *)dvp_entry, vpt_fld);
    370     switch (legacy_name) {
    371         case EN_EFILTERf:
    372             *result_name = TD2P_EGR_DVP_ATTRIBUTE_FIELD(vp_type, EN_EFILTERf);
    373             break;
    374         case VLAN_MEMBERSHIP_PROFILEf:
    375             *result_name = TD2P_EGR_DVP_ATTRIBUTE_FIELD(vp_type,
    376                     VLAN_MEMBERSHIP_PROFILEf);
    377             break;
    378         default:
    379             return BCM_E_NOT_FOUND;
    380             break;
    381     }
    382     return BCM_E_NONE;
    383 }
    384 
    385 #ifdef BCM_WARM_BOOT_SUPPORT
    386 /*
    387  * Function:
    388  *      _bcm_td2p_vp_group_reinit
    389  * Purpose:
    390  *      Recover the virtual port group data structures.
    391  * Parameters:
    392  *      unit - SOC unit number.
    393  * Returns:
    394  *      BCM_E_XXX
    395  */
    396 STATIC int
    397 _bcm_td2p_vp_group_reinit(int unit)
    398 {
    399     
    400 
    401     int rv = BCM_E_NONE;
    402     uint8 *source_vp_buf = NULL;
    403     uint8 *vlan_buf = NULL;
    404     uint8 *egr_dvp_buf = NULL;
    405     uint8 *vlan_vfi_mbrship_buf = NULL;
    406     uint8 *vlan_mpls_buf = NULL;
    407     int profile_ptr = 0;
    408     uint8 *egr_vlan_buf = NULL;
    409     int index_min, index_max;
    410     int i, k;
    411     source_vp_entry_t *svp_entry;
    412     int vp_group;
    413     vlan_tab_entry_t *vlan_entry = NULL;
    414     vlan_mpls_entry_t *vlan_mpls_entry;
    415 #if defined(BCM_TRIDENT3_SUPPORT)
    416     vlan_attrs_1_entry_t *vlan_attrs_entry;
    417 #endif
    418     soc_mem_t vlan_mpls_mem = VLAN_MPLSm;
    419     uint32 fldbuf[2];
    420     egr_dvp_attribute_entry_t *egr_dvp_entry = NULL;
    421     egr_vlan_entry_t *egr_vlan_entry = NULL;
    422     ing_vlan_vfi_membership_entry_t *ing_vlan_vfi_mbrship = NULL;
    423     egr_vlan_vfi_membership_entry_t *egr_vlan_vfi_mbrship = NULL;
    424     soc_field_t en_efilter_f;
    425     soc_field_t vm_prof_f;
    426     uint8                *vfi_buf       = NULL;
    427     vfi_entry_t          *vfi_entry     = NULL;
    428     egr_vfi_entry_t      *egr_vfi_entry = NULL;
    429     uint8                *stg_buf       = NULL;
    430     stg_tab_entry_t      *stg_entry     = NULL;
    431     egr_vlan_stg_entry_t *egr_stg_entry = NULL;
    432     int                   stg           = BCM_STG_DEFAULT;
    433     uint32                ut_grp_bmap[SOC_PBMP_WORD_MAX] = {0};
    434 
    435     if (soc_feature(unit, soc_feature_vp_group_ingress_vlan_membership)) {
    436 
    437         if(!bcm_td2p_ing_vp_group_unmanaged_get(unit)) {
    438             /* Recover ingress VP group's virtual ports from SOURCE_VP table */
    439 
    440             source_vp_buf = soc_cm_salloc(unit,
    441                     SOC_MEM_TABLE_BYTES(unit, SOURCE_VPm), "SOURCE_VP buffer");
    442             if (NULL == source_vp_buf) {
    443                 rv = BCM_E_MEMORY;
    444                 goto cleanup;
    445             }
    446 
    447             index_min = soc_mem_index_min(unit, SOURCE_VPm);
    448             index_max = soc_mem_index_max(unit, SOURCE_VPm);
    449             rv = soc_mem_read_range(unit, SOURCE_VPm, MEM_BLOCK_ANY,
    450                     index_min, index_max, source_vp_buf);
    451             if (SOC_FAILURE(rv)) {
    452                 goto cleanup;
    453             }
    454 
    455             for (i = index_min; i <= index_max; i++) {
    456                 svp_entry = soc_mem_table_idx_to_pointer
    457                     (unit, SOURCE_VPm, source_vp_entry_t *, source_vp_buf, i);
    458 
    459                 if (soc_SOURCE_VPm_field32_get(unit, svp_entry,
    460                                                ENABLE_IFILTERf) != 1) {
    461                     continue;
    462                 }
    463 
    464                 vp_group = soc_SOURCE_VPm_field32_get(unit, svp_entry,
    465                         VLAN_MEMBERSHIP_PROFILEf);
    466                 SHR_BITSET(ING_VP_GROUP(unit, vp_group)->gpp_vp_bitmap,
    467                            BCMI_VP_GROUP_VP_OFFSET + i);
    468                 ING_VP_GROUP(unit, vp_group)->gpp_vp_count++;
    469             }
    470 
    471             soc_cm_sfree(unit, source_vp_buf);
    472             source_vp_buf = NULL;
    473         }
    474         /* Recover ingress VP group's vlans from VLAN table */
    475 #if defined(BCM_TRIDENT3_SUPPORT)
    476         if (SOC_IS_TRIDENT3X(unit)) {
    477             vlan_mpls_mem = VLAN_ATTRS_1m;
    478         }
    479 #endif
    480         vlan_mpls_buf = soc_cm_salloc(unit,
    481                 SOC_MEM_TABLE_BYTES(unit, vlan_mpls_mem), "VLAN_MPLS buffer");
    482         if (NULL == vlan_mpls_buf) {
    483             rv = BCM_E_MEMORY;
    484             goto cleanup;
    485         }
    486         index_min = soc_mem_index_min(unit, vlan_mpls_mem);
    487         index_max = soc_mem_index_max(unit, vlan_mpls_mem);
    488         rv = soc_mem_read_range(unit, vlan_mpls_mem, MEM_BLOCK_ANY,
    489                 index_min, index_max, vlan_mpls_buf);
    490         if (SOC_FAILURE(rv)) {
    491             goto cleanup;
    492         }
    493 
    494         vlan_vfi_mbrship_buf = soc_cm_salloc(unit,
    495                 SOC_MEM_TABLE_BYTES(unit, ING_VLAN_VFI_MEMBERSHIPm), 
    496                 "ING_VLAN_VFI buffer");
    497         if (NULL == vlan_vfi_mbrship_buf) {
    498             rv = BCM_E_MEMORY;
    499             goto cleanup;
    500         }
    501         index_min = soc_mem_index_min(unit, ING_VLAN_VFI_MEMBERSHIPm);
    502         index_max = soc_mem_index_max(unit, ING_VLAN_VFI_MEMBERSHIPm);
    503         rv = soc_mem_read_range(unit, ING_VLAN_VFI_MEMBERSHIPm, 
    504                  MEM_BLOCK_ANY, index_min, index_max, vlan_vfi_mbrship_buf);
    505         if (SOC_FAILURE(rv)) {
    506             goto cleanup;
    507         }
    508 
    509         stg_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, STG_TABm),
    510                                 "STG_TAB buffer");
    511         if (NULL == stg_buf) {
    512             rv = BCM_E_MEMORY;
    513             goto cleanup;
    514         }
    515         index_min = soc_mem_index_min(unit, STG_TABm);
    516         index_max = soc_mem_index_max(unit, STG_TABm);
    517         rv = soc_mem_read_range(unit, STG_TABm, MEM_BLOCK_ANY,
    518                                 index_min, index_max, stg_buf);
    519         if (SOC_FAILURE(rv)) {
    520             goto cleanup;
    521         }
    522 
    523         vlan_buf = soc_cm_salloc(unit,
    524                                  SOC_MEM_TABLE_BYTES(unit, VLAN_TABm),
    525                                  "VLAN_TAB buffer");
    526         if (NULL == vlan_buf) {
    527             rv = BCM_E_MEMORY;
    528             goto cleanup;
    529         }
    530         index_min = soc_mem_index_min(unit, VLAN_TABm);
    531         index_max = soc_mem_index_max(unit, VLAN_TABm);
    532         rv = soc_mem_read_range(unit, VLAN_TABm, MEM_BLOCK_ANY,
    533                                 index_min, index_max, vlan_buf);
    534         if (SOC_FAILURE(rv)) {
    535             goto cleanup;
    536         }
    537 
    538         for (i = index_min; i <= index_max; i++) {
    539             vlan_entry = soc_mem_table_idx_to_pointer
    540                 (unit, VLAN_TABm, vlan_tab_entry_t *, vlan_buf, i);
    541 
    542             if (soc_VLAN_TABm_field32_get(unit, vlan_entry, VALIDf) == 0) {
    543                 continue;
    544             }
    545 
    546             if (soc_mem_is_valid(unit, VLAN_MPLSm)) {
    547                 vlan_mpls_entry = soc_mem_table_idx_to_pointer
    548                     (unit, vlan_mpls_mem, vlan_mpls_entry_t *, vlan_mpls_buf, i);
    549                 profile_ptr = soc_mem_field32_get(unit, vlan_mpls_mem, vlan_mpls_entry,
    550                                            MEMBERSHIP_PROFILE_PTRf);
    551             }
    552 #if defined(BCM_TRIDENT3_SUPPORT)
    553             else if (soc_mem_is_valid(unit, VLAN_ATTRS_1m)) {
    554                 vlan_attrs_entry = soc_mem_table_idx_to_pointer
    555                     (unit, vlan_mpls_mem, vlan_attrs_1_entry_t *, vlan_mpls_buf, i);
    556                 profile_ptr = soc_mem_field32_get(unit, vlan_mpls_mem, vlan_attrs_entry,
    557                         MEMBERSHIP_PROFILE_PTRf);
    558             }
    559 #endif
    560 
    561             rv = _bcm_vlan_vfi_membership_profile_mem_reference(
    562                      unit, profile_ptr, 1, 0);
    563             if (SOC_FAILURE(rv)) {
    564                 goto cleanup;
    565             }
    566 
    567             if (bcm_td2p_ing_vp_group_unmanaged_get(unit)) {
    568                 continue;
    569             }
    570 
    571             if (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) {
    572                if (soc_VLAN_TABm_field32_get(unit, vlan_entry,
    573                            VIRTUAL_PORT_ENf) == 0) {
    574                    continue;
    575                }
    576             }
    577 
    578             stg = soc_VLAN_TABm_field32_get(unit, vlan_entry, STGf);
    579 
    580             ing_vlan_vfi_mbrship = soc_mem_table_idx_to_pointer(unit, 
    581                     ING_VLAN_VFI_MEMBERSHIPm, 
    582                     ing_vlan_vfi_membership_entry_t *,
    583                     vlan_vfi_mbrship_buf, profile_ptr);
    584             soc_ING_VLAN_VFI_MEMBERSHIPm_field_get(unit, ing_vlan_vfi_mbrship,
    585                     VP_GROUP_BITMAPf, fldbuf);
    586 
    587             for (k = 0; k < VP_GROUP_BK(unit)->num_ing_vp_group; k++) {
    588                 if (fldbuf[k / 32] & (1 << (k % 32))) {
    589                     /* The bit in VP_GROUP_BITMAP that corresponds to
    590                      * VP group k is set.
    591                      */
    592                     SHR_BITSET(ING_VP_GROUP(unit, k)->vlan_vfi_bitmap, i);
    593 
    594                     if (stg != BCM_STG_DEFAULT) {
    595                         stg_entry =
    596                             soc_mem_table_idx_to_pointer(unit, STG_TABm,
    597                                                          stg_tab_entry_t *,
    598                                                          stg_buf, stg);
    599                         ING_VP_GROUP(unit, k)->stp_state =
    600                             soc_STG_TABm_field32_get(unit, stg_entry,
    601                                                      _bcm_vp_group_stp_field[k]);
    602                     }
    603                 }
    604             }
    605         }
    606 
    607         soc_cm_sfree(unit, vlan_buf);
    608         soc_cm_sfree(unit, vlan_mpls_buf);
    609         vlan_buf = NULL;
    610         vlan_mpls_buf = NULL;
    611 
    612         vfi_buf =
    613             soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, VFIm), "VFI buffer");
    614         if (NULL == vfi_buf) {
    615             rv = BCM_E_MEMORY;
    616             goto cleanup;
    617         }
    618 
    619         index_min = soc_mem_index_min(unit, VFIm);
    620         index_max = soc_mem_index_max(unit, VFIm);
    621         rv = soc_mem_read_range(unit, VFIm, MEM_BLOCK_ANY,
    622                                 index_min, index_max, vfi_buf);
    623         if (SOC_FAILURE(rv)) {
    624             goto cleanup;
    625         }
    626 
    627         for (i = index_min; i <= index_max; i++) {
    628             vfi_entry =
    629                 soc_mem_table_idx_to_pointer(unit, VFIm, vfi_entry_t *,
    630                                              vfi_buf, i);
    631             profile_ptr =
    632                 soc_VFIm_field32_get(unit, vfi_entry,
    633                                      MEMBERSHIP_PROFILE_PTRf);
    634             rv = _bcm_vlan_vfi_membership_profile_mem_reference(
    635                      unit, profile_ptr, 1, 0);
    636             if (SOC_FAILURE(rv)) {
    637                 goto cleanup;
    638             }
    639 
    640             if (bcm_td2p_ing_vp_group_unmanaged_get(unit)) {
    641                 continue;
    642             }
    643 
    644             stg = soc_VFIm_field32_get(unit, vfi_entry, STGf);
    645 
    646             ing_vlan_vfi_mbrship =
    647                 soc_mem_table_idx_to_pointer(unit,
    648                                              ING_VLAN_VFI_MEMBERSHIPm,
    649                                              ing_vlan_vfi_membership_entry_t *,
    650                                              vlan_vfi_mbrship_buf, profile_ptr);
    651 
    652             soc_ING_VLAN_VFI_MEMBERSHIPm_field_get(unit, ing_vlan_vfi_mbrship,
    653                                                    VP_GROUP_BITMAPf, fldbuf);
    654             for (k = 0; k < VP_GROUP_BK(unit)->num_ing_vp_group; k++) {
    655                 if (fldbuf[k / 32] & (1 << (k % 32))) {
    656                     /* The bit in VP_GROUP_BITMAP that corresponds to
    657                      * VP group k is set.
    658                      */
    659                     SHR_BITSET(ING_VP_GROUP(unit, k)->vlan_vfi_bitmap,
    660                                BCM_VLAN_COUNT + i);
    661 
    662                     if (stg != BCM_STG_DEFAULT) {
    663                         stg_entry =
    664                             soc_mem_table_idx_to_pointer(unit, STG_TABm,
    665                                                          stg_tab_entry_t *,
    666                                                          stg_buf, stg);
    667                         ING_VP_GROUP(unit, k)->stp_state =
    668                             soc_STG_TABm_field32_get(unit, stg_entry,
    669                                 _bcm_vp_group_stp_field[k]);
    670                     }
    671                 }
    672             }
    673         }
    674 
    675         soc_cm_sfree(unit, vfi_buf);
    676         soc_cm_sfree(unit, vlan_vfi_mbrship_buf);
    677         soc_cm_sfree(unit, stg_buf);
    678         vlan_vfi_mbrship_buf = NULL;
    679         vfi_buf = NULL;
    680         stg_buf = NULL;
    681     }
    682 
    683     if (soc_feature(unit, soc_feature_vp_group_egress_vlan_membership)) {
    684         if (!bcm_td2p_egr_vp_group_unmanaged_get(unit)) {
    685             /* Recover egress VP group's virtual ports from
    686              * EGR_DVP_ATTRIBUTE table
    687              */
    688 
    689             egr_dvp_buf = soc_cm_salloc(unit,
    690                     SOC_MEM_TABLE_BYTES(unit, EGR_DVP_ATTRIBUTEm),
    691                     "EGR_DVP buffer");
    692             if (NULL == egr_dvp_buf) {
    693                 rv = BCM_E_MEMORY;
    694                 goto cleanup;
    695             }
    696 
    697             index_min = soc_mem_index_min(unit, EGR_DVP_ATTRIBUTEm);
    698             index_max = soc_mem_index_max(unit, EGR_DVP_ATTRIBUTEm);
    699             rv = soc_mem_read_range(unit, EGR_DVP_ATTRIBUTEm, MEM_BLOCK_ANY,
    700                     index_min, index_max, egr_dvp_buf);
    701             if (SOC_FAILURE(rv)) {
    702                 goto cleanup;
    703             }
    704 
    705             for (i = index_min; i <= index_max; i++) {
    706                 egr_dvp_entry = soc_mem_table_idx_to_pointer
    707                     (unit, EGR_DVP_ATTRIBUTEm, egr_dvp_attribute_entry_t *,
    708                      egr_dvp_buf, i);
    709 
    710                 BCM_IF_ERROR_RETURN(_td2p_egr_dvp_attribute_field_name_get(unit,
    711                              egr_dvp_entry, EN_EFILTERf, &en_efilter_f));
    712 
    713                 if (soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, egr_dvp_entry,
    714                                                        en_efilter_f) != 1) {
    715                     continue;
    716                 }
    717 
    718                 BCM_IF_ERROR_RETURN(_td2p_egr_dvp_attribute_field_name_get(unit,
    719                              egr_dvp_entry, VLAN_MEMBERSHIP_PROFILEf,
    720                              &vm_prof_f));
    721 
    722                 vp_group = soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, egr_dvp_entry,
    723                         vm_prof_f);
    724                 SHR_BITSET(EG_VP_GROUP(unit, vp_group)->gpp_vp_bitmap,
    725                            BCMI_VP_GROUP_VP_OFFSET + i);
    726                 EG_VP_GROUP(unit, vp_group)->gpp_vp_count++;
    727             }
    728 
    729             soc_cm_sfree(unit, egr_dvp_buf);
    730             egr_dvp_buf = NULL;
    731         }
    732         /* Recover egress VP group's vlans from EGR_VLAN table */
    733 
    734         vlan_vfi_mbrship_buf = soc_cm_salloc(unit,
    735                 SOC_MEM_TABLE_BYTES(unit, EGR_VLAN_VFI_MEMBERSHIPm), 
    736                 "EGR_VLAN_VFI buffer");
    737         if (NULL == vlan_vfi_mbrship_buf) {
    738             rv = BCM_E_MEMORY;
    739             goto cleanup;
    740         }
    741 
    742         index_min = soc_mem_index_min(unit, EGR_VLAN_VFI_MEMBERSHIPm);
    743         index_max = soc_mem_index_max(unit, EGR_VLAN_VFI_MEMBERSHIPm);
    744         rv = soc_mem_read_range(unit, EGR_VLAN_VFI_MEMBERSHIPm, 
    745                  MEM_BLOCK_ANY, index_min, index_max, vlan_vfi_mbrship_buf);
    746         if (SOC_FAILURE(rv)) {
    747             goto cleanup;
    748         }
    749 
    750         stg_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, EGR_VLAN_STGm),
    751                                 "EGR_VLAN_STG buffer");
    752         if (NULL == stg_buf) {
    753             rv = BCM_E_MEMORY;
    754             goto cleanup;
    755         }
    756         index_min = soc_mem_index_min(unit, EGR_VLAN_STGm);
    757         index_max = soc_mem_index_max(unit, EGR_VLAN_STGm);
    758         rv = soc_mem_read_range(unit, EGR_VLAN_STGm, MEM_BLOCK_ANY,
    759                                 index_min, index_max, stg_buf);
    760         if (SOC_FAILURE(rv)) {
    761             goto cleanup;
    762         }
    763         egr_vlan_buf = soc_cm_salloc(unit,
    764                                      SOC_MEM_TABLE_BYTES(unit, EGR_VLANm),
    765                                      "EGR_VLAN buffer");
    766         if (NULL == egr_vlan_buf) {
    767             rv = BCM_E_MEMORY;
    768             goto cleanup;
    769         }
    770 
    771         index_min = soc_mem_index_min(unit, EGR_VLANm);
    772         index_max = soc_mem_index_max(unit, EGR_VLANm);
    773         rv = soc_mem_read_range(unit, EGR_VLANm, MEM_BLOCK_ANY,
    774                                 index_min, index_max, egr_vlan_buf);
    775         if (SOC_FAILURE(rv)) {
    776             goto cleanup;
    777         }
    778 
    779         for (i = index_min; i <= index_max; i++) {
    780             egr_vlan_entry = soc_mem_table_idx_to_pointer
    781                 (unit, EGR_VLANm, egr_vlan_entry_t *, egr_vlan_buf, i);
    782 
    783             if (soc_EGR_VLANm_field32_get(unit, egr_vlan_entry, VALIDf) == 0) {
    784                 continue;
    785             }
    786 
    787             profile_ptr = soc_EGR_VLANm_field32_get(unit, egr_vlan_entry,
    788                     MEMBERSHIP_PROFILE_PTRf);
    789             rv =_bcm_vlan_vfi_membership_profile_mem_reference
    790                     (unit, profile_ptr, 1, 1);
    791             if (SOC_FAILURE(rv)) {
    792                 goto cleanup;
    793             }
    794 
    795             if (bcm_td2p_egr_vp_group_unmanaged_get(unit)) {
    796                 continue;
    797             }
    798 
    799             stg = soc_EGR_VLANm_field32_get(unit, egr_vlan_entry, STGf);
    800 #if defined(BCM_TRIDENT3_SUPPORT)
    801             if (SOC_MEM_IS_VALID(unit, EGR_VLAN_VFI_UNTAGm)) {
    802                 uint32 prof_index;
    803                 egr_vlan_vfi_untag_entry_t egr_vlan_vfi;
    804                 prof_index = soc_mem_field32_get(unit, EGR_VLANm,
    805                                 egr_vlan_entry, UNTAG_PROFILE_PTRf);
    806                 rv = READ_EGR_VLAN_VFI_UNTAGm(unit, MEM_BLOCK_ANY, prof_index,
    807                                               &egr_vlan_vfi);
    808                 if (SOC_FAILURE(rv)) {
    809                     goto cleanup;
    810                 }
    811                 soc_mem_pbmp_field_get(unit, EGR_VLAN_VFI_UNTAGm, &egr_vlan_vfi,
    812                                        UT_VP_GRP_BITMAPf, (void *)ut_grp_bmap);
    813                 rv = _bcm_vlan_vfi_untag_profile_mem_reference(unit,
    814                         prof_index, 1);
    815                 if (SOC_FAILURE(rv)) {
    816                     goto cleanup;
    817                 }
    818             } else
    819 #endif
    820             {
    821                 soc_EGR_VLANm_field_get(unit, egr_vlan_entry,
    822                                         UT_VP_GRP_BITMAPf, ut_grp_bmap);
    823             }
    824 
    825             egr_vlan_vfi_mbrship = soc_mem_table_idx_to_pointer(unit,
    826                     EGR_VLAN_VFI_MEMBERSHIPm, 
    827                     egr_vlan_vfi_membership_entry_t *,
    828                     vlan_vfi_mbrship_buf, profile_ptr);
    829             soc_EGR_VLAN_VFI_MEMBERSHIPm_field_get(unit, egr_vlan_vfi_mbrship,
    830                         VP_GROUP_BITMAPf, fldbuf);
    831 
    832             for (k = 0; k < VP_GROUP_BK(unit)->num_eg_vp_group; k++) {
    833                 if (fldbuf[k / 32] & (1 << (k % 32))) {
    834                     /* The bit in VP_GROUP_BITMAP that corresponds to
    835                      * VP group k is set.
    836                      */
    837                     SHR_BITSET(EG_VP_GROUP(unit, k)->vlan_vfi_bitmap, i);
    838 
    839                     if (stg != BCM_STG_DEFAULT) {
    840                         egr_stg_entry =
    841                             soc_mem_table_idx_to_pointer(unit, EGR_VLAN_STGm,
    842                                                          egr_vlan_stg_entry_t *,
    843                                                          stg_buf, stg);
    844                         EG_VP_GROUP(unit, k)->stp_state =
    845                             soc_EGR_VLAN_STGm_field32_get(unit, egr_stg_entry,
    846                                 _bcm_vp_group_stp_field[k]);
    847                     }
    848 
    849                     EG_VP_GROUP(unit, k)->ut_state =
    850                         (ut_grp_bmap[k / 32] & (1 << (k % 32)));
    851 
    852                 }
    853             }
    854         }
    855         
    856         soc_cm_sfree(unit, egr_vlan_buf);
    857         egr_vlan_buf = NULL;
    858 
    859         vfi_buf =
    860             soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, EGR_VFIm),
    861                           "EGR_VFI buffer");
    862         if (NULL == vfi_buf) {
    863             rv = BCM_E_MEMORY;
    864             goto cleanup;
    865         }
    866 
    867         index_min = soc_mem_index_min(unit, EGR_VFIm);
    868         index_max = soc_mem_index_max(unit, EGR_VFIm);
    869         rv = soc_mem_read_range(unit, EGR_VFIm, MEM_BLOCK_ANY,
    870                                 index_min, index_max, vfi_buf);
    871         if (SOC_FAILURE(rv)) {
    872             goto cleanup;
    873         }
    874 
    875         for (i = index_min; i <= index_max; i++) {
    876             egr_vfi_entry =
    877                 soc_mem_table_idx_to_pointer(unit, EGR_VFIm, egr_vfi_entry_t *,
    878                                              vfi_buf, i);
    879             profile_ptr =
    880                 soc_EGR_VFIm_field32_get(unit, egr_vfi_entry,
    881                                          MEMBERSHIP_PROFILE_PTRf);
    882             rv = _bcm_vlan_vfi_membership_profile_mem_reference(
    883                      unit, profile_ptr, 1, 1);
    884             if (SOC_FAILURE(rv)) {
    885                 goto cleanup;
    886             }
    887 
    888             if (bcm_td2p_egr_vp_group_unmanaged_get(unit)) {
    889                 continue;
    890             }
    891 
    892             stg = soc_EGR_VFIm_field32_get(unit, egr_vfi_entry, STGf);
    893 #if defined(BCM_TRIDENT3_SUPPORT)
    894             if (SOC_MEM_IS_VALID(unit, EGR_VLAN_VFI_UNTAGm)) {
    895                 uint32 prof_index;
    896                 egr_vlan_vfi_untag_entry_t egr_vlan_vfi;
    897                 prof_index = soc_mem_field32_get(unit, EGR_VFIm,
    898                                 egr_vfi_entry, UNTAG_PROFILE_PTRf);
    899                 rv = READ_EGR_VLAN_VFI_UNTAGm(unit, MEM_BLOCK_ANY, prof_index,
    900                                               &egr_vlan_vfi);
    901                 if (SOC_FAILURE(rv)) {
    902                     goto cleanup;
    903                 }
    904                 soc_mem_pbmp_field_get(unit, EGR_VLAN_VFI_UNTAGm, &egr_vlan_vfi,
    905                                        UT_VP_GRP_BITMAPf, (void *)ut_grp_bmap);
    906                 rv = _bcm_vlan_vfi_untag_profile_mem_reference(unit,
    907                         prof_index, 1);
    908                 if (SOC_FAILURE(rv)) {
    909                     goto cleanup;
    910                 }
    911             }
    912 #endif
    913             egr_vlan_vfi_mbrship =
    914                 soc_mem_table_idx_to_pointer(unit,
    915                                              EGR_VLAN_VFI_MEMBERSHIPm,
    916                                              egr_vlan_vfi_membership_entry_t *,
    917                                              vlan_vfi_mbrship_buf, profile_ptr);
    918             soc_EGR_VLAN_VFI_MEMBERSHIPm_field_get(unit, egr_vlan_vfi_mbrship,
    919                                                    VP_GROUP_BITMAPf, fldbuf);
    920 
    921             for (k = 0; k < VP_GROUP_BK(unit)->num_eg_vp_group; k++) {
    922                 if (fldbuf[k / 32] & (1 << (k % 32))) {
    923                     /* The bit in VP_GROUP_BITMAP that corresponds to
    924                      * VP group k is set.
    925                      */
    926                     SHR_BITSET(EG_VP_GROUP(unit, k)->vlan_vfi_bitmap,
    927                                BCM_VLAN_COUNT + i);
    928 
    929                     if (stg != BCM_STG_DEFAULT) {
    930                         egr_stg_entry =
    931                             soc_mem_table_idx_to_pointer(unit, EGR_VLAN_STGm,
    932                                                          egr_vlan_stg_entry_t *,
    933                                                          stg_buf, stg);
    934                         EG_VP_GROUP(unit, k)->stp_state =
    935                             soc_EGR_VLAN_STGm_field32_get(unit, egr_stg_entry,
    936                                 _bcm_vp_group_stp_field[k]);
    937                     }
    938 #if defined(BCM_TRIDENT3_SUPPORT)
    939                     if (SOC_MEM_IS_VALID(unit, EGR_VLAN_VFI_UNTAGm)) {
    940                         EG_VP_GROUP(unit, k)->ut_state =
    941                             (ut_grp_bmap[k / 32] & (1 << (k % 32)));
    942                     }
    943 #endif
    944                 }
    945             }
    946         }
    947 
    948         soc_cm_sfree(unit, vfi_buf);
    949         soc_cm_sfree(unit, vlan_vfi_mbrship_buf);
    950         soc_cm_sfree(unit, stg_buf);
    951         vlan_vfi_mbrship_buf = NULL;
    952         vfi_buf = NULL;
    953         stg_buf = NULL;
    954     }
    955 
    956 cleanup:
    957     if (source_vp_buf) {
    958         soc_cm_sfree(unit, source_vp_buf);
    959     }
    960     if (vlan_buf) {
    961         soc_cm_sfree(unit, vlan_buf);
    962     }
    963     if (vlan_mpls_buf) {
    964         soc_cm_sfree(unit, vlan_mpls_buf);
    965     }
    966     if (egr_dvp_buf) {
    967         soc_cm_sfree(unit, egr_dvp_buf);
    968     }
    969     if (egr_vlan_buf) {
    970         soc_cm_sfree(unit, egr_vlan_buf);
    971     }
    972     if (vlan_vfi_mbrship_buf) {
    973         soc_cm_sfree(unit, vlan_vfi_mbrship_buf);
    974     }
    975     if (vfi_buf) {
    976         soc_cm_sfree(unit, vfi_buf);
    977     }
    978     if (stg_buf) {
    979         soc_cm_sfree(unit, stg_buf);
    980     }
    981 
    982     return rv;
    983 }
    984 #endif /* BCM_WARM_BOOT_SUPPORT */
    985 
    986 #ifndef BCM_SW_STATE_DUMP_DISABLE
    987 /*
    988  * Function:
    989  *     bcm_td2p_vp_group_sw_dump
    990  * Purpose:
    991  *     Displays VP group information maintained by software.
    992  * Parameters:
    993  *     unit - Device unit number
    994  * Returns:
    995  *     None
    996  */
    997 void
    998 bcm_td2p_vp_group_sw_dump(int unit)
    999 {
   1000     int i, k;
   1001     int vlan_vfi_count;
   1002     int gpp_vp_bit_size, num_gpp;
   1003     int gpp_vp_count, stp_state, ut_state;
   1004 
   1005     vlan_vfi_count = BCM_VLAN_COUNT + soc_mem_index_count(unit, VFIm);
   1006     num_gpp = BCMI_MAX_COE_MODULE_ID * BCMI_NUM_PORTS_PER_COE_MODULE;
   1007     gpp_vp_bit_size = soc_mem_index_count(unit, SOURCE_VPm) + num_gpp;
   1008 
   1009     cli_out("\nSW Information Ingress VP Group - Unit %d\n", unit);
   1010     for (i = 0; i < VP_GROUP_BK(unit)->num_ing_vp_group; i++) {
   1011         gpp_vp_count = ING_VP_GROUP(unit, i)->gpp_vp_count;
   1012         stp_state = ING_VP_GROUP(unit, i)->stp_state;
   1013         ut_state = ING_VP_GROUP(unit, i)->ut_state;
   1014 
   1015         if (gpp_vp_count == 0 && stp_state == 0 &&
   1016             ut_state == 0) {
   1017             continue;
   1018         }
   1019         cli_out("\n  Ingress Group = %d, ", i);
   1020         cli_out("GPP_VP Count = %d, ", gpp_vp_count);
   1021         cli_out("STP State = %d, ", stp_state);
   1022         cli_out("Untag State = %d\n", ut_state);
   1023 
   1024         cli_out("    GPP_VP List =");
   1025         for (k = 0; k < gpp_vp_bit_size; k++) {
   1026             if (SHR_BITGET(ING_VP_GROUP(unit, i)->gpp_vp_bitmap, k)) {
   1027 
   1028                 if(k < num_gpp) {
   1029                     cli_out(" GPP (mod,port) (%d,%d)", (k % BCMI_MAX_COE_MODULE_ID),
   1030                             (k - (k % BCMI_MAX_COE_MODULE_ID)));
   1031                 } else {
   1032                     cli_out(" VP %d", k);
   1033                 }
   1034             }
   1035         }
   1036         cli_out("\n");
   1037 
   1038         cli_out("    VLAN/VFI List =");
   1039         for (k = 0; k < vlan_vfi_count; k++) {
   1040             if (SHR_BITGET(ING_VP_GROUP(unit, i)->vlan_vfi_bitmap, k)) {
   1041                 if(k <= BCM_VLAN_MAX) {
   1042                     cli_out(" vlan %d", k);
   1043                 } else {
   1044                     cli_out(" vfi %d", k);
   1045                 }
   1046             }
   1047         }
   1048         cli_out("\n");
   1049     }
   1050 
   1051     cli_out("\nSW Information Egress VP Group - Unit %d\n", unit);
   1052     for (i = 0; i < VP_GROUP_BK(unit)->num_eg_vp_group; i++) {
   1053         gpp_vp_count = EG_VP_GROUP(unit, i)->gpp_vp_count;
   1054         stp_state = EG_VP_GROUP(unit, i)->stp_state;
   1055         ut_state = EG_VP_GROUP(unit, i)->ut_state;
   1056 
   1057         if (gpp_vp_count == 0 && stp_state == 0 &&
   1058             ut_state == 0) {
   1059             continue;
   1060         }
   1061         cli_out("\n  Egress VP Group = %d, ", i);
   1062         cli_out("GPP_VP Count = %d, ", gpp_vp_count);
   1063         cli_out("STP State = %d, ", stp_state);
   1064         cli_out("Untag State = %d\n", ut_state);
   1065 
   1066         cli_out("    GPP/VP List =");
   1067         for (k = 0; k < gpp_vp_bit_size; k++) {
   1068             if (SHR_BITGET(EG_VP_GROUP(unit, i)->gpp_vp_bitmap, k)) {
   1069 
   1070                 if(k < num_gpp) {
   1071                     cli_out(" GPP (mod,port) (%d,%d)", (k % BCMI_MAX_COE_MODULE_ID),
   1072                             (k - (k % BCMI_MAX_COE_MODULE_ID)));
   1073                 } else {
   1074                     cli_out(" VP %d", k);
   1075                 }
   1076             }
   1077         }
   1078         cli_out("\n");
   1079 
   1080         cli_out("    VLAN List =");
   1081         for (k = 0; k < vlan_vfi_count; k++) {
   1082             if (SHR_BITGET(EG_VP_GROUP(unit, i)->vlan_vfi_bitmap, k)) {
   1083                 if(k <= BCM_VLAN_MAX) {
   1084                     cli_out(" vlan %d", k);
   1085                 } else {
   1086                     cli_out(" vfi %d", k);
   1087                 }
   1088             }
   1089         }
   1090         cli_out("\n");
   1091     }
   1092 
   1093     return;
   1094 }
   1095 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   1096 
   1097 /*
   1098  * Function:
   1099  *      bcm_td2p_vp_group_init
   1100  * Purpose:
   1101  *      Initialize the virtual port group data structures.
   1102  * Parameters:
   1103  *      unit - SOC unit number.
   1104  * Returns:
   1105  *      BCM_E_XXX
   1106  */
   1107 int
   1108 bcm_td2p_vp_group_init(int unit)
   1109 {
   1110     int vlan_vfi_count;
   1111     int num_vp_groups = 0, num_vp = 0; 
   1112     int num_gpp = 0, i = 0;
   1113     int rv = BCM_E_NONE;
   1114     uint32 reg_value = 0;
   1115 
   1116     _bcm_td2p_vp_group_free_resources(unit);
   1117 
   1118 #ifdef BCM_WARM_BOOT_SUPPORT
   1119     if (SOC_WARM_BOOT(unit)) {
   1120     } else
   1121 #endif
   1122     {
   1123         _bcm_td2p_vp_group_unmanaged[unit].ingress = FALSE;
   1124         _bcm_td2p_vp_group_unmanaged[unit].egress  = FALSE;
   1125     }
   1126     sal_memset(VP_GROUP_BK(unit), 0, sizeof(_bcm_td2p_vp_group_bk_t));
   1127 
   1128     num_vp_groups = soc_mem_field_length(unit, ING_VLAN_VFI_MEMBERSHIPm,
   1129             VP_GROUP_BITMAPf);
   1130     VP_GROUP_BK(unit)->num_ing_vp_group = num_vp_groups;
   1131 
   1132     if (NULL == VP_GROUP_BK(unit)->ing_vp_group_array) {
   1133         VP_GROUP_BK(unit)->ing_vp_group_array = 
   1134             sal_alloc(sizeof(_bcm_td2p_vp_group_t) * num_vp_groups,
   1135                     "ingress vp group array");
   1136         if (NULL == VP_GROUP_BK(unit)->ing_vp_group_array) {
   1137             _bcm_td2p_vp_group_free_resources(unit);
   1138             return BCM_E_MEMORY;
   1139         }
   1140     }
   1141     sal_memset(VP_GROUP_BK(unit)->ing_vp_group_array, 0,
   1142             sizeof(_bcm_td2p_vp_group_t) * num_vp_groups);
   1143 
   1144     vlan_vfi_count = BCM_VLAN_COUNT + soc_mem_index_count(unit, VFIm);
   1145     num_gpp =  BCMI_MAX_COE_MODULE_ID * BCMI_NUM_PORTS_PER_COE_MODULE;
   1146     num_vp   =  soc_mem_index_count(unit, SOURCE_VPm);
   1147 
   1148     for (i = 0; i < num_vp_groups; i++) {
   1149         if (NULL == ING_VP_GROUP(unit, i)->gpp_vp_bitmap) {
   1150             ING_VP_GROUP(unit, i)->gpp_vp_bitmap = sal_alloc
   1151                 (SHR_BITALLOCSIZE(num_gpp + num_vp),
   1152            "ingress vp group vp gpp bitmap");
   1153             if (NULL == ING_VP_GROUP(unit, i)->gpp_vp_bitmap) {
   1154                 _bcm_td2p_vp_group_free_resources(unit);
   1155                 return BCM_E_MEMORY;
   1156             }
   1157         }
   1158         sal_memset(ING_VP_GROUP(unit, i)->gpp_vp_bitmap, 0,
   1159                    (SHR_BITALLOCSIZE(num_gpp + num_vp)));
   1160 
   1161         if (NULL == ING_VP_GROUP(unit, i)->vlan_vfi_bitmap) {
   1162             ING_VP_GROUP(unit, i)->vlan_vfi_bitmap = sal_alloc
   1163                 (SHR_BITALLOCSIZE(vlan_vfi_count),
   1164                   "ingress vp group vlan vfi bitmap");
   1165             if (NULL == ING_VP_GROUP(unit, i)->vlan_vfi_bitmap) {
   1166                 _bcm_td2p_vp_group_free_resources(unit);
   1167                 return BCM_E_MEMORY;
   1168             }
   1169         }
   1170 
   1171         sal_memset(ING_VP_GROUP(unit, i)->vlan_vfi_bitmap, 0,
   1172                          SHR_BITALLOCSIZE(vlan_vfi_count));
   1173     }
   1174 
   1175     /* Enable the STG checks on Ingress VP Groups */
   1176     soc_reg_field_set(unit, VP_GROUP_CHECK_ENABLEr, &reg_value,
   1177                       STG_ENABLEf, 1);
   1178     BCM_IF_ERROR_RETURN(WRITE_VP_GROUP_CHECK_ENABLEr(unit, reg_value));
   1179     
   1180     if (NULL == _bcm_vp_group_ing_mutex[unit]) {
   1181         _bcm_vp_group_ing_mutex[unit] = sal_mutex_create("vp group ing mutex");
   1182         if (_bcm_vp_group_ing_mutex[unit] == NULL) {
   1183             _bcm_td2p_vp_group_free_resources(unit);
   1184             return BCM_E_MEMORY;
   1185         }
   1186     }
   1187 
   1188     num_vp_groups = soc_mem_field_length(unit, EGR_VLAN_VFI_MEMBERSHIPm,
   1189             VP_GROUP_BITMAPf);
   1190     VP_GROUP_BK(unit)->num_eg_vp_group = num_vp_groups;
   1191 
   1192     if (NULL == VP_GROUP_BK(unit)->eg_vp_group_array) {
   1193         VP_GROUP_BK(unit)->eg_vp_group_array = 
   1194             sal_alloc(sizeof(_bcm_td2p_vp_group_t) * num_vp_groups,
   1195                     "egress vp group array");
   1196         if (NULL == VP_GROUP_BK(unit)->eg_vp_group_array) {
   1197             _bcm_td2p_vp_group_free_resources(unit);
   1198             return BCM_E_MEMORY;
   1199         }
   1200     }
   1201 
   1202     sal_memset(VP_GROUP_BK(unit)->eg_vp_group_array, 0,
   1203             sizeof(_bcm_td2p_vp_group_t) * num_vp_groups);
   1204 
   1205     num_vp = soc_mem_index_count(unit, EGR_DVP_ATTRIBUTEm);
   1206 
   1207     for (i = 0; i < num_vp_groups; i++) {
   1208         if (NULL == EG_VP_GROUP(unit, i)->gpp_vp_bitmap) {
   1209             EG_VP_GROUP(unit, i)->gpp_vp_bitmap = sal_alloc
   1210                 (SHR_BITALLOCSIZE(num_gpp + num_vp),
   1211                  "egress vp group vp gpp bitmap");
   1212             if (NULL == EG_VP_GROUP(unit, i)->gpp_vp_bitmap) {
   1213                 _bcm_td2p_vp_group_free_resources(unit);
   1214                 return BCM_E_MEMORY;
   1215             }
   1216         }
   1217 
   1218         sal_memset(EG_VP_GROUP(unit, i)->gpp_vp_bitmap, 0,
   1219                    (SHR_BITALLOCSIZE(num_gpp + num_vp)));
   1220 
   1221         if (NULL == EG_VP_GROUP(unit, i)->vlan_vfi_bitmap) {
   1222             EG_VP_GROUP(unit, i)->vlan_vfi_bitmap = sal_alloc
   1223                 (SHR_BITALLOCSIZE(vlan_vfi_count),
   1224                  "egress vp group vlan vfi bitmap");
   1225             if (NULL == EG_VP_GROUP(unit, i)->vlan_vfi_bitmap) {
   1226                 _bcm_td2p_vp_group_free_resources(unit);
   1227                 return BCM_E_MEMORY;
   1228             }
   1229         }
   1230 
   1231         sal_memset(EG_VP_GROUP(unit, i)->vlan_vfi_bitmap, 0,
   1232                 SHR_BITALLOCSIZE(vlan_vfi_count));
   1233     }
   1234 
   1235     /* Enables the STG checks and UT deletion on Egress VP Groups */
   1236     reg_value = 0;
   1237     soc_reg_field_set(unit, EGR_VP_GROUP_CHECK_ENABLEr, &reg_value,
   1238             STG_ENABLEf, 1);
   1239     soc_reg_field_set(unit, EGR_VP_GROUP_CHECK_ENABLEr, &reg_value,
   1240             UNTAG_ENABLEf, 1);
   1241     BCM_IF_ERROR_RETURN(WRITE_EGR_VP_GROUP_CHECK_ENABLEr(unit, reg_value)); 
   1242 
   1243     if (NULL == _bcm_vp_group_egr_mutex[unit]) {
   1244         _bcm_vp_group_egr_mutex[unit] = sal_mutex_create("vp group egr mutex");
   1245         if (_bcm_vp_group_egr_mutex[unit] == NULL) {
   1246             _bcm_td2p_vp_group_free_resources(unit);
   1247             return BCM_E_MEMORY;
   1248         }
   1249     }
   1250 
   1251     VP_GROUP_BK(unit)->vp_group_initialized = 1;
   1252 
   1253 #ifdef BCM_WARM_BOOT_SUPPORT
   1254     if (SOC_WARM_BOOT(unit)) {
   1255         rv = _bcm_td2p_vp_group_reinit(unit);
   1256         if (BCM_FAILURE(rv)) {
   1257             _bcm_td2p_vp_group_free_resources(unit);
   1258         }
   1259     }
   1260 #endif /* BCM_WARM_BOOT_SUPPORT */
   1261 
   1262     return rv;
   1263 }
   1264 
   1265 /*
   1266  * Function:
   1267  *      bcm_td2p_vp_group_detach
   1268  * Purpose:
   1269  *      De-initialize the virtual port group data structures.
   1270  * Parameters:
   1271  *      unit - SOC unit number.
   1272  * Returns:
   1273  *      BCM_E_XXX
   1274  */
   1275 int
   1276 bcm_td2p_vp_group_detach(int unit)
   1277 {
   1278     _bcm_td2p_vp_group_free_resources(unit);
   1279 
   1280     VP_GROUP_BK(unit)->vp_group_initialized = 0;
   1281 
   1282     return BCM_E_NONE;
   1283 }
   1284 
   1285 /*
   1286  * Function:
   1287  *      bcm_td2p_vlan_vp_group_set
   1288  * Purpose:
   1289  *      set/clear the specified VP group in the vlan's vp group bitmap.
   1290  * Parameters:
   1291  *      unit            - (IN) Device Number
   1292  *      vlan_vpn        - (IN) vlan/vpn ID
   1293  *      egress          - (IN) TURE for egress, FALSE for ingress
   1294  *      vp_group        - (IN) the specified VP group
   1295  *      enable          - (IN) TRUE to set, FALSE to clear
   1296  * Returns:
   1297  *      BCM_E_XXX
   1298  * Notes:
   1299  *      If vp_group == -1 and enable == false, clear the vp_group bitmap
   1300  */
   1301 
   1302 int
   1303 bcm_td2p_vlan_vp_group_set(int unit, int vlan_vpn, int egress, int vp_group, int enable)
   1304 {
   1305     int rv = BCM_E_NONE;
   1306     int field_len;
   1307     int bit_exist;
   1308     uint32 profile_idx;
   1309     uint32 vp_group_bitmap[2];
   1310     soc_mem_t mbrship_mem;
   1311     uint32 mbrship_entry[SOC_MAX_MEM_WORDS];
   1312 
   1313     BCM_IF_ERROR_RETURN(_bcm_td2p_vlan_vpn_mbrship_profile_get(
   1314                             unit, vlan_vpn, egress, &profile_idx));
   1315 
   1316     if (egress) {
   1317         mbrship_mem = EGR_VLAN_VFI_MEMBERSHIPm;
   1318     } else {
   1319         mbrship_mem = ING_VLAN_VFI_MEMBERSHIPm;
   1320     }
   1321 
   1322     /* safety check */
   1323     field_len = soc_mem_field_length(unit, mbrship_mem, VP_GROUP_BITMAPf);
   1324     if (vp_group >= 0) {
   1325         if (vp_group >= field_len) {
   1326             return BCM_E_PARAM;
   1327         }
   1328     } else if (enable) {
   1329         return BCM_E_PARAM;
   1330     }
   1331 
   1332     if (field_len > sizeof(vp_group_bitmap) * 8) {
   1333         return BCM_E_INTERNAL;
   1334     }
   1335 
   1336     soc_mem_lock(unit, mbrship_mem);
   1337     if ((rv = soc_mem_read(unit, mbrship_mem, MEM_BLOCK_ANY, profile_idx,
   1338                     mbrship_entry)) != BCM_E_NONE) {
   1339         soc_mem_unlock(unit, mbrship_mem);
   1340         return rv;
   1341     }
   1342 
   1343     if (vp_group >= 0) {
   1344         soc_mem_field_get(unit, mbrship_mem, mbrship_entry,
   1345                             VP_GROUP_BITMAPf, vp_group_bitmap);
   1346         bit_exist = vp_group_bitmap[vp_group/32] & (1 << (vp_group % 32));
   1347 
   1348         if (enable) {
   1349             if (bit_exist) {
   1350                 soc_mem_unlock(unit, mbrship_mem);
   1351                 return BCM_E_NONE;
   1352             }
   1353 
   1354             vp_group_bitmap[vp_group/32] |= 1 << (vp_group%32);
   1355         } else {
   1356             if (!bit_exist) {
   1357                 soc_mem_unlock(unit, mbrship_mem);
   1358                 return BCM_E_NONE;
   1359             }
   1360 
   1361             /* clear the vp_group */
   1362             vp_group_bitmap[vp_group/32] &= ~(1 << (vp_group%32));
   1363         }
   1364     } else {
   1365         /* clear the VP group bitmap for this vlan */
   1366         sal_memset(vp_group_bitmap, 0, sizeof(vp_group_bitmap));
   1367     }
   1368 
   1369     soc_mem_field_set(unit, mbrship_mem, mbrship_entry,
   1370                     VP_GROUP_BITMAPf, vp_group_bitmap);
   1371 
   1372     rv = _bcm_td2p_vlan_vfi_mbrship_profile_entry_set(unit,
   1373                                 vlan_vpn, egress, mbrship_entry);
   1374 
   1375     soc_mem_unlock(unit, mbrship_mem);
   1376 
   1377     return rv;
   1378 }
   1379 
   1380 /*
   1381  * Function:
   1382  *      bcm_td2p_vlan_vp_group_get
   1383  * Purpose:
   1384  *      get the flags indicating the given vp group is set for
   1385  *      ingress or/and egress.
   1386  * Parameters:
   1387  *      unit            - (IN) Device Number
   1388  *      vlan_vpn        - (IN) vlan/vpn ID
   1389  *      egress          - (IN) TURE for egress, FALSE for ingress
   1390  *      vp_group        - (IN) the specified VP group
   1391  *      enable          - (OUT) usage flag
   1392  * Returns:
   1393  *      BCM_E_XXX
   1394  */
   1395 
   1396 int
   1397 bcm_td2p_vlan_vp_group_get(int unit, int vlan_vpn, int egress, int vp_group, int *enable)
   1398 {
   1399     uint32 profile_idx;
   1400     uint32 vp_group_bitmap[2];
   1401     int field_len;
   1402     soc_mem_t mbrship_mem;
   1403     uint32 mbrship_entry[SOC_MAX_MEM_WORDS];
   1404 
   1405     BCM_IF_ERROR_RETURN(_bcm_td2p_vlan_vpn_mbrship_profile_get(
   1406                             unit, vlan_vpn, egress, &profile_idx));
   1407 
   1408     if (egress) {
   1409         mbrship_mem = EGR_VLAN_VFI_MEMBERSHIPm;
   1410     } else {
   1411         mbrship_mem = ING_VLAN_VFI_MEMBERSHIPm;
   1412     }
   1413 
   1414     /* safety check */
   1415     field_len = soc_mem_field_length(unit, mbrship_mem, VP_GROUP_BITMAPf);
   1416     if (vp_group >= field_len) {
   1417         return BCM_E_PARAM;
   1418     }
   1419     if (field_len > sizeof(vp_group_bitmap) * 8) {
   1420         return BCM_E_INTERNAL;
   1421     }
   1422 
   1423     BCM_IF_ERROR_RETURN(soc_mem_read(unit,
   1424         mbrship_mem, MEM_BLOCK_ANY, profile_idx, mbrship_entry));
   1425     soc_mem_field_get(unit, mbrship_mem,
   1426         (uint32 *)mbrship_entry, VP_GROUP_BITMAPf, vp_group_bitmap);
   1427 
   1428     *enable = 0;
   1429     if (vp_group_bitmap[vp_group/32] & (1 << (vp_group % 32))) {
   1430         *enable = TRUE;
   1431     }
   1432 
   1433     return BCM_E_NONE;
   1434 }
   1435 
   1436 /*
   1437  * Function:
   1438  *      _bcm_td2p_vp_local_ports_get
   1439  * Purpose:
   1440  *      Get the local ports on which the given VP resides.
   1441  * Parameters:
   1442  *      unit       - (IN) Device Number
   1443  *      vp         - (IN) Virtual port number
   1444  *      local_port_max   - (OUT) Size of local_port_array
   1445  *      local_port_array - (OUT) Array of local ports
   1446  *      local_port_count - (OUT) Number of local ports 
   1447  * Returns:
   1448  *      BCM_E_XXX
   1449  * Notes:
   1450  *      If local_port_max = 0 and local_port_array == NULL,
   1451  *      the number of local ports will still be returned in
   1452  *      local_port_count. 
   1453  */
   1454 
   1455 STATIC int
   1456 _bcm_td2p_vp_local_ports_get(int unit, int vp, int local_port_max,
   1457         bcm_port_t *local_port_array, int *local_port_count)
   1458 {
   1459     ing_dvp_table_entry_t dvp_entry;
   1460     ing_l3_next_hop_entry_t ing_nh;
   1461     uint32 nh_index;
   1462     bcm_trunk_t trunk_id = -1;
   1463     bcm_module_t modid = 0;
   1464     bcm_port_t port = 0;
   1465     int modid_local;
   1466 
   1467     if (local_port_max < 0) {
   1468         return BCM_E_PARAM;
   1469     }
   1470 
   1471     if ((local_port_max == 0) && (NULL != local_port_array)) {
   1472         return BCM_E_PARAM;
   1473     }
   1474 
   1475     if ((local_port_max > 0) && (NULL == local_port_array)) {
   1476         return BCM_E_PARAM;
   1477     }
   1478 
   1479     if (NULL == local_port_count) {
   1480         return BCM_E_PARAM;
   1481     }
   1482 
   1483     *local_port_count = 0;
   1484 
   1485     BCM_IF_ERROR_RETURN
   1486         (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry));
   1487     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry,
   1488             NEXT_HOP_INDEXf);
   1489     BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   1490                 nh_index, &ing_nh));
   1491 
   1492     if (soc_feature(unit, soc_feature_generic_dest)) {
   1493         uint32 dest_type = SOC_MEM_FIF_DEST_INVALID, dest = 0;
   1494         dest = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, &ing_nh,
   1495                                         DESTINATIONf, &dest_type);
   1496         if (dest_type == SOC_MEM_FIF_DEST_LAG) {
   1497             trunk_id = (dest & SOC_MEM_FIF_DGPP_TGID_MASK);
   1498         } else if (dest_type == SOC_MEM_FIF_DEST_DGPP) {
   1499             modid = (dest & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
   1500                       SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
   1501             port = dest & SOC_MEM_FIF_DGPP_PORT_MASK;
   1502         }
   1503     } else {
   1504     if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
   1505         trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf);
   1506         } else {
   1507             modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
   1508             port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf);
   1509         }
   1510     }
   1511 
   1512     if (trunk_id != -1) {
   1513         BCM_IF_ERROR_RETURN
   1514             (_bcm_esw_trunk_local_members_get(unit,
   1515                                              trunk_id, 
   1516                                              local_port_max,
   1517                                              local_port_array, 
   1518                                              local_port_count));
   1519     } else {
   1520         BCM_IF_ERROR_RETURN
   1521             (_bcm_esw_modid_is_local(unit, modid, &modid_local));
   1522         if (TRUE != modid_local) {
   1523             *local_port_count = 0;
   1524             return BCM_E_NONE;
   1525         }
   1526 
   1527         *local_port_count = 1;
   1528         if (NULL != local_port_array) {
   1529             local_port_array[0] = port;
   1530         }
   1531     }
   1532 
   1533     return BCM_E_NONE;
   1534 }
   1535 
   1536 /*
   1537  * Function:
   1538  *      bcm_td2p_vlan_vp_group_get_all
   1539  * Purpose:
   1540  *      get the array of gports and flags related to the gport.
   1541  * Parameters:
   1542  *      unit       - (IN) Device Number
   1543  *      vlan       - (IN) vlan mem entry index
   1544  *      array_max  - (IN) max size of the array 
   1545  *      bcm_gport_t *gport_array  - (IN) gport array
   1546  *      flags_array -(IN) flags array related to gports
   1547  *      port_cnt   - (IN/OUT) point to the first available array entry
   1548  * Returns:
   1549  *      BCM_E_XXX
   1550  */
   1551 
   1552 int
   1553 bcm_td2p_vlan_vp_group_get_all(
   1554       int unit,           /* unit number */
   1555       int vlan,           /* index to the vlan  memory table */
   1556       int array_max,      /* max size of the array */
   1557       bcm_gport_t *gport_array,    /* gport array */
   1558       int *flags_array,            /* flags array related to gports */
   1559       int *port_cnt)      /* point to the first available array entry */
   1560 {
   1561     int num_vp_groups;
   1562     int vpg;
   1563     int ing_enable;
   1564     int egr_enable;
   1565     int rv = BCM_E_NONE;
   1566 
   1567     num_vp_groups = soc_mem_field_length(unit, ING_VLAN_VFI_MEMBERSHIPm,
   1568             VP_GROUP_BITMAPf);
   1569 
   1570     for (vpg = 0; vpg < num_vp_groups; vpg++) {
   1571         ing_enable = 0;
   1572         egr_enable = 0;
   1573         if ((*port_cnt == array_max) && (gport_array || flags_array)) {
   1574             break;
   1575         }
   1576         if (flags_array) {
   1577             flags_array[*port_cnt] = 0;
   1578         }
   1579         if (soc_feature(unit,
   1580                   soc_feature_vp_group_ingress_vlan_membership) &&
   1581                   bcm_td2p_ing_vp_group_unmanaged_get(unit)) {
   1582             rv = bcm_td2p_vlan_vp_group_get(unit,vlan, FALSE, vpg, &ing_enable);
   1583             BCM_IF_ERROR_RETURN(rv);
   1584             if (ing_enable) {
   1585                 if (gport_array) {
   1586                     BCM_GPORT_VP_GROUP_SET(gport_array[*port_cnt],vpg);
   1587                 }
   1588                 if (flags_array) {
   1589                     flags_array[*port_cnt] = BCM_VLAN_PORT_INGRESS_ONLY;
   1590                 }
   1591             }
   1592         }
   1593         if (soc_feature(unit,
   1594                  soc_feature_vp_group_egress_vlan_membership) &&
   1595                  bcm_td2p_egr_vp_group_unmanaged_get(unit)) {
   1596             rv = bcm_td2p_vlan_vp_group_get(unit,vlan, TRUE, vpg, &egr_enable);
   1597             BCM_IF_ERROR_RETURN(rv);
   1598             if (egr_enable) {
   1599                 if (gport_array) {
   1600                     BCM_GPORT_VP_GROUP_SET(gport_array[*port_cnt],vpg);
   1601                 }
   1602                 if (flags_array) {
   1603                     flags_array[*port_cnt] |= BCM_VLAN_PORT_EGRESS_ONLY;
   1604                 }
   1605             }
   1606         }
   1607         if (ing_enable || egr_enable) {
   1608             (*port_cnt)++;
   1609         }
   1610     }
   1611     return BCM_E_NONE;
   1612 }
   1613 
   1614 /*
   1615  * Function:
   1616  *      _bcm_td2p_vp_vlan_vfi_bitmap_get
   1617  * Purpose:
   1618  *      Get a bitmap of all the VLANs the given VP belongs to.
   1619  * Parameters:
   1620  *      unit        - (IN) BCM device number
   1621  *      vp_gport    - (IN) VP gport ID 
   1622  *      vlan_vfi_bitmap - (OUT) Bitmap of VLANs
   1623  * Returns:
   1624  *      BCM_E_XXX
   1625  */
   1626 STATIC int
   1627 _bcm_td2p_vp_vlan_vfi_bitmap_get(int unit, bcm_gport_t vp_gport, SHR_BITDCL *vlan_vfi_bitmap)
   1628 {
   1629     int rv;
   1630     int vp;
   1631     int mc_type;
   1632     source_vp_entry_t svp_entry;
   1633     int vp_group;
   1634     egr_dvp_attribute_entry_t egr_dvp_entry;
   1635     bcm_port_t local_port;
   1636     int local_port_count;
   1637     int vlan_vfi_count;
   1638     uint8 *vlan_tab_buf = NULL;
   1639     uint8 *vfi_tab_buf = NULL;
   1640     int if_max, if_count = 0;
   1641     bcm_if_t *if_array = NULL;
   1642     int i, j, k;
   1643     vlan_tab_entry_t *vlan_tab_entry = NULL;
   1644     vfi_entry_t *vfi_entry = NULL;
   1645     int mc_index_array[3];
   1646     int match_prev_mc_index = FALSE;
   1647     bcm_multicast_t group;
   1648     bcm_gport_t local_gport;
   1649     bcm_if_t encap_id;
   1650     int match = FALSE;
   1651     bcm_trunk_member_t *member_array = NULL;
   1652     int member_count, member_max;
   1653     bcm_trunk_chip_info_t trunk_chip_info;
   1654     SHR_BITDCL *vlan_vfi_bitmap_tmp = NULL;
   1655 
   1656     if(vlan_vfi_bitmap == NULL) {
   1657         return BCM_E_PARAM;
   1658     }
   1659 
   1660     if (BCM_GPORT_IS_VLAN_PORT(vp_gport)) {
   1661         vp = BCM_GPORT_VLAN_PORT_ID_GET(vp_gport);
   1662         mc_type = _BCM_MULTICAST_TYPE_VLAN;
   1663     } else if (BCM_GPORT_IS_NIV_PORT(vp_gport)) {
   1664         vp = BCM_GPORT_NIV_PORT_ID_GET(vp_gport);
   1665         mc_type = _BCM_MULTICAST_TYPE_NIV;
   1666     } else if (BCM_GPORT_IS_EXTENDER_PORT(vp_gport)) {
   1667         vp = BCM_GPORT_EXTENDER_PORT_ID_GET(vp_gport);
   1668         mc_type = _BCM_MULTICAST_TYPE_EXTENDER;
   1669     } else if (BCM_GPORT_IS_VXLAN_PORT(vp_gport)) {
   1670         vp = BCM_GPORT_VXLAN_PORT_ID_GET(vp_gport);
   1671         mc_type = _BCM_MULTICAST_TYPE_VXLAN;
   1672     } else if (BCM_GPORT_IS_FLOW_PORT(vp_gport)) {
   1673         vp = BCM_GPORT_FLOW_PORT_ID_GET(vp_gport);
   1674         mc_type = _BCM_MULTICAST_TYPE_FLOW;
   1675     } else if (BCM_GPORT_IS_L2GRE_PORT(vp_gport)) {
   1676         vp = BCM_GPORT_L2GRE_PORT_ID_GET(vp_gport);
   1677         mc_type = _BCM_MULTICAST_TYPE_L2GRE;
   1678     } else if (BCM_GPORT_IS_MIM_PORT(vp_gport)) {
   1679         vp = BCM_GPORT_MIM_PORT_ID_GET(vp_gport);
   1680         mc_type = _BCM_MULTICAST_TYPE_MIM;
   1681     } else if (BCM_GPORT_IS_MPLS_PORT(vp_gport)) {
   1682         vp = BCM_GPORT_MPLS_PORT_ID_GET(vp_gport);
   1683         mc_type = _BCM_MULTICAST_TYPE_VPLS;
   1684     } else if (BCM_GPORT_IS_TRUNK(vp_gport)) {
   1685         BCM_IF_ERROR_RETURN(_bcm_esw_trunk_tid_to_vp_lag_vp(
   1686                     unit, BCM_GPORT_TRUNK_GET(vp_gport), &vp));
   1687         /* there is no need to set mc_type for vplag */
   1688         mc_type = 0;
   1689     } else {
   1690         return BCM_E_PARAM;
   1691     }
   1692 
   1693     vlan_vfi_count = BCM_VLAN_COUNT + soc_mem_index_count(unit, VFIm);
   1694 
   1695     /* Check if VP already belongs to a VP group.
   1696      * If so, just return the VP group's VLAN bitmap.
   1697      */
   1698     if (soc_feature(unit, soc_feature_vp_group_ingress_vlan_membership)) {
   1699         BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp_entry));
   1700         if (VP_FILTER_VP_GRP_BMAP ==
   1701             soc_SOURCE_VPm_field32_get(unit, &svp_entry, ENABLE_IFILTERf)) {
   1702             vp_group = soc_SOURCE_VPm_field32_get(unit, &svp_entry,
   1703                     VLAN_MEMBERSHIP_PROFILEf);
   1704             sal_memcpy(vlan_vfi_bitmap, 
   1705                        ING_VP_GROUP(unit, vp_group)->vlan_vfi_bitmap,
   1706                        SHR_BITALLOCSIZE(vlan_vfi_count));
   1707             return BCM_E_NONE;
   1708         }
   1709     }
   1710 
   1711     if (soc_feature(unit, soc_feature_vp_group_egress_vlan_membership)) {
   1712         soc_field_t en_efilter_f;
   1713         soc_field_t vm_prof_f;
   1714         BCM_IF_ERROR_RETURN
   1715             (READ_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ANY, vp, &egr_dvp_entry));
   1716 
   1717         BCM_IF_ERROR_RETURN(_td2p_egr_dvp_attribute_field_name_get(unit,
   1718                     &egr_dvp_entry, EN_EFILTERf, &en_efilter_f));
   1719 
   1720         if (VP_FILTER_VP_GRP_BMAP ==
   1721                 soc_EGR_DVP_ATTRIBUTEm_field32_get(
   1722                 unit, &egr_dvp_entry, en_efilter_f)) {
   1723             BCM_IF_ERROR_RETURN(_td2p_egr_dvp_attribute_field_name_get(unit,
   1724                         &egr_dvp_entry, VLAN_MEMBERSHIP_PROFILEf, &vm_prof_f));
   1725             vp_group = soc_EGR_DVP_ATTRIBUTEm_field32_get(unit, &egr_dvp_entry,
   1726                     vm_prof_f);
   1727             sal_memcpy(vlan_vfi_bitmap, EG_VP_GROUP(unit, vp_group)->vlan_vfi_bitmap,
   1728                     SHR_BITALLOCSIZE(vlan_vfi_count));
   1729             return BCM_E_NONE;
   1730         }
   1731     }
   1732 
   1733     /* need a special process for vp-lag */
   1734     if (BCM_GPORT_IS_TRUNK(vp_gport)) {
   1735         /* 1 get vp-lag member count max */
   1736         rv = bcm_esw_trunk_chip_info_get(unit, &trunk_chip_info);
   1737         VP_GROUP_CLEANUP(rv);
   1738 
   1739         /* 2 alloc member array according to the member count */
   1740         member_max = trunk_chip_info.vp_ports_max;
   1741         member_array = sal_alloc(member_max * sizeof(bcm_trunk_member_t),
   1742                                 "member array");
   1743         if (NULL == member_array) {
   1744             rv = BCM_E_MEMORY;
   1745             goto cleanup;
   1746         }
   1747         /* 3 get member array */
   1748         rv = bcm_esw_trunk_get(unit, BCM_GPORT_TRUNK_GET(vp_gport), NULL,
   1749                                member_max, member_array, &member_count);
   1750         VP_GROUP_CLEANUP(rv);
   1751 
   1752         /* 4 alloc vlan bitmap tmp */
   1753         vlan_vfi_bitmap_tmp = sal_alloc(SHR_BITALLOCSIZE(vlan_vfi_count),
   1754                                     "vlan bitmap tmp");
   1755         if (NULL == vlan_vfi_bitmap_tmp) {
   1756             rv = BCM_E_MEMORY;
   1757             goto cleanup;
   1758         }
   1759 
   1760         /* 5 get each member vlan bitmap, then or them together */
   1761         for (i = 0; i < member_count; i++) {
   1762             sal_memset(vlan_vfi_bitmap_tmp, 0, SHR_BITALLOCSIZE(vlan_vfi_count));
   1763             rv = _bcm_td2p_vp_vlan_vfi_bitmap_get(
   1764                     unit, member_array[i].gport, vlan_vfi_bitmap_tmp);
   1765             VP_GROUP_CLEANUP(rv);
   1766 
   1767             SHR_BITOR_RANGE(vlan_vfi_bitmap_tmp,
   1768                 vlan_vfi_bitmap, 0, vlan_vfi_count, vlan_vfi_bitmap);
   1769         }
   1770 
   1771         return BCM_E_NONE;
   1772     }
   1773 
   1774     /* VP does not belong to any VP group. Need to derive VLAN bitmap by
   1775      * searching through each VLAN table entry's BC_IDX/UMC_IDX/UUC_IDX
   1776      * multicast groups to see if VP belongs to their VP replication lists.
   1777      */ 
   1778 
   1779     /* Get one local port on which the VP resides.
   1780      * Even if the VP resides on a trunk group, only one trunk
   1781      * member is needed since all members of a trunk group
   1782      * have the same VP replication list.
   1783      */
   1784     BCM_IF_ERROR_RETURN(_bcm_td2p_vp_local_ports_get(unit,
   1785                         vp, 1, &local_port, &local_port_count));
   1786     if (local_port_count == 0) {
   1787         return BCM_E_PORT; 
   1788     }
   1789 
   1790     vlan_tab_buf = soc_cm_salloc(unit,
   1791             SOC_MEM_TABLE_BYTES(unit, VLAN_TABm), "VLAN_TAB buffer");
   1792     if (NULL == vlan_tab_buf) {
   1793         rv = BCM_E_MEMORY;
   1794         goto cleanup;
   1795     }
   1796 
   1797     rv = soc_mem_read_range(unit, VLAN_TABm, MEM_BLOCK_ANY,
   1798             0, BCM_VLAN_MAX, vlan_tab_buf);
   1799     VP_GROUP_CLEANUP(rv);
   1800 
   1801     vfi_tab_buf = soc_cm_salloc(unit,
   1802         SOC_MEM_TABLE_BYTES(unit, VFIm), "VFI buffer");
   1803     if (NULL == vfi_tab_buf) {
   1804         rv = BCM_E_MEMORY;
   1805         goto cleanup;
   1806     }
   1807 
   1808     
   1809     if (SOC_IS_MONTEREY(unit)) {
   1810         rv = soc_mem_read_range(unit, VFIm, MEM_BLOCK_ANY,
   1811                 0, BCM_MN_VPN_MAX, vfi_tab_buf);
   1812     } else {
   1813         rv = soc_mem_read_range(unit, VFIm, MEM_BLOCK_ANY,
   1814                 0, BCM_VPN_MAX, vfi_tab_buf);
   1815     }
   1816     VP_GROUP_CLEANUP(rv);
   1817 
   1818     if_max = soc_mem_index_count(unit, ING_L3_NEXT_HOPm);
   1819     if_array = sal_alloc(sizeof(bcm_if_t) * if_max, "if_array");
   1820     if (NULL == if_array) {
   1821         rv = BCM_E_MEMORY;
   1822         goto cleanup;
   1823     }
   1824     sal_memset(if_array, 0, sizeof(bcm_if_t) * if_max);
   1825 
   1826     SHR_BITCLR_RANGE(vlan_vfi_bitmap, 0, vlan_vfi_count);
   1827 
   1828     for (i = 0; i < vlan_vfi_count; i++) {
   1829         if (i < BCM_VLAN_COUNT) {
   1830             vlan_tab_entry = soc_mem_table_idx_to_pointer
   1831                 (unit, VLAN_TABm, vlan_tab_entry_t *, vlan_tab_buf, i);
   1832 
   1833             if (0 == soc_VLAN_TABm_field32_get(unit, vlan_tab_entry,
   1834                         VALIDf)) {
   1835                 continue;
   1836             }
   1837 
   1838             if (0 == soc_VLAN_TABm_field32_get(unit, vlan_tab_entry,
   1839                         VIRTUAL_PORT_ENf)) {
   1840                 continue;
   1841             }
   1842 
   1843             mc_index_array[0] = _bcm_xgs3_vlan_mcast_idx_get(
   1844                                    unit, vlan_tab_entry, BC_IDXf);
   1845             mc_index_array[1] = _bcm_xgs3_vlan_mcast_idx_get(
   1846                                     unit, vlan_tab_entry, UMC_IDXf);
   1847             mc_index_array[2] = _bcm_xgs3_vlan_mcast_idx_get(
   1848                                     unit, vlan_tab_entry, UUC_IDXf);
   1849         } else {
   1850             if (!_bcm_vfi_used_get(unit, (i-BCM_VLAN_COUNT), _bcmVfiTypeAny)) {
   1851                 continue;
   1852             }
   1853 
   1854             vfi_entry = soc_mem_table_idx_to_pointer
   1855                 (unit, VFIm, vfi_entry_t *, vfi_tab_buf, (i-BCM_VLAN_COUNT));
   1856 
   1857             if (soc_VFIm_field32_get(unit, vfi_entry, PT2PT_ENf)){
   1858                 continue;
   1859             }
   1860 #if defined(BCM_TRIDENT3_SUPPORT)
   1861             if (soc_feature(unit, soc_feature_generic_dest)) {
   1862                 uint32 dt;
   1863 
   1864                 mc_index_array[0] = soc_mem_field32_dest_get(unit, VFIm,
   1865                            vfi_entry, BC_DESTINATIONf, &dt);
   1866                 if (dt != SOC_MEM_FIF_DEST_IPMC) {
   1867                     rv = BCM_E_INTERNAL;
   1868                 }
   1869                 mc_index_array[1] = soc_mem_field32_dest_get(unit, VFIm,
   1870                             vfi_entry, UMC_DESTINATIONf, &dt);
   1871                 if (dt != SOC_MEM_FIF_DEST_IPMC) {
   1872                     rv =  BCM_E_INTERNAL;
   1873                 }
   1874                 mc_index_array[2] = soc_mem_field32_dest_get(unit, VFIm,
   1875                                 vfi_entry, UUC_DESTINATIONf, &dt);
   1876                 if (dt != SOC_MEM_FIF_DEST_IPMC) {
   1877                     rv = BCM_E_INTERNAL;
   1878                 }
   1879 
   1880                 VP_GROUP_CLEANUP(rv);
   1881             } else
   1882 #endif
   1883             {
   1884             mc_index_array[0] = soc_VFIm_field32_get(unit, vfi_entry, BC_INDEXf);
   1885             mc_index_array[1] = soc_VFIm_field32_get(unit, vfi_entry, UMC_INDEXf);
   1886             mc_index_array[2] = soc_VFIm_field32_get(unit, vfi_entry, UUC_INDEXf);
   1887         }
   1888         }
   1889 
   1890         for (j = 0; j < 3; j++) {
   1891 
   1892             /* Check if the same mc_index was already searched */
   1893             match_prev_mc_index = FALSE;
   1894             for (k = j - 1; k >= 0; k--) {
   1895                 if (mc_index_array[j] == mc_index_array[k]) {
   1896                     match_prev_mc_index = TRUE;
   1897                     break;
   1898                 }
   1899             }
   1900             if (match_prev_mc_index) {
   1901                 /* continue to next mc_index */
   1902                 continue;
   1903             }
   1904 
   1905             /* Get VP replication list for (mc_index, local_port) */
   1906             rv = bcm_esw_ipmc_egress_intf_get(unit, mc_index_array[j],
   1907                     local_port, if_max, if_array, &if_count);
   1908             VP_GROUP_CLEANUP(rv);
   1909 
   1910             /* Get VP's encap_id */
   1911             _BCM_MULTICAST_GROUP_SET(group, mc_type, mc_index_array[j]);
   1912             rv = bcm_esw_port_gport_get(unit, local_port, &local_gport);
   1913             VP_GROUP_CLEANUP(rv);
   1914 
   1915             if (BCM_GPORT_IS_VLAN_PORT(vp_gport))  {
   1916                 rv = bcm_esw_multicast_vlan_encap_get(unit, group,
   1917                         local_gport, vp_gport, &encap_id);
   1918             } else if (BCM_GPORT_IS_NIV_PORT(vp_gport)) {
   1919                 rv = bcm_esw_multicast_niv_encap_get(unit, group,
   1920                         local_gport, vp_gport, &encap_id);
   1921             } else if (BCM_GPORT_IS_EXTENDER_PORT(vp_gport)) {
   1922                 rv = bcm_esw_multicast_extender_encap_get(unit, group,
   1923                         local_gport, vp_gport, &encap_id);
   1924             } else if (BCM_GPORT_IS_VXLAN_PORT(vp_gport)) {
   1925                 rv = bcm_esw_multicast_vxlan_encap_get(unit, group,
   1926                         local_gport, vp_gport, &encap_id);
   1927             }
   1928 #if 0
   1929             else if (BCM_GPORT_IS_FLOW_PORT(vp_gport)) {
   1930                 rv = bcm_esw_multicast_flow_encap_get(unit, group,
   1931                         local_gport, vp_gport, &encap_id);
   1932             }
   1933 #endif
   1934             else if (BCM_GPORT_IS_MIM_PORT(vp_gport)) {
   1935                 rv = bcm_esw_multicast_mim_encap_get(unit, group,
   1936                         local_gport, vp_gport, &encap_id);
   1937             }
   1938             VP_GROUP_CLEANUP(rv);
   1939 
   1940             /* Search for VP's encap_id in if_array */
   1941             match = FALSE;
   1942             for (k = 0; k < if_count; k++) {
   1943                 if (encap_id == if_array[k]) {
   1944                     match = TRUE;
   1945                     break;
   1946                 }
   1947             }
   1948             if (match) {
   1949                 break;
   1950             }
   1951         }
   1952 
   1953         if (match) {
   1954             /* VP belongs to this VLAN */
   1955             SHR_BITSET(vlan_vfi_bitmap, i);
   1956         }
   1957     }
   1958 
   1959 cleanup:
   1960     if (vlan_tab_buf) {
   1961         soc_cm_sfree(unit, vlan_tab_buf);
   1962     }
   1963     if (vfi_tab_buf) {
   1964         soc_cm_sfree(unit, vfi_tab_buf);
   1965     }
   1966     if (if_array) {
   1967         sal_free(if_array);
   1968     }
   1969     if (vlan_vfi_bitmap_tmp) {
   1970         sal_free(vlan_vfi_bitmap_tmp);
   1971     }
   1972     if (member_array) {
   1973         sal_free(member_array);
   1974     }
   1975     return rv;
   1976 }
   1977 
   1978 /*
   1979  * Function:
   1980  *      _bcm_td2p_vlan_vfi_mbrship_profile_entry_set
   1981  * Purpose:
   1982  *      Given a VLAN/VFI value and a direction (Igr/Egr), set the
   1983  *      data associated with a profile entry and update the VLAN/VFI
   1984  *      with a new profile index
   1985  * Parameters:
   1986  *      unit - (IN) BCM device number
   1987  *      vlan_vpn - (IN) VLAN/VPN ID
   1988  *      egress  - (IN) If TRUE, VP handling is for egress, else ingress.
   1989  *      entry_data - (IN) Entry to write
   1990  * Returns:
   1991  *      BCM_E_XXX
   1992  */
   1993 
   1994 STATIC int
   1995 _bcm_td2p_vlan_vfi_mbrship_profile_entry_set(int unit,
   1996                                               bcm_vlan_t vlan_vpn,
   1997                                               int egress,
   1998                                               void *entry_data)
   1999 {
   2000     uint32 cur_prof_index = 0, new_prof_index = 0;
   2001 
   2002     /* Get the profile_idx associated with the VLAN/VFI */
   2003     BCM_IF_ERROR_RETURN(_bcm_td2p_vlan_vpn_mbrship_profile_get(
   2004                         unit, vlan_vpn, egress, &cur_prof_index));
   2005 
   2006     BCM_IF_ERROR_RETURN(_bcm_vlan_vfi_membership_profile_entry_op(
   2007                 unit, &entry_data, 1, TRUE, egress, &new_prof_index));
   2008     /* Write the new index into the VALN/VFI tables */
   2009     BCM_IF_ERROR_RETURN(_bcm_td2p_vlan_vpn_mbrship_profile_set(
   2010                             unit, vlan_vpn, egress, new_prof_index));
   2011 
   2012     /*
   2013      * If the old-profile-index entry is not default, delete it, note that if the
   2014      * same index is reallocated, the profile-mgmt would have incremented the
   2015      * ref-count anyway.
   2016      */
   2017     if(cur_prof_index != 0 && cur_prof_index != 1) {
   2018         BCM_IF_ERROR_RETURN(_bcm_vlan_vfi_membership_profile_entry_op(
   2019                             unit, NULL, 1, FALSE, egress, &cur_prof_index));
   2020 
   2021     }
   2022 
   2023     return BCM_E_NONE;
   2024 }
   2025 
   2026 /*
   2027  * Function:
   2028  *      _bcm_td2p_vlan_vpn_mbrship_profile_get
   2029  * Purpose:
   2030  *      Per direction get membership profile of the given vlan/vpn.
   2031  * Parameters:
   2032  *      unit - (IN) BCM device number
   2033  *      vlan_vpn   - (IN) VLAN/VPN ID
   2034  *      egress  - (IN) If TRUE, VP handling is for egress, else ingress.
   2035  *      prof_index - (OUT) The associated profile index if all goes well
   2036  * Returns:
   2037  *      BCM_E_XXX
   2038  */
   2039 
   2040 STATIC int
   2041 _bcm_td2p_vlan_vpn_mbrship_profile_get(int unit,
   2042                                             bcm_vlan_t vlan_vpn,
   2043                                             int egress,
   2044                                             uint32 *prof_index)
   2045 {
   2046     int index;
   2047     soc_mem_t mem;
   2048     uint32 vlan_vfi_entry[SOC_MAX_MEM_WORDS];
   2049 
   2050     if(prof_index == NULL) {
   2051         return BCM_E_PARAM;
   2052     }
   2053 
   2054     if (_BCM_VPN_VFI_IS_SET(vlan_vpn)) {
   2055         if (egress) {
   2056             mem = EGR_VFIm;
   2057         } else {
   2058             mem = VFIm;
   2059         }
   2060 
   2061         _BCM_VPN_GET(index, _BCM_VPN_TYPE_VFI, vlan_vpn);
   2062 
   2063     } else {
   2064         if (egress) {
   2065             mem = EGR_VLANm;
   2066         } else if (SOC_MEM_FIELD_VALID(unit, VLAN_ATTRS_1m,
   2067                                        MEMBERSHIP_PROFILE_PTRf)) {
   2068             mem = VLAN_ATTRS_1m;
   2069         } else {
   2070             mem = VLAN_MPLSm;
   2071         }
   2072 
   2073         index = vlan_vpn;
   2074     }
   2075 
   2076     /* Read the memory and extract the field in question */
   2077     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem,
   2078                 MEM_BLOCK_ANY, index, vlan_vfi_entry));
   2079 
   2080     /* Assign the profile index */
   2081     *prof_index = soc_mem_field32_get(unit, mem, vlan_vfi_entry,
   2082                                       MEMBERSHIP_PROFILE_PTRf);
   2083 
   2084     return BCM_E_NONE;
   2085 }
   2086 
   2087 /*
   2088  * Function:
   2089  *      _bcm_td2p_vlan_vpn_mbrship_profile_set
   2090  * Purpose:
   2091  *      Per direction set membership profile of the given vlan/vpn.
   2092  * Parameters:
   2093  *      unit - (IN) BCM device number
   2094  *      vlan_vpn   - (IN) VLAN/VPN ID
   2095  *      egress  - (IN) If TRUE, VP handling is for egress, else ingress.
   2096  *      prof_index - (OUT) The associated profile index if all goes well
   2097  * Returns:
   2098  *      BCM_E_XXX
   2099  */
   2100 
   2101 STATIC int
   2102 _bcm_td2p_vlan_vpn_mbrship_profile_set(int unit,
   2103                                             bcm_vlan_t vlan_vpn,
   2104                                             int egress, 
   2105                                             int prof_index)
   2106 {
   2107     int                 index = -1;
   2108     soc_mem_t           mem;
   2109 
   2110     /* Depending on VLAN/VFI, write to relevant memories */
   2111     if (_BCM_VPN_VFI_IS_SET(vlan_vpn)) {
   2112         if (egress) {
   2113             mem = EGR_VFIm;
   2114         } else {
   2115             mem = VFIm;
   2116         }
   2117 
   2118         /* Index in case of a VFI is the encoded value */
   2119         _BCM_VPN_GET(index, _BCM_VPN_TYPE_VFI, vlan_vpn);
   2120 
   2121     } else {
   2122         if (egress) {
   2123             mem = EGR_VLANm;
   2124         } else if (SOC_MEM_FIELD_VALID(unit, VLAN_ATTRS_1m,
   2125                                        MEMBERSHIP_PROFILE_PTRf)) {
   2126             mem = VLAN_ATTRS_1m;
   2127         } else {
   2128             mem = VLAN_MPLSm;
   2129         }
   2130 
   2131         index = vlan_vpn;
   2132     }
   2133 
   2134     BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit,
   2135         mem, index, MEMBERSHIP_PROFILE_PTRf, prof_index));
   2136 
   2137     if (mem == VLAN_ATTRS_1m &&
   2138         soc_mem_field_valid(unit, VLAN_TABm, MEMBERSHIP_PROFILE_PTRf)) {
   2139         BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit,
   2140             VLAN_TABm, index, MEMBERSHIP_PROFILE_PTRf, prof_index));
   2141     }
   2142 
   2143     return BCM_E_NONE;
   2144 }
   2145 
   2146 /*
   2147  * Function:
   2148  *      _bcm_td2p_vp_group_id_set
   2149  * Purpose:
   2150  *      For a given port, update its vp_group id into relevant memory
   2151  * Parameters:
   2152  *      unit - (IN) BCM device number
   2153  *      port  - (IN) Port in question
   2154  *      vp_group - (IN) vp_group to update with
   2155  *      egress - (IN) True if we are dealing with egress 
   2156  * Returns:
   2157  *      BCM_E_XXX
   2158  */
   2159 STATIC int
   2160 _bcm_td2p_vp_group_id_set(int unit, int port, int vp_group, int egress)
   2161 {
   2162     soc_mem_t                          port_mem;
   2163     soc_field_t                        mbrship_field;
   2164     int                                index;
   2165     egr_dvp_attribute_entry_t          egr_dvp_entry;
   2166 
   2167     if (BCM_GPORT_IS_SUBPORT_PORT(port)) {
   2168         if (egress) {
   2169             port_mem = EGR_GPP_ATTRIBUTESm;
   2170         } else {
   2171             port_mem = SOURCE_TRUNK_MAP_TABLEm;
   2172         }
   2173         mbrship_field = VLAN_MEMBERSHIP_PROFILEf;
   2174 
   2175         BCM_IF_ERROR_RETURN(_bcm_td2p_gpp_hw_index_get(unit, port, &index));
   2176     } else {
   2177         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &index));
   2178 
   2179         if (egress) {
   2180             port_mem = EGR_DVP_ATTRIBUTEm;
   2181 
   2182             BCM_IF_ERROR_RETURN(READ_EGR_DVP_ATTRIBUTEm(
   2183                 unit, MEM_BLOCK_ANY, index, &egr_dvp_entry));
   2184             BCM_IF_ERROR_RETURN(_td2p_egr_dvp_attribute_field_name_get(unit,
   2185                     &egr_dvp_entry, VLAN_MEMBERSHIP_PROFILEf, &mbrship_field));
   2186         } else {
   2187             port_mem = SOURCE_VPm;
   2188             mbrship_field = VLAN_MEMBERSHIP_PROFILEf;
   2189         }
   2190     }
   2191 
   2192     /* Modify the group into relevant memory */
   2193     BCM_IF_ERROR_RETURN(soc_mem_field32_modify(
   2194         unit, port_mem, index, mbrship_field, vp_group));
   2195 
   2196     return BCM_E_NONE;
   2197 }
   2198 
   2199 /*
   2200  * Function:
   2201  *      _bcm_td2p_vp_group_join
   2202  * Purpose:
   2203  *      Given a port and a vlan_vfi bmap, either join and existing
   2204  *      vp group or create a new group.
   2205  * Parameters:
   2206  *      unit - (IN) BCM device number
   2207  *      port  - (IN) Port number passed in
   2208  *      vlan_vfi_bmap - (IN) The VLAN/VFI bmap
   2209  *      stp_state - (IN) STP status
   2210  *      ut_state - (IN) Vlan untag status
   2211  *      egress -  (IN) Direction, TRUE is egress
   2212  *      vp_group -  (OUT) The alloted vp_group num, if all goes well
   2213  * Returns:
   2214  *      BCM_E_XXX
   2215  */
   2216 
   2217 int
   2218 _bcm_td2p_vp_group_join(int unit, int port, SHR_BITDCL *vlan_vfi_bmap,
   2219                             int stp_state, int ut_state, int egress, int *vp_group)
   2220 {
   2221     int rv = BCM_E_NONE;
   2222     int i;
   2223     int vpg;
   2224     int gport;
   2225     int port_offset = 0;
   2226     int vlan_vfi_count;
   2227     int num_grps = 0, vlan_count = 0;
   2228     int stg, vlan_vfi, vlan_vpn;
   2229     _bcm_td2p_vp_group_t *vp_grp_array = NULL;
   2230 
   2231     if (vlan_vfi_bmap == NULL)
   2232     {
   2233         return BCM_E_PARAM;
   2234     }
   2235 
   2236     VP_GROUP_LOCK_MEMS(unit, egress);
   2237     /* Get the data pertaining to Ingress/Egress */
   2238     if(egress) {
   2239         num_grps = VP_GROUP_BK(unit)->num_eg_vp_group;
   2240         vp_grp_array = EG_VP_GROUP(unit, 0);
   2241     } else {
   2242         num_grps = VP_GROUP_BK(unit)->num_ing_vp_group;
   2243         vp_grp_array = ING_VP_GROUP(unit, 0);
   2244     }
   2245 
   2246     /* Set the vp_group_num to invalid to start with */
   2247     vpg = _BCM_INVALID_VP_GROUP;
   2248     SHR_BITCOUNT_RANGE(vlan_vfi_bmap, vlan_count, 0, BCM_VLAN_COUNT);
   2249     vlan_vfi_count = BCM_VLAN_COUNT + soc_mem_index_count(unit, VFIm);
   2250 #if defined(BCM_TRIDENT3_SUPPORT)
   2251     if (SOC_MEM_IS_VALID(unit, EGR_VLAN_VFI_UNTAGm)) {
   2252         SHR_BITCOUNT_RANGE(vlan_vfi_bmap, vlan_count, 0, vlan_vfi_count);
   2253     }
   2254 #endif
   2255     /* Run through all vp groups to get a matched/new one */
   2256     for (i = 0; i < num_grps; i++) {
   2257         if (vp_grp_array[i].gpp_vp_count > 0 &&
   2258             SHR_BITEQ_RANGE(vlan_vfi_bmap,
   2259             vp_grp_array[i].vlan_vfi_bitmap, 0, vlan_vfi_count)) {
   2260 
   2261             if (vp_grp_array[i].stp_state != stp_state) {
   2262                 continue;
   2263             }
   2264             if (egress && vlan_count) {
   2265                 if (vp_grp_array[i].ut_state != ut_state) {
   2266                     continue;
   2267                 }
   2268             }
   2269             vpg = i;
   2270             break;
   2271         } else {
   2272             if (vp_grp_array[i].gpp_vp_count == 0 &&
   2273                 vpg == _BCM_INVALID_VP_GROUP) {
   2274 
   2275                 vpg = i;
   2276             }
   2277         }
   2278     }
   2279 
   2280     *vp_group = vpg;
   2281 
   2282     if (vpg == _BCM_INVALID_VP_GROUP) {
   2283         VP_GROUP_UNLOCK_MEMS(unit, egress);
   2284         return BCM_E_RESOURCE;
   2285     }
   2286 
   2287     if (vp_grp_array[vpg].gpp_vp_count == 0) {
   2288         vp_grp_array[vpg].stp_state = stp_state;
   2289         vp_grp_array[vpg].ut_state = ut_state;
   2290         sal_memcpy(vp_grp_array[vpg].vlan_vfi_bitmap,
   2291             vlan_vfi_bmap, SHR_BITALLOCSIZE(vlan_vfi_count));
   2292 
   2293         /* Update EGR_VLAN table's VP_GROUP_BITMAP field */
   2294         SHR_BIT_ITER(vlan_vfi_bmap, vlan_vfi_count, vlan_vfi) {
   2295             if(vlan_vfi < BCM_VLAN_COUNT) {
   2296                 vlan_vpn = vlan_vfi;
   2297 
   2298                 if (egress && ut_state) {
   2299                     rv = bcm_td2p_vp_group_ut_state_set(unit, vlan_vpn, vpg,
   2300                                                         ut_state);
   2301                     if (BCM_FAILURE(rv)) {
   2302                         VP_GROUP_UNLOCK_MEMS(unit, egress);
   2303                         return rv;
   2304                     }
   2305                 }
   2306             } else {
   2307                 _BCM_VPN_SET(vlan_vpn, _BCM_VPN_TYPE_VFI,
   2308                              (vlan_vfi - BCM_VLAN_COUNT));
   2309 #if defined(BCM_TRIDENT3_SUPPORT)
   2310                 if (SOC_MEM_IS_VALID(unit, EGR_VLAN_VFI_UNTAGm) &&
   2311                                                       egress && ut_state) {
   2312                     rv = bcm_td2p_vp_group_ut_state_set(unit, vlan_vpn, vpg,
   2313                                                         ut_state);
   2314                     if (BCM_FAILURE(rv)) {
   2315                         VP_GROUP_UNLOCK_MEMS(unit, egress);
   2316                         return rv;
   2317                     }
   2318                 }
   2319 #endif
   2320             }
   2321 
   2322             rv = bcm_td2p_vlan_vp_group_set(unit, vlan_vpn, egress, vpg, TRUE);
   2323             if (BCM_FAILURE(rv)) {
   2324                 VP_GROUP_UNLOCK_MEMS(unit, egress);
   2325                 return rv;
   2326             }
   2327 
   2328             rv = bcm_td2p_vp_group_vlan_vpn_stg_get(unit, vlan_vpn, egress,
   2329                                                     &stg);
   2330             if (BCM_FAILURE(rv)) {
   2331                 VP_GROUP_UNLOCK_MEMS(unit, egress);
   2332                 return rv;
   2333             }
   2334 
   2335             if(stg != BCM_STG_DEFAULT) {
   2336                 BCM_GPORT_VP_GROUP_SET(gport, vpg);
   2337                 rv = bcm_td2p_vp_group_stp_state_set(unit, stg, gport, egress,
   2338                                                      stp_state);
   2339                 if (BCM_FAILURE(rv)) {
   2340                     VP_GROUP_UNLOCK_MEMS(unit, egress);
   2341                     return rv;
   2342             }
   2343         }
   2344     }
   2345     }
   2346 
   2347     rv = _bcm_td2p_vp_group_resolve_port_num(unit, port, &port_offset);
   2348     if (BCM_FAILURE(rv)) {
   2349         VP_GROUP_UNLOCK_MEMS(unit, egress);
   2350         return rv;
   2351     }
   2352 
   2353     if (!SHR_BITGET(vp_grp_array[vpg].gpp_vp_bitmap, port_offset)) {
   2354         SHR_BITSET(vp_grp_array[vpg].gpp_vp_bitmap, port_offset);
   2355         vp_grp_array[vpg].gpp_vp_count++;
   2356     }
   2357 
   2358     rv = _bcm_td2p_vp_group_id_set(unit, port, vpg, egress);
   2359     if (BCM_FAILURE(rv)) {
   2360         VP_GROUP_UNLOCK_MEMS(unit, egress);
   2361         return rv;
   2362     }
   2363 
   2364     VP_GROUP_UNLOCK_MEMS(unit, egress);
   2365 
   2366     return BCM_E_NONE;
   2367 }
   2368 
   2369 /*
   2370  * Function:
   2371  *      _bcm_td2p_vp_group_leave
   2372  * Purpose:
   2373  *      Leave a given VP group
   2374   * Parameters:
   2375  *      unit - (IN) BCM device number
   2376  *      port   - (IN) Front-panel/Gpp/VP port value
   2377  *      vp_group - (IN) VP Group in question
   2378  *      egress  - (IN) If TRUE, VP handling is for egress, else ingress
   2379  * Returns:
   2380  *      BCM_E_XXX
   2381  */
   2382 STATIC int
   2383 _bcm_td2p_vp_group_leave(int unit, int port, int vp_group, int egress)
   2384 {
   2385     int gport;
   2386     int vlan_vfi_count;
   2387     int stg = 0, port_offset = 0;
   2388     int vlan_vfi = 0, vlan_vpn = 0;
   2389     _bcm_td2p_vp_group_t *vp_grp = NULL;
   2390 
   2391     /* Get the data pertaining to Ingress/Egress */
   2392     if(egress) {
   2393         vp_grp = EG_VP_GROUP(unit, vp_group);
   2394     } else {
   2395         vp_grp = ING_VP_GROUP(unit, vp_group);
   2396     }
   2397 
   2398     if (vp_grp->gpp_vp_count == 0) {
   2399         return BCM_E_NONE;
   2400     }
   2401 
   2402     BCM_IF_ERROR_RETURN(
   2403         _bcm_td2p_vp_group_resolve_port_num(unit, port, &port_offset));
   2404 
   2405     vp_grp->gpp_vp_count--;
   2406     SHR_BITCLR(vp_grp->gpp_vp_bitmap, port_offset);
   2407 
   2408     /* no port use this group, release it */
   2409     if(0 == vp_grp->gpp_vp_count) {
   2410         vlan_vfi_count = BCM_VLAN_COUNT + soc_mem_index_count(unit, VFIm);
   2411 
   2412         /* Run through all VLAN/VFI's and unset this vp_group bit */
   2413         SHR_BIT_ITER(vp_grp->vlan_vfi_bitmap, vlan_vfi_count, vlan_vfi) {
   2414             if(vlan_vfi <= BCM_VLAN_MAX) {
   2415                 vlan_vpn = vlan_vfi;
   2416                 if (egress) {
   2417                     BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_ut_state_set(unit,
   2418                             vlan_vpn, vp_group, _BCM_DEFAULT_UNTAGGED_STATE));
   2419                 }
   2420             } else {
   2421                 _BCM_VPN_SET(vlan_vpn, _BCM_VPN_TYPE_VFI,
   2422                              (vlan_vfi - (BCM_VLAN_MAX+1)));
   2423 #if defined(BCM_TRIDENT3_SUPPORT)
   2424                 if (SOC_MEM_IS_VALID(unit, EGR_VLAN_VFI_UNTAGm) && egress) {
   2425                     BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_ut_state_set(unit,
   2426                             vlan_vpn, vp_group, _BCM_DEFAULT_UNTAGGED_STATE));
   2427                 }
   2428 #endif
   2429             }
   2430 
   2431             BCM_IF_ERROR_RETURN(bcm_td2p_vlan_vp_group_set(
   2432                         unit, vlan_vpn, egress, vp_group, FALSE));
   2433 
   2434             BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_vlan_vpn_stg_get(
   2435                                         unit, vlan_vpn, egress, &stg));
   2436 
   2437             if(stg != BCM_STG_DEFAULT) {
   2438                 BCM_GPORT_VP_GROUP_SET(gport, vp_group);
   2439                 BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_stp_state_set(
   2440                     unit, stg, gport, egress, _BCM_DEFAULT_STP_STATE));
   2441             }
   2442         }
   2443 
   2444         /* Clear out the vlan_vfi array */
   2445         SHR_BITCLR_RANGE(vp_grp->vlan_vfi_bitmap, 0, vlan_vfi_count);
   2446     }
   2447 
   2448     return BCM_E_NONE;
   2449 }
   2450 
   2451 /*
   2452  * Function:
   2453  *      bcm_td2p_vp_group_port_move
   2454  * Purpose:
   2455  *      Move GPP/VP from one VP group to another due to add/remove
   2456  *      of the GPP/VP to/from VLAN.
   2457  * Parameters:
   2458  *      unit - (IN) BCM device number
   2459  *      gport   - (IN) Gpp/VP port value
   2460  *      vlan_vpn - (IN) vlan/vpn ID
   2461  *      add  - (IN) If TRUE, VP is added to VLAN, else removed from VLAN.
   2462  *      egress  - (IN) If TRUE, VP handling is for egress, else ingress.
   2463  *      flags - (IN) Flags value
   2464  * Returns:
   2465  *      BCM_E_XXX
   2466  */
   2467 int
   2468 bcm_td2p_vp_group_port_move(int unit, int gport, bcm_vlan_t vlan_vpn,
   2469                             int add, int egress, int flags)
   2470 {
   2471     int rv = BCM_E_NONE;
   2472     int index = 0, vlan_vfi_bit = 0;
   2473     int old_vp_group = 0, new_vp_group = 0;
   2474     int vlan_count, vlan_vfi_count;
   2475     int ut_state = 0, filter = 0;
   2476     SHR_BITDCL *vlan_vfi_bitmap = NULL;
   2477     _bcm_td2p_vp_group_t *cur_vp_grp = NULL;
   2478 
   2479     VP_GROUP_LOCK_MEMS(unit, egress);
   2480 
   2481     /* Get the current vp group associated with this port */
   2482     rv = bcm_td2p_vp_group_port_filter_get(
   2483             unit, gport, egress, &old_vp_group, &filter);
   2484     if (BCM_FAILURE(rv)) {
   2485         goto cleanup;
   2486     }
   2487 
   2488     if(BCM_GPORT_IS_SUBPORT_PORT(gport)) {
   2489         if (GPP_FILTER_VP_GRP_BMAP != filter) {
   2490             rv = BCM_E_DISABLED;
   2491             goto cleanup;
   2492         }
   2493     } else {
   2494         if (VP_FILTER_VP_GRP_BMAP != filter) {
   2495             rv = BCM_E_DISABLED;
   2496             goto cleanup;
   2497         }
   2498     }
   2499 
   2500     vlan_vfi_count = BCM_VLAN_COUNT + soc_mem_index_count(unit, VFIm);
   2501     vlan_vfi_bitmap = sal_alloc(SHR_BITALLOCSIZE(vlan_vfi_count), "vlan bitmap");
   2502     if (NULL == vlan_vfi_bitmap) {
   2503         rv = BCM_E_MEMORY;
   2504         goto cleanup;
   2505     }
   2506     sal_memset(vlan_vfi_bitmap, 0, SHR_BITALLOCSIZE(vlan_vfi_count));
   2507 
   2508     /* Get the current vlan_vfi bitmap associated with this old_group */
   2509     if (egress) {
   2510         cur_vp_grp = EG_VP_GROUP(unit, old_vp_group);
   2511     } else {
   2512         cur_vp_grp = ING_VP_GROUP(unit, old_vp_group);
   2513     }
   2514     sal_memcpy(vlan_vfi_bitmap, cur_vp_grp->vlan_vfi_bitmap,
   2515                                 SHR_BITALLOCSIZE(vlan_vfi_count));
   2516 
   2517     if(_BCM_VPN_VFI_IS_SET(vlan_vpn)) {
   2518 #if defined(BCM_TRIDENT3_SUPPORT)
   2519         if (SOC_MEM_IS_VALID(unit, EGR_VLAN_VFI_UNTAGm)) {
   2520             if ((flags & BCM_VLAN_GPORT_ADD_UNTAGGED) && egress) {
   2521                 ut_state = 1;
   2522             } else {
   2523                 ut_state = _BCM_DEFAULT_UNTAGGED_STATE;
   2524             }
   2525         }
   2526 #endif
   2527         _BCM_VPN_GET(index, _BCM_VPN_TYPE_VFI, vlan_vpn);
   2528         index += BCM_VLAN_COUNT;
   2529     } else {
   2530         if ((flags & BCM_VLAN_GPORT_ADD_UNTAGGED) && egress) {
   2531             ut_state = 1;
   2532         } else {
   2533             ut_state = _BCM_DEFAULT_UNTAGGED_STATE;
   2534         }
   2535 
   2536         index = vlan_vpn;
   2537     }
   2538 
   2539     /* Get changing status of the relevant bit*/
   2540     vlan_vfi_bit = SHR_BITGET(vlan_vfi_bitmap, index);
   2541     if(!vlan_vfi_bit && !add) { /* VP does not exist in vlan/vfi */
   2542         rv = BCM_E_NOT_FOUND;
   2543         goto cleanup;
   2544     }
   2545 
   2546     SHR_BITCOUNT_RANGE(vlan_vfi_bitmap, vlan_count, 0, BCM_VLAN_COUNT);
   2547 #if defined(BCM_TRIDENT3_SUPPORT)
   2548     if (SOC_MEM_IS_VALID(unit, EGR_VLAN_VFI_UNTAGm)) {
   2549         SHR_BITCOUNT_RANGE(vlan_vfi_bitmap, vlan_count, 0, vlan_vfi_count);
   2550     }
   2551 #endif
   2552     if (vlan_vfi_bit && add) { /* vp already exist in vlan/vfi */
   2553         if (egress && vlan_count) { /* check ut status for egress vlan */
   2554             if (ut_state == cur_vp_grp->ut_state) {
   2555                 goto cleanup;
   2556             }
   2557         } else {
   2558             goto cleanup;
   2559         }
   2560     }
   2561 
   2562     /* Set or clear the VLAN/VFI */
   2563     if (add) {
   2564         SHR_BITSET(vlan_vfi_bitmap, index);
   2565     } else {
   2566         SHR_BITCLR(vlan_vfi_bitmap, index);
   2567     }
   2568 
   2569     rv = _bcm_td2p_vp_group_join(unit, gport, vlan_vfi_bitmap,
   2570             cur_vp_grp->stp_state, ut_state, egress, &new_vp_group);
   2571     VP_GROUP_CLEANUP(rv);
   2572 
   2573     /* Now leave the previous group, if different from the old one */
   2574     if (old_vp_group != new_vp_group) {
   2575         rv = _bcm_td2p_vp_group_leave(unit, gport, old_vp_group, egress);
   2576     }
   2577 
   2578 cleanup:
   2579     if (vlan_vfi_bitmap) {
   2580         sal_free(vlan_vfi_bitmap);
   2581         vlan_vfi_bitmap = NULL;
   2582     }
   2583 
   2584     VP_GROUP_UNLOCK_MEMS(unit, egress);
   2585 
   2586     return rv;
   2587 }
   2588 
   2589 /*
   2590  * Function:
   2591  *      _bcm_td2p_gpp_hw_index_get
   2592  * Purpose:
   2593  *      Given a port and port_type, pass back the absolute value to
   2594  *      be used within a vp_group in addition to the offset.
   2595  *      bmap from the group this port is a member of.
   2596  * Parameters:
   2597  *      unit - (IN) BCM device number
   2598  *      port  - (IN) Port number
   2599  *      egress - (IN) True for egress
   2600  *      hw_index - (OUT) The hardware index
   2601  * Returns:
   2602  *      BCM_E_XXX
   2603  */
   2604 
   2605 STATIC int
   2606 _bcm_td2p_gpp_hw_index_get(int unit, int port, int *hw_index)
   2607 {
   2608     bcm_trunk_t trunk_id;
   2609     bcm_module_t mod_out;
   2610     bcm_port_t port_out;
   2611     int id;
   2612 
   2613     /* Resolve the port */
   2614     BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(
   2615         unit, port, &mod_out, &port_out, &trunk_id, &id));
   2616 
   2617     BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(
   2618                             unit, mod_out, port_out, hw_index));
   2619 
   2620     return BCM_E_NONE;
   2621 }
   2622 
   2623 /*
   2624  * Function:
   2625  *      _bcm_td2p_vp_group_resolve_port_num
   2626  * Purpose:
   2627  *      Get absolute offset of port for gpp_vp_bitmap updatation
   2628  * Parameters:
   2629  *      unit - (IN) BCM device number
   2630  *      port  - (IN) Port number passed in .
   2631  *      port_offset -  (OUT) The offset to be used for VP group bmap
   2632  * Returns:
   2633  *      BCM_E_XXX
   2634  */
   2635 
   2636 STATIC int
   2637 _bcm_td2p_vp_group_resolve_port_num(int unit, int port, int *port_offset)
   2638 {
   2639     int             vp;
   2640 
   2641     if(BCM_GPORT_IS_SUBPORT_PORT(port)) {
   2642         BCM_IF_ERROR_RETURN(_bcm_td2p_gpp_hw_index_get(unit, port, port_offset));
   2643     } else {
   2644         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &vp));
   2645 
   2646         /* VP's follow the GPP's, add the offset */
   2647         *port_offset = BCMI_VP_GROUP_VP_OFFSET + vp;
   2648     }
   2649 
   2650     return BCM_E_NONE;
   2651 }
   2652 
   2653 /*
   2654  * Function:
   2655  *      bcm_td2p_vp_group_port_filter_get
   2656  * Purpose:
   2657  *      Given a access_type and the port value,
   2658  *      return the current vp_group the entity belongs to.
   2659  * Parameters:
   2660  *      unit - (IN) BCM device number
   2661  *      port   - (IN) Gpp/VP port value
   2662  *      egress  - (IN) If TRUE, VP handling is for egress, else ingress
   2663  *      vp_group - (OUT) The vp_group associated with the entity
   2664  *      ifilter - (OUT) The ifilter value 
   2665  *      
   2666  * Returns:
   2667  *      BCM_E_XXX
   2668  */
   2669 STATIC int
   2670 bcm_td2p_vp_group_port_filter_get(int unit, int port, int egress, int *vp_group, int *filter)
   2671 {
   2672     int             port_index;
   2673     soc_mem_t       port_mem;
   2674     soc_field_t     mbrship_field;
   2675     soc_field_t     filter_field;
   2676     uint32          entry[SOC_MAX_MEM_WORDS];
   2677 
   2678     if (BCM_GPORT_IS_SUBPORT_PORT(port)) {
   2679         if (egress) {
   2680             port_mem = EGR_GPP_ATTRIBUTESm;
   2681             filter_field = EN_EFILTERf;
   2682             mbrship_field = VLAN_MEMBERSHIP_PROFILEf;
   2683         } else {
   2684             port_mem = SOURCE_TRUNK_MAP_TABLEm;
   2685             filter_field = EN_IFILTERf;
   2686             mbrship_field = VLAN_MEMBERSHIP_PROFILEf;
   2687         }
   2688 
   2689         BCM_IF_ERROR_RETURN(_bcm_td2p_gpp_hw_index_get(unit, port, &port_index));
   2690         BCM_IF_ERROR_RETURN(
   2691             soc_mem_read(unit, port_mem, MEM_BLOCK_ANY, port_index, &entry));
   2692 
   2693         *vp_group = soc_mem_field32_get(unit, port_mem, &entry, mbrship_field);
   2694 
   2695         if(egress) {
   2696             /* Currently '_bcm_esw_egr_port_tab_set' is defined only for KT2,
   2697                when the port handling gets cleaned up, we need to make it
   2698                generic and call this LPORT config from there.
   2699             */
   2700             BCM_IF_ERROR_RETURN(bcm_esw_port_egr_lport_field_get(
   2701                             unit, port, EGR_LPORT_PROFILEm,
   2702                             filter_field, (uint32*)filter));
   2703         } else {
   2704             BCM_IF_ERROR_RETURN(
   2705                 _bcm_esw_port_tab_get(unit, port, filter_field, filter));
   2706         }
   2707     } else {
   2708         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port_index));
   2709 
   2710         if (egress) {
   2711             port_mem = EGR_DVP_ATTRIBUTEm;
   2712 
   2713             BCM_IF_ERROR_RETURN(soc_mem_read(
   2714                 unit, port_mem, MEM_BLOCK_ANY, port_index, &entry));
   2715             BCM_IF_ERROR_RETURN(_td2p_egr_dvp_attribute_field_name_get(
   2716                                 unit, &entry, EN_EFILTERf, &filter_field));
   2717             BCM_IF_ERROR_RETURN(_td2p_egr_dvp_attribute_field_name_get(
   2718                     unit, &entry, VLAN_MEMBERSHIP_PROFILEf, &mbrship_field));
   2719         } else {
   2720             port_mem = SOURCE_VPm;
   2721             filter_field = ENABLE_IFILTERf;
   2722             mbrship_field = VLAN_MEMBERSHIP_PROFILEf;
   2723 
   2724             BCM_IF_ERROR_RETURN(soc_mem_read(
   2725                 unit, port_mem, MEM_BLOCK_ANY, port_index, &entry));
   2726         }
   2727 
   2728         *vp_group = soc_mem_field32_get(unit, port_mem, &entry, mbrship_field);
   2729         *filter = soc_mem_field32_get(unit, port_mem, &entry, filter_field);
   2730     }
   2731 
   2732     return BCM_E_NONE;
   2733 }
   2734 
   2735 /*
   2736  * Function:
   2737  *      bcm_td2p_vp_group_port_filter_set
   2738  * Purpose:
   2739  *      Given a access_type and the port value,
   2740  *      return the current vp_group the entity belongs to.
   2741  * Parameters:
   2742  *      unit - (IN) BCM device number
   2743  *      access_type - (IN) The data_type which can be FP, GPP/VP or STG
   2744  *      port   - (IN) Gpp/VP port value
   2745  *      egress  - (IN) If TRUE, VP handling is for egress, else ingress
   2746  *      ifilter - (IN) The ifilter value to set
   2747  *      
   2748  * Returns:
   2749  *      BCM_E_XXX
   2750  */
   2751 STATIC int
   2752 bcm_td2p_vp_group_port_filter_set(int unit, int port, int egress, int filter)
   2753 {
   2754     int             port_index;
   2755     soc_mem_t       port_mem;
   2756     soc_field_t     filter_field;
   2757     uint32          entry[SOC_MAX_MEM_WORDS];
   2758 
   2759     if (BCM_GPORT_IS_SUBPORT_PORT(port)) {
   2760         if (egress) {
   2761             filter_field = EN_EFILTERf;
   2762         } else {
   2763             filter_field = EN_IFILTERf;
   2764         }
   2765 
   2766         if (egress) {
   2767             BCM_IF_ERROR_RETURN(bcm_esw_port_egr_lport_field_set(unit, port,
   2768                             EGR_LPORT_PROFILEm, filter_field, filter));
   2769         } else {
   2770             BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port,
   2771                         _BCM_CPU_TABS_NONE, filter_field, filter));
   2772         }
   2773     } else {
   2774         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &port_index));
   2775 
   2776         if (egress) {
   2777             port_mem = EGR_DVP_ATTRIBUTEm;
   2778 
   2779             BCM_IF_ERROR_RETURN(soc_mem_read(
   2780                 unit, port_mem, MEM_BLOCK_ANY, port_index, &entry));
   2781             BCM_IF_ERROR_RETURN(_td2p_egr_dvp_attribute_field_name_get(
   2782                                 unit, &entry, EN_EFILTERf, &filter_field));
   2783         } else {
   2784             port_mem = SOURCE_VPm;
   2785             filter_field = ENABLE_IFILTERf;
   2786 
   2787             BCM_IF_ERROR_RETURN(soc_mem_read(
   2788                 unit, port_mem, MEM_BLOCK_ANY, port_index, &entry));
   2789         }
   2790 
   2791         soc_mem_field32_set(unit, port_mem, &entry, filter_field, filter);
   2792         BCM_IF_ERROR_RETURN(
   2793             soc_mem_write(unit, port_mem, MEM_BLOCK_ALL, port_index, &entry));
   2794     }
   2795 
   2796     return BCM_E_NONE;
   2797 }
   2798 
   2799 /*
   2800  * Function:
   2801  *      bcm_td2p_vp_group_ut_state_set
   2802  * Purpose:
   2803  *      Given an "EGR-VLAN" and a group, set the UT state.
   2804  *
   2805  * Parameters:
   2806  *      unit - (IN) BCM device number
   2807  *      egr_vlan - (IN) Egress VLAN
   2808  *      vp_group - (IN) - STP state that the value needs to be set to
   2809  *      ut_state - (IN) The UT state for the given group on this egr_vlan
   2810  * Returns:
   2811  *      BCM_E_XXX
   2812  */
   2813 int
   2814 bcm_td2p_vp_group_ut_state_set(int unit, int egr_vlan, int vp_group, int ut_state)
   2815 {
   2816     uint32              ut_grp_bmap[2];
   2817     egr_vlan_entry_t    egr_vlan_entry;
   2818 #if defined(BCM_TRIDENT3_SUPPORT)
   2819     egr_vlan_vfi_untag_entry_t egr_vlan_vfi;
   2820 #endif
   2821     int                 rv = BCM_E_NONE;
   2822 
   2823 #if defined(BCM_TRIDENT3_SUPPORT)
   2824     sal_memset(&egr_vlan_vfi, 0, sizeof(egr_vlan_vfi));
   2825     if (SOC_MEM_IS_VALID(unit, EGR_VLAN_VFI_UNTAGm)) {
   2826         BCM_IF_ERROR_RETURN(_bcm_td3_vlan_vfi_profile_entry_get(unit,
   2827                                                 egr_vlan, &egr_vlan_vfi));
   2828         soc_mem_field_get(unit, EGR_VLAN_VFI_UNTAGm, (uint32*)&egr_vlan_vfi,
   2829                 UT_VP_GRP_BITMAPf, ut_grp_bmap);
   2830     } else
   2831 #endif
   2832     {
   2833         BCM_IF_ERROR_RETURN(READ_EGR_VLANm(unit, MEM_BLOCK_ANY,
   2834                                             egr_vlan, &egr_vlan_entry));
   2835     soc_EGR_VLANm_field_get(unit, &egr_vlan_entry,
   2836             UT_VP_GRP_BITMAPf, ut_grp_bmap);
   2837     }
   2838 
   2839     /* Set or clear the relevant group */
   2840     if(ut_state) {
   2841         ut_grp_bmap[vp_group / 32] |= (1 << (vp_group % 32));
   2842     } else {
   2843         ut_grp_bmap[vp_group / 32] &= ~(1 << (vp_group % 32));
   2844     }
   2845 
   2846 #if defined(BCM_TRIDENT3_SUPPORT)
   2847     if (SOC_MEM_IS_VALID(unit, EGR_VLAN_VFI_UNTAGm)) {
   2848         soc_mem_field_set(unit, EGR_VLAN_VFI_UNTAGm, (uint32*)&egr_vlan_vfi,
   2849                 UT_VP_GRP_BITMAPf, ut_grp_bmap);
   2850         _bcm_td3_vlan_vfi_profile_entry_set(unit, egr_vlan, &egr_vlan_vfi);
   2851     } else
   2852 #endif
   2853     {
   2854     soc_EGR_VLANm_field_set(unit, &egr_vlan_entry,
   2855             UT_VP_GRP_BITMAPf, ut_grp_bmap);
   2856     BCM_IF_ERROR_RETURN
   2857         (WRITE_EGR_VLANm(unit, MEM_BLOCK_ALL, egr_vlan, &egr_vlan_entry));
   2858     }
   2859 
   2860     return rv;
   2861 }
   2862 
   2863 /*
   2864  * Function:
   2865  *      bcm_td2p_vp_group_ut_state_get
   2866  * Purpose:
   2867  *      Given an "VLAN" and a subport, get the port's states.
   2868  *
   2869  * Parameters:
   2870  *      unit  - (IN) BCM device number
   2871  *      gport - (IN) Subport port
   2872  *      vlan  - (IN) - vlan
   2873  *      flags - (OUT) Subport state
   2874  * Returns:
   2875  *      BCM_E_XXX
   2876  */
   2877 int
   2878 bcm_td2p_vp_group_ut_state_get(int unit, bcm_port_t gport, bcm_vlan_t vlan, int *ut_state)
   2879 {
   2880     int vp_group = 0, filter = 0;
   2881     uint32              ut_grp_bmap[2];
   2882     egr_vlan_entry_t    egr_vlan_entry;
   2883     egr_vlan_vfi_untag_entry_t egr_vlan_vfi;
   2884     uint32              prof_index = 0;
   2885 
   2886     if ((vlan > BCM_VLAN_MAX) && (!SOC_MEM_IS_VALID(unit, EGR_VLAN_VFI_UNTAGm))) {
   2887         return BCM_E_PARAM;
   2888     }
   2889 
   2890     if(BCM_GPORT_IS_VP_GROUP(gport)) {
   2891         vp_group = BCM_GPORT_VP_GROUP_GET(gport);
   2892     } else {
   2893         /* Get vp_group associated with this port */
   2894         BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_filter_get(
   2895                         unit, gport, TRUE, &vp_group, &filter));
   2896 
   2897         /* Make sure the filter values are set to vp_group */
   2898         if (BCM_GPORT_IS_SUBPORT_PORT(gport)) {
   2899             if (filter != GPP_FILTER_VP_GRP_BMAP) {
   2900                 return BCM_E_PARAM;
   2901             }
   2902         } else {
   2903             if (filter != VP_FILTER_VP_GRP_BMAP) {
   2904                 return BCM_E_PARAM;
   2905             }
   2906         }
   2907     }
   2908 
   2909     if (SOC_MEM_IS_VALID(unit, EGR_VLAN_VFI_UNTAGm)) {
   2910         /* Get the profile_idx associated with the VLAN/VFI */
   2911 #if defined(BCM_TRIDENT3_SUPPORT)
   2912         if (SOC_IS_TRIDENT3X(unit)) {
   2913             BCM_IF_ERROR_RETURN(_bcm_td3_vlan_vfi_profile_entry_get(unit,
   2914                                                     vlan, &egr_vlan_vfi));
   2915         } else
   2916 #endif
   2917         {
   2918             BCM_IF_ERROR_RETURN(READ_EGR_VLANm(unit, MEM_BLOCK_ANY, vlan, &egr_vlan_entry));
   2919             prof_index = soc_mem_field32_get(unit, EGR_VLANm,
   2920                                              &egr_vlan_entry, UNTAG_PROFILE_PTRf);
   2921             BCM_IF_ERROR_RETURN
   2922                 (READ_EGR_VLAN_VFI_UNTAGm(unit, MEM_BLOCK_ANY, prof_index, &egr_vlan_vfi));
   2923         }
   2924         soc_EGR_VLAN_VFI_UNTAGm_field_get(unit, &egr_vlan_vfi, UT_VP_GRP_BITMAPf, ut_grp_bmap);
   2925     } else {
   2926     BCM_IF_ERROR_RETURN(READ_EGR_VLANm(unit, MEM_BLOCK_ANY, vlan, &egr_vlan_entry));
   2927     soc_EGR_VLANm_field_get(unit, &egr_vlan_entry, UT_VP_GRP_BITMAPf, ut_grp_bmap);
   2928     }
   2929 
   2930     *ut_state = (ut_grp_bmap[vp_group / 32] & (1 << (vp_group % 32)));
   2931 
   2932     return BCM_E_NONE;
   2933 }
   2934 
   2935 /*
   2936  * Function:
   2937  *      bcm_td2p_vp_group_vlan_vpn_stg_set
   2938  * Purpose:
   2939  *      Attach a STG group to vlan/vpn.
   2940  * Parameters:
   2941  *      unit - (IN) BCM device number
   2942  *      vlan_vpn - (IN) vlan/vpn ID
   2943  *      egress  - (IN) If TRUE, VP handling is for egress, else ingress
   2944  *      stg - (OUT) The STG for the VLAN
   2945  *
   2946  * Returns:
   2947  *      BCM_E_XXX
   2948  */
   2949 int
   2950 bcm_td2p_vp_group_vlan_vpn_stg_set(int unit, int vlan_vpn, int egress, int stg)
   2951 {
   2952     int                rv = 0;
   2953     soc_mem_t          mem;
   2954     uint32             index = 0;
   2955     bcm_vlan_info_t *vi = &vlan_info[unit];
   2956     _bcm_virtual_bookkeeping_t *virtual_info = &_bcm_virtual_bk_info[unit];
   2957 
   2958     /* Depending on VLAN/VFI and direction, note the memory to use */
   2959     if (_BCM_VPN_VFI_IS_SET(vlan_vpn)) {
   2960         _BCM_VPN_GET(index, _BCM_VPN_TYPE_VFI, vlan_vpn);
   2961         if (virtual_info->vfi_bitmap != NULL &&
   2962             !_bcm_vfi_used_get(unit, index, _bcmVfiTypeAny)) {
   2963             return BCM_E_NOT_FOUND;
   2964         }
   2965 
   2966         if (!egress) {
   2967             mem = VFIm;
   2968         } else {
   2969             mem = EGR_VFIm;
   2970         }
   2971     } else {
   2972         index = vlan_vpn;
   2973         if (vi->init && !SHR_BITGET(vi->bmp.w, vlan_vpn)) {
   2974             return BCM_E_NOT_FOUND;
   2975         }
   2976 
   2977         if (!egress) {
   2978             mem = VLAN_TABm;
   2979         } else {
   2980             mem = EGR_VLANm;
   2981         }
   2982     }
   2983 
   2984     rv = soc_mem_field32_modify(unit, mem, index, STGf, stg);
   2985     if (BCM_SUCCESS(rv) &&
   2986         !egress && mem == VLAN_TABm &&
   2987         SOC_MEM_IS_VALID(unit, VLAN_ATTRS_1m)) {
   2988         rv = soc_mem_field32_modify(unit, VLAN_ATTRS_1m, index, STGf, stg);
   2989     }
   2990 
   2991     return rv;
   2992 }
   2993 
   2994 /*
   2995  * Function:
   2996  *      bcm_td2p_vp_group_vlan_vpn_stg_get
   2997  * Purpose:
   2998  *      Get stg group id of given vlan/vpn per direction.
   2999  * Parameters:
   3000  *      unit - (IN) BCM device number
   3001  *      vlan_vpn - (IN) vlan/vpn ID
   3002  *      egress  - (IN) If TRUE, VP handling is for egress, else ingress
   3003  *      stg - (OUT) The STG for the VLAN
   3004  *
   3005  * Returns:
   3006  *      BCM_E_XXX
   3007  */
   3008 int
   3009 bcm_td2p_vp_group_vlan_vpn_stg_get(int unit, int vlan_vpn, int egress, int *stg)
   3010 {
   3011     soc_mem_t          mem;
   3012     uint32             index = 0;
   3013     uint32 buf[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read memory entry. */
   3014     bcm_vlan_info_t *vi = &vlan_info[unit];
   3015     _bcm_virtual_bookkeeping_t *virtual_info = &_bcm_virtual_bk_info[unit];
   3016 
   3017     /* Depending on VLAN/VFI and direction, note the memory to use */
   3018     if (_BCM_VPN_VFI_IS_SET(vlan_vpn)) {
   3019         _BCM_VPN_GET(index, _BCM_VPN_TYPE_VFI, vlan_vpn);
   3020         if (virtual_info->vfi_bitmap != NULL &&
   3021             !_bcm_vfi_used_get(unit, index, _bcmVfiTypeAny)) {
   3022             return BCM_E_NOT_FOUND;
   3023         }
   3024 
   3025         if (egress) {
   3026             mem = EGR_VFIm;
   3027         } else {
   3028             mem = VFIm;
   3029         }
   3030     } else {
   3031         index = vlan_vpn;
   3032         if (vi->init && !SHR_BITGET(vi->bmp.w, vlan_vpn)) {
   3033             return BCM_E_NOT_FOUND;
   3034         }
   3035 
   3036         if (egress) {
   3037             mem = EGR_VLANm;
   3038         } else {
   3039             mem = VLAN_TABm;
   3040         }
   3041     }
   3042 
   3043     /* Read the memory location */
   3044     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, buf));
   3045     /* Assign the stp_state */
   3046     *stg = soc_mem_field32_get(unit, mem, buf, STGf);
   3047 
   3048     return BCM_E_NONE;
   3049 }
   3050 
   3051 /*
   3052  * Function:
   3053  *      bcm_td2p_vp_group_stg_move
   3054  * Purpose:
   3055  *      Move FP/GPP/VP from one VP group to another due to add/remove
   3056  * Parameters:
   3057  *      unit - (IN) BCM device number
   3058  *      port - (IN) Gpp/VP port value
   3059  *      stg - (IN) STG associated with the call, if the access_type is STG
   3060  *      stp_state - (IN) - STP state that the value needs to be set to
   3061  *      egress  - (IN) If TRUE, VP handling is for egress, else ingress
   3062  * Returns:
   3063  *      BCM_E_XXX
   3064  */
   3065 int
   3066 bcm_td2p_vp_group_stg_move(int unit, int stg, int gport, int stp_state, int egress)
   3067 {
   3068     int rv;
   3069     int filter = 0;
   3070     int vlan_vfi_count;
   3071     int old_vp_group = 0, new_vp_grp = 0;
   3072     _bcm_td2p_vp_group_t *cur_vp_grp = NULL;
   3073     SHR_BITDCL *vlan_vfi_bmap = NULL;
   3074 
   3075     VP_GROUP_LOCK_MEMS(unit, egress);
   3076 
   3077     /* Get the current vp group associated with this STG group */
   3078     rv = bcm_td2p_vp_group_port_filter_get(
   3079             unit, gport, egress, &old_vp_group, &filter);
   3080     if (BCM_FAILURE(rv)) {
   3081         goto cleanup;
   3082     }
   3083 
   3084     if(BCM_GPORT_IS_SUBPORT_PORT(gport)) {
   3085         if (GPP_FILTER_VP_GRP_BMAP != filter) {
   3086             rv = BCM_E_DISABLED;
   3087             goto cleanup;
   3088         }
   3089     } else {
   3090         if (VP_FILTER_VP_GRP_BMAP != filter) {
   3091             rv = BCM_E_DISABLED;
   3092             goto cleanup;
   3093         }
   3094     }
   3095 
   3096     if (egress) {
   3097         cur_vp_grp = EG_VP_GROUP(unit, old_vp_group);
   3098     } else {
   3099         cur_vp_grp = ING_VP_GROUP(unit, old_vp_group);
   3100     }
   3101 
   3102     if(stp_state == cur_vp_grp->stp_state) {
   3103         rv = BCM_E_NONE;
   3104         goto cleanup;
   3105     }
   3106 
   3107     vlan_vfi_count = BCM_VLAN_COUNT + soc_mem_index_count(unit, VFIm);
   3108     vlan_vfi_bmap = sal_alloc(SHR_BITALLOCSIZE(vlan_vfi_count), "vlan bitmap");
   3109     if (NULL == vlan_vfi_bmap) {
   3110         rv =  BCM_E_MEMORY;
   3111         goto cleanup;
   3112     }
   3113     sal_memset(vlan_vfi_bmap, 0, SHR_BITALLOCSIZE(vlan_vfi_count));
   3114 
   3115     if (SHR_BITEQ_RANGE(vlan_vfi_bmap,
   3116             cur_vp_grp->vlan_vfi_bitmap, 0, vlan_vfi_count)) {
   3117         rv = BCM_E_PARAM;
   3118         goto cleanup;
   3119     } else {
   3120         sal_memcpy(vlan_vfi_bmap, cur_vp_grp->vlan_vfi_bitmap,
   3121                             SHR_BITALLOCSIZE(vlan_vfi_count));
   3122     }
   3123 
   3124     /* Try and find a group we can re-use */
   3125     rv = _bcm_td2p_vp_group_join(unit, gport, vlan_vfi_bmap,
   3126             stp_state, cur_vp_grp->ut_state, egress, &new_vp_grp);
   3127     VP_GROUP_CLEANUP(rv);
   3128 
   3129     /* Now leave the previous group, if different from new group */
   3130     if (old_vp_group != new_vp_grp){
   3131         rv = _bcm_td2p_vp_group_leave(unit, gport, old_vp_group, egress);
   3132     }
   3133 
   3134 cleanup:
   3135     if(vlan_vfi_bmap) {
   3136         sal_free(vlan_vfi_bmap);
   3137         vlan_vfi_bmap = NULL;
   3138     }
   3139     VP_GROUP_UNLOCK_MEMS(unit, egress);
   3140 
   3141     return rv;
   3142 }
   3143 
   3144 /*
   3145  * Function:
   3146  *      bcm_td2p_vp_group_stp_init
   3147  * Purpose:
   3148  *      Init all vp group stp state for the given stg group.
   3149  * Parameters:
   3150  *      unit - (IN) BCM device number
   3151  *      stg - (IN) STG associated with the call, if the access_type is STG
   3152  *      egress  - (IN) If TRUE, VP handling is for egress, else ingress
   3153  *      stp_state - (IN) - STP state the stg-port belongs to
   3154  * Returns:
   3155  *      BCM_E_XXX
   3156  */
   3157 int
   3158 bcm_td2p_vp_group_stp_init(int unit, int stg, int egress, int stp_state)
   3159 {
   3160     int rv = BCM_E_NONE;
   3161     int vp_group = 0;
   3162     int num_grps = 0;
   3163     soc_mem_t mem;
   3164     uint32 stg_entry[SOC_MAX_MEM_WORDS];
   3165 
   3166     if (!soc_feature(unit, soc_feature_vlan_vfi_membership)){
   3167         return BCM_E_UNAVAIL;
   3168     }
   3169 
   3170     if (egress) {
   3171         mem = EGR_VLAN_STGm;
   3172         num_grps = soc_mem_field_length(unit,
   3173             EGR_VLAN_VFI_MEMBERSHIPm, VP_GROUP_BITMAPf);
   3174     } else {
   3175         mem = STG_TABm;
   3176         num_grps = soc_mem_field_length(unit,
   3177             ING_VLAN_VFI_MEMBERSHIPm, VP_GROUP_BITMAPf);
   3178     }
   3179 
   3180     soc_mem_lock(unit, mem);
   3181 
   3182     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, stg, &stg_entry);
   3183     VP_GROUP_CLEANUP(rv);
   3184 
   3185     for (vp_group = 0; vp_group < num_grps; vp_group++) {
   3186         soc_mem_field32_set(unit, mem, &stg_entry,
   3187             _bcm_vp_group_stp_field[vp_group], stp_state);
   3188     }
   3189 
   3190     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, stg, &stg_entry);
   3191 
   3192 cleanup:
   3193     soc_mem_unlock(unit, mem);
   3194 
   3195     return rv;
   3196 }
   3197 
   3198 /*
   3199  * Function:
   3200  *      bcm_td2p_vp_group_stp_state_set
   3201  * Purpose:
   3202  *      Given a port and a stg, sets it state
   3203  * Parameters:
   3204  *      unit - (IN) BCM device number
   3205  *      stg - (IN) STG associated with the call, if the access_type is STG
   3206  *      port - (IN) Port number
   3207  *      egress  - (IN) If TRUE, VP handling is for egress, else ingress
   3208  *      stp_state - (IN) - STP state the stg-port belongs to
   3209  * Returns:
   3210  *      BCM_E_XXX
   3211  */
   3212 int
   3213 bcm_td2p_vp_group_stp_state_set(int unit, int stg, int gport, int egress, int stp_state)
   3214 {
   3215     int rv = BCM_E_NONE;
   3216     int vp_group = 0, filter = 0;
   3217     soc_mem_t mem;
   3218 
   3219     if (!soc_feature(unit, soc_feature_vlan_vfi_membership)){
   3220         return BCM_E_UNAVAIL;
   3221     }
   3222 
   3223     if (egress) {
   3224         mem = EGR_VLAN_STGm;
   3225     } else {
   3226         mem = STG_TABm;
   3227     }
   3228 
   3229     if(BCM_GPORT_IS_VP_GROUP(gport)) {
   3230         vp_group = BCM_GPORT_VP_GROUP_GET(gport);
   3231     } else {
   3232         BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_filter_get(
   3233                 unit, gport, egress, &vp_group, &filter));
   3234     }
   3235 
   3236     soc_mem_lock(unit, mem);
   3237 
   3238     rv = soc_mem_field32_modify(unit, mem, stg,
   3239             _bcm_vp_group_stp_field[vp_group], stp_state);
   3240 
   3241     soc_mem_unlock(unit, mem);
   3242 
   3243     return rv;
   3244 }
   3245 
   3246 /*
   3247  * Function:
   3248  *      bcm_td2p_vp_group_stp_state_get
   3249  * Purpose:
   3250  *      Given a port and a stg, gets its state
   3251  * Parameters:
   3252  *      unit - (IN) BCM device number
   3253  *      stg - (IN) STG associated with the call, if the access_type is STG
   3254  *      port - (IN) Port number
   3255  *      egress  - (IN) If TRUE, VP handling is for egress, else ingress 
   3256  *      stp_state - (OUT) - STP state the stg-port belongs to
   3257  * Returns:
   3258  *      BCM_E_XXX
   3259  */
   3260 int
   3261 bcm_td2p_vp_group_stp_state_get(int unit, int stg, int gport, int egress, int *stp_state)
   3262 {
   3263     int rv = BCM_E_NONE;
   3264     int vp_group = 0, filter = 0;
   3265     soc_mem_t mem;
   3266     uint32 stg_entry[SOC_MAX_MEM_WORDS];
   3267 
   3268     if(BCM_GPORT_IS_VP_GROUP(gport)) {
   3269         vp_group = BCM_GPORT_VP_GROUP_GET(gport);
   3270     } else {
   3271         /* Get vp_group associated with this port */
   3272         BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_filter_get(
   3273                 unit, gport, egress, &vp_group, &filter));
   3274     }
   3275 
   3276     if (egress) {
   3277         mem = EGR_VLAN_STGm;
   3278     } else {
   3279         mem = STG_TABm;
   3280     }
   3281 
   3282     soc_mem_lock(unit, STG_TABm);
   3283     /* Read the relevant entry */
   3284     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, stg, &stg_entry);
   3285     soc_mem_unlock(unit, STG_TABm);
   3286     BCM_IF_ERROR_RETURN(rv);
   3287 
   3288     /* Get the STP state */
   3289     *stp_state = soc_mem_field32_get(unit, mem,&stg_entry,
   3290                             _bcm_vp_group_stp_field[vp_group]);
   3291 
   3292     return BCM_E_NONE;
   3293 }
   3294 
   3295 /*
   3296  * Function:
   3297  *      bcm_td2p_ing_vp_group_vlan_get_all
   3298  * Purpose:
   3299  *      Get all VPs from the VP groups belonging to the given VLAN.
   3300  * Parameters:
   3301  *      unit - (IN) BCM device number
   3302  *      vlan - (IN) VLAN ID 
   3303  *      gpp_vp_bitmap - (OUT) Bitmap of VPs.
   3304  * Returns:
   3305  *      BCM_E_XXX
   3306  */
   3307 int
   3308 bcm_td2p_ing_vp_group_vlan_get_all(int unit, bcm_vlan_t vlan,
   3309         SHR_BITDCL *gpp_vp_bitmap)
   3310 {
   3311     vlan_mpls_entry_t vlan_mpls_entry;
   3312     ing_vlan_vfi_membership_entry_t vlan_vfi_entry;
   3313     uint32 fldbuf[2];
   3314     int i;
   3315     uint32 profile_idx;
   3316 
   3317 #if defined(BCM_TRIDENT3_SUPPORT)
   3318     if (SOC_MEM_IS_VALID(unit, VLAN_ATTRS_1m)) {
   3319         vlan_attrs_1_entry_t vlan_tab;
   3320         SOC_IF_ERROR_RETURN(
   3321                 READ_VLAN_ATTRS_1m(unit, MEM_BLOCK_ANY, vlan, &vlan_tab));
   3322         profile_idx = soc_VLAN_ATTRS_1m_field32_get(unit, &vlan_tab,
   3323                 MEMBERSHIP_PROFILE_PTRf);
   3324     } else
   3325 #endif
   3326     {
   3327         SOC_IF_ERROR_RETURN
   3328         (READ_VLAN_MPLSm(unit, MEM_BLOCK_ANY, vlan, &vlan_mpls_entry));
   3329     soc_VLAN_MPLSm_field_get(unit, &vlan_mpls_entry, MEMBERSHIP_PROFILE_PTRf,
   3330             &profile_idx);
   3331     }
   3332 
   3333     BCM_IF_ERROR_RETURN
   3334         (READ_ING_VLAN_VFI_MEMBERSHIPm(unit, MEM_BLOCK_ANY, profile_idx,
   3335                                        &vlan_vfi_entry));
   3336     soc_ING_VLAN_VFI_MEMBERSHIPm_field_get(unit, &vlan_vfi_entry, 
   3337             VP_GROUP_BITMAPf, fldbuf);
   3338     for (i = 0; i < VP_GROUP_BK(unit)->num_ing_vp_group; i++) {
   3339         if (fldbuf[i / 32] & (1 << (i % 32))) {
   3340             /* The bit in VP_GROUP_BITMAP that corresponds to
   3341              * VP group i is set. Get all VPs in VP group i.
   3342              */
   3343             SHR_BITOR_RANGE(gpp_vp_bitmap, ING_VP_GROUP(unit, i)->gpp_vp_bitmap,
   3344                     0, (BCMI_VP_GROUP_GLP_COUNT + 
   3345                         soc_mem_index_count(unit, SOURCE_VPm)), 
   3346                         gpp_vp_bitmap);
   3347         }
   3348     }
   3349 
   3350     return BCM_E_NONE;
   3351 }
   3352 
   3353 /*
   3354  * Function:
   3355  *      bcm_td2p_eg_vp_group_vlan_get_all
   3356  * Purpose:
   3357  *      Get all VPs from the VP groups belonging to the given VLAN.
   3358  * Parameters:
   3359  *      unit - (IN) BCM device number
   3360  *      vlan - (IN) VLAN ID 
   3361  *      gpp_vp_bitmap - (OUT) Bitmap of VPs.
   3362  * Returns:
   3363  *      BCM_E_XXX
   3364  */
   3365 int
   3366 bcm_td2p_eg_vp_group_vlan_get_all(int unit, bcm_vlan_t vlan,
   3367         SHR_BITDCL *gpp_vp_bitmap)
   3368 {
   3369     egr_vlan_entry_t egr_vlan_entry;
   3370     egr_vlan_vfi_membership_entry_t vlan_vfi_entry;
   3371     uint32 fldbuf[2];
   3372     int i;
   3373     uint32 profile_idx;
   3374 
   3375     BCM_IF_ERROR_RETURN
   3376         (READ_EGR_VLANm(unit, MEM_BLOCK_ANY, vlan, &egr_vlan_entry));
   3377     soc_EGR_VLANm_field_get(unit, &egr_vlan_entry, MEMBERSHIP_PROFILE_PTRf,
   3378             &profile_idx);
   3379 
   3380     BCM_IF_ERROR_RETURN
   3381         (READ_EGR_VLAN_VFI_MEMBERSHIPm(unit, MEM_BLOCK_ANY, profile_idx, 
   3382                                        &vlan_vfi_entry));
   3383     soc_EGR_VLAN_VFI_MEMBERSHIPm_field_get(unit, &vlan_vfi_entry,
   3384             VP_GROUP_BITMAPf, fldbuf);
   3385 
   3386     for (i = 0; i < VP_GROUP_BK(unit)->num_eg_vp_group; i++) {
   3387         if (fldbuf[i / 32] & (1 << (i % 32))) {
   3388             /* The bit in VP_GROUP_BITMAP that corresponds to
   3389              * VP group i is set. Get all VPs in VP group i.
   3390              */
   3391             SHR_BITOR_RANGE(gpp_vp_bitmap, EG_VP_GROUP(unit, i)->gpp_vp_bitmap,
   3392                     0, (BCMI_VP_GROUP_GLP_COUNT + 
   3393                         soc_mem_index_count(unit, SOURCE_VPm)), 
   3394                         gpp_vp_bitmap);
   3395         }
   3396     }
   3397 
   3398     return BCM_E_NONE;
   3399 }
   3400 
   3401 #if defined(BCM_TRX_SUPPORT)
   3402 
   3403 /*
   3404  * Function:
   3405  *      bcm_td2p_vp_group_delete_all
   3406  * Purpose:
   3407  *      Delete all VP groups from the given VLAN.
   3408  * Parameters:
   3409  *      unit - (IN) BCM device number
   3410  *      vlan - (IN) VLAN ID
   3411  *      egress - (IN) TRUE for egress, FALSE for ingress
   3412  * Returns:
   3413  *      BCM_E_XXX
   3414  */
   3415 int
   3416 bcm_td2p_vp_group_delete_all(int unit, bcm_vlan_t vlan_vpn, int egress)
   3417 {
   3418     uint32 profile_idx;
   3419     uint32 fldbuf[2];
   3420     int mod, port, gport;
   3421     int grp;
   3422     int grp_num;
   3423     int gpp_vp;
   3424     int gpp_vp_num;
   3425     soc_mem_t mbrship_mem;
   3426     uint32 mbrship_entry[SOC_MAX_MEM_WORDS];
   3427     _bcm_td2p_vp_group_t *vp_grp = NULL;
   3428 
   3429     if (egress) {
   3430         mbrship_mem = EGR_VLAN_VFI_MEMBERSHIPm;
   3431         grp_num = VP_GROUP_BK(unit)->num_eg_vp_group;
   3432     } else {
   3433         mbrship_mem = ING_VLAN_VFI_MEMBERSHIPm;
   3434         grp_num = VP_GROUP_BK(unit)->num_ing_vp_group;
   3435     }
   3436 
   3437     BCM_IF_ERROR_RETURN(_bcm_td2p_vlan_vpn_mbrship_profile_get(
   3438                                 unit, vlan_vpn, egress, &profile_idx));
   3439 
   3440     if (profile_idx == 0 || profile_idx == 1) {
   3441         return BCM_E_NONE;
   3442     }
   3443 
   3444     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mbrship_mem,
   3445                         MEM_BLOCK_ANY, profile_idx, mbrship_entry));
   3446     soc_mem_field_get(unit, mbrship_mem, mbrship_entry, VP_GROUP_BITMAPf, fldbuf);
   3447 
   3448     gpp_vp_num =  BCMI_VP_GROUP_GLP_COUNT + soc_mem_index_count(unit, SOURCE_VPm);
   3449 
   3450     SHR_BIT_ITER(fldbuf, grp_num, grp) { /* find vp group used by this VLAN_VFI */
   3451         if (egress) {
   3452             vp_grp = EG_VP_GROUP(unit, grp);
   3453         } else {
   3454             vp_grp = ING_VP_GROUP(unit, grp);
   3455         }
   3456 
   3457         /* find GPP/VP used by this vp group */
   3458         SHR_BIT_ITER(vp_grp->gpp_vp_bitmap, gpp_vp_num, gpp_vp) {
   3459             if(gpp_vp < BCMI_VP_GROUP_GLP_COUNT) {
   3460                 /* Compute the (mod, port) for this GPP,
   3461                    based on the location */
   3462                 mod = gpp_vp % 255;
   3463                 port = gpp_vp - mod;
   3464                 BCM_GPORT_SUBPORT_PORT_SET(gport,
   3465                                            (((mod & 0xFF) << 0x7) | port ));
   3466             } else {
   3467                 if(_bcm_vp_encode_gport(unit, (gpp_vp-BCMI_VP_GROUP_VP_OFFSET),
   3468                                         &gport) != BCM_E_NONE) {
   3469                     return BCM_E_INTERNAL;
   3470                 }
   3471             }
   3472 
   3473             BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_move(unit,
   3474                                     gport, vlan_vpn, FALSE, egress, 0));
   3475         }
   3476     }
   3477 
   3478     return BCM_E_NONE;
   3479 }
   3480 
   3481 /*
   3482  * Function:
   3483  *      bcm_td2p_vp_vlan_member_set
   3484  * Purpose:
   3485  *      Set virtual port ingress and egress filter modes.
   3486  * Parameters:
   3487  *      unit  - (IN) BCM device number
   3488  *      gport - (IN) VP gport ID 
   3489  *      flags - (IN) Ingress and egress filter modes.
   3490  * Returns:
   3491  *      BCM_E_XXX
   3492  */
   3493 int
   3494 bcm_td2p_vp_vlan_member_set(int unit, bcm_gport_t gport, uint32 flags)
   3495 {
   3496     int rv = BCM_E_NONE;
   3497     int vp = -1;
   3498     int vlan_vfi_count;
   3499     int ing_vpg_managed, egr_vpg_managed;
   3500     int old_ifilter = 0, old_efilter = 0;
   3501     SHR_BITDCL *vlan_vfi_bitmap = NULL;
   3502     int old_ing_vpg = 0, old_egr_vpg = 0, vp_group = 0;
   3503     int filter_disable, filter_hash_table, filter_vp_grp;
   3504     int filter_vp_not_check = -1;
   3505 
   3506     if (BCM_GPORT_IS_SUBPORT_PORT(gport)) {
   3507         filter_disable = GPP_FILTER_DISABLE;
   3508         filter_hash_table = GPP_FILTER_HASH;
   3509         filter_vp_grp = GPP_FILTER_VP_GRP_BMAP;
   3510     } else {
   3511         filter_disable = VP_FILTER_DISABLE;
   3512         filter_hash_table = VP_FILTER_HASH;
   3513         filter_vp_grp = VP_FILTER_VP_GRP_BMAP;
   3514         filter_vp_not_check = VP_DO_NOT_CHECK;
   3515 
   3516         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &vp));
   3517 
   3518         if (!BCM_GPORT_IS_TRUNK(gport)) {
   3519             int local_port_num;
   3520 
   3521             BCM_IF_ERROR_RETURN(_bcm_td2p_vp_local_ports_get(
   3522                             unit, vp, 0, NULL, &local_port_num));
   3523             if ((local_port_num == 0) && 
   3524                 (flags & (BCM_PORT_VLAN_MEMBER_INGRESS | BCM_PORT_VLAN_MEMBER_EGRESS))) {
   3525                 return BCM_E_PORT;
   3526             }
   3527         }
   3528     }
   3529 
   3530     /* Get current filter mode */
   3531     BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_filter_get(
   3532             unit, gport, FALSE, &old_ing_vpg, &old_ifilter));
   3533     BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_filter_get(
   3534             unit, gport, TRUE, &old_egr_vpg, &old_efilter));
   3535 
   3536     if (flags & BCM_PORT_VLAN_MEMBER_VP_DO_NOT_CHECK) {
   3537         if (flags & BCM_PORT_VLAN_MEMBER_INGRESS) { 
   3538             if (old_ifilter != filter_vp_not_check) {
   3539                 BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_filter_set(
   3540                                      unit, gport, FALSE, filter_vp_not_check));
   3541             }
   3542         } else {
   3543             if (old_ifilter != filter_disable) {
   3544                 /* Disable checks */
   3545                 BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_filter_set(
   3546                                     unit, gport, FALSE, filter_disable));
   3547             }
   3548         }
   3549 
   3550         if(flags & BCM_PORT_VLAN_MEMBER_EGRESS) {
   3551             if (old_efilter != filter_vp_not_check) {
   3552                 BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_filter_set(
   3553                                      unit, gport, TRUE, filter_vp_not_check));
   3554             }
   3555         } else {
   3556             if (old_efilter != filter_disable) {
   3557                 /* Disable checks */
   3558                 BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_filter_set(
   3559                                     unit, gport, TRUE, filter_disable));
   3560             }
   3561         }
   3562     } else if (flags & BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP) { /* hash table */
   3563         if (flags & BCM_PORT_VLAN_MEMBER_INGRESS) {
   3564             if (old_ifilter != filter_hash_table) {
   3565                 /* enable hash table */
   3566                 BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_filter_set(
   3567                                 unit, gport, FALSE, filter_hash_table));
   3568             }
   3569         } else {
   3570             if (old_ifilter != filter_disable) {
   3571                 /* Disable checks */
   3572                 BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_filter_set(
   3573                                     unit, gport, FALSE, filter_disable));
   3574             }
   3575         }
   3576 
   3577         if (flags & BCM_PORT_VLAN_MEMBER_EGRESS) {
   3578             if (old_efilter != filter_hash_table) {
   3579                 /* enable hash table */
   3580                 BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_filter_set(
   3581                                     unit, gport, TRUE, filter_hash_table));
   3582             }
   3583         } else {
   3584             if (old_efilter != filter_disable) {
   3585                 /* Disable checks */
   3586                 BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_filter_set(
   3587                                     unit, gport, TRUE, filter_disable));
   3588             }
   3589         }
   3590     } else { /* vp group */
   3591         ing_vpg_managed = !bcm_td2p_ing_vp_group_unmanaged_get(unit);
   3592         egr_vpg_managed = !bcm_td2p_egr_vp_group_unmanaged_get(unit);
   3593 
   3594         if (((flags & BCM_PORT_VLAN_MEMBER_INGRESS) &&
   3595                 ing_vpg_managed && (old_ifilter != filter_vp_grp)) ||
   3596                 ((flags & BCM_PORT_VLAN_MEMBER_EGRESS) &&
   3597                 egr_vpg_managed && (old_efilter != filter_vp_grp))) {
   3598             vlan_vfi_count = BCM_VLAN_COUNT + soc_mem_index_count(unit, VFIm);
   3599 
   3600             vlan_vfi_bitmap = sal_alloc(
   3601                 SHR_BITALLOCSIZE(vlan_vfi_count), "vlan bitmap");
   3602             if (NULL == vlan_vfi_bitmap) {
   3603                 return BCM_E_MEMORY;
   3604             }
   3605             sal_memset(vlan_vfi_bitmap, 0,
   3606                        SHR_BITALLOCSIZE(vlan_vfi_count));
   3607 
   3608             if(!BCM_GPORT_IS_SUBPORT_PORT(gport)) {
   3609                 rv = _bcm_td2p_vp_vlan_vfi_bitmap_get(
   3610                             unit, gport, vlan_vfi_bitmap);
   3611                 VP_GROUP_CLEANUP(rv);
   3612             }
   3613         }
   3614 
   3615         if (flags & BCM_PORT_VLAN_MEMBER_INGRESS) {
   3616             if (old_ifilter != filter_vp_grp) {
   3617                 if (ing_vpg_managed) {
   3618                     rv = _bcm_td2p_vp_group_join(unit, gport, vlan_vfi_bitmap,
   3619                             _BCM_DEFAULT_STP_STATE, _BCM_DEFAULT_UNTAGGED_STATE,
   3620                             FALSE, &vp_group);
   3621                     VP_GROUP_CLEANUP(rv);
   3622                 }
   3623 
   3624                 /* Enable ingress VP group filtering */
   3625                 rv = bcm_td2p_vp_group_port_filter_set(
   3626                         unit, gport, FALSE, filter_vp_grp);
   3627                 VP_GROUP_CLEANUP(rv);
   3628             }
   3629         } else {
   3630             if (old_ifilter != filter_disable) {
   3631                 /* Disable ingress filtering */
   3632                 rv = bcm_td2p_vp_group_port_filter_set(
   3633                         unit, gport, FALSE, filter_disable);
   3634                 VP_GROUP_CLEANUP(rv);
   3635             }
   3636 
   3637             if (filter_vp_grp == old_ifilter) {
   3638                 if (!bcm_td2p_ing_vp_group_unmanaged_get(unit)) {
   3639                     /* Remove VP from VP group */
   3640                     rv = _bcm_td2p_vp_group_leave(unit, gport, old_ing_vpg, FALSE);
   3641                     VP_GROUP_CLEANUP(rv);
   3642 
   3643                     rv = _bcm_td2p_vp_group_id_set(unit, gport, 0, FALSE);
   3644                     VP_GROUP_CLEANUP(rv);
   3645                 }
   3646             }
   3647         }
   3648 
   3649         if (flags & BCM_PORT_VLAN_MEMBER_EGRESS) {
   3650             if (old_efilter != filter_vp_grp) {
   3651                 if (egr_vpg_managed) {
   3652                     rv = _bcm_td2p_vp_group_join(unit, gport, vlan_vfi_bitmap,
   3653                             _BCM_DEFAULT_STP_STATE, _BCM_DEFAULT_UNTAGGED_STATE,
   3654                             TRUE, &vp_group);
   3655                     VP_GROUP_CLEANUP(rv);
   3656                 }
   3657 
   3658                 /* Enable ingress VP group filtering */
   3659                 rv = bcm_td2p_vp_group_port_filter_set(
   3660                         unit, gport, TRUE, filter_vp_grp);
   3661                 VP_GROUP_CLEANUP(rv);
   3662             }
   3663         } else {
   3664             if (old_efilter != filter_disable) {
   3665                 /* Disable ingress filtering */
   3666                 rv = bcm_td2p_vp_group_port_filter_set(
   3667                         unit, gport, TRUE, filter_disable);
   3668                 VP_GROUP_CLEANUP(rv);
   3669             }
   3670 
   3671             if (filter_vp_grp == old_efilter) {
   3672                 if (!bcm_td2p_egr_vp_group_unmanaged_get(unit)) {
   3673                     /* Remove VP from VP group */
   3674                     rv = _bcm_td2p_vp_group_leave(unit, gport, old_egr_vpg, TRUE);
   3675                     VP_GROUP_CLEANUP(rv);
   3676 
   3677                     rv = _bcm_td2p_vp_group_id_set(unit, gport, 0, TRUE);
   3678                     VP_GROUP_CLEANUP(rv);
   3679                 }
   3680             }
   3681         }
   3682     }
   3683 
   3684 cleanup:
   3685     if (vlan_vfi_bitmap) {
   3686         sal_free(vlan_vfi_bitmap);
   3687     }
   3688 
   3689     return rv;
   3690 }
   3691 
   3692 #endif
   3693 
   3694 /*
   3695  * Function:
   3696  *      bcm_td2p_vp_vlan_member_get
   3697  * Purpose:
   3698  *      Get virtual port ingress and egress filter modes.
   3699  * Parameters:
   3700  *      unit  - (IN) BCM device number
   3701  *      gport - (IN) VP gport id
   3702  *      flags - (OUT) Ingress and egress filter modes.
   3703  * Returns:
   3704  *      BCM_E_XXX
   3705  */
   3706 int
   3707 bcm_td2p_vp_vlan_member_get(int unit, bcm_gport_t gport, uint32 *flags)
   3708 {
   3709     int cur_vp_group = 0;
   3710     int filter = 0, filter_hash_table, filter_vp_grp, filter_vp_do_not_check=-1;
   3711 
   3712     if (BCM_GPORT_IS_SUBPORT_PORT(gport)) {
   3713         filter_hash_table = GPP_FILTER_HASH;
   3714         filter_vp_grp = GPP_FILTER_VP_GRP_BMAP;
   3715     } else {
   3716         filter_hash_table = VP_FILTER_HASH;
   3717         filter_vp_grp = VP_FILTER_VP_GRP_BMAP;
   3718         filter_vp_do_not_check = VP_DO_NOT_CHECK;
   3719     }
   3720 
   3721     *flags = 0;
   3722     BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_filter_get(
   3723                 unit, gport, FALSE, &cur_vp_group, &filter));
   3724     if (filter == filter_vp_grp) {
   3725         *flags = BCM_PORT_VLAN_MEMBER_INGRESS;
   3726     } else if (filter == filter_hash_table) {
   3727         *flags = BCM_PORT_VLAN_MEMBER_INGRESS |
   3728                     BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP;
   3729     } else if (filter == filter_vp_do_not_check) {
   3730         *flags = BCM_PORT_VLAN_MEMBER_INGRESS |
   3731                     BCM_PORT_VLAN_MEMBER_VP_DO_NOT_CHECK;
   3732     }
   3733 
   3734     BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_filter_get(
   3735                 unit, gport, TRUE, &cur_vp_group, &filter));
   3736     if (filter == filter_vp_grp) {
   3737         *flags |= BCM_PORT_VLAN_MEMBER_EGRESS;
   3738     } else if (filter == filter_hash_table) {
   3739         *flags |= BCM_PORT_VLAN_MEMBER_EGRESS |
   3740                     BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP;
   3741     } else if (filter == filter_vp_do_not_check) {
   3742         *flags |= BCM_PORT_VLAN_MEMBER_EGRESS |
   3743                     BCM_PORT_VLAN_MEMBER_VP_DO_NOT_CHECK;
   3744     }
   3745 
   3746     return BCM_E_NONE;
   3747 }
   3748 
   3749 /*
   3750  * Function:
   3751  *      bcm_td2p_ing_vp_group_unmanaged_get
   3752  * Purpose:
   3753  *      Check if VP group resource is managed by user. If so, user will be
   3754  *      resposible to assign a VP group to a VP and add the VP group to the
   3755  *      vlan's VP group bitmap in order to establish the vlan membership.
   3756  * Parameters:
   3757  *      unit  - (IN) BCM device number
   3758  * Returns:
   3759  *      TRUE/FALSE
   3760  */
   3761 int
   3762 bcm_td2p_ing_vp_group_unmanaged_get(int unit)
   3763 {
   3764     return _bcm_td2p_vp_group_unmanaged[unit].ingress;
   3765 }
   3766 
   3767 int
   3768 bcm_td2p_egr_vp_group_unmanaged_get(int unit)
   3769 {
   3770     return _bcm_td2p_vp_group_unmanaged[unit].egress;
   3771 }
   3772 
   3773 /*
   3774  * Function:
   3775  *      bcm_td2p_ing_vp_group_unmanaged_set
   3776  * Purpose:
   3777  *      Set whether the VP group resource is managed by user.
   3778  * Parameters:
   3779  *      unit  - (IN) BCM device number
   3780         unmanaged - (IN) TRUE/FALSE
   3781  * Returns: BCM_E_XXX 
   3782  */
   3783 int
   3784 bcm_td2p_ing_vp_group_unmanaged_set(int unit, int flag)
   3785 {
   3786     int i;
   3787     int gpp_vp_count = 0;
   3788 
   3789     /* check if to set the same value */
   3790     if (_bcm_td2p_vp_group_unmanaged[unit].ingress == flag) {
   3791         return BCM_E_NONE;
   3792     }
   3793 
   3794     /* make sure auto method hasn't kicked in yet */
   3795     if (VP_GROUP_BK(unit)->vp_group_initialized) {
   3796         for (i = 0; i < VP_GROUP_BK(unit)->num_ing_vp_group; i++) {
   3797             if (0 == ING_VP_GROUP(unit, i)->gpp_vp_count){
   3798                     gpp_vp_count++;
   3799             }
   3800         }
   3801 
   3802         if (gpp_vp_count != VP_GROUP_BK(unit)->num_ing_vp_group) {
   3803             LOG_INFO(BSL_LS_BCM_VLAN,
   3804                      (BSL_META_U(unit, "Unmanaged mode set fails:"
   3805                             "VP group auto method already started\n")));
   3806             return BCM_E_EXISTS;
   3807         }
   3808     }
   3809     _bcm_td2p_vp_group_unmanaged[unit].ingress = flag;
   3810     return BCM_E_NONE;
   3811 }
   3812 
   3813 int
   3814 bcm_td2p_egr_vp_group_unmanaged_set(int unit, int flag)
   3815 {
   3816     int i;
   3817     int gpp_vp_count = 0;
   3818 
   3819     /* check if to set the same value */
   3820     if (_bcm_td2p_vp_group_unmanaged[unit].egress == flag) {
   3821         return BCM_E_NONE;
   3822     }
   3823 
   3824     /* make sure auto method hasn't kicked in yet */
   3825     if (VP_GROUP_BK(unit)->vp_group_initialized) {
   3826         for (i = 0; i < VP_GROUP_BK(unit)->num_eg_vp_group; i++) {
   3827             if (0 == EG_VP_GROUP(unit, i)->gpp_vp_count) {
   3828                     gpp_vp_count++;
   3829             }
   3830         }
   3831 
   3832         if (gpp_vp_count != VP_GROUP_BK(unit)->num_eg_vp_group) {
   3833             LOG_INFO(BSL_LS_BCM_VLAN,
   3834                      (BSL_META_U(unit, "Unmanaged mode set fails:"
   3835                             "VP group auto method already started\n")));
   3836 
   3837             return BCM_E_EXISTS;
   3838         }
   3839     }
   3840     _bcm_td2p_vp_group_unmanaged[unit].egress = flag;
   3841     return BCM_E_NONE;
   3842 }
   3843 
   3844 /*
   3845  * Function:
   3846  *      bcm_td2p_dvp_group_validate
   3847  * Purpose:
   3848  *      Check dvp group id valid or not
   3849  */
   3850 int
   3851 bcm_td2p_dvp_group_validate(int unit, int dvp_group_id)
   3852 {
   3853     int max_group_id;     
   3854 
   3855     max_group_id = (1 << soc_mem_field_length(unit, EGR_DVP_ATTRIBUTEm, 
   3856                                               VT_DVP_GROUP_IDf)) - 1;
   3857 #ifdef BCM_TRIDENT3_SUPPORT
   3858     if (SOC_IS_TRIDENT3X(unit)) {
   3859         if (SOC_MEM_FIELD_VALID(unit,EGR_DVP_ATTRIBUTEm,COMMON__VT_DVP_GROUP_IDf)) {
   3860             max_group_id = (1 << soc_mem_field_length(unit, EGR_DVP_ATTRIBUTEm,
   3861                                               COMMON__VT_DVP_GROUP_IDf)) - 1;
   3862         } else {
   3863             return BCM_E_UNAVAIL;
   3864         }
   3865     }
   3866 #endif
   3867     if ((dvp_group_id < 0) || (dvp_group_id > max_group_id)) {
   3868         return BCM_E_PARAM;
   3869     } 
   3870     
   3871     return BCM_E_NONE;
   3872 }
   3873 
   3874 /*
   3875  * Function:
   3876  *     bcm_td2p_vlan_vfi_mbrship_port_get
   3877  * Purpose:
   3878  *      Read the ING_PORT_BITMAP from a vlan entry.
   3879  */
   3880 int
   3881 bcm_td2p_vlan_vfi_mbrship_port_get(int unit,
   3882                     bcm_vlan_t vlan_vpn, int egress, pbmp_t *pbmp)
   3883 {
   3884     uint32 profile_idx;
   3885     soc_mem_t mbrship_mem;
   3886     soc_field_t port_field;
   3887     uint32 mbrship_entry[SOC_MAX_MEM_WORDS];
   3888 
   3889     if (egress) {
   3890         mbrship_mem = EGR_VLAN_VFI_MEMBERSHIPm;
   3891         port_field = PORT_BITMAPf;
   3892     } else {
   3893         mbrship_mem = ING_VLAN_VFI_MEMBERSHIPm;
   3894         port_field = ING_PORT_BITMAPf;
   3895     }
   3896 
   3897     BCM_IF_ERROR_RETURN(_bcm_td2p_vlan_vpn_mbrship_profile_get(
   3898                                 unit, vlan_vpn, egress, &profile_idx));
   3899 
   3900     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mbrship_mem,
   3901                 MEM_BLOCK_ANY, profile_idx, &mbrship_entry));
   3902 
   3903     soc_mem_pbmp_field_get(unit, mbrship_mem, &mbrship_entry, port_field, pbmp);
   3904 
   3905     return BCM_E_NONE;
   3906 }
   3907 
   3908 /*
   3909  * Function:
   3910  *      bcm_td2p_vlan_vpn_membership_delete
   3911  * Purpose:
   3912  *      Delete the VLAN Vfi membership entry.
   3913  * Parameters:
   3914  *      unit  - (IN) SOC unit number.
   3915  *      vlan_vpn  - (IN) VLAN/VPN ID.
   3916  * Returns:
   3917  *      BCM_E_XXX
   3918  */
   3919 int
   3920 bcm_td2p_vlan_vpn_membership_delete(int unit, bcm_vlan_t vlan_vpn)
   3921 {
   3922     uint32 profile_ptr = 0;
   3923 
   3924     /* Delete ingress vlan_vfi_membership profile */
   3925     BCM_IF_ERROR_RETURN(_bcm_td2p_vlan_vpn_mbrship_profile_get(
   3926                             unit, vlan_vpn, FALSE, &profile_ptr));
   3927 
   3928     if(profile_ptr != 0 && profile_ptr != 1) {
   3929         BCM_IF_ERROR_RETURN(_bcm_vlan_vfi_membership_profile_entry_op(
   3930                                 unit, NULL, 1, FALSE, FALSE, &profile_ptr));
   3931     }
   3932 
   3933     /* Delete egress vlan_vfi_membership profile */
   3934     BCM_IF_ERROR_RETURN(_bcm_td2p_vlan_vpn_mbrship_profile_get(
   3935                             unit, vlan_vpn, TRUE, &profile_ptr));
   3936 
   3937     if(profile_ptr != 0 && profile_ptr != 1) {
   3938         BCM_IF_ERROR_RETURN(_bcm_vlan_vfi_membership_profile_entry_op(
   3939                                 unit, NULL, 1, FALSE, TRUE, &profile_ptr));
   3940     }
   3941 
   3942     return BCM_E_NONE;
   3943 }
   3944 
   3945 /*
   3946  * Function:
   3947  *      bcm_td2p_vlan_vfi_mbrship_port_set
   3948  * Purpose:
   3949  *      Program membership port bitmap in vlan vfi membership tables
   3950  */
   3951 int
   3952 bcm_td2p_vlan_vfi_mbrship_port_set(int unit, bcm_vlan_t vlan_vpn,
   3953                                                     int egress, int add, pbmp_t pbmp)
   3954 {
   3955     uint32 profile_idx;
   3956     pbmp_t cur_pbmp;
   3957     pbmp_t tmp_pbmp;
   3958     soc_mem_t mbrship_mem;
   3959     soc_field_t port_field;
   3960     uint32 mbrship_entry[SOC_MAX_MEM_WORDS];
   3961 
   3962     if (egress) {
   3963         mbrship_mem = EGR_VLAN_VFI_MEMBERSHIPm;
   3964         port_field = PORT_BITMAPf;
   3965     } else {
   3966         mbrship_mem = ING_VLAN_VFI_MEMBERSHIPm;
   3967         port_field = ING_PORT_BITMAPf;
   3968     }
   3969 
   3970     BCM_IF_ERROR_RETURN(_bcm_td2p_vlan_vpn_mbrship_profile_get(
   3971                                 unit, vlan_vpn, egress, &profile_idx));
   3972 
   3973     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mbrship_mem,
   3974                 MEM_BLOCK_ANY, profile_idx, &mbrship_entry));
   3975 
   3976     soc_mem_pbmp_field_get(unit, mbrship_mem, &mbrship_entry, port_field, &cur_pbmp);
   3977     BCM_PBMP_ASSIGN(tmp_pbmp, cur_pbmp);
   3978 
   3979     if (add) {
   3980         BCM_PBMP_OR(cur_pbmp, pbmp);
   3981     } else {
   3982         BCM_PBMP_REMOVE(cur_pbmp, pbmp);
   3983     }
   3984 
   3985     if (BCM_PBMP_NEQ(tmp_pbmp, cur_pbmp)) {
   3986         soc_mem_pbmp_field_set(unit, mbrship_mem,
   3987                 &mbrship_entry, port_field, &cur_pbmp);
   3988         BCM_IF_ERROR_RETURN(_bcm_td2p_vlan_vfi_mbrship_profile_entry_set(
   3989                                     unit, vlan_vpn, egress, &mbrship_entry));
   3990     }
   3991 
   3992     return BCM_E_NONE;
   3993 }
   3994 
   3995 /*
   3996  * Function:
   3997  *      bcmi_td2p_vfi_control_params_check
   3998  *
   3999  * Purpose:
   4000  *      Verifies if input parameters are valid for the operation on the device
   4001  *
   4002  * Parameters:
   4003  *     unit    - (IN) BCM device number.
   4004  *     vid     - (IN) Vlan id. 
   4005  *     valid_fields - (IN) Valid fields, BCM_VLAN_CONTROL_VLAN_XXX_MASK.
   4006  *     control - (IN) Configuration.
   4007  *
   4008  * Returns:
   4009  *      BCM_E_PARAM for errorneous inputs
   4010  *      BCM_E_NONE  if all memebers in the structure are legal
   4011  */
   4012 STATIC int
   4013 bcmi_td2p_vfi_control_params_check(int unit, bcm_vlan_t vid,
   4014                                    uint32 valid_fields,
   4015                                    bcm_vlan_control_vlan_t *control)
   4016 {
   4017     uint32 supported_flags = 0;
   4018     uint32 supported_flags2 = 0;
   4019     uint32 supported_fields = 0;
   4020 
   4021     /*
   4022      * VFI_PROFILE table in TD2Plus supports only the following fields:
   4023      *
   4024      *  - IPMCV4_L2_ENABLE  : Enable IGMP-based L2 lookups for IPMCv4 packets
   4025      *  - IPMCV6_L2_ENABLE  : Enable IGMP-based L2 lookups for IPMCv6 packets
   4026      *  - L2_NON_UCAST_DROP : Drop all broadcast and multicast packets
   4027      *  - L2_NON_UCAST_TOCPU: Copy all broadcast and multicast packets to CPU
   4028      *  - L2_MISS_DROP      : Drop unknown unicast traffic, Do not flood.
   4029      *  - L2_MISS_TOCPU     : Copy unknown unicast traffic to the CPU
   4030      *  - LEARN_DISABLE     : Disable learning.
   4031      *  - EN_IFILTER        : Enable membership checks.
   4032      */
   4033 
   4034     /*
   4035      * VFI table can be programmed with the following fields:
   4036      *
   4037      *  - VRF           : Virtual Routing and Forwarding Instance
   4038      *  - VFI_CLASS_ID  : VFI Class ID for IFP lookup key
   4039      *  - L3_IIF        : Layer3 Incoming Interface to be assigned to the packet
   4040      *  - UUC_INDEX     : Default unknown unicast group for this VFI
   4041      *  - UMC_INDEX     : Default unknown multicast group for this VFI
   4042      *  - BC_INDEX      : Default Multicast group for broadcasting to this VFI
   4043      */
   4044     supported_fields = (BCM_VLAN_CONTROL_VLAN_INGRESS_IF_MASK |
   4045                         BCM_VLAN_CONTROL_VLAN_IF_CLASS_MASK |
   4046                         BCM_VLAN_CONTROL_VLAN_UNKNOWN_MULTICAST_GROUP_MASK |
   4047                         BCM_VLAN_CONTROL_VLAN_UNKNOWN_UNICAST_GROUP_MASK |
   4048                         BCM_VLAN_CONTROL_VLAN_BROADCAST_GROUP_MASK |
   4049                         BCM_VLAN_CONTROL_VLAN_VRF_MASK);
   4050 #if defined(BCM_TRIDENT3_SUPPORT)
   4051     if (soc_feature(unit, soc_feature_pvlan_on_vfi)) {
   4052         supported_fields |= BCM_VLAN_CONTROL_VLAN_FORWARDING_VLAN_MASK;
   4053     }
   4054 #endif
   4055     supported_flags =  (BCM_VLAN_IP4_MCAST_L2_DISABLE |
   4056                         BCM_VLAN_IP6_MCAST_L2_DISABLE |
   4057                         BCM_VLAN_UNKNOWN_UCAST_TOCPU |
   4058                         BCM_VLAN_UNKNOWN_UCAST_DROP |
   4059                         BCM_VLAN_NON_UCAST_TOCPU |
   4060                         BCM_VLAN_NON_UCAST_DROP |
   4061                         BCM_VLAN_LEARN_DISABLE |
   4062                         BCM_VLAN_L2_CLASS_ID_ONLY 
   4063                         );
   4064 
   4065     supported_flags2 = (BCM_VLAN_FLAGS2_MEMBER_INGRESS_DISABLE  |
   4066                         BCM_VLAN_FLAGS2_MEMBER_EGRESS_DISABLE
   4067                         );
   4068 
   4069 #if defined(BCM_HELIX5_SUPPORT)
   4070     supported_flags2 |= (BCM_VLAN_FLAGS2_WIRED_COS_MAP_SELECT |
   4071                         BCM_VLAN_FLAGS2_WIRELESS_COS_MAP_SELECT 
   4072                         );
   4073 #endif
   4074 
   4075     if (valid_fields != BCM_VLAN_CONTROL_VLAN_ALL_MASK) {
   4076         if ((~supported_fields) & valid_fields) {
   4077             return BCM_E_PARAM;
   4078         }
   4079     }
   4080 
   4081     if ((~supported_flags) & control->flags) {
   4082         return BCM_E_PARAM;
   4083     }
   4084 
   4085     if ((~supported_flags2) & control->flags2) {
   4086         return BCM_E_PARAM;
   4087     }
   4088 
   4089     if (control->flags & BCM_VLAN_L2_CLASS_ID_ONLY) {
   4090         if (valid_fields & BCM_VLAN_CONTROL_VLAN_IF_CLASS_MASK) {
   4091             if ((control->if_class < 0) ||
   4092                 (control->if_class > SOC_INTF_CLASS_MAX(unit))) {
   4093                 return BCM_E_PARAM;
   4094             }
   4095         } else {
   4096             return BCM_E_PARAM;
   4097         }
   4098     }
   4099 
   4100     if (valid_fields & BCM_VLAN_CONTROL_VLAN_VRF_MASK) {
   4101         if ((control->vrf < 0) ||
   4102             (control->vrf > SOC_VRF_MAX(unit))) {
   4103             return BCM_E_PARAM;
   4104         }
   4105     }
   4106 
   4107 #if defined(BCM_TRIDENT3_SUPPORT)
   4108     if (soc_feature(unit, soc_feature_egr_intf_vlan_vfi_deoverlay)) {
   4109         if (control->egress_vlan != BCM_VLAN_NONE) {
   4110             return BCM_E_PARAM;
   4111         }
   4112     }
   4113 #endif
   4114 
   4115     VLAN_CHK_ID(unit, control->egress_vlan);
   4116 
   4117 
   4118     /*
   4119      * There is no provision to implicitly map L3 IIFs to VFIs.
   4120      * Hence, assigning L3 IIF class id through this API is not allowed.
   4121      * Users should use bcm_l3_ingress_create() to create L3 ingress interfaces
   4122      * and assign class ids through the same API.
   4123      */
   4124 
   4125     if (!soc_feature(unit, soc_feature_vp_sharing)) {
   4126         if (control->egress_vlan != BCM_VLAN_NONE) {
   4127             return BCM_E_PARAM;
   4128         }
   4129     }
   4130 
   4131 #if defined(BCM_TRIDENT3_SUPPORT)
   4132     if (soc_feature(unit, soc_feature_pvlan_on_vfi)) {
   4133         VLAN_CHK_ID(unit, control->forwarding_vlan);
   4134     }
   4135 #endif
   4136 
   4137     return BCM_E_NONE;
   4138 }
   4139 
   4140 /*
   4141  * Function:
   4142  *      bcmi_td2p_vfi_profile_add
   4143  *
   4144  * Purpose:
   4145  *      Programs VFI_PROFILE table based on input bcm_vlan_control_vlan_t
   4146  *
   4147  * Parameters:
   4148  *     unit    - (IN) BCM device number.
   4149  *     valid_fields - (IN) Valid fields, BCM_VLAN_CONTROL_VLAN_XXX_MASK.
   4150  *     vfi_control - (IN) Configuration.
   4151  *     profile_index - (OUT) Profile index allocated by soc_mem_profile_add
   4152  *
   4153  * Returns:
   4154  *      BCM_E_XXXs
   4155  */
   4156 STATIC int
   4157 bcmi_td2p_vfi_profile_add(int unit, uint32 valid_fields,
   4158                           bcm_vlan_control_vlan_t *vfi_control,
   4159                           int old_profile_index, int *profile_index)
   4160 {
   4161     int i;
   4162     soc_field_t field;
   4163     int field_num = 0;
   4164     uint32 index;
   4165     int value;
   4166     vfi_profile_entry_t vfi_profile_entry;
   4167     vfi_profile_2_entry_t vfi_profile_2_entry;
   4168     soc_mem_t vfi_profile_mem = VFI_PROFILEm;
   4169     void *entries[3];
   4170     int vfi_profile_flags_map[][4] = {
   4171         /* field,                            flag,            bool_invert,          0: flags; 1: flags2 */
   4172         {L2_NON_UCAST_DROPf,   BCM_VLAN_NON_UCAST_DROP,         0,        0},
   4173         {L2_NON_UCAST_TOCPUf,  BCM_VLAN_NON_UCAST_TOCPU,        0,        0},
   4174         {L2_MISS_DROPf,        BCM_VLAN_UNKNOWN_UCAST_DROP,     0,        0},
   4175         {L2_MISS_TOCPUf,       BCM_VLAN_UNKNOWN_UCAST_TOCPU,    0,        0},
   4176         {IPMCV4_L2_ENABLEf,    BCM_VLAN_IP4_MCAST_L2_DISABLE,   1,        0},
   4177         {IPMCV6_L2_ENABLEf,    BCM_VLAN_IP6_MCAST_L2_DISABLE,   1,        0},
   4178         {LEARN_DISABLEf,       BCM_VLAN_LEARN_DISABLE,          0,        0},
   4179         {EN_IFILTERf,          BCM_VLAN_FLAGS2_MEMBER_INGRESS_DISABLE, 1, 1},
   4180             {INVALIDf,             0,                               0}
   4181         };
   4182 
   4183     entries[0] = &vfi_profile_entry;
   4184     if (soc_feature(unit, soc_feature_vfi_combo_profile)) {
   4185         entries[1] = &vfi_profile_2_entry;
   4186     }
   4187     if (_BCM_INVALID_VFI_PROFILE != old_profile_index) {
   4188         BCM_IF_ERROR_RETURN(
   4189             _bcm_vfi_profile_entry_get(unit, old_profile_index, 1, entries));
   4190     } else {
   4191         sal_memset(&vfi_profile_entry, 0, sizeof(vfi_profile_entry_t));
   4192         sal_memset(&vfi_profile_2_entry, 0, sizeof(vfi_profile_2_entry_t));
   4193     }
   4194 
   4195     field_num = COUNTOF(vfi_profile_flags_map);
   4196     for (i = 0; i < field_num; i++) {
   4197         field = vfi_profile_flags_map[i][0];
   4198         if (field == INVALIDf) {
   4199             continue;
   4200         }
   4201 
   4202         if (vfi_profile_flags_map[i][3] == 0) {
   4203         value = ((vfi_profile_flags_map[i][2]) ?
   4204                  (!(vfi_control->flags & vfi_profile_flags_map[i][1])):
   4205                  ((vfi_control->flags & vfi_profile_flags_map[i][1])));
   4206         } else {
   4207             /* flags2 */
   4208             value = ((vfi_profile_flags_map[i][2]) ?
   4209                      (!(vfi_control->flags2 & vfi_profile_flags_map[i][1])):
   4210                      ((vfi_control->flags2 & vfi_profile_flags_map[i][1])));
   4211         }
   4212 
   4213         value = !!value;
   4214         soc_mem_field32_set(unit, vfi_profile_mem, &vfi_profile_entry, field, value);
   4215     }
   4216 
   4217     BCM_IF_ERROR_RETURN(_bcm_vfi_profile_entry_add(unit, entries, 1, &index));
   4218 
   4219     *profile_index = index;
   4220     return BCM_E_NONE;
   4221 }
   4222 
   4223 /*
   4224  * Function:
   4225  *      bcmi_td2p_vfi_profile_get
   4226  *
   4227  * Purpose:
   4228  *      Reads VFI_PROFILE table and fills vfi_control
   4229  *
   4230  * Parameters:
   4231  *     unit    - (IN) BCM device number.
   4232  *     profile_index - (IN) Profile index.
   4233  *     vfi_control - (IN) Configuration.
   4234  *
   4235  * Returns:
   4236  *      BCM_E_XXXs
   4237  */
   4238 STATIC int
   4239 bcmi_td2p_vfi_profile_get(int unit, uint8 profile_index, bcm_vlan_control_vlan_t *vfi_control)
   4240 {
   4241     int rv;
   4242     int i;
   4243     soc_field_t field;
   4244     int field_num = 0;
   4245     int value;
   4246     vfi_profile_entry_t vfi_profile_entry;
   4247     vfi_profile_2_entry_t vfi_profile_2_entry;
   4248     soc_mem_t vfi_profile_mem = VFI_PROFILEm;
   4249     void *entries[2];
   4250     int vfi_profile_flags_map[][4] = {
   4251         /* field,                         flag,                        bool_invert,  0: flags; 1: flags2 */
   4252         {L2_NON_UCAST_DROPf,   BCM_VLAN_NON_UCAST_DROP,         0,        0},
   4253         {L2_NON_UCAST_TOCPUf,  BCM_VLAN_NON_UCAST_TOCPU,        0,        0},
   4254         {L2_MISS_DROPf,        BCM_VLAN_UNKNOWN_UCAST_DROP,     0,        0},
   4255         {L2_MISS_TOCPUf,       BCM_VLAN_UNKNOWN_UCAST_TOCPU,    0,        0},
   4256         {IPMCV4_L2_ENABLEf,    BCM_VLAN_IP4_MCAST_L2_DISABLE,   1,        0},
   4257         {IPMCV6_L2_ENABLEf,    BCM_VLAN_IP6_MCAST_L2_DISABLE,   1,        0},
   4258         {LEARN_DISABLEf,       BCM_VLAN_LEARN_DISABLE,          0,        0},
   4259         {EN_IFILTERf,          BCM_VLAN_FLAGS2_MEMBER_INGRESS_DISABLE, 1, 1},
   4260             {INVALIDf,             0,                               0}
   4261         };
   4262 
   4263     entries[0] = &vfi_profile_entry;
   4264     if (soc_feature(unit, soc_feature_vfi_combo_profile)) {
   4265         entries[1] = &vfi_profile_2_entry;
   4266     }
   4267 
   4268     rv = _bcm_vfi_profile_entry_get(unit, profile_index, 1, entries);
   4269     BCM_IF_ERROR_RETURN(rv);
   4270 
   4271     field_num = COUNTOF(vfi_profile_flags_map);
   4272     for (i = 0; i < field_num; i++) {
   4273         field = vfi_profile_flags_map[i][0];
   4274         if (field == INVALIDf) {
   4275             continue;
   4276         }
   4277         value = soc_mem_field32_get(unit, vfi_profile_mem, &vfi_profile_entry, field);
   4278         if (vfi_profile_flags_map[i][3] == 0) {
   4279         vfi_control->flags |= ((vfi_profile_flags_map[i][2]) ?
   4280                                   ((!value)  ? vfi_profile_flags_map[i][1] : 0) :
   4281                                   ((value) ? vfi_profile_flags_map[i][1] : 0));
   4282         } else {
   4283             /* flags2 */
   4284             vfi_control->flags2 |= ((vfi_profile_flags_map[i][2]) ?
   4285                                        ((!value)  ? vfi_profile_flags_map[i][1] : 0) :
   4286                                        ((value) ? vfi_profile_flags_map[i][1] : 0));
   4287         }
   4288     }
   4289 
   4290     return BCM_E_NONE;
   4291 }
   4292 
   4293 
   4294 /*
   4295  * Function:
   4296  *      bcmi_td2p_vfi_control_ingress_set
   4297  *
   4298  * Purpose:
   4299  *      Programs VFI table according to vfi_control
   4300  *
   4301  * Parameters:
   4302  *     unit    - (IN) BCM device number.
   4303  *     valid_fields - (IN) Valid fields, BCM_VLAN_CONTROL_VLAN_XXX_MASK.
   4304  *     vfi_control - (IN) Configuration.
   4305  *
   4306  * Returns:
   4307  *      BCM_E_XXXs
   4308  */
   4309 STATIC int
   4310 bcmi_td2p_vfi_control_ingress_set(int unit, int vfi, uint32 valid_fields, bcm_vlan_control_vlan_t *control)
   4311 {
   4312     int rv;
   4313     int i;
   4314     soc_field_t field;
   4315     int field_num = 0;
   4316     int value;
   4317     int profile_index;
   4318     int old_profile_index;
   4319     vfi_entry_t vfi_entry;
   4320     soc_mem_t mem = VFIm;
   4321     struct vfi_fields_s {
   4322         soc_field_t field;
   4323         uint32  valid_field;
   4324         int    *vlan_control_obj;
   4325     } vfi_field_values[] = {
   4326             {VFI_CLASS_IDf, BCM_VLAN_CONTROL_VLAN_IF_CLASS_MASK},
   4327             {L3_IIFf,       BCM_VLAN_CONTROL_VLAN_INGRESS_IF_MASK},
   4328             {UUC_INDEXf,    BCM_VLAN_CONTROL_VLAN_UNKNOWN_UNICAST_GROUP_MASK},
   4329             {UMC_INDEXf,    BCM_VLAN_CONTROL_VLAN_UNKNOWN_MULTICAST_GROUP_MASK},
   4330             {BC_INDEXf,     BCM_VLAN_CONTROL_VLAN_BROADCAST_GROUP_MASK},
   4331             {VRFf,          BCM_VLAN_CONTROL_VLAN_VRF_MASK},
   4332 #if defined(BCM_TRIDENT3_SUPPORT)
   4333             {FID_IDf,       BCM_VLAN_CONTROL_VLAN_FORWARDING_VLAN_MASK}, /*td3 only*/
   4334 #endif
   4335             {INVALIDf,      0, 0}
   4336     };
   4337 
   4338     vfi_field_values[0].vlan_control_obj = &(control->if_class);
   4339     vfi_field_values[1].vlan_control_obj = &(control->ingress_if);
   4340     vfi_field_values[2].vlan_control_obj = &(control->unknown_unicast_group);
   4341     vfi_field_values[3].vlan_control_obj = &(control->unknown_multicast_group);
   4342     vfi_field_values[4].vlan_control_obj = &(control->broadcast_group);
   4343     vfi_field_values[5].vlan_control_obj = &(control->vrf);
   4344 #if defined(BCM_TRIDENT3_SUPPORT)
   4345     vfi_field_values[6].vlan_control_obj = (int*)&(control->forwarding_vlan);
   4346 
   4347     if (!soc_feature(unit, soc_feature_pvlan_on_vfi)) {
   4348         valid_fields &= ~BCM_VLAN_CONTROL_VLAN_FORWARDING_VLAN_MASK;
   4349     }
   4350 
   4351     if (soc_feature(unit, soc_feature_generic_dest)) {
   4352         vfi_field_values[2].field = UUC_DESTINATIONf;
   4353         vfi_field_values[3].field = UMC_DESTINATIONf;
   4354         vfi_field_values[4].field = BC_DESTINATIONf;
   4355     }
   4356 #endif
   4357 
   4358 #if defined(BCM_TRIDENT3_SUPPORT)
   4359     if (soc_feature(unit, soc_feature_generic_dest)) {
   4360         vfi_field_values[2].field = UUC_DESTINATIONf;
   4361         vfi_field_values[3].field = UMC_DESTINATIONf;
   4362         vfi_field_values[4].field = BC_DESTINATIONf;
   4363     }
   4364 #endif
   4365 
   4366     /*
   4367      * VFI table can be programmed with the following fields:
   4368      *
   4369      *  - VRF           : Virtual Routing and Forwarding Instance
   4370      *  - VFI_CLASS_ID  : VFI Class ID for IFP lookup key
   4371      *  - L3_IIF        : Layer3 Incoming Interface to be assigned to the packet
   4372      *  - UUC_INDEX     : Default unknown unicast group for this VFI
   4373      *  - UMC_INDEX     : Default unknown multicast group for this VFI
   4374      *  - BC_INDEX      : Default Multicast group for broadcasting to this VFI
   4375      */
   4376 
   4377     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, (int)vfi, &vfi_entry);
   4378     BCM_IF_ERROR_RETURN(rv);
   4379 
   4380     old_profile_index = soc_mem_field32_get(unit, mem,
   4381                                             &vfi_entry, VFI_PROFILE_PTRf);
   4382 
   4383     field_num = COUNTOF(vfi_field_values);
   4384     for (i = 0; i < field_num; i++) {
   4385         field = vfi_field_values[i].field;
   4386         if (!(valid_fields & vfi_field_values[i].valid_field) || (field == INVALIDf)) {
   4387             continue;
   4388         }
   4389         value = *(vfi_field_values[i].vlan_control_obj);
   4390 #if defined(BCM_TRIDENT3_SUPPORT)
   4391         if (field == FID_IDf) {
   4392             value = *((uint16 *)vfi_field_values[i].vlan_control_obj);
   4393         }
   4394 
   4395         if (soc_feature(unit, soc_feature_generic_dest) &&
   4396                     ((field == UUC_DESTINATIONf) || (field == UMC_DESTINATIONf) ||
   4397                     (field == BC_DESTINATIONf))) {
   4398             soc_mem_field32_dest_set(unit, mem, &vfi_entry, field,
   4399                                                     SOC_MEM_FIF_DEST_IPMC,value);
   4400         } else
   4401 #endif
   4402         {
   4403         soc_mem_field32_set(unit, mem, &vfi_entry, field, value);
   4404     }
   4405     }
   4406 
   4407     if (control->vrf == 0) {
   4408         soc_mem_field32_set(unit, mem, &vfi_entry, VRF_VALIDf, 0);
   4409     } else {
   4410         soc_mem_field32_set(unit, mem, &vfi_entry, VRF_VALIDf, 1);
   4411     }
   4412 
   4413 #if defined(BCM_HELIX5_SUPPORT)
   4414     if (soc_feature(unit, soc_feature_vlan_wirelss_traffic_select)) {
   4415         if (control->flags2 & BCM_VLAN_FLAGS2_WIRED_COS_MAP_SELECT &&
   4416             control->flags2 & BCM_VLAN_FLAGS2_WIRELESS_COS_MAP_SELECT) {
   4417             return BCM_E_PARAM;
   4418         }
   4419 
   4420         if (control->flags2 & BCM_VLAN_FLAGS2_WIRED_COS_MAP_SELECT) {
   4421             soc_mem_field32_set(unit, mem, &vfi_entry, WIRED_WIRELESSf, 0x1);
   4422         }
   4423 
   4424         if (control->flags2 & BCM_VLAN_FLAGS2_WIRELESS_COS_MAP_SELECT) {
   4425             soc_mem_field32_set(unit, mem, &vfi_entry, WIRED_WIRELESSf, 0x2);
   4426         }
   4427     }
   4428 #endif
   4429 
   4430 
   4431     /* Add profile object */
   4432     rv = bcmi_td2p_vfi_profile_add(unit, valid_fields,
   4433             control, old_profile_index, &profile_index);
   4434     BCM_IF_ERROR_RETURN(rv);
   4435 
   4436     /* Overwrite the the profile pointer in VFI with the new profile index */
   4437     soc_mem_field32_set(unit, mem, &vfi_entry, VFI_PROFILE_PTRf, profile_index);
   4438 
   4439     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, vfi, &vfi_entry);
   4440     BCM_IF_ERROR_RETURN(rv);
   4441 
   4442     /* Delete the old profile object */
   4443     if (old_profile_index > 0) {
   4444         rv = _bcm_vfi_profile_entry_delete(unit, old_profile_index);
   4445         BCM_IF_ERROR_RETURN(rv);
   4446     }
   4447 
   4448     return BCM_E_NONE;
   4449 }
   4450 
   4451 /*
   4452  * Function:
   4453  *      bcmi_td2p_vfi_control_egress_set
   4454  *
   4455  * Purpose:
   4456  *      Programs EGR_VFI table according to vfi_control
   4457  *
   4458  * Parameters:
   4459  *     unit    - (IN) BCM device number.
   4460  *     valid_fields - (IN) Valid fields, BCM_VLAN_CONTROL_VLAN_XXX_MASK.
   4461  *     vfi_control - (IN) Configuration.
   4462  *
   4463  * Returns:
   4464  *      BCM_E_XXXs
   4465  */
   4466 STATIC int
   4467 bcmi_td2p_vfi_control_egress_set(int unit, int vfi, uint32 valid_fields, bcm_vlan_control_vlan_t *control)
   4468 {
   4469 
   4470     int rv;
   4471     int i;
   4472     soc_field_t field;
   4473     int field_num = 0;
   4474     int value;
   4475     egr_vfi_entry_t vfi_entry;
   4476     soc_mem_t mem = EGR_VFIm;
   4477     struct vfi_fields_s {
   4478         soc_field_t field;
   4479         uint32  valid_field;
   4480         uint16    *vlan_control_obj;
   4481     } vfi_field_values[] = {
   4482             {OVIDf, BCM_VLAN_CONTROL_VLAN_ALL_MASK},
   4483             {INVALIDf, 0, NULL}
   4484     };
   4485 
   4486     vfi_field_values[0].vlan_control_obj = (uint16 *)&(control->egress_vlan);
   4487 
   4488     /* Read the memory */
   4489     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, (int)vfi, &vfi_entry);
   4490     BCM_IF_ERROR_RETURN(rv);
   4491 
   4492     field_num = COUNTOF(vfi_field_values);
   4493     for (i = 0; i < field_num; i++) {
   4494         field = vfi_field_values[i].field;
   4495         if (!(valid_fields & vfi_field_values[i].valid_field) || (field == INVALIDf) ||
   4496             (soc_feature(unit, soc_feature_egr_intf_vlan_vfi_deoverlay) && (field == OVIDf))) {
   4497             continue;
   4498         }
   4499         value = *(vfi_field_values[i].vlan_control_obj);
   4500         /* update each field */
   4501         if (soc_mem_field_valid(unit, mem, field)) {
   4502         soc_mem_field32_set(unit, mem, &vfi_entry, field, value);
   4503     }
   4504     }
   4505 
   4506     if (soc_mem_field_valid(unit, mem, EN_EFILTERf)) {
   4507         /* EN_EFILTERf is enabled by default during the VPN creation */
   4508         if (control->flags2 & BCM_VLAN_FLAGS2_MEMBER_EGRESS_DISABLE) {
   4509             soc_mem_field32_set(unit, mem, &vfi_entry, EN_EFILTERf, 0);
   4510         } else {
   4511             soc_mem_field32_set(unit, mem, &vfi_entry, EN_EFILTERf, 1);
   4512         }
   4513     }
   4514 
   4515     /* Write the memory back */
   4516     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, vfi, &vfi_entry);
   4517     BCM_IF_ERROR_RETURN(rv);
   4518 
   4519     return BCM_E_NONE;
   4520 }
   4521 
   4522 /*
   4523  * Function:
   4524  *      bcmi_td2p_vfi_control_ingress_get
   4525  *
   4526  * Purpose:
   4527  *      Reads VFI table and fills vfi_control
   4528  *
   4529  * Parameters:
   4530  *     unit    - (IN) BCM device number.
   4531  *     valid_fields - (IN) Valid fields, BCM_VLAN_CONTROL_VLAN_XXX_MASK.
   4532  *     vfi_control - (OUT) Configuration.
   4533  *
   4534  * Returns:
   4535  *      BCM_E_XXXs
   4536  */
   4537 STATIC int
   4538 bcmi_td2p_vfi_control_ingress_get(int unit, int vfi, uint32 valid_fields, bcm_vlan_control_vlan_t *control)
   4539 {
   4540     int rv;
   4541     int i;
   4542     soc_field_t field;
   4543     int field_num = 0;
   4544     int value;
   4545     uint8 profile_index;
   4546     vfi_entry_t vfi_entry;
   4547     soc_mem_t mem = VFIm;
   4548     struct vfi_fields_s {
   4549         soc_field_t field;
   4550         uint32  valid_field;
   4551         int    *vlan_control_obj;
   4552     } vfi_field_values[] = {
   4553             {VFI_CLASS_IDf, BCM_VLAN_CONTROL_VLAN_IF_CLASS_MASK},
   4554             {L3_IIFf,       BCM_VLAN_CONTROL_VLAN_INGRESS_IF_MASK},
   4555             {UUC_INDEXf,    BCM_VLAN_CONTROL_VLAN_UNKNOWN_UNICAST_GROUP_MASK},
   4556             {UMC_INDEXf,    BCM_VLAN_CONTROL_VLAN_UNKNOWN_MULTICAST_GROUP_MASK},
   4557             {BC_INDEXf,     BCM_VLAN_CONTROL_VLAN_BROADCAST_GROUP_MASK},
   4558             {VRFf,          BCM_VLAN_CONTROL_VLAN_VRF_MASK},
   4559 #if defined(BCM_TRIDENT3_SUPPORT)
   4560             {FID_IDf,       BCM_VLAN_CONTROL_VLAN_FORWARDING_VLAN_MASK},
   4561 #endif
   4562             {INVALIDf,      0, 0}
   4563     };
   4564 
   4565     vfi_field_values[0].vlan_control_obj = &(control->if_class);
   4566     vfi_field_values[1].vlan_control_obj = &(control->ingress_if);
   4567     vfi_field_values[2].vlan_control_obj = &(control->unknown_unicast_group);
   4568     vfi_field_values[3].vlan_control_obj = &(control->unknown_multicast_group);
   4569     vfi_field_values[4].vlan_control_obj = &(control->broadcast_group);
   4570     vfi_field_values[5].vlan_control_obj = &(control->vrf);
   4571 #if defined(BCM_TRIDENT3_SUPPORT)
   4572     if (!soc_feature(unit, soc_feature_pvlan_on_vfi)) {
   4573         valid_fields &= ~BCM_VLAN_CONTROL_VLAN_FORWARDING_VLAN_MASK;
   4574     }
   4575 
   4576     if (soc_feature(unit, soc_feature_generic_dest)) {
   4577         vfi_field_values[2].field = UUC_DESTINATIONf;
   4578         vfi_field_values[3].field = UMC_DESTINATIONf;
   4579         vfi_field_values[4].field = BC_DESTINATIONf;
   4580     }
   4581 #endif
   4582  
   4583     /* Read the memory */
   4584     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, (int)vfi, &vfi_entry);
   4585     BCM_IF_ERROR_RETURN(rv);
   4586 
   4587     field_num = COUNTOF(vfi_field_values);
   4588     for (i = 0; i < field_num; i++) {
   4589         field = vfi_field_values[i].field;
   4590         if (!(valid_fields & vfi_field_values[i].valid_field) || (field == INVALIDf)) {
   4591             continue;
   4592         }
   4593         /* read each field */
   4594 #if defined(BCM_TRIDENT3_SUPPORT)
   4595         if (soc_feature(unit, soc_feature_generic_dest) &&
   4596             ((field == UUC_DESTINATIONf) || (field == UMC_DESTINATIONf) ||
   4597                     (field == BC_DESTINATIONf))) {
   4598             uint32 dest_type = 0;
   4599             value = soc_mem_field32_dest_get(unit, mem, &vfi_entry, field,
   4600                                             &dest_type);
   4601         } else
   4602 #endif
   4603         {
   4604         value = soc_mem_field32_get(unit, mem, &vfi_entry, field);
   4605         }
   4606 #if defined(BCM_TRIDENT3_SUPPORT)
   4607         if (field == FID_IDf) {
   4608             control->forwarding_vlan = value & 0xffff;
   4609         } else
   4610 #endif
   4611         {
   4612             *(vfi_field_values[i].vlan_control_obj) = value;
   4613         }
   4614     }
   4615 
   4616     control->flags |= (control->if_class) ? BCM_VLAN_L2_CLASS_ID_ONLY : 0;
   4617 
   4618 #if defined(BCM_HELIX5_SUPPORT)
   4619     if (soc_feature(unit, soc_feature_vlan_wirelss_traffic_select)) {
   4620         value = soc_mem_field32_get(unit, mem, &vfi_entry, WIRED_WIRELESSf);
   4621         if (value == 0x1) {
   4622             control->flags2 |= BCM_VLAN_FLAGS2_WIRED_COS_MAP_SELECT;
   4623         }
   4624         if (value == 0x2) {
   4625             control->flags2 |= BCM_VLAN_FLAGS2_WIRELESS_COS_MAP_SELECT;
   4626         }
   4627     }
   4628 #endif
   4629 
   4630     profile_index = soc_mem_field32_get(unit, mem, &vfi_entry, VFI_PROFILE_PTRf);
   4631     BCM_IF_ERROR_RETURN(bcmi_td2p_vfi_profile_get(unit, profile_index, control));
   4632 
   4633     return BCM_E_NONE;
   4634 }
   4635 
   4636 /*
   4637  * Function:
   4638  *      bcmi_td2p_vfi_control_egress_get
   4639  *
   4640  * Purpose:
   4641  *      Reads EGR_VFI table and fills vfi_control
   4642  *
   4643  * Parameters:
   4644  *     unit    - (IN) BCM device number.
   4645  *     valid_fields - (IN) Valid fields, BCM_VLAN_CONTROL_VLAN_XXX_MASK.
   4646  *     vfi_control - (OUT) Configuration.
   4647  *
   4648  * Returns:
   4649  *      BCM_E_XXXs
   4650  */
   4651 STATIC int
   4652 bcmi_td2p_vfi_control_egress_get(int unit, int vfi, uint32 valid_fields, bcm_vlan_control_vlan_t *control)
   4653 {
   4654 
   4655     int rv;
   4656     int i;
   4657     int value;
   4658     soc_field_t field;
   4659     int field_num = 0;
   4660     egr_vfi_entry_t vfi_entry;
   4661     soc_mem_t mem = EGR_VFIm;
   4662 
   4663     struct vfi_fields_s {
   4664         soc_field_t field;
   4665         uint32  valid_field;
   4666         uint16    *vlan_control_obj;
   4667     } vfi_field_values[] = {
   4668             {OVIDf, BCM_VLAN_CONTROL_VLAN_ALL_MASK},
   4669             {INVALIDf, 0, NULL}
   4670     };
   4671 
   4672     vfi_field_values[0].vlan_control_obj = (uint16 *)&(control->egress_vlan);
   4673 
   4674     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, (int)vfi, &vfi_entry);
   4675     BCM_IF_ERROR_RETURN(rv);
   4676 
   4677     field_num = COUNTOF(vfi_field_values);
   4678     for (i = 0; i < field_num; i++) {
   4679         field = vfi_field_values[i].field;
   4680         if (!(valid_fields & vfi_field_values[i].valid_field) || (field == INVALIDf) ||
   4681             (soc_feature(unit, soc_feature_egr_intf_vlan_vfi_deoverlay) && (field == OVIDf))) {
   4682             continue;
   4683         }
   4684         if (soc_mem_field_valid(unit, mem, field)) {
   4685         value = soc_mem_field32_get(unit, mem, &vfi_entry, field);
   4686         *(vfi_field_values[i].vlan_control_obj) = value;
   4687     }
   4688     }
   4689 
   4690     if (soc_mem_field_valid(unit, mem, EN_EFILTERf)) {
   4691         if (soc_mem_field32_get(unit, mem, &vfi_entry, EN_EFILTERf) == 0) {
   4692             control->flags2 |= BCM_VLAN_FLAGS2_MEMBER_EGRESS_DISABLE;
   4693         } else {
   4694             control->flags2 &= ~BCM_VLAN_FLAGS2_MEMBER_EGRESS_DISABLE;
   4695         }
   4696     }
   4697 
   4698     BCM_IF_ERROR_RETURN(rv);
   4699 
   4700     return BCM_E_NONE;
   4701 }
   4702 
   4703 
   4704 /*
   4705  * Function :
   4706  *    bcmi_td2p_vlan_control_vpn_set
   4707  *
   4708  * Purpose  :
   4709  *    Configures various controls on the VFI.
   4710  *
   4711  * Parameters:
   4712  *     unit    - (IN) BCM device number.
   4713  *     vid     - (IN) Vlan id.
   4714  *     valid_fields - (IN) Valid fields, BCM_VLAN_CONTROL_VLAN_XXX_MASK.
   4715  *     control - (IN) Configuration structure.
   4716  *
   4717  * Return :
   4718  *    BCM_E_XXX
   4719  */
   4720 int
   4721 bcmi_td2p_vlan_control_vpn_set(int unit, bcm_vlan_t vid, uint32 valid_fields,
   4722                                bcm_vlan_control_vlan_t *control)
   4723 {
   4724 
   4725     int rv;
   4726     int vfi;
   4727 
   4728     _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vid);
   4729 
   4730     rv = bcmi_td2p_vfi_control_params_check(unit, vid, valid_fields, control);
   4731     BCM_IF_ERROR_RETURN(rv);
   4732 
   4733     /* Update VFI & VI_PROFILE tables per vlan_control INPUT */
   4734     rv = bcmi_td2p_vfi_control_ingress_set(unit, vfi, valid_fields, control);
   4735     BCM_IF_ERROR_RETURN(rv);
   4736 
   4737     /* Update EGR_VFI table */
   4738     rv = bcmi_td2p_vfi_control_egress_set(unit, vfi, valid_fields, control);
   4739     BCM_IF_ERROR_RETURN(rv);
   4740 
   4741     return BCM_E_NONE;
   4742 }
   4743 
   4744 /*
   4745  * Function :
   4746  *    bcmi_td2p_vlan_control_vpn_get
   4747  *
   4748  * Purpose  :
   4749  *
   4750  * Parameters:
   4751  *     unit    - (IN) BCM device number.
   4752  *     vid     - (IN) Vlan id.
   4753  *     control - (OUT) Configuration structure.
   4754  *
   4755  * Return :
   4756  *    BCM_E_XXX
   4757  */
   4758 int
   4759 bcmi_td2p_vlan_control_vpn_get(int unit, bcm_vlan_t vid, uint32 valid_fields,
   4760                                bcm_vlan_control_vlan_t *control)
   4761 {
   4762     int rv;
   4763     int vfi;
   4764 
   4765     _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vid);
   4766 
   4767     rv = bcmi_td2p_vfi_control_ingress_get(unit, vfi, valid_fields, control);
   4768     BCM_IF_ERROR_RETURN(rv);
   4769 
   4770     rv = bcmi_td2p_vfi_control_egress_get(unit, vfi, valid_fields, control);
   4771     BCM_IF_ERROR_RETURN(rv);
   4772 
   4773     return BCM_E_NONE;
   4774 }
   4775 
   4776 /*
   4777  * Function:
   4778  *      bcm_td2p_dvp_vlan_xlate_key_set
   4779  * Description:
   4780  *      Set egress vlan translation key per VXLAN gport
   4781  *
   4782  * Parameters:
   4783  *      unit             - (IN) unit number
   4784  *      port_id         - (IN) vxlan gport 
   4785  *      key_type      - (IN) Hardware egress vlan translation key type.
   4786  *
   4787  * Return Value:
   4788  *      BCM_E_XXX
   4789  */
   4790 int
   4791 bcm_td2p_dvp_vlan_xlate_key_set(int unit, bcm_gport_t port_id, int key_type)
   4792 {
   4793     int vp = -1, egr_key_type = 0, rv = BCM_E_UNAVAIL;
   4794     soc_mem_t mem = EGR_DVP_ATTRIBUTEm;
   4795     int network_port = 0;
   4796     source_vp_entry_t svp;
   4797     egr_dvp_attribute_entry_t egr_dvp_attribute;
   4798     _bcm_vp_info_t vp_info;
   4799 
   4800     if (BCM_GPORT_IS_VXLAN_PORT(port_id)) {
   4801         vp = BCM_GPORT_VXLAN_PORT_ID_GET(port_id);
   4802         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
   4803             return BCM_E_NOT_FOUND;
   4804         }
   4805     } else if (BCM_GPORT_IS_MIM_PORT(port_id)) {
   4806         vp = BCM_GPORT_MIM_PORT_ID_GET(port_id);
   4807         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   4808             return BCM_E_NOT_FOUND;
   4809         }
   4810     } else if (BCM_GPORT_IS_MPLS_PORT(port_id)) {
   4811         vp = BCM_GPORT_MPLS_PORT_ID_GET(port_id);
   4812         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
   4813             return BCM_E_NOT_FOUND;
   4814         }
   4815     } else if (BCM_GPORT_IS_L2GRE_PORT(port_id)) {
   4816         vp = BCM_GPORT_L2GRE_PORT_ID_GET(port_id);
   4817         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) {
   4818             return BCM_E_NOT_FOUND;
   4819         }
   4820     }
   4821 
   4822     /* Check for Network-Port */
   4823     sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   4824     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
   4825     if (BCM_FAILURE(rv)) {
   4826         return rv;
   4827     }
   4828 
   4829     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
   4830     if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
   4831         network_port = TRUE;
   4832     } else {
   4833         network_port = FALSE;
   4834     }
   4835 
   4836     /* bcmVlanTranslateEgressKeyVpn only for network port*/
   4837     if ((!network_port) && (key_type == TD2PLUS_DVP_EVLXLT_HASH_KEY_TYPE_VFI)) {
   4838         return BCM_E_UNAVAIL;
   4839     }
   4840 
   4841     sal_memset(&egr_dvp_attribute, 0, 
   4842                sizeof(egr_dvp_attribute_entry_t));
   4843     /* coverity[negative_returns] */
   4844     rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
   4845     if (BCM_FAILURE(rv)) {
   4846         return rv;
   4847     }
   4848     if ((network_port) && (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan))) {
   4849         egr_key_type = soc_mem_field32_get(unit, mem, &egr_dvp_attribute,
   4850                                            VXLAN__EVXLT_KEY_SELf);
   4851     } else if ((network_port) && (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre))) {
   4852         egr_key_type = soc_mem_field32_get(unit, mem, &egr_dvp_attribute,
   4853                                         L2GRE__EVXLT_KEY_SELf);
   4854     } else {
   4855         egr_key_type = soc_mem_field32_get(unit, mem, &egr_dvp_attribute, 
   4856                                            COMMON__EVXLT_KEY_SELf);
   4857     }
   4858     if (egr_key_type != key_type) { 
   4859         if ((network_port) && (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan))) {
   4860             soc_mem_field32_set(unit, mem, &egr_dvp_attribute, 
   4861                                 VXLAN__EVXLT_KEY_SELf, key_type);
   4862         } else if ((network_port) && (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre))) {
   4863             soc_mem_field32_set(unit, mem, &egr_dvp_attribute,
   4864                                 L2GRE__EVXLT_KEY_SELf, key_type);
   4865         } else {
   4866             soc_mem_field32_set(unit, mem, &egr_dvp_attribute, 
   4867                                 COMMON__EVXLT_KEY_SELf, key_type);
   4868         }
   4869         rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, 
   4870                            vp, &egr_dvp_attribute);
   4871         if (BCM_FAILURE(rv)) {
   4872             return rv;
   4873         }
   4874     }
   4875 
   4876     return rv;
   4877 }
   4878 
   4879 /*
   4880  * Function:
   4881  *      bcm_td2p_dvp_vlan_xlate_key_get
   4882  * Description:
   4883  *      Get egress vlan translation key per gport
   4884  *
   4885  * Parameters:
   4886  *      unit             - (IN) unit number
   4887  *      port_id         - (IN) vxlan gport 
   4888  *      key_type      - (IN) Hardware egress vlan translation key type.
   4889  *
   4890  * Return Value:
   4891  *      BCM_E_XXX
   4892  */
   4893 int
   4894 bcm_td2p_dvp_vlan_xlate_key_get(int unit, bcm_gport_t port_id, int *key_type)
   4895 {
   4896     int vp = -1, rv = BCM_E_UNAVAIL;
   4897     soc_mem_t mem = EGR_DVP_ATTRIBUTEm;
   4898     int network_port = 0;
   4899     source_vp_entry_t svp;
   4900     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   4901     _bcm_vp_info_t vp_info;
   4902 
   4903     if (key_type == NULL) {
   4904         return BCM_E_PARAM;
   4905     }
   4906 
   4907     if (BCM_GPORT_IS_VXLAN_PORT(port_id)) {
   4908         vp = BCM_GPORT_VXLAN_PORT_ID_GET(port_id);
   4909         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
   4910             return BCM_E_NOT_FOUND;
   4911         }
   4912     } else if (BCM_GPORT_IS_MIM_PORT(port_id)) {
   4913         vp = BCM_GPORT_MIM_PORT_ID_GET(port_id);
   4914         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   4915             return BCM_E_NOT_FOUND;
   4916         }
   4917     } else if (BCM_GPORT_IS_MPLS_PORT(port_id)) {
   4918         vp = BCM_GPORT_MPLS_PORT_ID_GET(port_id);
   4919         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
   4920             return BCM_E_NOT_FOUND;
   4921         }
   4922     } else if (BCM_GPORT_IS_L2GRE_PORT(port_id)) {
   4923         vp = BCM_GPORT_L2GRE_PORT_ID_GET(port_id);
   4924         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre)) {
   4925             return BCM_E_NOT_FOUND;
   4926         }
   4927     }
   4928 
   4929     /* Check for Network-Port */
   4930     sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   4931     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
   4932     if (BCM_FAILURE(rv)) {
   4933         return rv;
   4934     }
   4935 
   4936     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
   4937     if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
   4938         network_port = TRUE;
   4939     } else {
   4940         network_port = FALSE;
   4941     }
   4942  
   4943     sal_memset(&egr_dvp_attribute, 0, 
   4944                sizeof(egr_dvp_attribute_entry_t));
   4945     /* coverity[negative_returns] */
   4946     rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
   4947     if (BCM_FAILURE(rv)) {
   4948         return rv;
   4949     }
   4950     if ((network_port) && (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan))) {
   4951         *key_type = soc_mem_field32_get(unit, mem, &egr_dvp_attribute, 
   4952                                         VXLAN__EVXLT_KEY_SELf);
   4953     } else if ((network_port) && (_bcm_vp_used_get(unit, vp, _bcmVpTypeL2Gre))) {
   4954         *key_type = soc_mem_field32_get(unit, mem, &egr_dvp_attribute,
   4955                                         L2GRE__EVXLT_KEY_SELf);
   4956     } else {
   4957         *key_type = soc_mem_field32_get(unit, mem, &egr_dvp_attribute, 
   4958                                         COMMON__EVXLT_KEY_SELf);
   4959     }
   4960 
   4961     return rv;
   4962 }
   4963 
   4964 int
   4965 bcm_td2p_ing_vp_vlan_membership_get_all(int unit, bcm_vlan_t vlan,
   4966         SHR_BITDCL *vp_bitmap, int arr_size, int *flags_arr)
   4967 {
   4968     int rv = BCM_E_NONE;
   4969     soc_mem_t mem;
   4970     int chunk_size, num_chunks, chunk_index;
   4971     int alloc_size;
   4972     uint8 *buf = NULL;
   4973     int i, entry_index_min, entry_index_max;
   4974     uint32 *buf_entry;
   4975     int vp;
   4976     int sp_state;
   4977     int vfi = -1;
   4978     _bcm_vp_vlan_mbrship_key_type_e key_type;
   4979     soc_field_t vld_fld = VALIDf;
   4980 
   4981     if (_BCM_VPN_VFI_IS_SET(vlan)) {
   4982         _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vlan);
   4983     }
   4984 
   4985     if (NULL == vp_bitmap) {
   4986         return BCM_E_PARAM;
   4987     }
   4988     if (arr_size != soc_mem_index_count(unit, SOURCE_VPm)) {
   4989         return BCM_E_PARAM;
   4990     }
   4991     if (NULL == flags_arr) {
   4992         return BCM_E_PARAM;
   4993     }
   4994 
   4995     mem = ING_VP_VLAN_MEMBERSHIPm;
   4996 
   4997     chunk_size = 1024;
   4998     num_chunks = soc_mem_index_count(unit, mem) / chunk_size;
   4999     if (soc_mem_index_count(unit, mem) % chunk_size) {
   5000         num_chunks++;
   5001     }
   5002 
   5003     alloc_size = sizeof(ing_vp_vlan_membership_entry_t) * chunk_size;
   5004     buf = soc_cm_salloc(unit, alloc_size, "ING_VP_VLAN_MEMBERSHIP buffer");
   5005     if (NULL == buf) {
   5006         rv = BCM_E_MEMORY;
   5007         goto cleanup;
   5008     }
   5009 
   5010     if (soc_feature(unit, soc_feature_base_valid)) {
   5011         vld_fld = BASE_VALIDf;
   5012     }
   5013 
   5014     for (chunk_index = 0; chunk_index < num_chunks; chunk_index++) {
   5015 
   5016         /* Get a chunk of entries */
   5017         entry_index_min = chunk_index * chunk_size;
   5018         entry_index_max = entry_index_min + chunk_size - 1;
   5019         if (entry_index_max > soc_mem_index_max(unit, mem)) {
   5020             entry_index_max = soc_mem_index_max(unit, mem);
   5021         }
   5022         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   5023                 entry_index_min, entry_index_max, buf);
   5024         if (SOC_FAILURE(rv)) {
   5025             goto cleanup;
   5026         }
   5027 
   5028         /* Read each entry of the chunk to extract VP and flags */
   5029         for (i = 0; i < (entry_index_max - entry_index_min + 1); i++) {
   5030             buf_entry = soc_mem_table_idx_to_pointer(unit,
   5031                     mem, uint32 *, buf, i);
   5032 
   5033             key_type = soc_mem_field32_get(unit, mem, buf_entry, KEY_TYPEf);
   5034 
   5035             if (soc_mem_field32_get(unit, mem, buf_entry, vld_fld) == 0) {
   5036                 continue;
   5037             }
   5038 
   5039             if (key_type == _bcm_vp_vlan_mbrship_vp_vfi_type) {
   5040                 if (soc_mem_field32_get(unit, mem, buf_entry, VFIf) != vfi) {
   5041                     continue;
   5042                 }
   5043             } else {
   5044                 if (soc_mem_field32_get(unit, mem, buf_entry, VLANf) != vlan) {
   5045                     continue;
   5046                 }
   5047             }
   5048 
   5049             vp = soc_mem_field32_get(unit, mem, buf_entry, VPf);
   5050             if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan) &&
   5051                 !_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv) &&
   5052                 !_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender) &&
   5053                 !_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan) &&
   5054                 !_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
   5055                 continue;
   5056             }
   5057             SHR_BITSET(vp_bitmap, vp);
   5058 
   5059             sp_state = soc_mem_field32_get(unit, mem, buf_entry, SP_TREEf);
   5060             if (sp_state == PVP_STP_DISABLED) {
   5061                 flags_arr[vp] = BCM_VLAN_GPORT_ADD_STP_DISABLE;
   5062             } else if (sp_state == PVP_STP_LEARNING) {
   5063                 flags_arr[vp] = BCM_VLAN_GPORT_ADD_STP_LEARN;
   5064             } else if (sp_state == PVP_STP_BLOCKING) {
   5065                 flags_arr[vp] = BCM_VLAN_GPORT_ADD_STP_BLOCK;
   5066             } else {
   5067                 flags_arr[vp] = BCM_VLAN_GPORT_ADD_STP_FORWARD;
   5068             }
   5069         }
   5070     }
   5071 
   5072 cleanup:
   5073     if (buf) {
   5074         soc_cm_sfree(unit, buf);
   5075     }
   5076 
   5077     return rv;
   5078 }
   5079 
   5080 int
   5081 bcm_td2p_egr_vp_vlan_membership_get_all(int unit, bcm_vlan_t vlan,
   5082         SHR_BITDCL *vp_bitmap, int arr_size, int *flags_arr)
   5083 {
   5084     int rv = BCM_E_NONE;
   5085     soc_mem_t mem;
   5086     int chunk_size, num_chunks, chunk_index;
   5087     int alloc_size;
   5088     uint8 *buf = NULL;
   5089     int i, entry_index_min, entry_index_max;
   5090     uint32 *buf_entry;
   5091     int vp;
   5092     int sp_state;
   5093     int untag;
   5094     int vfi = -1;
   5095     _bcm_vp_vlan_mbrship_key_type_e key_type;
   5096     soc_field_t vld_fld = VALIDf;
   5097 
   5098     if (_BCM_VPN_VFI_IS_SET(vlan)) {
   5099         _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vlan);
   5100     }
   5101 
   5102     if (NULL == vp_bitmap) {
   5103         return BCM_E_PARAM;
   5104     }
   5105     if (arr_size != soc_mem_index_count(unit, SOURCE_VPm)) {
   5106         return BCM_E_PARAM;
   5107     }
   5108     if (NULL == flags_arr) {
   5109         return BCM_E_PARAM;
   5110     }
   5111 
   5112     mem = EGR_VP_VLAN_MEMBERSHIPm;
   5113     if (soc_feature(unit, soc_feature_base_valid)) {
   5114         vld_fld = BASE_VALIDf;
   5115     }
   5116 
   5117     chunk_size = 1024;
   5118     num_chunks = soc_mem_index_count(unit, mem) / chunk_size;
   5119     if (soc_mem_index_count(unit, mem) % chunk_size) {
   5120         num_chunks++;
   5121     }
   5122 
   5123     alloc_size = sizeof(egr_vp_vlan_membership_entry_t) * chunk_size;
   5124     buf = soc_cm_salloc(unit, alloc_size, "EGR_VP_VLAN_MEMBERSHIP buffer");
   5125     if (NULL == buf) {
   5126         rv = BCM_E_MEMORY;
   5127         goto cleanup;
   5128     }
   5129 
   5130     for (chunk_index = 0; chunk_index < num_chunks; chunk_index++) {
   5131 
   5132         /* Get a chunk of entries */
   5133         entry_index_min = chunk_index * chunk_size;
   5134         entry_index_max = entry_index_min + chunk_size - 1;
   5135         if (entry_index_max > soc_mem_index_max(unit, mem)) {
   5136             entry_index_max = soc_mem_index_max(unit, mem);
   5137         }
   5138         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   5139                 entry_index_min, entry_index_max, buf);
   5140         if (SOC_FAILURE(rv)) {
   5141             goto cleanup;
   5142         }
   5143 
   5144         /* Read each entry of the chunk to extract VP and flags */
   5145         for (i = 0; i < (entry_index_max - entry_index_min + 1); i++) {
   5146             buf_entry = soc_mem_table_idx_to_pointer(unit,
   5147                     mem, uint32 *, buf, i);
   5148 
   5149             key_type = soc_mem_field32_get(unit, mem, buf_entry, KEY_TYPEf);
   5150 
   5151             if (soc_mem_field32_get(unit, mem, buf_entry, vld_fld) == 0) {
   5152                 continue;
   5153             }
   5154 
   5155             if (key_type == _bcm_vp_vlan_mbrship_vp_vfi_type) {
   5156                 if (soc_mem_field32_get(unit, mem, buf_entry, VFIf) != vfi) {
   5157                     continue;
   5158                 }
   5159             } else {
   5160                 if (soc_mem_field32_get(unit, mem, buf_entry, VLANf) != vlan) {
   5161                     continue;
   5162                 }
   5163             }
   5164 
   5165             vp = soc_mem_field32_get(unit, mem, buf_entry, VPf);
   5166             if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan) &&
   5167                 !_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv) &&
   5168                 !_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender) &&
   5169                 !_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan) &&
   5170                 !_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
   5171                 continue;
   5172             }
   5173             SHR_BITSET(vp_bitmap, vp);
   5174 
   5175             sp_state = soc_mem_field32_get(unit, mem, buf_entry, SP_TREEf);
   5176             if (sp_state == PVP_STP_DISABLED) {
   5177                 flags_arr[vp] = BCM_VLAN_GPORT_ADD_STP_DISABLE;
   5178             } else if (sp_state == PVP_STP_LEARNING) {
   5179                 flags_arr[vp] = BCM_VLAN_GPORT_ADD_STP_LEARN;
   5180             } else if (sp_state == PVP_STP_BLOCKING) {
   5181                 flags_arr[vp] = BCM_VLAN_GPORT_ADD_STP_BLOCK;
   5182             } else {
   5183                 flags_arr[vp] = BCM_VLAN_GPORT_ADD_STP_FORWARD;
   5184             }
   5185 
   5186             untag = soc_mem_field32_get(unit, mem, buf_entry, UNTAGf);
   5187             if (untag) {
   5188                 flags_arr[vp] |= BCM_VLAN_PORT_UNTAGGED;
   5189             }
   5190         }
   5191     }
   5192 
   5193 cleanup:
   5194     if (buf) {
   5195         soc_cm_sfree(unit, buf);
   5196     }
   5197 
   5198     return rv;
   5199 }
   5200 
   5201 int
   5202 bcm_td2p_vp_vlan_membership_get_all(int unit, bcm_vlan_t vlan, int array_max,
   5203                                     bcm_gport_t *gport_array, int *flags_array,
   5204                                     int *array_size)
   5205 {
   5206     int i = 0;
   5207     int rv = 0;
   5208     int num_vp = 0;
   5209     SHR_BITDCL *ing_vp_bitmap = NULL;
   5210     int *ing_flags_arr = NULL;
   5211     SHR_BITDCL *egr_vp_bitmap = NULL;
   5212     int *egr_flags_arr = NULL;
   5213     int flags = 0;
   5214 
   5215     if ((array_max > 0) && (NULL == gport_array)) {
   5216         return BCM_E_PARAM;
   5217     }
   5218 
   5219     if ((array_max > 0) && (*array_size >= array_max)) {
   5220         return BCM_E_NONE;
   5221     }
   5222 
   5223     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   5224 
   5225     ing_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "ing_vp_bitmap");
   5226     if (NULL == ing_vp_bitmap) {
   5227         rv = BCM_E_MEMORY;
   5228         goto cleanup;
   5229     }
   5230     sal_memset(ing_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
   5231 
   5232     ing_flags_arr = sal_alloc(num_vp * sizeof(int), "ing_flags_arr");
   5233     if (NULL == ing_flags_arr) {
   5234         rv = BCM_E_MEMORY;
   5235         goto cleanup;
   5236     }
   5237     sal_memset(ing_flags_arr, 0, num_vp * sizeof(int));
   5238 
   5239     if (soc_feature(unit, soc_feature_ing_vp_vlan_membership)) {
   5240         rv = bcm_td2p_ing_vp_vlan_membership_get_all(unit, vlan, ing_vp_bitmap,
   5241                 num_vp, ing_flags_arr);
   5242         if (BCM_FAILURE(rv)) {
   5243             goto cleanup;
   5244         }
   5245     }
   5246 
   5247     egr_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "egr_vp_bitmap");
   5248     if (NULL == egr_vp_bitmap) {
   5249         rv = BCM_E_MEMORY;
   5250         goto cleanup;
   5251     }
   5252     sal_memset(egr_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
   5253 
   5254     egr_flags_arr = sal_alloc(num_vp * sizeof(int), "egr_flags_arr");
   5255     if (NULL == egr_flags_arr) {
   5256         rv = BCM_E_MEMORY;
   5257         goto cleanup;
   5258     }
   5259     sal_memset(egr_flags_arr, 0, num_vp * sizeof(int));
   5260 
   5261     if (soc_feature(unit, soc_feature_egr_vp_vlan_membership)) {
   5262         rv = bcm_td2p_egr_vp_vlan_membership_get_all(unit, vlan, egr_vp_bitmap,
   5263                 num_vp, egr_flags_arr);
   5264         if (BCM_FAILURE(rv)) {
   5265             goto cleanup;
   5266         }
   5267     }
   5268 
   5269     for (i = 0; i < num_vp; i++) {
   5270         if (!SHR_BITGET(ing_vp_bitmap, i) &&
   5271             !SHR_BITGET(egr_vp_bitmap, i)) {
   5272             continue;
   5273         }
   5274 
   5275         if (0 == array_max) {
   5276             (*array_size)++;
   5277         } else {
   5278             if (_bcm_vp_used_get(unit, i, _bcmVpTypeVlan)) {
   5279                 BCM_GPORT_VLAN_PORT_ID_SET(gport_array[*array_size], i);
   5280             } else if (_bcm_vp_used_get(unit, i, _bcmVpTypeNiv)) {
   5281                 BCM_GPORT_NIV_PORT_ID_SET(gport_array[*array_size], i);
   5282             } else if (_bcm_vp_used_get(unit, i, _bcmVpTypeExtender)) {
   5283                 BCM_GPORT_EXTENDER_PORT_ID_SET(gport_array[*array_size], i);
   5284             } else if (_bcm_vp_used_get(unit, i, _bcmVpTypeVxlan)) {
   5285                 BCM_GPORT_VXLAN_PORT_ID_SET(gport_array[*array_size], i);
   5286             } else if (_bcm_vp_used_get(unit, i, _bcmVpTypeMpls)) {
   5287                 BCM_GPORT_MPLS_PORT_ID_SET(gport_array[*array_size], i);
   5288             } else {
   5289                 rv = BCM_E_INTERNAL;
   5290                 goto cleanup;
   5291             }
   5292 
   5293             if (NULL != flags_array) {
   5294                 flags_array[*array_size] = ing_flags_arr[i] |
   5295                                            egr_flags_arr[i] |
   5296                                            BCM_VLAN_GPORT_ADD_VP_VLAN_MEMBERSHIP;
   5297 
   5298                 if (SHR_BITGET(ing_vp_bitmap, i) && !SHR_BITGET(egr_vp_bitmap, i)) {
   5299                     flags_array[*array_size] |= BCM_VLAN_GPORT_ADD_INGRESS_ONLY;
   5300                 }
   5301 
   5302                 if (!SHR_BITGET(ing_vp_bitmap, i) && SHR_BITGET(egr_vp_bitmap, i)) {
   5303                     flags_array[*array_size] |= BCM_VLAN_GPORT_ADD_EGRESS_ONLY;
   5304                 }
   5305 
   5306                 rv = bcm_tr2_vlan_gport_get(unit, vlan, gport_array[*array_size], &flags);
   5307                 if (BCM_FAILURE(rv)) {
   5308                     goto cleanup;
   5309                 }
   5310                 flags_array[*array_size] |= flags;
   5311 
   5312             }
   5313 
   5314             (*array_size)++;
   5315             if (*array_size == array_max) {
   5316                 break;
   5317             }
   5318         }
   5319     }
   5320 
   5321 cleanup:
   5322     if (NULL != ing_vp_bitmap) {
   5323         sal_free(ing_vp_bitmap);
   5324     }
   5325     if (NULL != ing_flags_arr) {
   5326         sal_free(ing_flags_arr);
   5327     }
   5328     if (NULL != egr_vp_bitmap) {
   5329         sal_free(egr_vp_bitmap);
   5330     }
   5331     if (NULL != egr_flags_arr) {
   5332         sal_free(egr_flags_arr);
   5333     }
   5334 
   5335     return rv;
   5336 
   5337 }
   5338 
   5339 /*
   5340  * Function :
   5341  *    bcmi_td2p_vfi_block_update
   5342  *
   5343  * Purpose  :
   5344  *    Update blocking profile on VFI.
   5345  *
   5346  * Parameters:
   5347  *     unit    - (IN) BCM device number.
   5348  *     block   - (IN) Block configuration.
   5349  *
   5350  * Return :
   5351  *    BCM_E_XXX
   5352  */
   5353 int
   5354 bcmi_td2p_vfi_block_update(int unit, int vfi, _trx_vlan_block_t *block)
   5355 {
   5356     int rv;                 /* Operation return status. */
   5357     soc_mem_t mem;          /* Vlan profile table memory. */
   5358     int old_profile_idx;    /* Profile index.           */
   5359     void *entries[3], *entry;
   5360     vfi_profile_entry_t vfi_profile_entry;
   5361     vfi_profile_2_entry_t vfi_profile_2_entry;
   5362     uint32 profile_index;
   5363     vfi_entry_t vfi_entry;
   5364 
   5365     /* Input parameters check. */
   5366     if (NULL == block) {
   5367         return (BCM_E_PARAM);
   5368     }
   5369 
   5370     /* Get original vlan profile. */
   5371     rv = soc_mem_read(unit, VFIm, MEM_BLOCK_ANY, (int)vfi, &vfi_entry);
   5372     BCM_IF_ERROR_RETURN(rv);
   5373 
   5374     old_profile_idx = soc_mem_field32_get(unit, VFIm,
   5375                                           &vfi_entry, VFI_PROFILE_PTRf);
   5376 
   5377     mem = VFI_PROFILE_2m;
   5378     entries[0] = &vfi_profile_entry;
   5379     entries[1] = &vfi_profile_2_entry;
   5380     BCM_IF_ERROR_RETURN(
   5381         _bcm_vfi_profile_entry_get(unit, old_profile_idx, 1, entries));
   5382 
   5383     entry = &vfi_profile_2_entry;
   5384     /* Bitmap A  */
   5385     soc_mem_pbmp_field_set(unit, mem, entry, BLOCK_MASK_Af,
   5386                            &block->first_mask);
   5387 
   5388     /* Bitmap B  */
   5389     soc_mem_pbmp_field_set(unit, mem, entry, BLOCK_MASK_Bf,
   5390                            &block->second_mask);
   5391 
   5392     /* Broadcast mask select. */
   5393     soc_mem_field32_set(unit, mem, entry, BCAST_MASK_SELf,
   5394                         block->broadcast_mask_sel);
   5395 
   5396     /* Unknown unicast mask select. */
   5397     if (soc_mem_field_valid(unit, mem,
   5398                             UNKNOWN_UCAST_MASK_SELf)) {
   5399         soc_mem_field32_set(unit, mem, entry, UNKNOWN_UCAST_MASK_SELf,
   5400                         block->unknown_unicast_mask_sel);
   5401     }
   5402 
   5403     /* Unknown multicast mask select. */
   5404     if (soc_mem_field_valid(unit, mem,
   5405                             UNKNOWN_MCAST_MASK_SELf)) {
   5406         soc_mem_field32_set(unit, mem, entry, UNKNOWN_MCAST_MASK_SELf,
   5407                         block->unknown_mulitcast_mask_sel);
   5408     }
   5409 
   5410     /* Unknown multicast mask select. */
   5411     if (soc_mem_field_valid(unit, mem, KNOWN_MCAST_MASK_SELf)) {
   5412         soc_mem_field32_set(unit, mem, entry, KNOWN_MCAST_MASK_SELf,
   5413                         block->known_mulitcast_mask_sel);
   5414     }
   5415 
   5416     BCM_IF_ERROR_RETURN(
   5417         _bcm_vfi_profile_entry_add(unit, entries, 1, &profile_index));
   5418 
   5419     /* Overwrite the the profile pointer in VFI with the new profile index */
   5420     soc_mem_field32_set(unit, VFIm, &vfi_entry, VFI_PROFILE_PTRf,
   5421                         profile_index);
   5422 
   5423     BCM_IF_ERROR_RETURN(
   5424         soc_mem_write(unit, VFIm, MEM_BLOCK_ALL, vfi, &vfi_entry));
   5425 
   5426     /* Delete the old profile object */
   5427     if (old_profile_idx > 0) {
   5428         BCM_IF_ERROR_RETURN(
   5429             _bcm_vfi_profile_entry_delete(unit, old_profile_idx));
   5430     }
   5431 
   5432     return (BCM_E_NONE);
   5433 }
   5434 
   5435 /*
   5436  * Function :
   5437  *    bcmi_td2p_vlan_block_set
   5438  *
   5439  * Purpose  :
   5440  *    Configures VFI specific traffic blocking parameters.
   5441  *
   5442  * Parameters:
   5443  *     unit    - (IN) BCM device number.
   5444  *     vid     - (IN) Vlan id.
   5445  *     block   - (IN) Block configuration.
   5446  *
   5447  * Return :
   5448  *    BCM_E_XXX
   5449  */
   5450 int
   5451 bcmi_td2p_vlan_block_set(int unit, bcm_vlan_t vid, bcm_vlan_block_t *block)
   5452 {
   5453     bcm_pbmp_t         array[_BCM_VLAN_BLOCK_LOOKUP_TYPES];
   5454     _trx_vlan_block_t  hw_block;       /* HW block structure.      */
   5455     int                rv;             /* Operation return status. */
   5456     int vfi;
   5457 
   5458     /* Input parameters check. */
   5459     if (NULL == block) {
   5460         return (BCM_E_PARAM);
   5461     }
   5462 
   5463     /* Store block mask in a array. */
   5464     BCM_PBMP_ASSIGN(array[0], block->broadcast);
   5465     BCM_PBMP_ASSIGN(array[1], block->unknown_unicast);
   5466     BCM_PBMP_ASSIGN(array[2], block->unknown_multicast);
   5467     BCM_PBMP_ASSIGN(array[3], block->known_multicast);
   5468 
   5469     /* Select first  shortest mask. */
   5470 
   5471     /* Coverity
   5472      * The index coverity thinks outside of boundary is actually for
   5473      * the field pbits of the pbmp structure.
   5474      */
   5475     /* coverity[overrun-buffer-val: FALSE] */
   5476     rv = _vlan_block_bitmap_min(unit, array,
   5477                                 _BCM_VLAN_BLOCK_LOOKUP_TYPES,
   5478                                 &hw_block.first_mask);
   5479     BCM_IF_ERROR_RETURN(rv);
   5480 
   5481     /* Clear those masks in the array that exactly match the shortest mask. */
   5482     /* coverity[overrun-buffer-val: FALSE] */
   5483     rv = _vlan_block_bitmap_clear(unit, array,
   5484                                   _BCM_VLAN_BLOCK_LOOKUP_TYPES,
   5485                                   hw_block.first_mask);
   5486     BCM_IF_ERROR_RETURN(rv);
   5487 
   5488     /* Select second shortest mask. */
   5489     /* coverity[overrun-buffer-val: FALSE] */
   5490     rv = _vlan_block_bitmap_min(unit, array,
   5491                                 _BCM_VLAN_BLOCK_LOOKUP_TYPES,
   5492                                 &hw_block.second_mask);
   5493     BCM_IF_ERROR_RETURN(rv);
   5494 
   5495 
   5496     /* Get mask selector for each lookup type. */
   5497     rv = _vlan_block_select_get(unit, block->broadcast, hw_block.first_mask,
   5498                                 hw_block.second_mask,
   5499                                 &hw_block.broadcast_mask_sel);
   5500     BCM_IF_ERROR_RETURN(rv);
   5501 
   5502     rv = _vlan_block_select_get(unit, block->unknown_unicast,
   5503                                 hw_block.first_mask, hw_block.second_mask,
   5504                                 &hw_block.unknown_unicast_mask_sel);
   5505     BCM_IF_ERROR_RETURN(rv);
   5506 
   5507     rv = _vlan_block_select_get(unit, block->unknown_multicast,
   5508                                 hw_block.first_mask, hw_block.second_mask,
   5509                                 &hw_block.unknown_mulitcast_mask_sel);
   5510     BCM_IF_ERROR_RETURN(rv);
   5511 
   5512     rv = _vlan_block_select_get(unit, block->known_multicast,
   5513                                 hw_block.first_mask, hw_block.second_mask,
   5514                                 &hw_block.known_mulitcast_mask_sel);
   5515     BCM_IF_ERROR_RETURN(rv);
   5516 
   5517     _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vid);
   5518 
   5519     BCM_IF_ERROR_RETURN(
   5520         bcmi_td2p_vfi_block_update(unit, vfi, &hw_block));
   5521 
   5522     return (BCM_E_NONE);
   5523 }
   5524 
   5525 /*
   5526  * Function :
   5527  *    bcmi_td2p_vlan_block_get
   5528  *
   5529  * Purpose  :
   5530  *    Get VFI specific traffic blocking parameters
   5531  *
   5532  * Parameters:
   5533  *     unit    - (IN) BCM device number.
   5534  *     vid     - (IN) Vlan id.
   5535  *     block   - (IN) Block configuration.
   5536  *
   5537  * Return :
   5538  *    BCM_E_XXX
   5539  */
   5540 int
   5541 bcmi_td2p_vlan_block_get (int unit, bcm_vlan_t vid, bcm_vlan_block_t *block)
   5542 {
   5543     _trx_vlan_block_t  hw_block; /* Vlan block profile.      */
   5544     int                rv;        /* Operation return status. */
   5545     soc_mem_t mem;
   5546     int profile_index;
   5547     vfi_entry_t vfi_entry;
   5548     uint32 buf[SOC_MAX_MEM_FIELD_WORDS]; /* HW entry buffer.     */
   5549     int vfi;
   5550 
   5551     /* Input parameters check. */
   5552     if (NULL == block) {
   5553         return (BCM_E_PARAM);
   5554     }
   5555 
   5556     /* Get original vlan profile. */
   5557     mem = VFIm;
   5558     _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vid);
   5559     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, (int)vfi, &vfi_entry);
   5560     BCM_IF_ERROR_RETURN(rv);
   5561 
   5562     profile_index = soc_mem_field32_get(unit, mem,
   5563                                         &vfi_entry, VFI_PROFILE_PTRf);
   5564 
   5565     /* READ VFI_PROFILE_2 portion. */
   5566     sal_memset(buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   5567     mem = VFI_PROFILE_2m;
   5568 
   5569     /* READ vfi profile 2 table. */
   5570     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, profile_index, buf);
   5571     if (BCM_FAILURE(rv)) {
   5572         return (rv);
   5573     }
   5574 
   5575     /* Bitmap A  */
   5576     soc_mem_pbmp_field_get(unit, mem, buf, BLOCK_MASK_Af,
   5577                            &hw_block.first_mask);
   5578 
   5579     /* Bitmap B  */
   5580     soc_mem_pbmp_field_get(unit, mem, buf, BLOCK_MASK_Bf,
   5581                            &hw_block.second_mask);
   5582 
   5583     /* Broadcast mask select. */
   5584     hw_block.broadcast_mask_sel =
   5585         soc_mem_field32_get(unit, mem, buf, BCAST_MASK_SELf);
   5586 
   5587     /* Unknown unicast mask select. */
   5588     hw_block.unknown_unicast_mask_sel =
   5589         soc_mem_field32_get(unit, mem, buf, UNKNOWN_UCAST_MASK_SELf);
   5590 
   5591     /* Unknown multicast mask select. */
   5592     hw_block.unknown_mulitcast_mask_sel =
   5593         soc_mem_field32_get(unit, mem, buf, UNKNOWN_MCAST_MASK_SELf);
   5594 
   5595     /* Unknown multicast mask select. */
   5596     hw_block.known_mulitcast_mask_sel =
   5597         soc_mem_field32_get(unit, mem, buf, KNOWN_MCAST_MASK_SELf);
   5598 
   5599     rv = _vlan_block_mask_create (unit, hw_block.first_mask,
   5600                                   hw_block.second_mask,
   5601                                   hw_block.broadcast_mask_sel,
   5602                                   &block->broadcast);
   5603     BCM_IF_ERROR_RETURN(rv);
   5604 
   5605     rv = _vlan_block_mask_create (unit, hw_block.first_mask,
   5606                                   hw_block.second_mask,
   5607                                   hw_block.unknown_unicast_mask_sel,
   5608                                   &block->unknown_unicast);
   5609     BCM_IF_ERROR_RETURN(rv);
   5610 
   5611     rv = _vlan_block_mask_create (unit,
   5612                                   hw_block.first_mask,
   5613                                   hw_block.second_mask,
   5614                                   hw_block.unknown_mulitcast_mask_sel,
   5615                                   &block->unknown_multicast);
   5616     BCM_IF_ERROR_RETURN(rv);
   5617 
   5618     rv = _vlan_block_mask_create (unit,
   5619                                   hw_block.first_mask,
   5620                                   hw_block.second_mask,
   5621                                   hw_block.known_mulitcast_mask_sel,
   5622                                   &block->known_multicast);
   5623     BCM_IF_ERROR_RETURN(rv);
   5624 
   5625     return (BCM_E_NONE);
   5626 }
   5627 #endif /* BCM_TRIDENT2PLUS_SUPPORT && INCLUDE_L3 */
   5628