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 (35979B)


      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 trident3 specific vlan features.
      9  */
     10 
     11 #include <soc/defs.h>
     12 #include <soc/field.h>
     13 #include <sal/core/libc.h>
     14 #include <shared/bsl.h>
     15 
     16 #if defined(BCM_TRIDENT3_SUPPORT)
     17 #include <sal/core/libc.h>
     18 #include <soc/drv.h>
     19 #include <soc/hash.h>
     20 #include <soc/trident2.h>
     21 #include <soc/trident3.h>
     22 #include <soc/mem.h>
     23 #include <bcm/port.h>
     24 #include <bcm/error.h>
     25 
     26 #include <bcm_int/esw/port.h>
     27 #include <bcm_int/esw/mirror.h>
     28 #include <bcm_int/esw/firebolt.h>
     29 #include <bcm_int/esw/trident3.h>
     30 #include <bcm_int/esw/vpn.h>
     31 #include <bcm_int/esw/trx.h>
     32 
     33 /*
     34  * Function:
     35  *      _bcm_td3_vlan_vfi_untag_profile_ptr_get
     36  * Purpose:
     37  *      Given a VLAN/VFI value, get the VLAN/VFI untag profile.
     38  * Parameters:
     39  *      unit - (IN) BCM device number
     40  *      vlan_vfi   - (IN) VLAN/VFI in question
     41  *      prof_index - (OUT) The associated profile index if all goes well
     42  * Returns:
     43  *      BCM_E_XXX
     44  */
     45 
     46 STATIC int
     47 _bcm_td3_vlan_vfi_untag_profile_ptr_get(int unit,
     48                                         bcm_vlan_t vlan_vfi,
     49                                         uint32 *prof_index)
     50 {
     51     int                 rv = BCM_E_NONE;
     52     uint32              *entry = NULL, index;
     53     soc_mem_t           mem;
     54 
     55     if (prof_index == NULL) {
     56         return BCM_E_PARAM;
     57     }
     58 
     59     /* Depending on VLAN/VFI, set relevant memory and index */
     60     if (!_BCM_VPN_VFI_IS_SET(vlan_vfi)) {
     61         mem = EGR_VLANm;
     62         /* Index in case of a VLAN is same as what is passed in */
     63         index = vlan_vfi;
     64     } else {
     65         mem = EGR_VFIm;
     66         /* Index in case of a VFI is the encoded value */
     67         _BCM_VPN_GET(index, _BCM_VPN_TYPE_VFI, vlan_vfi);
     68     }
     69 
     70     /* Allocated the desired size */
     71     entry = sal_alloc(SOC_MEM_BYTES(unit, mem), "Get VLAN/VFI profile index");
     72     if (entry == NULL) {
     73         return BCM_E_MEMORY;
     74     }
     75 
     76     /* Read the memory and extract the field in question */
     77     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, entry);
     78     if (rv < 0) {
     79         sal_free(entry);
     80         return rv;
     81     }
     82 
     83     /* Assign the profile index */
     84     *prof_index = soc_mem_field32_get(unit, mem, entry, UNTAG_PROFILE_PTRf);
     85 
     86     sal_free(entry);
     87 
     88     return rv;
     89 }
     90 
     91 /*
     92  * Function:
     93  *      _bcm_td3_vlan_vfi_untag_profile_ptr_set
     94  * Purpose:
     95  *      Given a VLAN/VFI value, prof_index set
     96  *      the associated VLAN_VFI profile.
     97  * Parameters:
     98  *      unit - (IN) BCM device number
     99  *      vlan_vfi   - (IN) VLAN/VFI value
    100  *      prof_index - (OUT) The associated profile index if all goes well
    101  * Returns:
    102  *      BCM_E_XXX
    103  */
    104 
    105 STATIC int
    106 _bcm_td3_vlan_vfi_untag_profile_ptr_set(int unit,
    107                                         bcm_vlan_t vlan_vfi,
    108                                         int prof_index)
    109 {
    110     int                 index = -1;
    111     soc_mem_t           mem;
    112 
    113     /* Depending on VLAN/VFI, write to relevant memories */
    114     if (!_BCM_VPN_VFI_IS_SET(vlan_vfi)) {
    115         mem = EGR_VLANm;
    116         index = vlan_vfi;
    117     } else {
    118         mem = EGR_VFIm;
    119         /* Index in case of a VFI is the encoded value */
    120         _BCM_VPN_GET(index, _BCM_VPN_TYPE_VFI, vlan_vfi);
    121     }
    122 
    123     LOG_INFO(BSL_LS_BCM_VLAN,
    124         (BSL_META_U(unit,"!: mem: %s index: %d prof_index: %d\n"),
    125                         SOC_MEM_NAME(unit, mem), index, prof_index));
    126 
    127     SOC_IF_ERROR_RETURN(
    128         soc_mem_field32_modify(unit, mem, index, UNTAG_PROFILE_PTRf, prof_index));
    129 
    130     return BCM_E_NONE;
    131 }
    132 
    133 /*
    134  * Function:
    135  *      _bcm_td3_vlan_vfi_profile_entry_set
    136  * Purpose:
    137  *      Given a VLAN/VFI value and a direction (Igr/Egr), set the
    138  *      data associated with a profile entry and update the VLAN/VFI
    139  *      with a new profile index
    140  * Parameters:
    141  *      unit - (IN) BCM device number
    142  *      vlan_vfi - (IN) VLAN/VFI value
    143  *      egress  - (IN) If TRUE, VP handling is for egress, else ingress.
    144  *      entry_data - (IN) Entry to write
    145  * Returns:
    146  *      BCM_E_XXX
    147  */
    148 
    149 int
    150 _bcm_td3_vlan_vfi_profile_entry_set(int unit, bcm_vlan_t vlan_vfi,
    151                                     void *entry_data)
    152 {
    153     uint32 cur_prof_index = 0, new_prof_index = 0;
    154     int32 cur_idx_ref_count = 0, new_idx_ref_count = 0;
    155 
    156     /* Get the profile_idx associated with the VLAN/VFI */
    157     _bcm_td3_vlan_vfi_untag_profile_ptr_get(unit, vlan_vfi, &cur_prof_index);
    158 
    159     /* Gather the ref counts */
    160     BCM_IF_ERROR_RETURN
    161         (_bcm_vlan_vfi_untag_profile_ref_count(unit, cur_prof_index,
    162                                                &cur_idx_ref_count));
    163 
    164     LOG_INFO(BSL_LS_BCM_VLAN,
    165         (BSL_META_U(unit,"\n\n!:Enter!Before profile: vlan_vfi: %d Old index %d "
    166                          "old_ref_cnt %d \n"),
    167                          vlan_vfi, cur_prof_index, cur_idx_ref_count));
    168 
    169     /* Depending on the direction, update the  relevant profile index,
    170        delete the old one */
    171 
    172     BCM_IF_ERROR_RETURN(_bcm_vlan_vfi_untag_profile_entry_op(unit, &entry_data, 1, 1,
    173                             (uint32 *)&new_prof_index));
    174 
    175     /* Write the new index into the VALN/VFI tables */
    176     _bcm_td3_vlan_vfi_untag_profile_ptr_set(unit, vlan_vfi, new_prof_index);
    177 
    178     /*
    179      * If the old-profile-index entry is non-zero delete it, note that if the
    180      * same index is reallocated, the profile-mgmt would have incremented the
    181      * ref-count anyway.
    182      */
    183     if (cur_prof_index != 0) {
    184         _bcm_vlan_vfi_untag_profile_entry_op(unit, NULL, 1, 0,
    185                                              &cur_prof_index);
    186     }
    187 
    188     /* Gather the ref counts */
    189     BCM_IF_ERROR_RETURN
    190         (_bcm_vlan_vfi_untag_profile_ref_count(unit, cur_prof_index,
    191                                                &cur_idx_ref_count));
    192     BCM_IF_ERROR_RETURN
    193         (_bcm_vlan_vfi_untag_profile_ref_count(unit,new_prof_index,
    194                                                &new_idx_ref_count));
    195 
    196     LOG_INFO(BSL_LS_BCM_VLAN,
    197         (BSL_META_U(unit,"!: After profile: old_index %d "
    198                          "old_ref_cnt %d new_index %d "
    199                          "new_ref_count: %d \n"),
    200                         cur_prof_index, cur_idx_ref_count,
    201                         new_prof_index, new_idx_ref_count));
    202 
    203     LOG_INFO(BSL_LS_BCM_VLAN,
    204         (BSL_META_U(unit,"!: Old index %d New index %d "
    205                          "vlan-vfi %d Data0 0x%x Data1 0x%x "
    206                          "Data2 0x%x Data3 0x%x Data4 0x%x Data5 0x%x Exit!\n\n\n"),
    207                          cur_prof_index, new_prof_index, vlan_vfi,
    208                          ((egr_vlan_vfi_untag_entry_t *)entry_data)->entry_data[5],
    209                          ((egr_vlan_vfi_untag_entry_t *)entry_data)->entry_data[4],
    210                          ((egr_vlan_vfi_untag_entry_t *)entry_data)->entry_data[3],
    211                          ((egr_vlan_vfi_untag_entry_t *)entry_data)->entry_data[2],
    212                          ((egr_vlan_vfi_untag_entry_t *)entry_data)->entry_data[1],
    213                          ((egr_vlan_vfi_untag_entry_t *)entry_data)->entry_data[0]));
    214 
    215     return BCM_E_NONE;
    216 }
    217 
    218 /*
    219  * Function:
    220  *      _bcm_td3_vlan_vfi_profile_entry_get
    221  * Purpose:
    222  *      Given a VLAN/VFI value, return the utag profile entry
    223  * Parameters:
    224  *      unit - (IN) BCM device number
    225  *      vlan_vfi - (IN) VLAN/VFI value
    226  *      entry_data - (OUT) Entry returned
    227  * Returns:
    228  *      BCM_E_XXX
    229  */
    230 
    231 int
    232 _bcm_td3_vlan_vfi_profile_entry_get(int unit, bcm_vlan_t vlan_vfi,
    233                                     void *entry_data)
    234 {
    235     int rv = BCM_E_NONE;
    236     uint32 prof_index = 0;
    237     /* Get the profile_idx associated with the VLAN/VFI */
    238     BCM_IF_ERROR_RETURN(_bcm_td3_vlan_vfi_untag_profile_ptr_get(unit, vlan_vfi, &prof_index));
    239 
    240     rv = READ_EGR_VLAN_VFI_UNTAGm(unit, MEM_BLOCK_ANY, prof_index, entry_data);
    241     return rv;
    242 }
    243 /*
    244  * Function:
    245  *      bcm_td3_vlan_vfi_untag_init
    246  * Purpose:
    247  *      Program membership port bitmap in vlan vfi membership tables
    248  */
    249 int
    250 bcm_td3_vlan_vfi_untag_init(int unit, bcm_vlan_t vid, pbmp_t pbmp)
    251 {
    252     egr_vlan_vfi_untag_entry_t egr_vlan_vfi;
    253     egr_vlan_entry_t egr_vtab;
    254     uint32 profile_ptr = 0;
    255 
    256     SOC_IF_ERROR_RETURN(READ_EGR_VLANm(unit, MEM_BLOCK_ANY, vid, &egr_vtab));
    257     profile_ptr = soc_EGR_VLANm_field32_get(unit, &egr_vtab,
    258                                             UNTAG_PROFILE_PTRf);
    259 
    260     SOC_IF_ERROR_RETURN
    261         (READ_EGR_VLAN_VFI_UNTAGm(unit, MEM_BLOCK_ANY, profile_ptr,
    262                                   &egr_vlan_vfi));
    263 
    264     soc_mem_pbmp_field_set(unit, EGR_VLAN_VFI_UNTAGm, &egr_vlan_vfi,
    265                            UT_PORT_BITMAPf, &pbmp);
    266 
    267     SOC_IF_ERROR_RETURN(
    268         _bcm_td3_vlan_vfi_profile_entry_set(unit, vid, &egr_vlan_vfi));
    269 
    270     return BCM_E_NONE;
    271 }
    272 
    273 /*
    274  * Function:
    275  *      bcm_td3_vlan_vfi_untag_add
    276  * Purpose:
    277  *      Program membership port bitmap in vlan vfi untag tables
    278  */
    279 int
    280 bcm_td3_vlan_vfi_untag_add(int unit, bcm_vlan_t vid, pbmp_t pbmp, pbmp_t ubmp)
    281 {
    282     egr_vlan_vfi_untag_entry_t egr_vlan_vfi;
    283     pbmp_t      cur_pbmp;
    284     uint32      prof_index = 0;
    285 
    286     /* Get the profile_idx associated with the VLAN/VFI */
    287     _bcm_td3_vlan_vfi_untag_profile_ptr_get(unit, vid, &prof_index);
    288 
    289     /* Only allow untagged ports on the vlan. */
    290     SOC_PBMP_AND(ubmp, pbmp);
    291 
    292     /* Draco does not have room for CMIC/IPIC in ubmp */
    293     SOC_PBMP_REMOVE(ubmp, PBMP_CMIC(unit));
    294     SOC_PBMP_REMOVE(ubmp, PBMP_ST_ALL(unit));
    295 
    296     BCM_IF_ERROR_RETURN
    297         (READ_EGR_VLAN_VFI_UNTAGm(unit, MEM_BLOCK_ANY, prof_index, &egr_vlan_vfi));
    298     soc_mem_pbmp_field_get(unit, EGR_VLAN_VFI_UNTAGm, &egr_vlan_vfi,
    299             UT_PORT_BITMAPf, &cur_pbmp);
    300     BCM_PBMP_REMOVE(cur_pbmp, pbmp);
    301     BCM_PBMP_OR(cur_pbmp, ubmp);
    302     soc_mem_pbmp_field_set(unit, EGR_VLAN_VFI_UNTAGm, &egr_vlan_vfi,
    303             UT_PORT_BITMAPf, &cur_pbmp);
    304 
    305     _bcm_td3_vlan_vfi_profile_entry_set(unit, vid, &egr_vlan_vfi);
    306 
    307     return BCM_E_NONE;
    308 }
    309 
    310 /*
    311  * Function:
    312  *      bcm_td3_vlan_vfi_untag_delete
    313  * Purpose:
    314  *      Program membership port bitmap in vlan vfi untag tables
    315  */
    316 int
    317 bcm_td3_vlan_vfi_untag_delete(int unit, bcm_vlan_t vid, pbmp_t pbmp)
    318 {
    319     egr_vlan_vfi_untag_entry_t egr_vlan_vfi;
    320     pbmp_t      cur_pbmp;
    321     uint32      prof_index = 0;
    322 
    323     /* Get the profile_idx associated with the VLAN/VFI */
    324     _bcm_td3_vlan_vfi_untag_profile_ptr_get(unit, vid, &prof_index);
    325 
    326     BCM_IF_ERROR_RETURN
    327         (READ_EGR_VLAN_VFI_UNTAGm(unit, MEM_BLOCK_ANY, prof_index, &egr_vlan_vfi));
    328     soc_mem_pbmp_field_get(unit, EGR_VLAN_VFI_UNTAGm, &egr_vlan_vfi,
    329             UT_PORT_BITMAPf, &cur_pbmp);
    330     BCM_PBMP_REMOVE(cur_pbmp, pbmp);
    331     soc_mem_pbmp_field_set(unit, EGR_VLAN_VFI_UNTAGm, &egr_vlan_vfi,
    332             UT_PORT_BITMAPf, &cur_pbmp);
    333 
    334     _bcm_td3_vlan_vfi_profile_entry_set(unit, vid, &egr_vlan_vfi);
    335 
    336     return BCM_E_NONE;
    337 }
    338 
    339 /*
    340  * Function:
    341  *      bcm_td3_egr_vlan_vfi_untag_destroy
    342  * Purpose:
    343  *      Delete the VLAN Vfi membership entry.
    344  * Parameters:
    345  *      unit  - (IN) SOC unit number.
    346  *      vlan  - (IN) VLAN ID.
    347  * Returns:
    348  *      BCM_E_XXX
    349  */
    350 int
    351 bcm_td3_vlan_vfi_untag_destroy(int unit, bcm_vlan_t vlan)
    352 {
    353     uint32 profile_ptr = 0;
    354     egr_vlan_vfi_untag_entry_t ing_vlan_vfi;
    355     int cur_ref_count = 0;
    356 
    357     sal_memset(&ing_vlan_vfi, 0, sizeof(egr_vlan_vfi_untag_entry_t));
    358 
    359     /* Get the MEMBERSHIP_PROFILE_PTR */
    360     _bcm_td3_vlan_vfi_untag_profile_ptr_get(unit, vlan, &profile_ptr);
    361     _bcm_vlan_vfi_untag_profile_ref_count(unit, profile_ptr, &cur_ref_count);
    362 
    363     LOG_INFO(BSL_LS_BCM_VLAN,
    364         (BSL_META_U(unit,"!: Deleting profile %d for vlan_vfi: %d cur_ref_cnt: %d \n"),
    365                     profile_ptr, vlan, cur_ref_count));
    366 
    367     /*  Delete the Reference Count, if the profile is non-zero */
    368     if (profile_ptr != 0) {
    369         BCM_IF_ERROR_RETURN(_bcm_vlan_vfi_untag_profile_entry_op(unit, NULL, 1,
    370                                 0, &profile_ptr));
    371     }
    372 
    373     return BCM_E_NONE;
    374 }
    375 
    376 
    377 /*
    378  * Function:
    379  *     bcm_td3_vlan_table_utport_get
    380  * Purpose:
    381  *      Read the UT_PORT_BITMAP from a vlan entry.
    382  */
    383 int
    384 bcm_td3_vlan_table_ut_port_get(int unit, bcm_vlan_t vid, pbmp_t *ut_pbmp)
    385 {
    386     egr_vlan_vfi_untag_entry_t egr_vlan_vfi;
    387     uint32      prof_index = 0;
    388 
    389     /* Upper layer already checks that vid is valid
    390      * Get the profile_idx associated with the VLAN/VFI */
    391     _bcm_td3_vlan_vfi_untag_profile_ptr_get(unit, vid, &prof_index);
    392 
    393     SOC_IF_ERROR_RETURN
    394         (READ_EGR_VLAN_VFI_UNTAGm(unit, MEM_BLOCK_ANY, prof_index,
    395             &egr_vlan_vfi));
    396     soc_mem_pbmp_field_get(unit, EGR_VLAN_VFI_UNTAGm, &egr_vlan_vfi,
    397             UT_PORT_BITMAPf, ut_pbmp);
    398 
    399     return BCM_E_NONE;
    400 }
    401 
    402 /*
    403  * Function:
    404  *      _bcm_td3_vlan_mac_action_add
    405  * Description   :
    406  *      Add association from MAC address to VLAN.
    407  *      If the entry already exists, update the action.
    408  * Parameters   :
    409  *      unit      (IN) BCM unit number
    410  *      mac       (IN) MAC address
    411  *      action    (IN) Action for outer and inner tag
    412  * Note:
    413  *   Program VLAN_XLATE_1_DOUBLEm.
    414  */
    415 int _bcm_td3_vlan_mac_action_add(int unit, bcm_mac_t mac,
    416                                  bcm_vlan_action_set_t *action)
    417 {
    418     int rv;
    419     uint32 profile_idx;
    420     vlan_xlate_2_double_entry_t vx1ent;
    421     soc_mem_t mem = VLAN_XLATE_2_DOUBLEm;
    422 
    423     BCM_IF_ERROR_RETURN(_bcm_trx_vlan_action_verify(unit, action));
    424     if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
    425         if (action->priority == -1) {
    426             return BCM_E_PARAM;  /* no default priority action to take*/
    427         }
    428     }
    429 
    430     BCM_IF_ERROR_RETURN
    431         (_bcm_trx_vlan_action_profile_entry_add(unit, action, &profile_idx));
    432 
    433     sal_memset(&vx1ent, 0, sizeof(vx1ent));
    434     soc_mem_mac_addr_set(unit, mem, &vx1ent, MAC__MAC_ADDRf, mac);
    435     soc_mem_field32_set(unit, mem, &vx1ent, KEY_TYPEf,
    436                         TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC);
    437     soc_mem_field32_set(unit, mem, &vx1ent, DATA_TYPEf,
    438                         TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC);
    439     soc_mem_field32_set(unit, mem, &vx1ent, MAC__OVIDf, action->new_outer_vlan);
    440     soc_mem_field32_set(unit, mem, &vx1ent, MAC__IVIDf, action->new_inner_vlan);
    441 
    442     if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
    443         soc_mem_field32_set(unit, mem, &vx1ent, MAC__OPRIf, action->priority);
    444         soc_mem_field32_set(unit, mem, &vx1ent, MAC__OCFIf,
    445                             action->new_outer_cfi);
    446         soc_mem_field32_set(unit, mem, &vx1ent, MAC__IPRIf,
    447                             action->new_inner_pkt_prio);
    448         soc_mem_field32_set(unit, mem, &vx1ent, MAC__ICFIf,
    449                             action->new_inner_cfi);
    450     } else {
    451         if (action->priority >= BCM_PRIO_MIN &&
    452             action->priority <= BCM_PRIO_MAX) {
    453             soc_mem_field32_set(unit, mem, &vx1ent, MAC__PRIf, action->priority);
    454         }
    455     }
    456     soc_mem_field32_set(unit, mem, &vx1ent, MAC__TAG_ACTION_PROFILE_PTRf,
    457                         profile_idx);
    458 
    459     if (SOC_MEM_FIELD_VALID(unit, mem, MAC__VLAN_ACTION_VALIDf)) {
    460         soc_mem_field32_set(unit, mem, &vx1ent, MAC__VLAN_ACTION_VALIDf, 1);
    461     }
    462     soc_mem_field32_set(unit, mem, &vx1ent, BASE_VALID_0f, 3);
    463     soc_mem_field32_set(unit, mem, &vx1ent, BASE_VALID_1f, 7);
    464 
    465     rv = soc_mem_insert_return_old(unit, mem, MEM_BLOCK_ALL, &vx1ent, &vx1ent);
    466 
    467     if (rv == SOC_E_EXISTS) {
    468         /* Delete the old vlan action profile entry */
    469         profile_idx = soc_mem_field32_get(unit, mem, &vx1ent,
    470                                           MAC__TAG_ACTION_PROFILE_PTRf);
    471         rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx);
    472     }
    473 
    474     return rv;
    475 }
    476 
    477 /*
    478  * Function:
    479  *      _bcm_td3_vlan_mac_action_get
    480  * Description   :
    481  *      Get association from MAC address to VLAN tag actions.
    482  * Parameters   :
    483  *      unit      (IN) BCM unit number
    484  *      mac       (IN) MAC address
    485  *      action    (OUT) Action for outer and inner tag
    486  * Returns:
    487  *      BCM_E_XXX
    488  */
    489 int
    490 _bcm_td3_vlan_mac_action_get(int unit, bcm_mac_t mac,
    491                              bcm_vlan_action_set_t *action)
    492 {
    493     vlan_xlate_2_double_entry_t vx1ent;     /* Lookup key hw buffer.      */
    494     vlan_xlate_2_double_entry_t res_vx1ent; /* Lookup result buffer.      */
    495     uint32 profile_idx;                     /* Vlan action profile index. */
    496     int rv;                                 /* Operation return status.   */
    497     int idx = 0;                            /* Lookup result entry index. */
    498     soc_mem_t mem = VLAN_XLATE_2_DOUBLEm;
    499 
    500     /* Input parameters check. */
    501     if (NULL == action) {
    502         return (BCM_E_PARAM);
    503     }
    504 
    505     /* Reset lookup key and result destination buffer. */
    506     sal_memset(&vx1ent, 0, sizeof(vx1ent));
    507     sal_memset(&res_vx1ent, 0, sizeof(res_vx1ent));
    508 
    509     /* Initialize lookup key. */
    510     soc_mem_mac_addr_set(unit, mem, &vx1ent, MAC__MAC_ADDRf, mac);
    511     soc_mem_field32_set(unit, mem, &vx1ent, KEY_TYPEf,
    512                         TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC);
    513     soc_mem_field32_set(unit, mem, &vx1ent, DATA_TYPEf,
    514                         TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC);
    515     /* Perform VLAN_MAC table search by mac address. */
    516     soc_mem_lock(unit, mem);
    517     rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL, &idx,
    518                         &vx1ent, &res_vx1ent, 0);
    519     soc_mem_unlock(unit, mem);
    520     BCM_IF_ERROR_RETURN(rv);
    521 
    522     action->new_outer_vlan =
    523         soc_mem_field32_get(unit, mem, &res_vx1ent, MAC__OVIDf);
    524     action->new_inner_vlan =
    525         soc_mem_field32_get(unit, mem, &res_vx1ent, MAC__IVIDf);
    526     if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
    527         action->priority =
    528             soc_mem_field32_get(unit, mem, &res_vx1ent, MAC__OPRIf);
    529         action->new_outer_cfi =
    530             soc_mem_field32_get(unit, mem, &res_vx1ent, MAC__OCFIf);
    531         action->new_inner_pkt_prio =
    532             soc_mem_field32_get(unit, mem, &res_vx1ent, MAC__IPRIf);
    533         action->new_inner_cfi =
    534             soc_mem_field32_get(unit, mem, &res_vx1ent, MAC__ICFIf);
    535     } else {
    536         action->priority = soc_mem_field32_get(unit, mem, &res_vx1ent, MAC__PRIf);
    537     }
    538 
    539     /* Read action profile data. */
    540     profile_idx = soc_mem_field32_get(unit, mem, &res_vx1ent,
    541                                       MAC__TAG_ACTION_PROFILE_PTRf);
    542     _bcm_trx_vlan_action_profile_entry_get(unit, action, profile_idx);
    543 
    544     return (BCM_E_NONE);
    545 }
    546 
    547 /*
    548  * Function:
    549  *      _bcm_td3_vlan_mac_delete
    550  * Purpose:
    551  *      Delete a vlan mac lookup entry.
    552  * Parameters:
    553  *      unit      (IN) BCM unit number
    554  *      mac       (IN) MAC address
    555  * Returns:
    556  *      BCM_E_XXX
    557  */
    558 int
    559 _bcm_td3_vlan_mac_delete(int unit, bcm_mac_t mac)
    560 {
    561     int rv;
    562     vlan_xlate_2_double_entry_t vx1ent;
    563     uint32 profile_idx;
    564     soc_mem_t mem = VLAN_XLATE_2_DOUBLEm;
    565 
    566     sal_memset(&vx1ent, 0, sizeof(vx1ent));
    567     soc_mem_mac_addr_set(unit, mem, &vx1ent, MAC__MAC_ADDRf, mac);
    568     soc_mem_field32_set(unit, mem, &vx1ent, KEY_TYPEf,
    569                         TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC);
    570     soc_mem_field32_set(unit, mem, &vx1ent, DATA_TYPEf,
    571                         TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC);
    572     soc_mem_lock(unit, mem);
    573     rv = soc_mem_delete_return_old(unit, mem, MEM_BLOCK_ALL, &vx1ent, &vx1ent);
    574     soc_mem_unlock(unit, mem);
    575     if (rv == SOC_E_NOT_FOUND) {
    576         rv = SOC_E_NONE;
    577     } else if ((rv == SOC_E_NONE) &&
    578                (soc_mem_field32_get(unit, mem, &vx1ent, BASE_VALID_0f) == 3) &&
    579                (soc_mem_field32_get(unit, mem, &vx1ent, BASE_VALID_1f) == 7)) {
    580         profile_idx = soc_mem_field32_get(unit, mem, &vx1ent,
    581                                           MAC__TAG_ACTION_PROFILE_PTRf);
    582         /* Delete the old vlan action profile entry */
    583         rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx);
    584     }
    585     return rv;
    586 }
    587 
    588 /*
    589  * Function:
    590  *      _bcm_td3_vlan_mac_delete_all
    591  * Purpose:
    592  *      Delete all vlan mac lookup entry.
    593  * Parameters:
    594  *      unit      (IN) BCM unit number
    595  * Returns:
    596  *      BCM_E_XXX
    597  */
    598 int
    599 _bcm_td3_vlan_mac_delete_all(int unit)
    600 {
    601     int i, imin, imax, nent, rv;
    602     uint32 old_profile_idx;
    603     vlan_xlate_2_double_entry_t *vxtab, *vmnull, *vxtabp;
    604     soc_mem_t mem = VLAN_XLATE_2_DOUBLEm;
    605 
    606     imin = soc_mem_index_min(unit, mem);
    607     imax = soc_mem_index_max(unit, mem);
    608     nent = soc_mem_index_count(unit, mem);
    609 
    610     vxtab = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, mem), "vlan_xlate");
    611 
    612     if (vxtab == NULL) {
    613         return BCM_E_MEMORY;
    614     }
    615 
    616     vmnull = soc_mem_entry_null(unit, mem);
    617 
    618     soc_mem_lock(unit, mem);
    619     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
    620                             imin, imax, vxtab);
    621     if (rv < 0) {
    622         soc_mem_unlock(unit, mem);
    623         soc_cm_sfree(unit, vxtab);
    624         return rv;
    625     }
    626 
    627     for (i = 0; i < nent; i++) {
    628         vxtabp = soc_mem_table_idx_to_pointer(unit, mem,
    629                         vlan_xlate_2_double_entry_t *, vxtab, i);
    630 
    631         if (!((soc_mem_field32_get(unit, mem, vxtabp, BASE_VALID_0f) == 3) &&
    632               (soc_mem_field32_get(unit, mem, vxtabp, BASE_VALID_1f) == 7)) ||
    633             (soc_mem_field32_get(unit, mem, vxtabp, KEY_TYPEf) !=
    634              TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC)) {
    635             continue;
    636         }
    637         old_profile_idx = soc_mem_field32_get(unit, mem, vxtabp,
    638                                               MAC__TAG_ACTION_PROFILE_PTRf);
    639 
    640         rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, i, vmnull);
    641 
    642         if (rv >= 0) {
    643             /* Delete the old vlan action profile entry */
    644             rv = _bcm_trx_vlan_action_profile_entry_delete(unit, old_profile_idx);
    645         }
    646     }
    647 
    648     soc_mem_unlock(unit, mem);
    649     soc_cm_sfree(unit, vxtab);
    650     return rv;
    651 }
    652 
    653 /*
    654  * Function:
    655  *      _bcm_td3_vlan_mac_action_traverse
    656  * Description   :
    657  *      Traverse over vlan mac actions, which are used for VLAN
    658  *      tag/s assignment to untagged packets.
    659  * Parameters   :
    660  *      unit            (IN) BCM unit number
    661  *      cb              (IN) Call back function
    662  *      user_data       (IN) User provided data to pass to a call back
    663  * Returns:
    664  *      BCM_E_XXX
    665  */
    666 int
    667 _bcm_td3_vlan_mac_action_traverse(int unit,
    668                                   bcm_vlan_mac_action_traverse_cb cb,
    669                                   void *user_data)
    670 {
    671     int idx, imin, imax, nent, rv;
    672     uint32 profile_idx;
    673     bcm_mac_t  mac;
    674     bcm_vlan_action_set_t action;
    675     vlan_xlate_2_double_entry_t * vmtab, *vmtabp;
    676     soc_mem_t mem = VLAN_XLATE_2_DOUBLEm;
    677 
    678     /* Input parameters check. */
    679     if (NULL == cb) {
    680         return (BCM_E_PARAM);
    681     }
    682 
    683     imin = soc_mem_index_min(unit, mem);
    684     imax = soc_mem_index_max(unit, mem);
    685     nent = soc_mem_index_count(unit, mem);
    686     vmtab = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, mem), "vlan_mac");
    687 
    688     if (vmtab == NULL) {
    689         return BCM_E_MEMORY;
    690     }
    691 
    692     soc_mem_lock(unit, mem);
    693     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, imin, imax, vmtab);
    694     if (BCM_FAILURE(rv)) {
    695         soc_mem_unlock(unit, mem);
    696         soc_cm_sfree(unit, vmtab);
    697         return rv;
    698     }
    699 
    700     for (idx = 0; idx < nent; idx++) {
    701         sal_memset(mac, 0, sizeof(bcm_mac_t));
    702         sal_memset(&action, 0, sizeof(bcm_vlan_action_set_t));
    703         vmtabp = soc_mem_table_idx_to_pointer(unit, mem,
    704                                               vlan_xlate_2_double_entry_t *,
    705                                               vmtab, idx);
    706 
    707         if (!((soc_mem_field32_get(unit, mem, vmtabp, BASE_VALID_0f) == 3) &&
    708               (soc_mem_field32_get(unit, mem, vmtabp, BASE_VALID_1f) == 7)) ||
    709             (soc_mem_field32_get(unit, mem, vmtabp, KEY_TYPEf) !=
    710              TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC)) {
    711             continue;
    712         }
    713 
    714         /* Get entry mac address. */
    715         soc_mem_mac_addr_get(unit, mem, vmtabp, MAC__MAC_ADDRf, mac);
    716 
    717         action.new_outer_vlan =
    718             soc_mem_field32_get(unit, mem, vmtabp, MAC__OVIDf);
    719         action.new_inner_vlan =
    720             soc_mem_field32_get(unit, mem, vmtabp, MAC__IVIDf);
    721         if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
    722             action.priority = soc_mem_field32_get(unit, mem, vmtabp, MAC__OPRIf);
    723             action.new_outer_cfi =
    724                 soc_mem_field32_get(unit, mem, vmtabp, MAC__OCFIf);
    725             action.new_inner_pkt_prio =
    726                 soc_mem_field32_get(unit, mem, vmtabp, MAC__IPRIf);
    727             action.new_inner_cfi =
    728                 soc_mem_field32_get(unit, mem, vmtabp, MAC__ICFIf);
    729         } else {
    730             action.priority =
    731                 soc_mem_field32_get(unit, mem, vmtabp, MAC__PRIf);
    732         }
    733 
    734         /* Read action profile data. */
    735         profile_idx =
    736             soc_mem_field32_get(unit, mem, vmtabp, MAC__TAG_ACTION_PROFILE_PTRf);
    737         _bcm_trx_vlan_action_profile_entry_get(unit, &action, profile_idx);
    738 
    739         /* Call traverse callback with the data. */
    740         rv = cb(unit, mac, &action, user_data);
    741         if (BCM_FAILURE(rv)) {
    742             soc_mem_unlock(unit, mem);
    743             soc_cm_sfree(unit, vmtab);
    744             return rv;
    745         }
    746     }
    747 
    748     soc_mem_unlock(unit, mem);
    749     soc_cm_sfree(unit, vmtab);
    750     return rv;
    751 }
    752 
    753 /*
    754  * Function:
    755  *      bcmi_td3_def_vfi_profile_add
    756  *
    757  * Purpose:
    758  *      Programs VFI_PROFILE table based on vpn type
    759  *
    760  * Parameters:
    761  *     unit    - (IN) BCM device number.
    762  *     int  - (IN) is_eline
    763  *     profile_index - (OUT) Profile index allocated by soc_mem_profile_add
    764  *
    765  * Returns:
    766  *      BCM_E_XXXs
    767  */
    768 int
    769 _bcm_td3_def_vfi_profile_add(int unit, int is_eline, uint32 *profile_index){
    770     vfi_profile_entry_t vfi_profile_entry;
    771     void *entries[1];
    772     int value = 0;
    773 
    774     sal_memset(&vfi_profile_entry, 0, sizeof(vfi_profile_entry_t));
    775     /* from bcm56870_a0_cancun_cmh.yml */
    776     if(is_eline) {
    777         value = 8;
    778     }
    779     else {
    780         value = 4;
    781     }
    782 
    783     soc_mem_field32_set(unit, VFI_PROFILEm, &vfi_profile_entry,
    784         PKT_FLOW_SELECT_CTRL_ID_2f, value);
    785     soc_mem_field32_set(unit, VFI_PROFILEm, &vfi_profile_entry,
    786         EN_IFILTERf, 1);
    787     entries[0] = &vfi_profile_entry;
    788     BCM_IF_ERROR_RETURN(_bcm_vfi_profile_entry_add(unit, entries, 1,
    789         profile_index));
    790 
    791     return BCM_E_NONE;
    792 }
    793 
    794 /*
    795  * Function:
    796  *      _bcm_td3_sd_tag_action_profile_get
    797  *
    798  * Purpose:
    799  *      get vlan profile index based on sd_tag action
    800  *
    801  * Parameters:
    802  *     unit - (IN) BCM device number.
    803  *     int  - (IN) sd_tag_action_present
    804  *     int  - (IN) sd_tag_action_not_present
    805  *     index - (IN, OUT) Profile index
    806  *
    807  * Returns:
    808  *      BCM_E_XXXs
    809  */
    810 int
    811 _bcm_td3_sd_tag_action_profile_get(
    812         int unit,
    813         int sd_tag_action_present,
    814         int sd_tag_action_not_present,
    815         uint32 *index)
    816 {
    817     int rv = BCM_E_NONE;
    818     bcm_vlan_action_set_t action;
    819     uint32 new_index = 0;
    820 
    821 
    822     bcm_vlan_action_set_t_init(&action);
    823 
    824     /* sd_tag_action_not_present
    825      * 0 = NOOP 1 = ADD_VID_TPID 2 = RSVD_2 3 = RSVD_3
    826      */
    827     if (sd_tag_action_not_present == 1) {
    828         action.outer_tpid_action = bcmVlanTpidActionModify;
    829         action.it_outer = bcmVlanActionAdd;
    830         action.it_outer_pkt_prio = bcmVlanActionAdd;
    831         action.it_outer_cfi = bcmVlanActionAdd;
    832         action.ut_outer  = bcmVlanActionAdd;
    833         action.ut_outer_pkt_prio  = bcmVlanActionAdd;
    834         action.ut_outer_cfi  = bcmVlanActionAdd;
    835     } else {
    836         action.outer_tpid_action = bcmVlanTpidActionNone;
    837         action.it_outer = bcmVlanActionNone;
    838         action.ut_outer  = bcmVlanActionNone;
    839     }
    840 
    841     /* sd_tag_action_present
    842      * 0 = NOOP
    843      * 1 = REPLACE_VID_TPID
    844      * 2 = REPLACE_VID_ONLY
    845      * 3 = DELETE
    846      * 4 = REPLACE_VID_PRI_TPID
    847      * 5 = REPLACE_VID_PRI_ONLY
    848      * 6 = REPLACE_PRI_ONLY
    849      * 7 = REPLACE_TPID_ONLY
    850      */
    851     if (sd_tag_action_present == 0){
    852         action.outer_tpid_action = bcmVlanTpidActionNone;
    853         action.ot_outer = bcmVlanActionNone;
    854         action.ot_outer_pkt_prio = bcmVlanActionNone;
    855         action.ot_outer_cfi = bcmVlanActionNone;
    856         action.dt_outer = bcmVlanActionNone;
    857         action.dt_outer_pkt_prio = bcmVlanActionNone;
    858         action.dt_outer_cfi = bcmVlanActionNone;
    859     } else if (sd_tag_action_present == 1) {
    860         action.outer_tpid_action = bcmVlanTpidActionModify;
    861         action.ot_outer = bcmVlanActionReplace;
    862         action.ot_outer_pkt_prio = bcmVlanActionNone;
    863         action.ot_outer_cfi = bcmVlanActionNone;
    864         action.dt_outer = bcmVlanActionReplace;
    865         action.dt_outer_pkt_prio = bcmVlanActionNone;
    866         action.dt_outer_cfi = bcmVlanActionNone;
    867     } else if (sd_tag_action_present == 2) {
    868         action.outer_tpid_action = bcmVlanTpidActionNone;
    869         action.ot_outer = bcmVlanActionReplace;
    870         action.ot_outer_pkt_prio = bcmVlanActionNone;
    871         action.ot_outer_cfi = bcmVlanActionNone;
    872         action.dt_outer = bcmVlanActionReplace;
    873         action.dt_outer_pkt_prio = bcmVlanActionNone;
    874         action.dt_outer_cfi = bcmVlanActionNone;
    875     } else if (sd_tag_action_present == 3) {
    876         action.outer_tpid_action = bcmVlanTpidActionModify;
    877         action.ot_outer = bcmVlanActionDelete;
    878         action.ot_outer_pkt_prio = bcmVlanActionDelete;
    879         action.ot_outer_cfi = bcmVlanActionDelete;
    880         action.dt_outer = bcmVlanActionDelete;
    881         action.dt_outer_pkt_prio = bcmVlanActionDelete;
    882         action.dt_outer_cfi = bcmVlanActionDelete;
    883     } else if (sd_tag_action_present == 4) {
    884         action.outer_tpid_action = bcmVlanTpidActionModify;
    885         action.ot_outer = bcmVlanActionReplace;
    886         action.ot_outer_pkt_prio = bcmVlanActionReplace;
    887         action.ot_outer_cfi = bcmVlanActionReplace;
    888         action.dt_outer = bcmVlanActionReplace;
    889         action.dt_outer_pkt_prio = bcmVlanActionReplace;
    890         action.dt_outer_cfi = bcmVlanActionReplace;
    891     } else if (sd_tag_action_present == 5) {
    892         action.outer_tpid_action = bcmVlanTpidActionNone;
    893         action.ot_outer = bcmVlanActionReplace;
    894         action.ot_outer_pkt_prio = bcmVlanActionReplace;
    895         action.ot_outer_cfi = bcmVlanActionReplace;
    896         action.dt_outer = bcmVlanActionReplace;
    897         action.dt_outer_pkt_prio = bcmVlanActionReplace;
    898         action.dt_outer_cfi = bcmVlanActionReplace;
    899     } else if (sd_tag_action_present == 6) {
    900         action.outer_tpid_action = bcmVlanTpidActionNone;
    901         action.ot_outer = bcmVlanActionNone;
    902         action.ot_outer_pkt_prio = bcmVlanActionReplace;
    903         action.ot_outer_cfi = bcmVlanActionReplace;
    904         action.dt_outer = bcmVlanActionNone;
    905         action.dt_outer_pkt_prio = bcmVlanActionReplace;
    906         action.dt_outer_cfi = bcmVlanActionReplace;
    907     } else if (sd_tag_action_present == 7) {
    908         action.outer_tpid_action = bcmVlanTpidActionModify;
    909         action.ot_outer = bcmVlanActionNone;
    910         action.ot_outer_pkt_prio = bcmVlanActionNone;
    911         action.ot_outer_cfi = bcmVlanActionNone;
    912         action.dt_outer = bcmVlanActionNone;
    913         action.dt_outer_pkt_prio = bcmVlanActionNone;
    914         action.dt_outer_cfi = bcmVlanActionNone;
    915     } else  {
    916         /* default as 0 */
    917         action.outer_tpid_action = bcmVlanTpidActionNone;
    918         action.ot_outer = bcmVlanActionNone;
    919         action.ot_outer_pkt_prio = bcmVlanActionNone;
    920         action.dt_outer = bcmVlanActionNone;
    921         action.dt_outer_pkt_prio = bcmVlanActionNone;
    922     }
    923 
    924     rv = _bcm_trx_egr_vlan_action_profile_entry_add(unit, &action, &new_index);
    925     if (rv != BCM_E_NONE) {
    926         return rv;
    927     }
    928     if (new_index != *index) {
    929         if (*index != 0) {
    930             rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, *index);
    931         }
    932         *index = new_index;
    933     }
    934 
    935     return rv;
    936 }
    937 
    938 /*
    939  * Function:
    940  *      _bcm_td3_sd_tag_action_get
    941  *
    942  * Purpose:
    943  *      get sd_tag action based on vlan profile index
    944  *
    945  * Parameters:
    946  *     unit  - (IN) BCM device number.
    947  *     index - (IN) Profile index
    948  *     int  - (OUT) sd_tag_action_present
    949  *     int  - (OUT) sd_tag_action_not_present
    950  *
    951  * Returns:
    952  *      BCM_E_XXXs
    953  */
    954 int
    955 _bcm_td3_sd_tag_action_get(
    956         int unit,
    957         uint32 index,
    958         int *sd_tag_action_present,
    959         int *sd_tag_action_not_present)
    960 {
    961     bcm_vlan_action_set_t action;
    962 
    963     bcm_vlan_action_set_t_init(&action);
    964 
    965     _bcm_trx_egr_vlan_action_profile_entry_get(unit, &action, index);
    966 
    967     if ((action.it_outer == bcmVlanActionAdd) &&
    968         (action.ut_outer == bcmVlanActionAdd)) {
    969         *sd_tag_action_not_present = 1;
    970     } else {
    971         *sd_tag_action_not_present = 0;
    972     }
    973 
    974     if ((action.outer_tpid_action == bcmVlanTpidActionNone) &&
    975         (action.ot_outer == bcmVlanActionNone) &&
    976         (action.ot_outer_pkt_prio == bcmVlanActionNone)) {
    977 
    978         *sd_tag_action_present = 0;
    979     } else if ((action.outer_tpid_action == bcmVlanTpidActionModify) &&
    980         (action.ot_outer == bcmVlanActionReplace) &&
    981         (action.ot_outer_pkt_prio == bcmVlanActionNone)) {
    982 
    983         *sd_tag_action_present = 1;
    984     } else if ((action.outer_tpid_action == bcmVlanTpidActionNone) &&
    985         (action.ot_outer == bcmVlanActionReplace) &&
    986         (action.ot_outer_pkt_prio == bcmVlanActionNone)) {
    987 
    988         *sd_tag_action_present = 2;
    989     } else if ((action.outer_tpid_action == bcmVlanTpidActionModify) &&
    990         (action.ot_outer == bcmVlanActionDelete)) {
    991 
    992         *sd_tag_action_present = 3;
    993     } else if ((action.outer_tpid_action == bcmVlanTpidActionModify) &&
    994         (action.ot_outer == bcmVlanActionReplace) &&
    995         (action.ot_outer_pkt_prio == bcmVlanActionReplace)) {
    996 
    997         *sd_tag_action_present = 4;
    998     } else if ((action.outer_tpid_action == bcmVlanTpidActionNone) &&
    999         (action.ot_outer == bcmVlanActionReplace) &&
   1000         (action.ot_outer_pkt_prio == bcmVlanActionReplace)) {
   1001 
   1002         *sd_tag_action_present = 5;
   1003     } else if ((action.outer_tpid_action == bcmVlanTpidActionNone) &&
   1004         (action.ot_outer == bcmVlanActionNone) &&
   1005         (action.ot_outer_pkt_prio == bcmVlanActionReplace)) {
   1006 
   1007         *sd_tag_action_present = 6;
   1008     } else if ((action.outer_tpid_action == bcmVlanTpidActionModify) &&
   1009         (action.ot_outer == bcmVlanActionNone) &&
   1010         (action.ot_outer_pkt_prio == bcmVlanActionNone)) {
   1011 
   1012         *sd_tag_action_present = 7;
   1013     } else  {
   1014         /* default as 0 */
   1015         *sd_tag_action_present = 0;
   1016     }
   1017 
   1018     return BCM_E_NONE;
   1019 }
   1020 
   1021 /*
   1022  * Function:
   1023  *      _bcm_td3_def_vlan_profile_get
   1024  *
   1025  * Purpose:
   1026  *      get vlan profile index to add vlan for untagged packet
   1027  *
   1028  * Parameters:
   1029  *     unit - (IN) BCM device number.
   1030  *     index - (IN, OUT) Profile index
   1031  *
   1032  * Returns:
   1033  *      BCM_E_XXXs
   1034  */
   1035 int
   1036 _bcm_td3_def_vlan_profile_get(
   1037         int unit,
   1038         uint32 *index)
   1039 {
   1040     int rv = BCM_E_NONE;
   1041     bcm_vlan_action_set_t action;
   1042     uint32 new_index = 0;
   1043 
   1044 
   1045     bcm_vlan_action_set_t_init(&action);
   1046 
   1047 
   1048     action.ut_outer  = bcmVlanActionAdd;
   1049 
   1050     rv = _bcm_trx_vlan_action_profile_entry_add(unit, &action, &new_index);
   1051     if (rv != BCM_E_NONE) {
   1052         return rv;
   1053     }
   1054     if (new_index != *index) {
   1055         if ((*index != 0) && (*index != 1)) {
   1056             rv = _bcm_trx_vlan_action_profile_entry_delete(unit, *index);
   1057         }
   1058         *index = new_index;
   1059     }
   1060 
   1061     return rv;
   1062 }
   1063 
   1064 /*
   1065  * Function:
   1066  *      _bcm_td3_vlan_shared_vlan_enable_get
   1067  *
   1068  * Purpose:
   1069  *      get shared vlan enable status
   1070  *
   1071  * Parameters:
   1072  *     unit - (IN) BCM device number.
   1073  *     enable - (OUT) enable status
   1074  *
   1075  * Returns:
   1076  *      BCM_E_XXXs
   1077  */
   1078 int
   1079 _bcm_td3_vlan_shared_vlan_enable_get(int unit, int *enable)
   1080 {
   1081     bcm_vlan_info_t *vi = &vlan_info[unit];
   1082     *enable = vi->shared_vlan_enable;
   1083 
   1084     return BCM_E_NONE;
   1085 }
   1086 
   1087 /*
   1088  * Function:
   1089  *      _bcm_td3_vlan_shared_vlan_enable_set
   1090  *
   1091  * Purpose:
   1092  *      set shared vlan enable status
   1093  *
   1094  * Parameters:
   1095  *     unit - (IN) BCM device number.
   1096  *     enable - (IN) enable status
   1097  *
   1098  * Returns:
   1099  *      BCM_E_XXXs
   1100  */
   1101 int
   1102 _bcm_td3_vlan_shared_vlan_enable_set(int unit, int enable)
   1103 {
   1104     bcm_vlan_info_t *vi = &vlan_info[unit];
   1105     vi->shared_vlan_enable = enable ? 1 : 0;
   1106 
   1107     return BCM_E_NONE;
   1108 }
   1109 
   1110 #endif /* BCM_TRIDENT3_SUPPORT */
   1111