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

mim.c (332395B)


      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:    mim.c
      8  * Purpose: Manages MiM functions
      9  */
     10 
     11 #include <soc/defs.h>
     12 #include <sal/core/libc.h>
     13 #include <shared/bsl.h>
     14 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3)
     15 
     16 #include <soc/drv.h>
     17 #include <soc/scache.h>
     18 #include <soc/hash.h>
     19 #include <soc/util.h>
     20 #include <soc/triumph.h>
     21 
     22 #if defined BCM_METROLITE_SUPPORT
     23 #include <soc/katana2.h>
     24 #endif
     25 
     26 #include <bcm/error.h>
     27 #include <bcm/mim.h>
     28 
     29 #include <bcm_int/esw/mbcm.h>
     30 #include <bcm_int/esw/l3.h>
     31 #include <bcm_int/esw/firebolt.h>
     32 #include <bcm_int/esw/triumph.h>
     33 #include <bcm_int/esw/triumph2.h>
     34 #include <bcm_int/esw/xgs3.h>
     35 #include <bcm_int/esw/mim.h>
     36 #include <bcm_int/common/multicast.h>
     37 #include <bcm_int/esw/virtual.h>
     38 #include <bcm_int/esw/trx.h>
     39 #include <bcm_int/esw/stack.h>
     40 #include <bcm_int/esw/switch.h>
     41 #if defined(BCM_TRIUMPH3_SUPPORT)
     42 #include <bcm_int/esw/triumph3.h>
     43 #endif /* BCM_TRIUMPH3_SUPPORT*/
     44 
     45 #include <bcm_int/esw_dispatch.h>
     46 #include <bcm_int/api_xlate_port.h>
     47 #include <bcm_int/esw/failover.h>
     48 
     49 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
     50 #include <bcm_int/esw/policer.h>
     51 #endif
     52 #if defined(BCM_KATANA2_SUPPORT)
     53 #include <bcm_int/esw/katana2.h>
     54 #endif
     55 #if defined(BCM_TRIDENT2_SUPPORT)
     56 #include <bcm_int/esw/trident2.h>
     57 #endif /* BCM_TRIDENT2_SUPPORT */
     58 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
     59 #include <bcm_int/esw/trident2plus.h>
     60 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
     61 #if defined(BCM_TRIDENT3_SUPPORT)
     62 #include <soc/esw/cancun.h>
     63 #include <bcm_int/esw/trident3.h>
     64 #endif
     65 #if defined(BCM_TOMAHAWK2_SUPPORT)
     66 #include <bcm_int/esw/tomahawk2.h>
     67 #endif /* BCM_TOMAHAWK2_SUPPORT */
     68 
     69 _bcm_tr2_mim_bookkeeping_t  _bcm_tr2_mim_bk_info[BCM_MAX_NUM_UNITS];
     70 
     71 /* Flag to check initialized status */
     72 STATIC int mim_initialized[BCM_MAX_NUM_UNITS];
     73 
     74 STATIC sal_mutex_t _mim_mutex[BCM_MAX_NUM_UNITS] = {NULL};
     75 
     76 #define L3_INFO(unit)    (&_bcm_l3_bk_info[unit])
     77 #define MIM_INFO(_unit_) (&_bcm_tr2_mim_bk_info[_unit_])
     78 #define VPN_ISID(_unit_, _vfi_)  \
     79         (_bcm_tr2_mim_bk_info[_unit_].vpn_info[_vfi_].isid)
     80 
     81 #define MIM_INIT(unit)                                    \
     82     do {                                                  \
     83         if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {  \
     84             return BCM_E_UNIT;                            \
     85         }                                                 \
     86         if (!mim_initialized[unit]) {                     \
     87             return BCM_E_INIT;                            \
     88         }                                                 \
     89     } while (0)
     90 
     91 /* 
     92  * MIM module lock
     93  */
     94 #define MIM_LOCK(unit) \
     95         sal_mutex_take(_mim_mutex[unit], sal_mutex_FOREVER);
     96 
     97 #define MIM_UNLOCK(unit) \
     98         sal_mutex_give(_mim_mutex[unit]); 
     99 
    100 /*
    101  * L3 interface usage bitmap operations
    102  */
    103 #define _BCM_MIM_INTF_USED_GET(_u_, _intf_) \
    104         SHR_BITGET(MIM_INFO(_u_)->intf_bitmap, (_intf_))
    105 #define _BCM_MIM_INTF_USED_SET(_u_, _intf_) \
    106         SHR_BITSET(MIM_INFO((_u_))->intf_bitmap, (_intf_))
    107 #define _BCM_MIM_INTF_USED_CLR(_u_, _intf_) \
    108         SHR_BITCLR(MIM_INFO((_u_))->intf_bitmap, (_intf_))
    109 
    110 #ifdef BCM_WARM_BOOT_SUPPORT
    111 #define MEM_CHUNK_MAX_ENTRY 1024
    112 
    113 #define _BCM_CHUNK_GET_INDEX(unit, mem, mem_index ) \
    114     (mem_index - (mem_index / MEM_CHUNK_MAX_ENTRY) * MEM_CHUNK_MAX_ENTRY)
    115 
    116 #define _BCM_CHUNK_GET_MEM_BUFFER(chunk_buf) \
    117         ((void*)((int32*)chunk_buf + 1))
    118 
    119 #define _BCM_CHUNK_SET_INDEX_OFFSET(chunk_buf, val) \
    120         (*((int32*)chunk_buf) = val)
    121 #define _BCM_CHUNK_GET_INDEX_OFFSET(chunk_buf) \
    122         (*((int32*)(chunk_buf)))
    123 
    124 STATIC int _bcm_chunk_memory_alloc(int unit, soc_mem_t mem, void **mem_buf);
    125 STATIC int _bcm_chunk_get_mem_entry(int unit, soc_mem_t mem, int index, 
    126                                     void *chunk_buf, void **mem_entry);
    127 #endif
    128 STATIC int _bcm_tr2_mim_port_delete(int unit, bcm_vpn_t vpn, int vp);
    129 STATIC int _bcm_tr2_mim_egr_vxlt_sd_tag_actions_get(int unit,
    130                                                     bcm_mim_port_t *mim_port,
    131                                                     bcm_mim_vpn_config_t *vpn_info,
    132                                                     uint32 *egr_vlan_xlate_entry);
    133 
    134 int _bcm_tr2_mim_egr_vxlt_sd_tag_actions(int unit, bcm_mim_port_t *mim_port,
    135                                          bcm_mim_vpn_config_t *vpn_info,
    136                                          uint32 *evxlt_entry);
    137 int _bcm_tr2_mim_egr_vxlt_sd_tag_actions_delete(int unit,
    138                                 uint32 *egr_vlan_xlate_entry);
    139 typedef uint32 MEM_ENTRY_T[SOC_MAX_MEM_FIELD_WORDS];
    140 
    141 /*
    142  * Function:
    143  *      bcm_mim_enable
    144  * Purpose:
    145  *      Enable/disable MiM function.
    146  * Parameters:
    147  *      unit - SOC unit number.
    148  *      enable - TRUE: enable MiM support; FALSE: disable MiM support.
    149  * Returns:
    150  *      BCM_E_XXX.
    151  */
    152 STATIC int
    153 bcm_tr2_mim_enable(int unit, int enable)
    154 {
    155     int port;
    156     int idx;
    157     uint32 ptab[SOC_MAX_MEM_WORDS];
    158     bcm_pbmp_t port_pbmp;
    159     soc_mem_t port_mem;
    160 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_KATANA_SUPPORT)
    161     uint32 flags;
    162 #endif
    163 
    164 #if defined(BCM_TRIDENT3_SUPPORT)
    165     if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) {
    166         port_mem = ING_DEVICE_PORTm;
    167     } else
    168 #endif
    169     {
    170         port_mem = PORT_TABm;
    171     }
    172 
    173 
    174     BCM_PBMP_CLEAR(port_pbmp);
    175     BCM_PBMP_ASSIGN(port_pbmp, PBMP_PORT_ALL(unit));
    176 #ifdef BCM_KATANA2_SUPPORT
    177     if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) {
    178         BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &port_pbmp));
    179     }
    180     if (soc_feature(unit, soc_feature_linkphy_coe) ||
    181         soc_feature(unit, soc_feature_subtag_coe)) {
    182         _bcm_kt2_subport_pbmp_update(unit, &port_pbmp);
    183     }
    184 #endif
    185 
    186     PBMP_ITER(port_pbmp, port) {
    187         /* No MiM lookup on stacking ports. */
    188         if (IS_ST_PORT(unit, port)) {
    189             continue;
    190         }
    191         /* wait for SDK-95379, modfiy this to unblock others. */
    192 #if defined(BCM_TRIDENT3_SUPPORT)
    193         if (!SOC_IS_TRIDENT3X(unit))
    194 #endif
    195         {
    196             BCM_IF_ERROR_RETURN
    197                 (bcm_esw_port_control_set(unit, port, bcmPortControlMacInMac,
    198                                       (enable) ? 1 : 0));
    199         }
    200     }
    201     /* Enable MC_TERM_ENABLE on loopback port */
    202 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_KATANA_SUPPORT)
    203     if (SOC_IS_ENDURO(unit) || SOC_IS_KATANAX(unit)) {
    204         PBMP_ALL_ITER(unit, port) {
    205             if (IS_LB_PORT(unit, port)) {
    206                 BCM_IF_ERROR_RETURN
    207                     (soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, port, &ptab));
    208                 soc_PORT_TABm_field32_set(unit, &ptab, 
    209                               MIM_MC_TERM_ENABLEf, (enable) ? 1 : 0);    
    210                 BCM_IF_ERROR_RETURN
    211                     (soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, port, &ptab));
    212                 /* 
    213                  * The loopback port is subjected to ingress/egress vlan +
    214                  * spanning tree check in Enduro.
    215                  *  - Disable VLAN membership check for loopback port. 
    216                  *  - Set STG state to forwarding.
    217                  */
    218                 BCM_IF_ERROR_RETURN
    219                     (bcm_esw_port_vlan_member_get(unit, port, &flags));
    220                 flags &= ~(BCM_PORT_VLAN_MEMBER_EGRESS);
    221                 BCM_IF_ERROR_RETURN
    222                     (bcm_esw_port_vlan_member_set(unit, port, flags));
    223                 BCM_IF_ERROR_RETURN
    224                     (bcm_esw_port_stp_set(unit, port, BCM_STG_STP_FORWARD));
    225             }
    226         }
    227     } else 
    228 #endif /* BCM_ENDURO_SUPPORT */
    229     {
    230     if (SOC_IS_TRIUMPH3(unit)) {
    231         /* Triumph3 nlf passthru loopback port */
    232         idx = AXP_PORT(unit, SOC_AXP_NLF_PASSTHRU);
    233 #if defined(BCM_TRIDENT_SUPPORT)
    234     } else if (SOC_IS_TD_TT(unit)) {
    235         idx = LB_PORT(unit);        
    236 #endif /* BCM_TRIDENT_SUPPORT */ 
    237     } else {
    238         idx = 54;
    239     }
    240     BCM_IF_ERROR_RETURN
    241         (soc_mem_read(unit, port_mem, MEM_BLOCK_ANY, idx, ptab));
    242     /* For TD3, it is done by c-code. We don't have to configure anything */
    243 #if defined(BCM_TRIDENT3_SUPPORT)
    244     if (!SOC_IS_TRIDENT3X(unit))
    245 #endif
    246     {
    247         soc_mem_field32_set(unit, port_mem, ptab, 
    248                  MIM_MC_TERM_ENABLEf, (enable) ? 1 : 0);
    249     }
    250     BCM_IF_ERROR_RETURN
    251         (soc_mem_write(unit, port_mem, MEM_BLOCK_ALL, idx, ptab));
    252     }
    253 
    254     return BCM_E_NONE;
    255 }
    256 
    257 /*
    258  * Function:
    259  *      _bcm_tr2_mim_free_resources
    260  * Purpose:
    261  *      Free all allocated tables and memory
    262  * Parameters:
    263  *      unit - SOC unit number
    264  * Returns:
    265  *      Nothing
    266  */
    267 STATIC void
    268 _bcm_tr2_mim_free_resources(int unit)
    269 {
    270     _bcm_tr2_mim_bookkeeping_t *mim_info = MIM_INFO(unit);
    271 
    272     if (_mim_mutex[unit]) {
    273         sal_mutex_destroy(_mim_mutex[unit]);
    274         _mim_mutex[unit] = NULL;
    275     } 
    276     if (mim_info->vpn_info) {
    277         sal_free(mim_info->vpn_info);
    278         mim_info->vpn_info = NULL;
    279     }
    280     if (mim_info->port_info) {
    281         sal_free(mim_info->port_info);
    282         mim_info->port_info = NULL;
    283     }
    284     if (mim_info->intf_bitmap) {
    285         sal_free(mim_info->intf_bitmap);
    286         mim_info->intf_bitmap = NULL;
    287     }
    288 }
    289 
    290 /*
    291  * Function:
    292  *      _bcm_tr2_mim_hw_clear
    293  * Purpose:
    294  *     Perform HW tables clean up for MiM module.
    295  * Parameters:
    296  *      unit     - Device Number
    297  * Returns:
    298  *      BCM_E_XXX
    299  */
    300 STATIC int
    301 _bcm_tr2_mim_hw_clear(int unit)
    302 {
    303     int rv, rv_error = BCM_E_NONE;
    304 
    305     rv = bcm_tr2_mim_enable(unit, FALSE);
    306     if (BCM_FAILURE(rv)) {
    307         rv_error = rv;
    308     }
    309 
    310     /* Destroy all VPNs */
    311     rv = bcm_tr2_mim_vpn_destroy_all(unit);
    312     if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) {
    313         rv_error = rv;
    314     }
    315 
    316     return rv_error;
    317 }
    318 
    319 /*
    320  * Function:
    321  *      bcm_mim_detach
    322  * Purpose:
    323  *      Detach the MIM software module
    324  * Parameters:
    325  *      unit     - Device Number
    326  * Returns:
    327  *      BCM_E_XXX
    328  */
    329 int 
    330 bcm_tr2_mim_detach(int unit)
    331 {
    332     int rv = BCM_E_NONE;
    333 
    334     if (mim_initialized[unit] == FALSE) {
    335         return BCM_E_NONE;
    336     } 
    337 
    338     if (0 == SOC_HW_ACCESS_DISABLE(unit)) {
    339         rv = _bcm_tr2_mim_hw_clear(unit);
    340     }
    341 
    342     _bcm_tr2_mim_free_resources(unit);
    343     mim_initialized[unit] = FALSE;
    344     return rv;
    345 }
    346 
    347 #ifdef BCM_WARM_BOOT_SUPPORT
    348 STATIC void
    349 _bcm_tr2_mim_port_flex_stat_recover(int unit, source_vp_entry_t *source_vp, 
    350                                     int index)
    351 {
    352     int fs_idx;
    353     if (soc_feature(unit, soc_feature_gport_service_counters)) {
    354         if (soc_mem_field_valid(unit, SOURCE_VPm, VINTF_CTR_IDXf)) {
    355             fs_idx = soc_mem_field32_get(unit, SOURCE_VPm, source_vp,
    356                                          VINTF_CTR_IDXf);
    357             if (fs_idx) {
    358                 BCM_GPORT_MIM_PORT_ID_SET(index, index);
    359                 _bcm_esw_flex_stat_reinit_add(unit, _bcmFlexStatTypeGport,
    360                                               fs_idx, index);
    361             }
    362         }
    363     }
    364     return;
    365 }
    366 
    367 STATIC void
    368 _bcm_tr2_mim_vpn_flex_stat_recover(int unit, vfi_entry_t *vfi, 
    369                                    int index)
    370 {
    371     int fs_idx;
    372     if (soc_feature(unit, soc_feature_gport_service_counters)) {
    373         if (soc_mem_field_valid(unit, VFIm, SERVICE_CTR_IDXf)) {
    374             fs_idx = soc_mem_field32_get(unit, VFIm, vfi,
    375                                          SERVICE_CTR_IDXf);
    376             if (fs_idx) {
    377                 _BCM_MIM_VPN_SET(index, _BCM_MIM_VPN_TYPE_MIM, index);
    378                 _bcm_esw_flex_stat_reinit_add(unit, _bcmFlexStatTypeService,
    379                                               fs_idx, index);
    380             }
    381         }
    382     }
    383     return;
    384 }
    385 
    386 STATIC int
    387 _bcm_tr2_mim_source_vp_tpid_recover(int unit, source_vp_entry_t *source_vp, int vp)
    388 {
    389     int tpid_enable, index, rv = BCM_E_NONE;
    390     if (soc_SOURCE_VPm_field32_get(unit, source_vp, SD_TAG_MODEf) == 1) {
    391 #if defined(BCM_TRIDENT3_SUPPORT)
    392         if (SOC_IS_TRIDENT3X(unit)) {
    393             uint32 svp1[SOC_MAX_MEM_WORDS] = {0};
    394             rv = READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, &svp1);
    395             if (rv < 0) {
    396                 return rv;
    397             }
    398             tpid_enable = soc_SVP_ATTRS_1m_field32_get(unit, svp1, TPID_ENABLEf);
    399         } else
    400 #endif
    401         {
    402             tpid_enable = soc_SOURCE_VPm_field32_get(unit, source_vp, TPID_ENABLEf);
    403         }
    404         for (index = 0; index < 4; index++) {
    405             if (tpid_enable & (1 << index)) {
    406                 rv = _bcm_fb2_outer_tpid_tab_ref_count_add(unit, index, 1);
    407                 break;
    408             }
    409         }
    410     }  
    411     return rv;
    412 }
    413 
    414 STATIC int
    415 _bcm_tr2_mim_egr_vxlt_tpid_recover(int unit,  
    416                                    uint32 *egr_vlan_xlate)
    417 {
    418     int tpid_enable, index, rv = BCM_E_NONE;
    419     soc_mem_t  hw_mem;
    420 
    421 #if defined(BCM_TRIDENT3_SUPPORT)
    422     if (soc_feature(unit, soc_feature_base_valid)) {
    423         hw_mem = EGR_VLAN_XLATE_1_DOUBLEm;
    424     } else
    425 #endif
    426     {
    427         hw_mem = EGR_VLAN_XLATEm;
    428     }
    429 
    430     if ((soc_mem_field32_get(unit, hw_mem, egr_vlan_xlate, 
    431          MIM_ISID__SD_TAG_ACTION_IF_NOT_PRESENTf) == 1) || 
    432         (soc_mem_field32_get(unit, hw_mem, egr_vlan_xlate,
    433          MIM_ISID__SD_TAG_ACTION_IF_PRESENTf) == 1)
    434 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
    435          || (soc_mem_field32_get(unit, hw_mem, egr_vlan_xlate,
    436          MIM_ISID__SD_TAG_ACTION_IF_PRESENTf) == 0x7)
    437 #endif
    438          ) {
    439         /* BCM_MIM_PORT_EGRESS_SERVICE_VLAN_TPID_REPLACE or 
    440            BCM_MIM_PORT_EGRESS_SERVICE_VLAN_ADD */ 
    441         tpid_enable = soc_mem_field32_get(unit, hw_mem, egr_vlan_xlate, 
    442                                                  MIM_ISID__SD_TAG_TPID_INDEXf);
    443         if (SOC_IS_TRIDENT3X(unit)) {
    444             for (index = 0; index < 4; index++) {
    445                 if (tpid_enable & (1 << index)) {
    446                     rv = _bcm_fb2_outer_tpid_tab_ref_count_add(unit, index, 1);
    447                     break;
    448                 }
    449             }
    450         } else {
    451             rv = _bcm_fb2_outer_tpid_tab_ref_count_add(unit, tpid_enable, 1);
    452         }
    453     }  
    454     return rv;
    455 }
    456 
    457 STATIC int
    458 _bcm_tr2_mim_egr_nh_tpid_recover(int unit,  
    459                                  egr_l3_next_hop_entry_t *egr_l3_next_hop)
    460 {
    461     int index, tpid_idx, rv = BCM_E_NONE;
    462     if ((soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_l3_next_hop, 
    463          SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf) == 1) || 
    464         (soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_l3_next_hop, 
    465          SD_TAG__SD_TAG_ACTION_IF_PRESENTf) == 1)
    466 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
    467          ||(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_l3_next_hop,
    468          SD_TAG__SD_TAG_ACTION_IF_PRESENTf) == 0x7)
    469 #endif
    470          ) {
    471         /* BCM_MIM_PORT_EGRESS_SERVICE_VLAN_TPID_REPLACE or 
    472            BCM_MIM_PORT_EGRESS_SERVICE_VLAN_ADD */ 
    473         tpid_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_l3_next_hop, 
    474                                                  SD_TAG__SD_TAG_TPID_INDEXf);
    475         if (SOC_IS_TRIDENT3X(unit)) {
    476             for (index = 0; index < 4; index++) {
    477                 if (tpid_idx & (1 << index)) {
    478                     rv = _bcm_fb2_outer_tpid_tab_ref_count_add(unit, index, 1);
    479                     break;
    480                 }
    481             }
    482         } else {
    483             rv = _bcm_fb2_outer_tpid_tab_ref_count_add(unit, tpid_idx, 1);
    484         }
    485     }  
    486     return rv;
    487 }
    488 
    489 STATIC int
    490 _bcm_tr2_mim_port_associated_data_recover(int unit, int vp, int stable_size)
    491 {
    492     int idx, nh_index, macda_idx, intf_num, rv = BCM_E_NONE;
    493     uint32 nh_flags, port_flags;
    494     ing_l3_next_hop_entry_t ing_nh_entry;
    495     egr_l3_next_hop_entry_t egr_nh_entry;
    496     ing_dvp_table_entry_t ing_dvp_entry;
    497     bcm_module_t mod_in, mod_out;
    498     bcm_port_t port_in, port_out, phys_port;
    499     bcm_trunk_t trunk_id;
    500     bcm_l3_egress_t nh_info;
    501     _bcm_port_info_t *info;
    502 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
    503     bcm_port_t      local_member_array[SOC_MAX_NUM_PP_PORTS];
    504     int             max_num_ports = SOC_MAX_NUM_PP_PORTS;
    505 #else
    506     bcm_port_t      local_member_array[SOC_MAX_NUM_PORTS];
    507     int             max_num_ports = SOC_MAX_NUM_PORTS;
    508 #endif
    509     int local_member_count;
    510     int entry_type = 0;
    511     int is_trunk = 0;
    512 
    513     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_DVP_TABLEm, MEM_BLOCK_ANY, 
    514                                      vp, &ing_dvp_entry));
    515     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &ing_dvp_entry, 
    516                                               NEXT_HOP_INDEXf);
    517     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
    518                                      nh_index, &ing_nh_entry));
    519     BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
    520                                      nh_index, &egr_nh_entry));
    521 
    522     bcm_l3_egress_t_init(&nh_info);
    523 
    524     nh_flags = _BCM_L3_SHR_UPDATE | _BCM_L3_SHR_WRITE_DISABLE | 
    525                _BCM_L3_SHR_WITH_ID;
    526     rv = bcm_xgs3_nh_add(unit, nh_flags, &nh_info, &nh_index);
    527     BCM_IF_ERROR_RETURN(rv);
    528 
    529     if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh_entry, 
    530                                          ENTRY_TYPEf) == 0x2) {
    531         if (soc_feature(unit, soc_feature_generic_dest)) {
    532             uint32 dt, dv;
    533             dv = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm,
    534                     &ing_nh_entry, DESTINATIONf, &dt);
    535             if (dt == SOC_MEM_FIF_DEST_LAG) {
    536                 /* Trunk group */
    537                 trunk_id = dv & SOC_MEM_FIF_DGPP_TGID_MASK;
    538                 is_trunk = 1;
    539             } else {
    540                 port_in = dv & SOC_MEM_FIF_DGPP_PORT_MASK;
    541                 mod_in = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
    542                           SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
    543             }
    544         } else {
    545             if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh_entry, Tf)) {
    546                 trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh_entry, TGIDf);
    547                 is_trunk = 1;
    548             } else {
    549                 mod_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh_entry, MODULE_IDf);
    550                 port_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh_entry, PORT_NUMf);
    551             }
    552         }
    553 
    554         /* Type is SVP */
    555         if (is_trunk) {
    556             MIM_INFO(unit)->port_info[vp].modid = -1;
    557             MIM_INFO(unit)->port_info[vp].port = -1;
    558             MIM_INFO(unit)->port_info[vp].tgid = trunk_id;
    559             /* Update each local physical port's SW state */
    560             if (stable_size == 0) {
    561                 /* When persistent storage is available, this state is recovered
    562                    in the port module */
    563                 rv = _bcm_esw_trunk_local_members_get(unit, trunk_id,
    564                         max_num_ports, local_member_array, &local_member_count);
    565                 BCM_IF_ERROR_RETURN(rv);
    566                 for (idx = 0; idx < local_member_count; idx++) {
    567                     _bcm_port_info_access(unit, local_member_array[idx], &info);
    568                     info->vp_count++;
    569                     BCM_IF_ERROR_RETURN(
    570                         bcm_esw_port_vlan_member_get(
    571                             unit, local_member_array[idx], &port_flags));
    572                     BCM_IF_ERROR_RETURN(
    573                         bcm_esw_port_vlan_member_set(
    574                             unit, local_member_array[idx], port_flags));
    575                 }
    576             }
    577         } else {
    578             rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
    579                                         mod_in, port_in, &mod_out, &port_out);
    580             MIM_INFO(unit)->port_info[vp].modid = mod_out;
    581             MIM_INFO(unit)->port_info[vp].port = port_out;
    582             MIM_INFO(unit)->port_info[vp].tgid = -1;
    583             /* Update the physical port's SW state */
    584             if (stable_size == 0) {
    585                 /* When persistent storage is available, this state is recovered
    586                    in the port module */
    587                 phys_port = MIM_INFO(unit)->port_info[vp].port; 
    588                 if (soc_feature(unit, soc_feature_sysport_remap)) { 
    589                     BCM_XLATE_SYSPORT_S2P(unit, &phys_port); 
    590                 }
    591                 _bcm_port_info_access(unit, phys_port, &info);
    592                 info->vp_count++;
    593                 BCM_IF_ERROR_RETURN(
    594                     bcm_esw_port_vlan_member_get(unit, phys_port, &port_flags));
    595                 BCM_IF_ERROR_RETURN(
    596                     bcm_esw_port_vlan_member_set(unit, phys_port, port_flags));
    597             }
    598         }
    599     } else {
    600         return BCM_E_INTERNAL; /* Should never happen */
    601     }
    602 
    603 #if defined(BCM_TRIDENT3_SUPPORT)
    604 	if (SOC_IS_TRIDENT3X(unit)) {
    605         entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
    606 			&egr_nh_entry, DATA_TYPEf);
    607 	} else
    608 #endif /* BCM_TRIDENT3_SUPPORT */
    609 	{
    610 	    entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
    611 			&egr_nh_entry, ENTRY_TYPEf);
    612 	}
    613 
    614     if (entry_type == 2) {
    615         /* SD TAG view - recover TPID reference counts */
    616         rv = _bcm_tr2_mim_egr_nh_tpid_recover(unit, &egr_nh_entry);
    617         BCM_IF_ERROR_RETURN(rv);
    618     }
    619     if (entry_type == 3) {
    620         /* MIM view - recover MACDA profile and interface reference counts */
    621         macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get
    622                         (unit, &egr_nh_entry, MIM__MAC_DA_PROFILE_INDEXf);
    623         _bcm_common_profile_mem_ref_cnt_update(unit, EGR_MAC_DA_PROFILEm, 
    624                                                macda_idx, 1);
    625         intf_num = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry,
    626                                                     MIM__INTF_NUMf);
    627         if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, MIM__ISID_LOOKUP_TYPEf)) {
    628             if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry,
    629                                                   MIM__ISID_LOOKUP_TYPEf) == 0) {
    630                 MIM_INFO(unit)->port_info[vp].flags = _BCM_MIM_PORT_TYPE_NETWORK;
    631             } else {
    632                 MIM_INFO(unit)->port_info[vp].flags = _BCM_MIM_PORT_TYPE_PEER;
    633             }
    634         }
    635 
    636         _BCM_MIM_INTF_USED_SET(unit, intf_num);
    637         BCM_L3_INTF_USED_SET(unit, intf_num);
    638     }
    639 
    640 #if defined(BCM_TRIDENT3_SUPPORT)
    641     if (SOC_IS_TRIDENT3X(unit)) {
    642         soc_mem_t mem = EGR_DVP_ATTRIBUTEm;
    643         egr_dvp_attribute_entry_t egr_dvp_attribute;
    644 
    645         sal_memset(&egr_dvp_attribute, 0, sizeof(egr_dvp_attribute_entry_t));
    646         rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
    647         BCM_IF_ERROR_RETURN(rv);
    648 
    649         if (SOC_MEM_FIELD_VALID(unit, mem, COMMON__EVXLT_KEY_SELf)) {
    650             if (soc_mem_field32_get(unit, mem, &egr_dvp_attribute,
    651                                      COMMON__EVXLT_KEY_SELf) == 0x1) {
    652                 MIM_INFO(unit)->port_info[vp].flags = _BCM_MIM_PORT_TYPE_NETWORK;
    653             } else if (soc_mem_field32_get(unit, mem, &egr_dvp_attribute,
    654                                             COMMON__EVXLT_KEY_SELf) == 0x2) {
    655                 MIM_INFO(unit)->port_info[vp].flags = _BCM_MIM_PORT_TYPE_PEER;
    656             }
    657         }
    658     }
    659 #endif
    660     return rv;
    661 }
    662 
    663 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1, 0)
    664 #define BCM_WB_VERSION_1_1                SOC_SCACHE_VERSION(1, 1)
    665 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_1
    666 
    667 /*
    668  * Function:
    669  *      _bcm_tr2_mim_wb_alloc
    670  *
    671  * Purpose:
    672  *      Alloc persisitent memory for Level 2 Warm Boot scache.
    673  *
    674  * Parameters:
    675  *      unit - (IN) Device Unit Number.
    676  *
    677  * Returns:
    678  *      BCM_E_XXX
    679  */
    680 STATIC int
    681 _bcm_tr2_mim_wb_alloc(int unit)
    682 {
    683     int alloc_sz = 0, rv = BCM_E_NONE;
    684     soc_scache_handle_t scache_handle;
    685     int num_vp = 0;
    686 
    687     uint8 *mim_state;
    688     int stable_size;
    689 
    690     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    691 
    692     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
    693         return BCM_E_NONE;
    694     }
    695 
    696     if (soc_feature(unit, soc_feature_vp_lag)) {
    697         /* Size of Initiator of all VP */
    698         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    699         /*
    700          * Size of All match_key's flags && index && gport(trunk_id, modid, port) &&
    701          * match_vlan && match_inner_vlan && match_label &&
    702          * match_tunnel_srcmac && match_tunnel_vlan.
    703          */
    704         alloc_sz += num_vp * (sizeof(uint32) * 2 + sizeof(bcm_gport_t) +
    705                               sizeof(bcm_vlan_t) * 2 + sizeof(bcm_mpls_label_t) +
    706                               sizeof(bcm_mac_t) + sizeof(bcm_vlan_t));
    707     }
    708 #if defined(BCM_TRIDENT_SUPPORT)
    709     else if (soc_feature(unit, soc_feature_mim_peer_sharing)) {
    710         /* Size of the flags of all ports */
    711         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    712         alloc_sz += num_vp * sizeof(uint32);
    713     }
    714 #endif /* BCM_TRIDENT_SUPPORT */
    715 
    716     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MIM, 0);
    717     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
    718                                  alloc_sz, (uint8**)&mim_state,
    719                                  BCM_WB_DEFAULT_VERSION, NULL);
    720     if (BCM_FAILURE(rv)) {
    721         return rv;
    722     }
    723 
    724     return BCM_E_NONE;
    725 }
    726 
    727 /*
    728  * Function:
    729  *      _bcm_tr2_mim_wb_recover
    730  *
    731  * Purpose:
    732  *      Recover MIM module info for Level 2 Warm Boot from persisitent memory
    733  *
    734  * Warm Boot Version Map:
    735  *      see _bcm_esw_mim_sync definition
    736  *
    737  * Parameters:
    738  *      unit - (IN) Device Unit Number.
    739  *
    740  * Returns:
    741  *      BCM_E_XXX
    742  */
    743 STATIC int
    744 _bcm_tr2_mim_wb_recover(int unit)
    745 {
    746     int i, rv = BCM_E_NONE;
    747     int num_vp = 0;
    748     int stable_size;
    749     uint16 recovered_ver = 0;
    750     bcm_gport_t gport;
    751     uint8 *mim_state = NULL;
    752     soc_scache_handle_t scache_handle;
    753     _bcm_tr2_mim_bookkeeping_t *mim_info;
    754 #if defined(BCM_TRIDENT_SUPPORT)
    755     int additional_scache_size = 0;
    756 #endif /* BCM_TRIDENT_SUPPORT */
    757 
    758     mim_info = MIM_INFO(unit);
    759 
    760     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    761 
    762     /* Requires extended scache support level-2 warmboot */
    763     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
    764         return BCM_E_NONE;
    765     }
    766 
    767     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MIM, 0);
    768     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    769                                  0, &mim_state,
    770                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
    771     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    772         return rv;
    773     } else if (rv == BCM_E_NOT_FOUND) {
    774         return _bcm_tr2_mim_wb_alloc(unit);
    775     }
    776 
    777     if (mim_state == NULL) {
    778         return BCM_E_NONE;
    779     }
    780 
    781     if (soc_feature(unit, soc_feature_vp_lag)) {
    782         /*
    783          * Recover the index && gport(trunk_id, modid, port) && match_vlan &&
    784          * match_inner_vlan of each Match Key.
    785          */
    786         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    787         for (i = 0; i < num_vp; i++) {
    788             sal_memcpy(&(mim_info->port_info[i].flags), mim_state,
    789                        sizeof(uint32));
    790             mim_state += sizeof(uint32);
    791             sal_memcpy(&(mim_info->port_info[i].index), mim_state,
    792                        sizeof(uint32));
    793             mim_state += sizeof(uint32);
    794             sal_memcpy(&gport, mim_state, sizeof(bcm_gport_t));
    795             if (BCM_GPORT_IS_TRUNK(gport)) {
    796                 mim_info->port_info[i].tgid =
    797                     BCM_GPORT_TRUNK_GET(gport);
    798             } else if (BCM_GPORT_IS_MODPORT(gport)) {
    799                 mim_info->port_info[i].modid =
    800                     BCM_GPORT_MODPORT_MODID_GET(gport);
    801                 mim_info->port_info[i].port =
    802                     BCM_GPORT_MODPORT_PORT_GET(gport);
    803             }
    804             mim_state += sizeof(bcm_gport_t);
    805             sal_memcpy(&(mim_info->port_info[i].match_vlan), mim_state,
    806                        sizeof(bcm_vlan_t));
    807             mim_state += sizeof(bcm_vlan_t);
    808             sal_memcpy(&(mim_info->port_info[i].match_inner_vlan),
    809                        mim_state, sizeof(bcm_vlan_t));
    810             mim_state += sizeof(bcm_vlan_t);
    811             sal_memcpy(&(mim_info->port_info[i].match_label), mim_state,
    812                        sizeof(bcm_mpls_label_t));
    813             mim_state += sizeof(bcm_mpls_label_t);
    814             sal_memcpy(&(mim_info->port_info[i].match_tunnel_srcmac),
    815                        mim_state, sizeof(bcm_mac_t));
    816             mim_state += sizeof(bcm_mac_t);
    817             sal_memcpy(&(mim_info->port_info[i].match_tunnel_vlan),
    818                        mim_state, sizeof(bcm_vlan_t));
    819             mim_state += sizeof(bcm_vlan_t);
    820         }
    821     }
    822 #if defined(BCM_TRIDENT_SUPPORT)
    823     else if (soc_feature(unit, soc_feature_mim_peer_sharing)) {
    824         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    825         if (recovered_ver >= BCM_WB_VERSION_1_1) {
    826             /* Recover the flags of each port */
    827             for (i = 0; i < num_vp; i++) {
    828                 sal_memcpy(&(mim_info->port_info[i].flags), mim_state,
    829                            sizeof(uint32));
    830                 mim_state += sizeof(uint32);
    831             }
    832         } else {
    833             additional_scache_size += num_vp * sizeof(uint32);
    834         }
    835     }
    836 
    837     if (additional_scache_size > 0) {
    838         rv = soc_scache_realloc(unit, scache_handle, additional_scache_size);
    839         if(BCM_FAILURE(rv)) {
    840            return rv;
    841         }
    842     }
    843 #endif /* BCM_TRIDENT_SUPPORT */
    844 
    845     return BCM_E_NONE;
    846 }
    847 
    848 /*
    849  * Function:
    850  *      bcm_tr2_mim_sync
    851  *
    852  * Purpose:
    853  *      Record MIM module persistent info for Level 2 Warm Boot
    854  *
    855  * Warm Boot Version Map:
    856  *  WB_VERSION_1_0
    857  *
    858  * Parameters:
    859  *      unit - (IN) Device Unit Number.
    860  *
    861  * Returns:
    862  *      BCM_E_XXX
    863  */
    864 int
    865 bcm_tr2_mim_sync(int unit)
    866 {
    867     int i, num_vp = 0;
    868     int stable_size;
    869     bcm_gport_t gport;
    870     uint8 *mim_state;
    871     soc_scache_handle_t scache_handle;
    872     _bcm_tr2_mim_bookkeeping_t *mim_info;
    873 
    874     /* Parameter validation checks */
    875     if (!SOC_UNIT_VALID(unit)) {
    876         return BCM_E_UNIT;
    877     }
    878 
    879     mim_info = MIM_INFO(unit);
    880 
    881     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    882 
    883     /* Requires extended scache support level-2 warmboot */
    884     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
    885         return BCM_E_NONE;
    886     }
    887 
    888     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MIM, 0);
    889     BCM_IF_ERROR_RETURN(
    890         _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    891                                 0, &mim_state, BCM_WB_DEFAULT_VERSION, NULL));
    892 
    893     if (soc_feature(unit, soc_feature_vp_lag)) {
    894         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    895         /*
    896          * Since we can't recover index && gport(trunk_id, modid, port) &&
    897          * match_vlan && match_inner_vlan from HW if we add this mim port to
    898          * VPLAG, so we need to store it for warmboot recovery. Total is 34*16K.
    899          */
    900         for (i = 0; i < num_vp; i++) {
    901             sal_memcpy(mim_state, &(mim_info->port_info[i].flags), sizeof(uint32));
    902             mim_state += sizeof(uint32);
    903             sal_memcpy(mim_state, &(mim_info->port_info[i].index), sizeof(uint32));
    904             mim_state += sizeof(uint32);
    905             if (mim_info->port_info[i].tgid != -1) {
    906                 BCM_GPORT_TRUNK_SET(gport, mim_info->port_info[i].tgid);
    907             } else if (mim_info->port_info[i].modid != -1) {
    908                 BCM_GPORT_MODPORT_SET(gport,
    909                                       mim_info->port_info[i].modid,
    910                                       mim_info->port_info[i].port);
    911             } else {
    912                 gport = BCM_GPORT_INVALID;
    913             }
    914             sal_memcpy(mim_state, &gport, sizeof(bcm_gport_t));
    915             mim_state += sizeof(bcm_gport_t);
    916             sal_memcpy(mim_state, &(mim_info->port_info[i].match_vlan),
    917                        sizeof(bcm_vlan_t));
    918             mim_state += sizeof(bcm_vlan_t);
    919             sal_memcpy(mim_state, &(mim_info->port_info[i].match_inner_vlan),
    920                        sizeof(bcm_vlan_t));
    921             mim_state += sizeof(bcm_vlan_t);
    922             sal_memcpy(mim_state, &(mim_info->port_info[i].match_label),
    923                        sizeof(bcm_mpls_label_t));
    924             mim_state += sizeof(bcm_mpls_label_t);
    925             sal_memcpy(mim_state, &(mim_info->port_info[i].match_tunnel_srcmac),
    926                        sizeof(bcm_mac_t));
    927             mim_state += sizeof(bcm_mac_t);
    928             sal_memcpy(mim_state, &(mim_info->port_info[i].match_tunnel_vlan),
    929                        sizeof(bcm_vlan_t));
    930             mim_state += sizeof(bcm_vlan_t);
    931         }
    932     }
    933 #if defined(BCM_TRIDENT_SUPPORT)
    934     else if (soc_feature(unit, soc_feature_mim_peer_sharing)) {
    935         /* Store the flags of each port */
    936         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    937         for (i = 0; i < num_vp; i++) {
    938             sal_memcpy(mim_state,
    939                        &(mim_info->port_info[i].flags),sizeof(uint32));
    940             mim_state += sizeof(uint32);
    941         }
    942     }
    943 #endif /* BCM_TRIDENT_SUPPORT */
    944 
    945     return BCM_E_NONE;
    946 }
    947 
    948 /*
    949  * Function:
    950  *      _bcm_tr2_mim_reinit
    951  * Purpose:
    952  *      Warm boot recovery for the MIM software module
    953  * Parameters:
    954  *      unit     - Device Number
    955  * Returns:
    956  *      BCM_E_XXX
    957  */
    958 STATIC int 
    959 _bcm_tr2_mim_reinit(int unit)
    960 {
    961     int rv, i, index_min, index_max, stable_size;
    962     uint32 vfi_entry[SOC_MAX_MEM_WORDS] = {0};
    963     uint32 vfi_1_entry[SOC_MAX_MEM_WORDS] = {0};
    964     int vfi, isid, index, tpid_enable, vp = 0;
    965     uint32 key_type;
    966     uint8 *mpls_entry_buf = NULL; /* MPLS_ENTRY DMA buffer */
    967     MEM_ENTRY_T *mpls_entry;
    968     uint8 *vlan_xlate_buf = NULL; /* VLAN_XLATE DMA buffer */
    969     void * vlan_xlate;
    970     uint8 *egr_vlan_xlate_buf = NULL; /* EGR_VLAN_XLATE DMA buffer */
    971     void * egr_vlan_xlate;
    972     uint8 *source_vp_buf = NULL; /* SOURCE_VP DMA buffer */
    973     source_vp_entry_t *source_vp;
    974     uint8 *source_trunk_map_buf = NULL; /* SOURCE_TRUNK_MAP DMA buffer */
    975     source_trunk_map_table_entry_t *source_trunk_map;
    976     soc_mem_t mpls_mem = MPLS_ENTRYm;
    977     soc_mem_t xlate_mem, egr_xlate_mem = EGR_VLAN_XLATEm;
    978     int         isid_key_type;
    979     void    *mem_entry[1], *mem_buf[1];
    980     _bcm_vp_info_t vp_info;
    981     soc_mem_t vfi_mem;
    982     soc_mem_t vfi_1_mem;
    983 
    984     _bcm_vp_info_init(&vp_info);
    985     vp_info.vp_type = _bcmVpTypeMim;
    986 
    987     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    988 
    989     /* If Level 1 of limited Level 2, proceed only if SOC_WARM_BOOT_MIM
    990      * is set */
    991     if ((stable_size == 0) || SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
    992         if (!SOC_WARM_BOOT_IS_MIM(unit)) {
    993             return BCM_E_NONE;
    994         }
    995     }
    996 
    997 #if defined(BCM_TRIUMPH3_SUPPORT)    
    998     if (SOC_IS_TRIUMPH3(unit)) {
    999         mpls_mem =  MPLS_ENTRY_EXTDm;
   1000         xlate_mem = VLAN_XLATE_EXTDm;
   1001         isid_key_type = 0x18;
   1002     } else
   1003 #endif /* BCM_TRIUMPH3_SUPPORT */
   1004     {
   1005 #if defined(BCM_TRIDENT3_SUPPORT)
   1006        if (soc_feature(unit, soc_feature_base_valid)) {
   1007            egr_xlate_mem = EGR_VLAN_XLATE_1_DOUBLEm;
   1008            xlate_mem = VLAN_XLATE_1_DOUBLEm;
   1009        } else
   1010 #endif
   1011        {
   1012            xlate_mem = VLAN_XLATEm;
   1013        }
   1014        isid_key_type = 0x2;
   1015     }
   1016 
   1017     /* Allocate Chunk Memory buffer for various tables */
   1018     mem_buf[0] = &mpls_entry_buf;
   1019     rv = _bcm_chunk_memory_alloc(unit, mpls_mem, mem_buf[0]);
   1020     if (BCM_FAILURE(rv) || (NULL == mpls_entry_buf)) {
   1021        goto cleanup;
   1022     }
   1023 
   1024     mem_buf[0] = &vlan_xlate_buf;
   1025     rv = _bcm_chunk_memory_alloc(unit, xlate_mem, mem_buf[0]);
   1026     if (BCM_FAILURE(rv) || (NULL == vlan_xlate_buf)) {
   1027        goto cleanup;
   1028     }
   1029 
   1030     mem_buf[0] = &egr_vlan_xlate_buf;
   1031     rv = _bcm_chunk_memory_alloc(unit, egr_xlate_mem, mem_buf[0]);
   1032     if (BCM_FAILURE(rv) || (NULL == egr_vlan_xlate_buf)) {
   1033        goto cleanup;
   1034     }
   1035 
   1036     mem_buf[0] = &source_vp_buf;
   1037     rv = _bcm_chunk_memory_alloc(unit, SOURCE_VPm, mem_buf[0]);
   1038     if (BCM_FAILURE(rv) || (NULL == source_vp_buf)) {
   1039        goto cleanup;
   1040     }
   1041 
   1042     mem_buf[0] = &source_trunk_map_buf;
   1043     rv = _bcm_chunk_memory_alloc(unit, SOURCE_TRUNK_MAP_TABLEm, mem_buf[0]);
   1044     if (BCM_FAILURE(rv) || (NULL == source_trunk_map_buf)) {
   1045        goto cleanup;
   1046     }
   1047 
   1048     
   1049     /* Get all valid VFIs (VPNs) */
   1050     index_min = soc_mem_index_min(unit, mpls_mem);
   1051     index_max = soc_mem_index_max(unit, mpls_mem);
   1052     for (i = index_min; i <= index_max; i++) {
   1053         mem_entry[0] = &mpls_entry;
   1054         rv = _bcm_chunk_get_mem_entry(unit, mpls_mem, i ,
   1055                                       mpls_entry_buf, mem_entry[0]);
   1056         if (BCM_FAILURE(rv) || (NULL == mpls_entry)) {
   1057             goto cleanup;
   1058         }
   1059 
   1060 #if defined(BCM_TRIUMPH3_SUPPORT)    
   1061         if (SOC_IS_TRIUMPH3(unit)) {
   1062             if (soc_mem_field32_get(unit, mpls_mem, mpls_entry, VALID_0f) == 0 
   1063             && soc_mem_field32_get(unit, mpls_mem, mpls_entry, VALID_1f) == 0) {
   1064                 continue;
   1065             }
   1066             
   1067             if (soc_mem_field32_get(unit, mpls_mem, mpls_entry, KEY_TYPE_0f) 
   1068                                             != isid_key_type) {
   1069                 /* MIM_ISID */
   1070                 continue;
   1071             }
   1072         } else
   1073 #endif /* BCM_TRIUMPH3_SUPPORT */
   1074         {
   1075 #if defined(BCM_TRIDENT3_SUPPORT)
   1076             if (soc_feature(unit, soc_feature_base_valid)) {
   1077                 if (soc_mem_field32_get(unit, mpls_mem, mpls_entry, BASE_VALID_0f) != 3) {
   1078                     continue;
   1079                 }
   1080                 if (soc_mem_field32_get(unit, mpls_mem, mpls_entry, BASE_VALID_1f) != 7) {
   1081                     continue;
   1082                 }
   1083             } else
   1084 #endif
   1085             {
   1086                 if (soc_mem_field32_get(unit, mpls_mem, mpls_entry, VALIDf) == 0) {
   1087                     continue;
   1088                 }
   1089             }
   1090 
   1091 #if defined(BCM_TRIDENT_SUPPORT)
   1092             if (soc_feature(unit, soc_feature_mim_peer_sharing) &&
   1093                 (soc_mem_field32_get(unit, mpls_mem,
   1094                                      mpls_entry, KEY_TYPEf) == 0x3)) {
   1095                     /* MIM_ISID_SVP */
   1096                     vp = soc_mem_field32_get(unit, mpls_mem,
   1097                                              mpls_entry, MIM_ISID__SVPf);
   1098                     MIM_INFO(unit)->port_info[vp].vfi_count++;
   1099                     continue;
   1100             }
   1101 #endif /* BCM_TRIDENT_SUPPORT */
   1102 
   1103             if (soc_mem_field32_get(unit, mpls_mem, mpls_entry, KEY_TYPEf) 
   1104                                             != isid_key_type) {
   1105                 /* MIM_ISID */
   1106                 continue;
   1107             }
   1108         }
   1109         vfi = soc_mem_field32_get(unit, mpls_mem, mpls_entry, MIM_ISID__VFIf);
   1110         isid = soc_mem_field32_get(unit, mpls_mem, mpls_entry, MIM_ISID__ISIDf);
   1111         if ((stable_size == 0) || SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   1112             rv = _bcm_vfi_alloc_with_id(unit, VFIm, _bcmVfiTypeMim, vfi);
   1113             if (BCM_FAILURE(rv)) {
   1114                 goto cleanup;
   1115             }
   1116         } else {
   1117             if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   1118                 /* VFI bitmap is recovered by virtual_init */
   1119                 continue;
   1120             }
   1121         }
   1122         VPN_ISID(unit, vfi) = isid;
   1123 
   1124 #if defined(BCM_TRIDENT3_SUPPORT)
   1125         if (SOC_MEM_FIELD_VALID(unit, VFIm, SD_TAG_MODEf)) {
   1126             vfi_mem = VFIm;
   1127             vfi_1_mem = VFI_ATTRS_1m;
   1128         } else
   1129 #endif
   1130         {
   1131             vfi_mem = VFI_1m;
   1132             vfi_1_mem = VFI_1m;
   1133         }
   1134         /* Retrieve TPID reference counts if applicable */
   1135         rv = soc_mem_read(unit, vfi_mem,
   1136                           MEM_BLOCK_ANY, vfi, vfi_entry);
   1137         if (BCM_FAILURE(rv)) {
   1138             goto cleanup;
   1139         }
   1140         
   1141         rv = soc_mem_read(unit, vfi_1_mem,
   1142                           MEM_BLOCK_ANY, vfi, vfi_1_entry);
   1143         if (BCM_FAILURE(rv)) {
   1144             goto cleanup;
   1145         }
   1146 
   1147         if (soc_mem_field32_get(unit, vfi_mem, vfi_entry, SD_TAG_MODEf) == 1) {
   1148             tpid_enable = soc_mem_field32_get(unit, vfi_1_mem, vfi_1_entry, 
   1149                                                  TPID_ENABLEf);
   1150             for (index = 0; index < 4; index++) {
   1151                 if (tpid_enable & (1 << index)) {
   1152                     rv = _bcm_fb2_outer_tpid_tab_ref_count_add(unit, index, 1);
   1153                     break;
   1154                 }
   1155             }
   1156         }  
   1157         /* Retrieve flex stats for the VFI */
   1158         rv = READ_VFIm(unit, MEM_BLOCK_ANY, vfi, vfi_entry);
   1159         if (BCM_FAILURE(rv)) {
   1160             goto cleanup;
   1161         }
   1162         _bcm_tr2_mim_vpn_flex_stat_recover(unit, (void *)vfi_entry, vfi);
   1163     }
   1164 
   1165     /* Get all virtual ports from VLAN_XLATE */
   1166     index_min = soc_mem_index_min(unit, xlate_mem);
   1167     index_max = soc_mem_index_max(unit, xlate_mem);
   1168     for (i = index_min; i <= index_max; i++) {
   1169         mem_entry[0] = &vlan_xlate;
   1170         rv = _bcm_chunk_get_mem_entry(unit, xlate_mem, i ,
   1171                                       vlan_xlate_buf, mem_entry[0]);
   1172         if (BCM_FAILURE(rv) || (NULL == vlan_xlate)) {
   1173             goto cleanup;
   1174         }
   1175  
   1176 #if defined(BCM_TRIUMPH3_SUPPORT)    
   1177         if (SOC_IS_TRIUMPH3(unit)) {
   1178             if (soc_mem_field32_get(unit, xlate_mem, vlan_xlate, VALID_0f) &&
   1179               soc_mem_field32_get(unit, xlate_mem, vlan_xlate, VALID_1f) == 0) {
   1180                 continue;
   1181             }
   1182         } else
   1183 #endif /* BCM_TRIUMPH3_SUPPORT */
   1184         {
   1185 #if defined(BCM_TRIDENT3_SUPPORT)
   1186             if (soc_feature(unit, soc_feature_base_valid)) {
   1187                 if (soc_mem_field32_get(unit, xlate_mem,
   1188                              vlan_xlate, BASE_VALID_0f) != 3) {
   1189                     continue;
   1190                 }
   1191                 if (soc_mem_field32_get(unit, xlate_mem,
   1192                              vlan_xlate, BASE_VALID_1f) != 7) {
   1193                     continue;
   1194                 }
   1195             } else
   1196 #endif
   1197             {
   1198                 if (soc_mem_field32_get(unit, xlate_mem,
   1199                              vlan_xlate, VALIDf) == 0) {
   1200                     continue;
   1201                 }
   1202             }
   1203         }
   1204 
   1205         if (soc_mem_field32_get(unit, xlate_mem, vlan_xlate, MPLS_ACTIONf) != 1) {
   1206             continue; /* Entry is not for an SVP */
   1207         }
   1208 
   1209 #if defined(BCM_TRIUMPH3_SUPPORT)    
   1210         if (SOC_IS_TRIUMPH3(unit)) {
   1211         key_type = soc_mem_field32_get(unit, xlate_mem, vlan_xlate, 
   1212                                        KEY_TYPE_0f);
   1213             if ((key_type != TR3_VLXLT_X_HASH_KEY_TYPE_OVID) &&
   1214                     (key_type != TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID)) {
   1215                 continue;
   1216             }
   1217         } else
   1218 #endif /* BCM_TRIUMPH3_SUPPORT */
   1219         {
   1220             key_type = soc_mem_field32_get(unit, xlate_mem, vlan_xlate, 
   1221                                               KEY_TYPEf);
   1222             if ((key_type != TR_VLXLT_HASH_KEY_TYPE_OVID) &&
   1223                     (key_type != TR_VLXLT_HASH_KEY_TYPE_IVID_OVID)) {
   1224                 continue;
   1225             }
   1226         }
   1227 
   1228         vp = soc_mem_field32_get(unit, xlate_mem, vlan_xlate, SOURCE_VPf);
   1229         if ((stable_size == 0) || SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   1230             vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
   1231             rv = _bcm_vp_used_set(unit, vp, vp_info);
   1232             if (BCM_FAILURE(rv)) {
   1233                 goto cleanup;
   1234             }
   1235         } else {
   1236             if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   1237                 /* VFI bitmap is recovered by virtual_init */
   1238                 continue;
   1239             }
   1240         }
   1241         switch (key_type) {
   1242         case TR_VLXLT_HASH_KEY_TYPE_OVID:
   1243 #if defined(BCM_TRIUMPH3_SUPPORT)    
   1244         case TR3_VLXLT_X_HASH_KEY_TYPE_OVID:
   1245 #endif /* BCM_TRIUMPH3_SUPPORT */
   1246 
   1247             MIM_INFO(unit)->port_info[vp].flags |= 
   1248                                      _BCM_MIM_PORT_TYPE_ACCESS_PORT_VLAN;
   1249             MIM_INFO(unit)->port_info[vp].match_vlan = 
   1250                 soc_mem_field32_get(unit, xlate_mem, vlan_xlate, OVIDf);
   1251             _bcm_tr2_mim_port_match_count_adjust(unit, vp, 1);
   1252             break;
   1253         case TR_VLXLT_HASH_KEY_TYPE_IVID_OVID:
   1254 #if defined(BCM_TRIUMPH3_SUPPORT)    
   1255         case TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID:
   1256 #endif /* BCM_TRIUMPH3_SUPPORT */
   1257 
   1258             MIM_INFO(unit)->port_info[vp].flags |= 
   1259                              _BCM_MIM_PORT_TYPE_ACCESS_PORT_VLAN_STACKED;
   1260             MIM_INFO(unit)->port_info[vp].match_vlan = 
   1261                 soc_mem_field32_get(unit, xlate_mem, vlan_xlate, OVIDf);
   1262             MIM_INFO(unit)->port_info[vp].match_inner_vlan = 
   1263                 soc_mem_field32_get(unit, xlate_mem, vlan_xlate, IVIDf);
   1264             _bcm_tr2_mim_port_match_count_adjust(unit, vp, 1);
   1265             break;
   1266             /* coverity[dead_error_begin] */
   1267         default:
   1268             break; /* Should never happen */
   1269         }
   1270         /* Recover TPID reference counts */
   1271         mem_entry[0] = &source_vp;
   1272         rv = _bcm_chunk_get_mem_entry(unit, SOURCE_VPm, vp ,
   1273                                       source_vp_buf, mem_entry[0]);
   1274         if (BCM_FAILURE(rv) || (NULL == source_vp)) {
   1275             goto cleanup;
   1276         }
   1277 
   1278         rv = _bcm_tr2_mim_source_vp_tpid_recover(unit, source_vp, vp);
   1279         if (BCM_FAILURE(rv)) {
   1280             goto cleanup;
   1281         }
   1282         /* Recover port flex stats */
   1283         _bcm_tr2_mim_port_flex_stat_recover(unit, source_vp, vp);
   1284         /* Recover other port data */
   1285         rv = _bcm_tr2_mim_port_associated_data_recover(unit, vp, stable_size);
   1286         if (BCM_FAILURE(rv)) {
   1287             goto cleanup;
   1288         }
   1289     }
   1290 
   1291     /* Get all virtual ports from MPLS_ENTRY */
   1292     index_min = soc_mem_index_min(unit, mpls_mem);
   1293     index_max = soc_mem_index_max(unit, mpls_mem);
   1294     for (i = index_min; i <= index_max; i++) {
   1295         mem_entry[0] = &mpls_entry;
   1296         rv = _bcm_chunk_get_mem_entry(unit, mpls_mem, i ,
   1297                                       mpls_entry_buf, mem_entry[0]);
   1298         if (BCM_FAILURE(rv) || (NULL == mpls_entry)) {
   1299             goto cleanup;
   1300         }
   1301 
   1302 #if defined(BCM_TRIUMPH3_SUPPORT)    
   1303         if (SOC_IS_TRIUMPH3(unit)) {
   1304             if (soc_mem_field32_get(unit, mpls_mem, mpls_entry, VALID_0f) == 0 
   1305             && soc_mem_field32_get(unit, mpls_mem, mpls_entry, VALID_1f) == 0) {
   1306                 continue;
   1307             }
   1308             key_type = soc_mem_field32_get(unit, mpls_mem, mpls_entry, 
   1309                                            KEY_TYPE_0f);
   1310         } else
   1311 #endif /* BCM_TRIUMPH3_SUPPORT */
   1312         {
   1313 #if defined(BCM_TRIDENT3_SUPPORT)
   1314             if (soc_feature(unit, soc_feature_base_valid)) {
   1315                 if (soc_mem_field32_get(unit, mpls_mem, mpls_entry, BASE_VALID_0f) != 3) {
   1316                     continue;
   1317                 }
   1318                 if (soc_mem_field32_get(unit, mpls_mem, mpls_entry, BASE_VALID_1f) != 7) {
   1319                     continue;
   1320                 }
   1321             } else
   1322 #endif
   1323             {
   1324                 if (soc_mem_field32_get(unit, mpls_mem, mpls_entry, VALIDf) == 0) {
   1325                     continue;
   1326                 }
   1327             }
   1328             key_type = soc_mem_field32_get(unit, mpls_mem, mpls_entry, 
   1329                                                            KEY_TYPEf);
   1330         }
   1331 
   1332         if ((soc_mem_field32_get(unit, mpls_mem, mpls_entry, MPLS_ACTION_IF_BOSf) 
   1333                                          != 1) && (key_type == 0)) {
   1334             continue; /* Not an SVP */
   1335         }
   1336         switch (key_type) {
   1337         case 0: /* MPLS Label */
   1338 #if defined(BCM_TRIUMPH3_SUPPORT)
   1339         case 17:
   1340         case 19:
   1341 #endif /* BCM_TRIUMPH3_SUPPORT */
   1342             vp = soc_mem_field32_get(unit, mpls_mem, mpls_entry, SOURCE_VPf);
   1343             if ((stable_size == 0) || SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   1344                 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
   1345                 rv = _bcm_vp_used_set(unit, vp, vp_info);
   1346                 if (BCM_FAILURE(rv)) {
   1347                     goto cleanup;
   1348                 }
   1349             } else {
   1350                 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   1351                     /* VFI bitmap is recovered by virtual_init */
   1352                     continue;
   1353                 }
   1354             }
   1355             MIM_INFO(unit)->port_info[vp].flags |= 
   1356                              _BCM_MIM_PORT_TYPE_ACCESS_LABEL;
   1357             MIM_INFO(unit)->port_info[vp].match_label = 
   1358                 soc_mem_field32_get(unit, mpls_mem, mpls_entry, MPLS_LABELf);
   1359             break;
   1360         case 1: /* MIM NVP */
   1361 #if defined(BCM_TRIUMPH3_SUPPORT)
   1362         case 23:
   1363 #endif /* BCM_TRIUMPH3_SUPPORT */
   1364             vp = soc_mem_field32_get(unit, mpls_mem, mpls_entry, MIM_NVP__SVPf);
   1365             if ((stable_size != 0) && !SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   1366                 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   1367                     /* VFI bitmap is recovered by virtual_init */
   1368                     continue;
   1369                 }
   1370             }
   1371             soc_mem_mac_addr_get(unit, mpls_mem, mpls_entry, MIM_NVP__BMACSAf, 
   1372                              MIM_INFO(unit)->port_info[vp].match_tunnel_srcmac);
   1373             MIM_INFO(unit)->port_info[vp].match_tunnel_vlan = 
   1374                 soc_mem_field32_get(unit, mpls_mem, mpls_entry, MIM_NVP__BVIDf);
   1375 
   1376             if (SOC_MEM_FIELD_VALID(unit, mpls_mem, MIM_NVP__ISID_LOOKUP_TYPEf)) {
   1377                 if (soc_mem_field32_get(unit, mpls_mem, mpls_entry, 
   1378                                                 MIM_NVP__ISID_LOOKUP_TYPEf)) {
   1379                     MIM_INFO(unit)->port_info[vp].flags |= _BCM_MIM_PORT_TYPE_PEER;
   1380                     vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
   1381                 } else {
   1382                     MIM_INFO(unit)->port_info[vp].flags |= 
   1383                                                         _BCM_MIM_PORT_TYPE_NETWORK;
   1384                     vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
   1385                 }
   1386             }
   1387             rv = _bcm_vp_used_set(unit, vp, vp_info);
   1388             if (BCM_FAILURE(rv)) {
   1389                 goto cleanup;
   1390             }
   1391             break;
   1392         default:
   1393             continue; /* Handled elsewhere */
   1394         }
   1395         /* Recover TPID reference counts */
   1396         mem_entry[0] = &source_vp;
   1397         rv = _bcm_chunk_get_mem_entry(unit, SOURCE_VPm, vp ,
   1398                                       source_vp_buf, mem_entry[0]);
   1399         if (BCM_FAILURE(rv) || (NULL == source_vp)) {
   1400             goto cleanup;
   1401         }
   1402 
   1403         rv = _bcm_tr2_mim_source_vp_tpid_recover(unit, source_vp, vp);
   1404         if (BCM_FAILURE(rv)) {
   1405             goto cleanup;
   1406         }
   1407         /* Recover port flex stats */
   1408         _bcm_tr2_mim_port_flex_stat_recover(unit, source_vp, vp);
   1409         /* Recover other port data */
   1410         rv = _bcm_tr2_mim_port_associated_data_recover(unit, vp, stable_size);
   1411         if (BCM_FAILURE(rv)) {
   1412             goto cleanup;
   1413         }
   1414     }
   1415 
   1416     /* Get all virtual ports from SOURCE_TRUNK_MAP */
   1417     index_min = soc_mem_index_min(unit, SOURCE_TRUNK_MAP_TABLEm);
   1418     index_max = soc_mem_index_max(unit, SOURCE_TRUNK_MAP_TABLEm);
   1419     for (i = index_min; i <= index_max; i++) {
   1420         bcm_module_t modid;
   1421         bcm_port_t port;
   1422         bcm_trunk_t tgid;
   1423         mem_entry[0] = &source_trunk_map;
   1424         rv = _bcm_chunk_get_mem_entry(unit, SOURCE_TRUNK_MAP_TABLEm, i ,
   1425                            source_trunk_map_buf, mem_entry[0]);
   1426         if (BCM_FAILURE(rv) || (NULL == source_trunk_map)) {
   1427             goto cleanup;
   1428         }
   1429 
   1430         vp = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, source_trunk_map, 
   1431                                                      SOURCE_VPf);
   1432         if (vp == 0) {
   1433             continue;
   1434         }
   1435         /* If VP has already been discovered, no need to proceed further */
   1436         /* This can happen for the trunk access case */
   1437         if (MIM_INFO(unit)->port_info[vp].flags != 0) {
   1438             continue;
   1439         }
   1440         if ((stable_size == 0) || SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   1441             vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
   1442             rv = _bcm_vp_used_set(unit, vp, vp_info);
   1443             if (BCM_FAILURE(rv)) {
   1444                 goto cleanup;
   1445             }
   1446         } else {
   1447             if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   1448                 /* VFI bitmap is recovered by virtual_init */
   1449                 continue;
   1450             }
   1451         }
   1452         if (soc_feature(unit, soc_feature_vp_lag)) {
   1453             modid = SOC_IS_ENDURO(unit) ? i / 64 : i / SOC_PORT_ADDR_MAX(unit);
   1454             port = SOC_IS_ENDURO(unit) ? i % 64 : i % SOC_PORT_ADDR_MAX(unit);
   1455             rv = _bcm_esw_trunk_port_property_get(unit, modid, port, &tgid);
   1456             if (BCM_FAILURE(rv) && (tgid != -1)) {
   1457                 goto cleanup;
   1458             }
   1459             if (tgid == -1) {
   1460                 MIM_INFO(unit)->port_info[vp].flags |=
   1461                     _BCM_MIM_PORT_TYPE_ACCESS_PORT;
   1462                 MIM_INFO(unit)->port_info[vp].index = i;
   1463             } else {
   1464                 MIM_INFO(unit)->port_info[vp].flags |=
   1465                     _BCM_MIM_PORT_TYPE_ACCESS_PORT_TRUNK;
   1466                 MIM_INFO(unit)->port_info[vp].index = tgid;
   1467             }
   1468             /* Recover TPID reference counts */
   1469             mem_entry[0] = &source_vp;
   1470             rv = _bcm_chunk_get_mem_entry(unit, SOURCE_VPm, vp ,
   1471                                           source_vp_buf, mem_entry[0]);
   1472             if (BCM_FAILURE(rv) || (NULL == source_vp)) {
   1473                 goto cleanup;
   1474             }
   1475 
   1476             rv = _bcm_tr2_mim_source_vp_tpid_recover(unit, source_vp, vp);
   1477             if (BCM_FAILURE(rv)) {
   1478                 goto cleanup;
   1479             }
   1480         }
   1481         /* Recover port flex stats */
   1482         _bcm_tr2_mim_port_flex_stat_recover(unit, source_vp, vp);
   1483         /* Recover other port data */
   1484         rv = _bcm_tr2_mim_port_associated_data_recover(unit, vp, stable_size);
   1485         if (BCM_FAILURE(rv)) {
   1486             goto cleanup;
   1487         }
   1488     } 
   1489 
   1490     /* Recover TPID reference counts from EGR_VLAN_XLATE */
   1491     index_min = soc_mem_index_min(unit, egr_xlate_mem);
   1492     index_max = soc_mem_index_max(unit, egr_xlate_mem);
   1493     for (i = index_min; i <= index_max; i++) {
   1494         mem_entry[0] = &egr_vlan_xlate;
   1495         rv = _bcm_chunk_get_mem_entry(unit, egr_xlate_mem, i ,
   1496                                 egr_vlan_xlate_buf, mem_entry[0]);
   1497         if (BCM_FAILURE(rv) || (NULL == egr_vlan_xlate)) {
   1498             goto cleanup;
   1499         }
   1500 #if defined(BCM_TRIDENT3_SUPPORT)
   1501         if (soc_feature(unit, soc_feature_base_valid)) {
   1502             if (soc_mem_field32_get(unit, egr_xlate_mem,
   1503                          egr_vlan_xlate, BASE_VALID_0f) != 3) {
   1504                 continue;
   1505             }
   1506             if (soc_mem_field32_get(unit, egr_xlate_mem,
   1507                          egr_vlan_xlate, BASE_VALID_1f) != 7) {
   1508                 continue;
   1509             }
   1510         } else
   1511 #endif
   1512         {
   1513             if (soc_mem_field32_get(unit, egr_xlate_mem,
   1514                          egr_vlan_xlate, VALIDf) == 0) {
   1515                 continue;
   1516             }
   1517         }
   1518 #if defined(BCM_TRIUMPH3_SUPPORT)
   1519         if (SOC_IS_TRIUMPH3(unit)) {
   1520             if (soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate, 
   1521                                                 KEY_TYPEf) != 3) {
   1522                 continue; /* Not MIM_ISID_DVP */
   1523             }
   1524         } else 
   1525 #endif /* BCM_TRIUMPH3_SUPPORT */
   1526         {
   1527 #if defined(BCM_TRIDENT3_SUPPORT)
   1528             if (soc_feature(unit, soc_feature_base_valid)) {
   1529                 if (soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate, 
   1530                                                     DATA_TYPEf) != 4) {
   1531                     continue; /* Not ISID_DVP_XLATE */
   1532                 }
   1533             } else
   1534 #endif
   1535             {
   1536                 if (soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate, 
   1537                                                     ENTRY_TYPEf) != 4) {
   1538                     continue; /* Not ISID_DVP_XLATE */
   1539                 }
   1540             }
   1541 
   1542         }
   1543         rv = _bcm_tr2_mim_egr_vxlt_tpid_recover(unit, egr_vlan_xlate);
   1544         if (BCM_FAILURE(rv)) {
   1545             goto cleanup;
   1546         }
   1547     }
   1548 
   1549     /* Recover L2 scache */
   1550     rv = _bcm_tr2_mim_wb_recover(unit);
   1551 
   1552 cleanup:
   1553     if (mpls_entry_buf) {
   1554         soc_cm_sfree(unit, mpls_entry_buf);
   1555     }
   1556     if (vlan_xlate_buf) {
   1557         soc_cm_sfree(unit, vlan_xlate_buf);
   1558     }
   1559     if (egr_vlan_xlate_buf) {
   1560         soc_cm_sfree(unit, egr_vlan_xlate_buf);
   1561     }
   1562     if (source_vp_buf) {
   1563         soc_cm_sfree(unit, source_vp_buf);
   1564     }
   1565     if (source_trunk_map_buf) {
   1566         soc_cm_sfree(unit, source_trunk_map_buf);
   1567     }
   1568     return rv;
   1569 }
   1570 
   1571 #endif /* BCM_WARM_BOOT_SUPPORT */
   1572 
   1573 /*
   1574  * Function:
   1575  *      bcm_mim_init
   1576  * Purpose:
   1577  *      Initialize the MIM software module
   1578  * Parameters:
   1579  *      unit     - Device Number
   1580  * Returns:
   1581  *      BCM_E_XXX
   1582  */
   1583 int 
   1584 bcm_tr2_mim_init(int unit)
   1585 {
   1586     int num_vfi, num_vp, num_intf, rv = BCM_E_NONE;
   1587     _bcm_tr2_mim_bookkeeping_t *mim_info = MIM_INFO(unit);
   1588 
   1589 
   1590     if (!L3_INFO(unit)->l3_initialized) {
   1591         LOG_INFO(BSL_LS_BCM_L3,
   1592                  (BSL_META_U(unit,
   1593                              "L3 module must be initialized first\n")));
   1594         return BCM_E_NONE;
   1595     }
   1596 
   1597     
   1598 
   1599     if (mim_initialized[unit]) {
   1600         BCM_IF_ERROR_RETURN(bcm_tr2_mim_detach(unit));
   1601     }
   1602     num_vfi = soc_mem_index_count(unit, VFIm);
   1603     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   1604     num_intf = soc_mem_index_count(unit, EGR_L3_INTFm);
   1605 
   1606     sal_memset(mim_info, 0, sizeof(_bcm_tr2_mim_bookkeeping_t));
   1607 
   1608     if (mim_info->vpn_info == NULL) {
   1609         mim_info->vpn_info = sal_alloc(sizeof(_bcm_tr2_vpn_info_t) 
   1610                                        * num_vfi, "mim_vpn_info");
   1611         if (mim_info->vpn_info == NULL) {
   1612             _bcm_tr2_mim_free_resources(unit);
   1613             return BCM_E_MEMORY;
   1614         }
   1615     }
   1616     sal_memset(mim_info->vpn_info, 0, sizeof(_bcm_tr2_vpn_info_t) * num_vfi);
   1617 
   1618     if (mim_info->port_info == NULL) {
   1619         mim_info->port_info = sal_alloc(sizeof(_bcm_tr2_mim_port_info_t) 
   1620                                        * num_vp, "mim_port_info");
   1621         if (mim_info->port_info == NULL) {
   1622             _bcm_tr2_mim_free_resources(unit);
   1623             return BCM_E_MEMORY;
   1624         }
   1625     }
   1626     sal_memset(mim_info->port_info, 0, sizeof(_bcm_tr2_mim_port_info_t) * num_vp);
   1627 
   1628     if (_mim_mutex[unit] == NULL) {
   1629         _mim_mutex[unit] = sal_mutex_create("mim mutex");
   1630         if (_mim_mutex[unit] == NULL) {
   1631             _bcm_tr2_mim_free_resources(unit);
   1632             return BCM_E_MEMORY;
   1633         }
   1634     }
   1635 
   1636     if (NULL == mim_info->intf_bitmap) {
   1637         mim_info->intf_bitmap =
   1638             sal_alloc(SHR_BITALLOCSIZE(num_intf), "intf_bitmap");
   1639         if (mim_info->intf_bitmap == NULL) {
   1640             _bcm_tr2_mim_free_resources(unit);
   1641             return BCM_E_MEMORY;
   1642         }
   1643     }
   1644     sal_memset(mim_info->intf_bitmap, 0, SHR_BITALLOCSIZE(num_intf));    
   1645 
   1646 #ifdef BCM_WARM_BOOT_SUPPORT
   1647     if (SOC_WARM_BOOT(unit)) {
   1648         /* Warm Boot recovery */
   1649         rv = _bcm_tr2_mim_reinit(unit); 
   1650     } else {
   1651         rv = _bcm_tr2_mim_wb_alloc(unit);
   1652     }
   1653 
   1654     if (BCM_FAILURE(rv)) {
   1655         _bcm_tr2_mim_free_resources(unit);
   1656         return rv;
   1657     }
   1658 #endif /* BCM_WARM_BOOT_SUPPORT */
   1659 
   1660     if(!SOC_WARM_BOOT(unit)) {
   1661         /* Enable MiM */
   1662         rv = bcm_tr2_mim_enable(unit, TRUE);
   1663         if (BCM_FAILURE(rv)) {
   1664             _bcm_tr2_mim_free_resources(unit);
   1665             return rv;
   1666         }
   1667     }
   1668 
   1669     mim_initialized[unit] = TRUE;
   1670     return rv;
   1671 }
   1672 
   1673 /*
   1674  * Function:
   1675  *      bcm_mim_vpn_create
   1676  * Purpose:
   1677  *      Create a VPN instance
   1678  * Parameters:
   1679  *      unit  - (IN)  Device Number
   1680  *      info  - (IN/OUT) VPN configuration info
   1681  * Returns:
   1682  *      BCM_E_XXX
   1683  */
   1684 int 
   1685 bcm_tr2_mim_vpn_create(int unit, bcm_mim_vpn_config_t *info)
   1686 {   
   1687     int index, rv = BCM_E_PARAM;
   1688     vfi_entry_t vfi_entry;
   1689     vfi_1_entry_t vfi_1_entry;
   1690     uint32 mpls_entry[SOC_MAX_MEM_WORDS] = {0};
   1691     bcm_mim_vpn_config_t old_info;
   1692     uint32 egr_vlan_xlate_entry[SOC_MAX_MEM_WORDS];
   1693     int vfi, bc_group = 0, umc_group = 0, uuc_group = 0, num_vfi;
   1694     int bc_group_type, umc_group_type, uuc_group_type;
   1695     soc_mem_t mpls_mem = MPLS_ENTRYm;
   1696     bcm_vpn_t mim_vpn_min=0;
   1697     int hw_idx;
   1698     int proto_pkt_idx;
   1699     soc_mem_t egr_xlate_mem;
   1700 #if defined(BCM_TRIDENT3_SUPPORT)
   1701     uint32 vfi_attrs_1_entry[SOC_MAX_MEM_WORDS] = {0};
   1702 #endif
   1703 
   1704     MIM_INIT(unit);
   1705 
   1706     num_vfi = soc_mem_index_count(unit, VFIm);
   1707 
   1708     bcm_mim_vpn_config_t_init(&old_info);
   1709 
   1710 #if defined(BCM_TRIDENT3_SUPPORT)
   1711     if (soc_feature(unit, soc_feature_base_valid)) {
   1712         egr_xlate_mem = EGR_VLAN_XLATE_1_DOUBLEm;
   1713     } else
   1714 #endif
   1715     {
   1716         egr_xlate_mem = EGR_VLAN_XLATEm;
   1717     }
   1718 
   1719     /* For Point-to_point service, multicast groups are not valid */
   1720     if (info->flags & BCM_MIM_VPN_ELINE) { 
   1721 
   1722         /* For point-to-point vpn groups are not valid */
   1723         if ((info->broadcast_group != 0) || 
   1724             (info->unknown_unicast_group != 0) || 
   1725             (info->unknown_multicast_group != 0)){
   1726             return BCM_E_PARAM; 
   1727         }    
   1728         
   1729     } else {
   1730 
   1731         /* Check that the groups are valid. */
   1732 
   1733         bc_group_type = _BCM_MULTICAST_TYPE_GET(info->broadcast_group);
   1734         bc_group = _BCM_MULTICAST_ID_GET(info->broadcast_group);
   1735         umc_group_type = _BCM_MULTICAST_TYPE_GET(info->unknown_multicast_group);
   1736         umc_group = _BCM_MULTICAST_ID_GET(info->unknown_multicast_group);
   1737         uuc_group_type = _BCM_MULTICAST_TYPE_GET(info->unknown_unicast_group);
   1738         uuc_group = _BCM_MULTICAST_ID_GET(info->unknown_unicast_group);
   1739 
   1740         if ((bc_group_type != _BCM_MULTICAST_TYPE_MIM) ||
   1741             (umc_group_type != _BCM_MULTICAST_TYPE_MIM) ||
   1742             (uuc_group_type != _BCM_MULTICAST_TYPE_MIM) ||
   1743             (bc_group >= soc_mem_index_count(unit, L3_IPMCm)) ||
   1744             (umc_group >= soc_mem_index_count(unit, L3_IPMCm)) ||
   1745             (uuc_group >= soc_mem_index_count(unit, L3_IPMCm))) {
   1746             return BCM_E_PARAM;
   1747         }
   1748     }
   1749     /* validate parameter protocol_pkt */
   1750     if (SOC_MEM_FIELD_VALID(unit, VFIm, PROTOCOL_PKT_INDEXf)) {
   1751         rv = _bcm_xgs3_protocol_packet_actions_validate(unit,
   1752                                &info->protocol_pkt);
   1753         if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) {
   1754             return rv;
   1755         }
   1756     }
   1757     /* Validate lookup id value */
   1758 #if defined(BCM_TRIUMPH3_SUPPORT)    
   1759     if (SOC_IS_TRIUMPH3(unit)) {
   1760         mpls_mem = MPLS_ENTRY_EXTDm;
   1761     } else
   1762 #endif /* BCM_TRIUMPH3_SUPPORT */
   1763     {
   1764         mpls_mem = MPLS_ENTRYm;
   1765     }
   1766 
   1767     if ( info->lookup_id >= 0 ) {
   1768         /* coverity[large_shift : FALSE] */
   1769         if (!SOC_MEM_FIELD32_VALUE_FIT(unit, mpls_mem, MIM_ISID__ISIDf, 
   1770                                       info->lookup_id)) {
   1771             LOG_WARN(BSL_LS_BCM_MIM,
   1772                      (BSL_META_U(unit,
   1773                                  "lookup_id value exceeds 0x%x \n"),
   1774                                  SOC_MEM_FIELD32_VALUE_MAX(unit, mpls_mem, MIM_ISID__ISIDf)));
   1775             return BCM_E_PARAM;
   1776         }
   1777     }
   1778 
   1779 
   1780     MIM_LOCK(unit);
   1781     if (info->flags & BCM_MIM_VPN_WITH_ID) {
   1782             _BCM_MIM_VPN_SET(mim_vpn_min, _BCM_MIM_VPN_TYPE_MIM, 0);
   1783             if (info->vpn < mim_vpn_min || 
   1784                 info->vpn > (mim_vpn_min + num_vfi - 1) ) {
   1785                 MIM_UNLOCK(unit);
   1786                 return BCM_E_PARAM;
   1787             }
   1788 
   1789         /* Check if VFI exists and handle the replace case */
   1790         _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, info->vpn);
   1791         if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   1792             if ((info->flags & BCM_MIM_VPN_REPLACE)) {
   1793 
   1794                 /* do not allow P2P -> P2M or P2M -> P2P */
   1795                 /* Read the VFI table to check if point-to-point vpn */
   1796                 sal_memset(&vfi_entry, 0, sizeof(vfi_entry_t));
   1797                 rv = READ_VFIm(unit, MEM_BLOCK_ALL, vfi, &vfi_entry);
   1798                 if (BCM_FAILURE(rv)) {
   1799                     MIM_UNLOCK(unit);
   1800                     return rv;
   1801                 }
   1802 
   1803                 /* ELINE */
   1804                 if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
   1805                    if (!(info->flags & BCM_MIM_VPN_ELINE)) {
   1806                        MIM_UNLOCK(unit);
   1807                        return BCM_E_PARAM;
   1808                    }   
   1809                 } else { /* ELAN */
   1810                    if (!(info->flags & BCM_MIM_VPN_MIM)) {
   1811                        MIM_UNLOCK(unit);
   1812                        return BCM_E_PARAM;
   1813                    }   
   1814                 }
   1815                 
   1816                 /* Get old ISID lookup id to delete from mpls and xlate table */
   1817                 rv = bcm_tr2_mim_vpn_get( unit, info->vpn, &old_info);
   1818                 if (BCM_FAILURE(rv)) {
   1819                     MIM_UNLOCK(unit);
   1820                     return rv;
   1821                 }
   1822             } else {
   1823                 MIM_UNLOCK(unit);
   1824                 return BCM_E_EXISTS;
   1825             }
   1826         } else {
   1827            rv = _bcm_vfi_alloc_with_id(unit, VFIm, _bcmVfiTypeMim, vfi);
   1828            if (rv < 0) {
   1829                MIM_UNLOCK(unit);
   1830                return rv;
   1831            }
   1832         }
   1833     } else {
   1834         /* Allocate a free VFI entry */
   1835         rv = _bcm_vfi_alloc(unit, VFIm, _bcmVfiTypeMim, &vfi);
   1836         if (rv < 0) {
   1837             MIM_UNLOCK(unit);
   1838             return rv;
   1839         }
   1840     }
   1841     VPN_ISID(unit, vfi) = info->lookup_id;
   1842 
   1843     /* Commit the VFI entry to HW */
   1844     BCM_IF_ERROR_RETURN(READ_VFIm(unit, MEM_BLOCK_ALL, vfi, &vfi_entry));
   1845     if (!(info->flags & BCM_MIM_VPN_ELINE)) {
   1846 #if defined(BCM_TRIDENT3_SUPPORT)
   1847         if (soc_feature(unit, soc_feature_generic_dest)) {
   1848             soc_mem_field32_dest_set(unit, VFIm, &vfi_entry,
   1849                 UMC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, umc_group);
   1850             soc_mem_field32_dest_set(unit, VFIm, &vfi_entry,
   1851                 UUC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, uuc_group);
   1852             soc_mem_field32_dest_set(unit, VFIm, &vfi_entry,
   1853                 BC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, bc_group);
   1854         } else
   1855 #endif
   1856         {
   1857             soc_VFIm_field32_set(unit, &vfi_entry, UMC_INDEXf, umc_group);
   1858             soc_VFIm_field32_set(unit, &vfi_entry, UUC_INDEXf, uuc_group);
   1859             soc_VFIm_field32_set(unit, &vfi_entry, BC_INDEXf, bc_group);
   1860         }
   1861 #if  defined(BCM_TRIDENT3_SUPPORT)
   1862         if (SOC_IS_TRIDENT3X(unit)) {
   1863             uint32 profile_idx = 0;
   1864             rv = _bcm_td3_def_vfi_profile_add(unit,
   1865                 info->flags & BCM_MIM_VPN_ELINE, &profile_idx);
   1866             if (BCM_E_NONE == rv) {
   1867                 soc_VFIm_field32_set(unit, &vfi_entry, VFI_PROFILE_PTRf, profile_idx);
   1868             }
   1869         }
   1870 #endif
   1871     }
   1872 
   1873     /* If ELINE service set the PT2PT field */
   1874     if (info->flags & BCM_MIM_VPN_ELINE) {
   1875         soc_VFIm_field32_set(unit, &vfi_entry, PT2PT_ENf, 0x1);
   1876     }
   1877 
   1878 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
   1879                                                 defined(BCM_APACHE_SUPPORT)
   1880     if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit)) {
   1881         rv = _bcm_esw_add_policer_to_table(unit, info->policer_id, VFIm, 0,
   1882                                                     &vfi_entry);
   1883         if (rv < 0) {
   1884             MIM_UNLOCK(unit);
   1885             return rv;
   1886         }
   1887     }
   1888 #endif /* BCM_KATANA_SUPPORT  or BCM_TRIUMPH3_SUPPORT or BCM_APACHE_SUPPORT */
   1889 
   1890     if (info->flags & BCM_MIM_VPN_BVID_DROP_NOMATCH) {
   1891         soc_VFIm_field32_set(unit, &vfi_entry, BVIDf, info->tunnel_vlan & 0xfff);
   1892     }
   1893 
   1894     if (info->flags & BCM_MIM_VPN_QOS_INGRESS_MAP_INT_PRIORITY) {
   1895         rv = _bcm_tr2_qos_id2idx(unit, info->qos_map_id, &hw_idx);
   1896         if (BCM_FAILURE(rv)) {
   1897             MIM_UNLOCK(unit);
   1898             return rv;
   1899         }
   1900         soc_mem_field32_set(unit, VFIm, &vfi_entry, TRUST_DOT1P_PTRf, hw_idx);
   1901 
   1902         if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT2X(unit)) { 
   1903             soc_mem_field32_set(unit, VFIm, &vfi_entry,
   1904                                 PHB2_USE_INNER_DOT1Pf, info->int_pri & 0x1);
   1905         } else {
   1906             soc_mem_field32_set(unit, VFIm, &vfi_entry,
   1907                                 USE_INNER_PRIf, info->int_pri & 0x1);
   1908         }
   1909     }
   1910 
   1911     if (info->flags & BCM_MIM_VPN_QOS_INGRESS_MAP_FIX_INT_PRIORITY) {
   1912         /** index 1024 to 1040 are reserved for fixed priority mapping */
   1913         soc_mem_field32_set(unit, VFIm, &vfi_entry,
   1914                             TRUST_DOT1P_PTRf, info->int_pri + 16);
   1915         if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT2X(unit)) { 
   1916             soc_mem_field32_set(unit, VFIm, &vfi_entry, PHB2_USE_INNER_DOT1Pf, 0);
   1917         } else {
   1918             soc_mem_field32_set(unit, VFIm, &vfi_entry, USE_INNER_PRIf, 0);
   1919         } 
   1920 
   1921         if (SOC_IS_ENDURO(unit) || SOC_IS_TRIUMPH2(unit)) {
   1922             /** set fix priority at location 1024 + fixed priority */
   1923             ing_pri_cng_map_entry_t imap;
   1924             rv = READ_ING_PRI_CNG_MAPm(unit, MEM_BLOCK_ANY,
   1925                 (1024 + info->int_pri), &imap);
   1926             if (BCM_FAILURE(rv)) {
   1927                 MIM_UNLOCK(unit);
   1928                 return rv;
   1929             }
   1930 
   1931             soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, &imap, PRIf, info->int_pri);
   1932             rv = WRITE_ING_PRI_CNG_MAPm(unit, MEM_BLOCK_ANY,
   1933                 (1024 + info->int_pri), &imap);
   1934             if (BCM_FAILURE(rv)) {
   1935                 MIM_UNLOCK(unit);
   1936                 return rv;
   1937             }
   1938         }
   1939     }
   1940     if (SOC_MEM_FIELD_VALID (unit,VFIm, PROTOCOL_PKT_INDEXf)) {
   1941         if (info->flags & BCM_MIM_VPN_REPLACE) {
   1942             proto_pkt_idx = soc_VFIm_field32_get(unit, &vfi_entry,
   1943                                                  PROTOCOL_PKT_INDEXf);
   1944         } else {
   1945             proto_pkt_idx = -1;
   1946         }
   1947         rv = _bcm_xgs3_protocol_pkt_ctrl_set(unit, proto_pkt_idx,
   1948                                              &info->protocol_pkt,
   1949                                              &proto_pkt_idx);
   1950         if (BCM_SUCCESS(rv)) {
   1951             soc_VFIm_field32_set(unit, &vfi_entry, PROTOCOL_PKT_INDEXf,
   1952                                  proto_pkt_idx);
   1953         } else if (rv != BCM_E_UNAVAIL) {
   1954             return rv;
   1955         }
   1956     }
   1957     rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi, &vfi_entry);
   1958 
   1959     if (rv < 0) {
   1960         MIM_UNLOCK(unit);
   1961         return rv;
   1962     }
   1963 
   1964     /* Check for incoming SD-tag match */
   1965     if (info->flags & BCM_MIM_VPN_MATCH_SERVICE_VLAN_TPID) {
   1966         sal_memset(&vfi_1_entry, 0, sizeof(vfi_1_entry_t));
   1967         rv = _bcm_fb2_outer_tpid_entry_add(unit, info->match_service_tpid, &index);
   1968         if (rv < 0) {
   1969             MIM_UNLOCK(unit);
   1970             return rv;
   1971         }
   1972 #if defined(BCM_TRIDENT3_SUPPORT)
   1973         if (SOC_MEM_FIELD_VALID(unit, VFIm, SD_TAG_MODEf)) {
   1974             rv = READ_VFIm(unit, MEM_BLOCK_ALL, vfi, &vfi_entry);
   1975             if (rv < 0) {
   1976                 MIM_UNLOCK(unit);
   1977                 return rv;
   1978             }
   1979             soc_VFIm_field32_set(unit, &vfi_entry, SD_TAG_MODEf, 1);
   1980             rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi, &vfi_entry);
   1981             if (rv < 0) {
   1982                 MIM_UNLOCK(unit);
   1983                 return rv;
   1984             }
   1985             rv = READ_VFI_ATTRS_1m(unit, MEM_BLOCK_ALL, vfi, &vfi_attrs_1_entry);
   1986             if (rv < 0) {
   1987                 MIM_UNLOCK(unit);
   1988                 return rv;
   1989             }
   1990             soc_VFI_ATTRS_1m_field32_set(unit, vfi_attrs_1_entry, TPID_ENABLEf, (1 << index));
   1991             rv = WRITE_VFI_ATTRS_1m(unit, MEM_BLOCK_ALL, vfi, &vfi_attrs_1_entry);
   1992             if (rv < 0) {
   1993                 MIM_UNLOCK(unit);
   1994                 return rv;
   1995             }
   1996         } else
   1997 #endif
   1998         {
   1999             soc_VFI_1m_field32_set(unit, &vfi_1_entry, SD_TAG_MODEf, 1);
   2000             soc_VFI_1m_field32_set(unit, &vfi_1_entry, TPID_ENABLEf, (1 << index));
   2001             rv = WRITE_VFI_1m(unit, MEM_BLOCK_ALL, vfi, &vfi_1_entry);
   2002             if (rv < 0) {
   2003                 MIM_UNLOCK(unit);
   2004                 return rv;
   2005             }
   2006         }
   2007     }
   2008 
   2009     if ( info->lookup_id >= 0 ) {
   2010         /* Program the ISID to VFI mapping */
   2011         sal_memset(&mpls_entry, 0, sizeof(mpls_entry));
   2012 #if defined(BCM_TRIUMPH3_SUPPORT)    
   2013         if (SOC_IS_TRIUMPH3(unit)) {
   2014             soc_mem_field32_set(unit, mpls_mem, &mpls_entry, KEY_TYPE_0f, 0x18);
   2015             soc_mem_field32_set(unit, mpls_mem, &mpls_entry, KEY_TYPE_1f, 0x18);
   2016             soc_mem_field32_set(unit, mpls_mem, &mpls_entry, VALID_0f, 0x1);
   2017             soc_mem_field32_set(unit, mpls_mem, &mpls_entry, VALID_1f, 0x1);
   2018         } else
   2019 #endif /* BCM_TRIUMPH3_SUPPORT */
   2020         {
   2021             soc_mem_field32_set(unit, mpls_mem, &mpls_entry, KEY_TYPEf, 0x2);
   2022 #if defined(BCM_TRIDENT3_SUPPORT)
   2023             if (soc_feature(unit, soc_feature_base_valid)) {
   2024                 soc_mem_field32_set(unit, mpls_mem, &mpls_entry, BASE_VALID_0f, 3); 
   2025                 soc_mem_field32_set(unit, mpls_mem, &mpls_entry, BASE_VALID_1f, 7); 
   2026                 soc_mem_field32_set(unit, mpls_mem, &mpls_entry, DATA_TYPEf, 0x2);
   2027             } else
   2028 #endif
   2029             {
   2030                 soc_mem_field32_set(unit, mpls_mem, &mpls_entry, VALIDf, 0x1);
   2031             }
   2032         }
   2033         /* key */
   2034         soc_mem_field32_set(unit, mpls_mem, &mpls_entry, MIM_ISID__ISIDf, info->lookup_id);
   2035         /* data */
   2036         soc_mem_field32_set(unit, mpls_mem, &mpls_entry, MIM_ISID__VFIf, vfi);
   2037         rv = soc_mem_search(unit, mpls_mem, MEM_BLOCK_ANY, &index,
   2038                             &mpls_entry, &mpls_entry, 0);
   2039         if (rv == SOC_E_NONE) {
   2040             if ( (info->flags & BCM_MIM_VPN_REPLACE) && (info->lookup_id == old_info.lookup_id)) {
   2041                 /*replace with the same lookup_id*/
   2042             } else {
   2043                 _bcm_vfi_free(unit, _bcmVfiTypeMim, vfi);
   2044                 MIM_UNLOCK(unit);
   2045                 return BCM_E_EXISTS;
   2046             }
   2047         } else if (rv != SOC_E_NOT_FOUND) {
   2048             _bcm_vfi_free(unit, _bcmVfiTypeMim, vfi);
   2049             MIM_UNLOCK(unit);
   2050             return rv;
   2051         }
   2052     
   2053         if ((info->flags & BCM_MIM_VPN_WITH_ID) &&
   2054             (info->flags & BCM_MIM_VPN_REPLACE) &&
   2055             (old_info.lookup_id >= 0)) {
   2056             /* Delete old lookup ISID from mpls entry table*/
   2057             soc_mem_field32_set(unit, mpls_mem, &mpls_entry, MIM_ISID__ISIDf, old_info.lookup_id);   
   2058             rv = soc_mem_delete(unit, mpls_mem, MEM_BLOCK_ALL, &mpls_entry);
   2059             if (BCM_FAILURE(rv)) {
   2060                 MIM_UNLOCK(unit);
   2061                 return rv;
   2062             } 
   2063         }
   2064         soc_mem_field32_set(unit, mpls_mem, &mpls_entry, MIM_ISID__ISIDf, info->lookup_id);
   2065         rv = soc_mem_insert(unit, mpls_mem, MEM_BLOCK_ALL, &mpls_entry);
   2066         if (rv < 0) {
   2067             if ((info->flags & BCM_MIM_VPN_WITH_ID) &&
   2068                 (info->flags & BCM_MIM_VPN_REPLACE) &&
   2069                 (old_info.lookup_id >= 0)) {
   2070                     /* Re-insert old lookup ISID into mpls entry table */
   2071                     soc_mem_field32_set(unit, mpls_mem, &mpls_entry, MIM_ISID__ISIDf, old_info.lookup_id);
   2072                     soc_mem_insert(unit, mpls_mem, MEM_BLOCK_ALL, &mpls_entry);
   2073             }
   2074             MIM_UNLOCK(unit);
   2075             return rv;
   2076         }
   2077     
   2078         /* Program the VFI to ISID mapping */
   2079         sal_memset(egr_vlan_xlate_entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   2080 #if defined(BCM_TRIUMPH3_SUPPORT)    
   2081         if (SOC_IS_TRIUMPH3(unit)) {
   2082             soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, 
   2083                                             KEY_TYPEf, 0x2); /* MIM_ISID */
   2084         } else
   2085 #endif /* BCM_TRIUMPH3_SUPPORT */
   2086         {
   2087 #if defined(BCM_TRIDENT3_SUPPORT)
   2088             if (soc_feature(unit, soc_feature_base_valid)) {
   2089                 soc_mem_field32_set(unit, egr_xlate_mem,
   2090                     egr_vlan_xlate_entry, DATA_TYPEf, 0x3);
   2091                 soc_mem_field32_set(unit, egr_xlate_mem,
   2092                     egr_vlan_xlate_entry, KEY_TYPEf, 0x3);
   2093             } else
   2094 #endif
   2095             {
   2096                 soc_mem_field32_set(unit, egr_xlate_mem,
   2097                     egr_vlan_xlate_entry, ENTRY_TYPEf, 0x3);
   2098             }
   2099         }
   2100 #if defined(BCM_TRIDENT3_SUPPORT)
   2101         if (soc_feature(unit, soc_feature_base_valid)) {
   2102             soc_mem_field32_set(unit, egr_xlate_mem,
   2103                    egr_vlan_xlate_entry, BASE_VALID_0f, 0x3);
   2104             soc_mem_field32_set(unit, egr_xlate_mem,
   2105                    egr_vlan_xlate_entry, BASE_VALID_1f, 0x7);
   2106         } else
   2107 #endif
   2108         {
   2109             soc_mem_field32_set(unit, egr_xlate_mem, 
   2110                 egr_vlan_xlate_entry, VALIDf, 0x1);
   2111         }
   2112         /* MIIM_ISID key */
   2113         soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, MIM_ISID__VFIf, vfi);
   2114         /* MIIM_ISID data */
   2115         soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, MIM_ISID__ISIDf, 
   2116                                         info->lookup_id);
   2117 
   2118         rv = soc_mem_search(unit, egr_xlate_mem, MEM_BLOCK_ANY, &index,
   2119                             egr_vlan_xlate_entry, egr_vlan_xlate_entry, 0);
   2120         if (rv == SOC_E_NONE) {
   2121             if (!((info->flags & BCM_MIM_VPN_WITH_ID) &&
   2122                  (info->flags & BCM_MIM_VPN_REPLACE))) {
   2123                 _bcm_vfi_free(unit, _bcmVfiTypeMim, vfi);
   2124                 MIM_UNLOCK(unit);
   2125                 return BCM_E_EXISTS;
   2126             }
   2127         } else if (rv != SOC_E_NOT_FOUND) {
   2128             _bcm_vfi_free(unit, _bcmVfiTypeMim, vfi);
   2129             MIM_UNLOCK(unit);
   2130             return rv;
   2131         }
   2132 
   2133         if ((info->flags & BCM_MIM_VPN_WITH_ID) &&
   2134             (info->flags & BCM_MIM_VPN_REPLACE) &&
   2135             (old_info.lookup_id >= 0)){
   2136             /* Delete old lookup ISID from EGR_VLAN_XLATE entry */
   2137             rv = _bcm_tr2_mim_egr_vxlt_sd_tag_actions_delete(unit, egr_vlan_xlate_entry);
   2138             if (BCM_FAILURE(rv)) {
   2139                 MIM_UNLOCK(unit);
   2140                 return rv;
   2141             }
   2142 
   2143             rv = soc_mem_delete(unit, egr_xlate_mem, MEM_BLOCK_ALL, egr_vlan_xlate_entry);
   2144             if (BCM_FAILURE(rv)) {
   2145                 MIM_UNLOCK(unit);
   2146                 return rv;
   2147             }
   2148         }
   2149 
   2150         if (info->flags & BCM_MIM_VPN_QOS_SDTAG_NO_ACTION) {
   2151             soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   2152                     MIM_ISID__SD_TAG_ACTION_IF_PRESENTf, 0); 
   2153         }
   2154 
   2155         if (info->flags & BCM_MIM_VPN_QOS_SDTAG_FIX_PRIORITY) {
   2156             soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   2157                 MIM_ISID__SD_TAG_DOT1P_PRI_SELECTf, 0);
   2158             soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   2159                 MIM_ISID__SD_TAG_ACTION_IF_PRESENTf, 0x5);
   2160             soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   2161                 MIM_ISID__NEW_PRIf, info->int_pri & 0x7);
   2162             soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   2163                 MIM_ISID__NEW_CFIf, ((info->int_pri >> 0x3) & 0x1)); 
   2164         }
   2165 
   2166         if (info->flags & BCM_MIM_VPN_QOS_SDTAG_MAP_INT_PRIORITY) {
   2167             rv = _bcm_tr2_qos_id2idx(unit, info->qos_map_id, &hw_idx);
   2168             if (BCM_FAILURE(rv)) {
   2169                 MIM_UNLOCK(unit);
   2170                 return rv;
   2171             }
   2172             soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   2173                 MIM_ISID__SD_TAG_DOT1P_PRI_SELECTf, 0x1);
   2174             soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   2175                 MIM_ISID__SD_TAG_ACTION_IF_PRESENTf, 0x5);
   2176             soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   2177                 MIM_ISID__DOT1P_MAPPING_PTRf, hw_idx);
   2178         }
   2179 
   2180         if (info->flags & BCM_MIM_VPN_QOS_ITAG_FIX_PRIORITY) {
   2181             soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   2182                 MIM_ISID__ISID_DOT1P_PRI_SELECTf, 0);
   2183             soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   2184                 MIM_ISID__NEW_PRIf, info->int_pri & 0x7);
   2185             soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   2186                 MIM_ISID__NEW_CFIf, ((info->int_pri >> 0x3) & 0x1)); 
   2187             soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   2188                 MIM_ISID__NEW_CFIf, ((info->int_pri >> 0x3) & 0x1));
   2189         }
   2190 
   2191         if (info->flags & BCM_MIM_VPN_QOS_ITAG_MAP_SDTAG_PRIORITY) {
   2192             soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   2193                 MIM_ISID__ISID_DOT1P_PRI_SELECTf, 0x1);
   2194         }
   2195 
   2196         if (info->flags & BCM_MIM_VPN_EGRESS_SERVICE_TPID_REPLACE) {
   2197             if (soc_feature(unit, soc_feature_evt_replace_tpid_only)) {
   2198                 rv = _bcm_tr2_mim_egr_vxlt_sd_tag_actions(unit, NULL,
   2199                                                           info,
   2200                                                           egr_vlan_xlate_entry);
   2201                 if (BCM_FAILURE(rv)) {
   2202                     MIM_UNLOCK(unit);
   2203                     return rv;
   2204                 }
   2205             } else {
   2206                 MIM_UNLOCK(unit);
   2207                 return BCM_E_UNAVAIL;
   2208             }
   2209         }
   2210 
   2211         rv = soc_mem_insert(unit, egr_xlate_mem, MEM_BLOCK_ALL, egr_vlan_xlate_entry);
   2212         if (rv < 0) {
   2213             MIM_UNLOCK(unit);
   2214             return rv;
   2215         }
   2216     } else if ((info->flags & BCM_MIM_VPN_REPLACE) &&
   2217                (old_info.lookup_id >= 0)) { 
   2218         sal_memset(&mpls_entry, 0, sizeof(mpls_entry));
   2219 #if defined(BCM_TRIUMPH3_SUPPORT)
   2220         if (SOC_IS_TRIUMPH3(unit)) {
   2221             soc_mem_field32_set(unit, mpls_mem, &mpls_entry, KEY_TYPE_0f, 0x18);
   2222             soc_mem_field32_set(unit, mpls_mem, &mpls_entry, KEY_TYPE_1f, 0x18);
   2223             soc_mem_field32_set(unit, mpls_mem, &mpls_entry, VALID_0f, 0x1);
   2224             soc_mem_field32_set(unit, mpls_mem, &mpls_entry, VALID_1f, 0x1);
   2225         } else
   2226 #endif /* BCM_TRIUMPH3_SUPPORT */
   2227         {
   2228     	    soc_mem_field32_set(unit, mpls_mem, &mpls_entry, KEY_TYPEf, 0x2);
   2229 #if defined(BCM_TRIDENT3_SUPPORT)
   2230             if (soc_feature(unit, soc_feature_base_valid)) {
   2231                 soc_mem_field32_set(unit, mpls_mem, &mpls_entry, BASE_VALID_0f, 3); 
   2232                 soc_mem_field32_set(unit, mpls_mem, &mpls_entry, BASE_VALID_1f, 7); 
   2233             } else
   2234 #endif
   2235             {
   2236                 soc_mem_field32_set(unit, mpls_mem, &mpls_entry, VALIDf, 0x1);
   2237             }
   2238 	    }
   2239         /* key */
   2240         soc_mem_field32_set(unit, mpls_mem, &mpls_entry, MIM_ISID__ISIDf, old_info.lookup_id);
   2241         /* data */
   2242         soc_mem_field32_set(unit, mpls_mem, &mpls_entry, MIM_ISID__VFIf, vfi);
   2243         soc_mem_delete(unit, mpls_mem, MEM_BLOCK_ANY, &mpls_entry);
   2244 
   2245         /* Program the VFI to ISID mapping */
   2246         sal_memset(egr_vlan_xlate_entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   2247 #if defined(BCM_TRIUMPH3_SUPPORT)
   2248         if (SOC_IS_TRIUMPH3(unit)) {
   2249             soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   2250                                               KEY_TYPEf, 0x2); /* MIM_ISID */
   2251         } else
   2252 #endif /* BCM_TRIUMPH3_SUPPORT */
   2253         {
   2254 #if defined(BCM_TRIDENT3_SUPPORT)
   2255             if (soc_feature(unit, soc_feature_base_valid)) {
   2256                 soc_mem_field32_set(unit, egr_xlate_mem,
   2257                     egr_vlan_xlate_entry, DATA_TYPEf, 0x3);
   2258                 soc_mem_field32_set(unit, egr_xlate_mem,
   2259                     egr_vlan_xlate_entry, KEY_TYPEf, 0x3);
   2260             } else
   2261 #endif
   2262             {
   2263                 soc_mem_field32_set(unit, egr_xlate_mem,
   2264                     egr_vlan_xlate_entry, ENTRY_TYPEf, 0x3);
   2265             }
   2266         }
   2267 #if defined(BCM_TRIDENT3_SUPPORT)
   2268         if (soc_feature(unit, soc_feature_base_valid)) {
   2269             soc_mem_field32_set(unit, egr_xlate_mem,
   2270                    egr_vlan_xlate_entry, BASE_VALID_0f, 0x3);
   2271             soc_mem_field32_set(unit, egr_xlate_mem,
   2272                    egr_vlan_xlate_entry, BASE_VALID_1f, 0x7);
   2273         } else
   2274 #endif
   2275         {
   2276             soc_mem_field32_set(unit, egr_xlate_mem, 
   2277                 egr_vlan_xlate_entry, VALIDf, 0x1);
   2278         }
   2279 
   2280         /* MIIM_ISID key */
   2281         soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, MIM_ISID__VFIf, vfi);
   2282         /* MIIM_ISID data */
   2283         soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, MIM_ISID__ISIDf,
   2284 				        old_info.lookup_id);
   2285         rv = _bcm_tr2_mim_egr_vxlt_sd_tag_actions_delete(unit, egr_vlan_xlate_entry);
   2286         if (BCM_FAILURE(rv)) {
   2287             MIM_UNLOCK(unit);
   2288             return rv;
   2289         }
   2290         soc_mem_delete(unit, egr_xlate_mem, MEM_BLOCK_ALL, egr_vlan_xlate_entry);
   2291     }
   2292 
   2293 #ifdef BCM_WARM_BOOT_SUPPORT
   2294     SOC_CONTROL_LOCK(unit);
   2295     SOC_CONTROL(unit)->scache_dirty = 1;
   2296     SOC_CONTROL_UNLOCK(unit);
   2297 #endif
   2298 
   2299     MIM_UNLOCK(unit);
   2300 
   2301     _BCM_MIM_VPN_SET(info->vpn, _BCM_MIM_VPN_TYPE_MIM, vfi);
   2302     return rv;
   2303 }
   2304 
   2305 /*
   2306  * Function:
   2307  *      bcm_mim_vpn_destroy
   2308  * Purpose:
   2309  *      Delete a VPN instance
   2310  * Parameters:
   2311  *      unit - Device Number
   2312  *      vpn - VPN instance ID
   2313  * Returns:
   2314  *      BCM_E_XXX
   2315  */
   2316 int 
   2317 bcm_tr2_mim_vpn_destroy(int unit, bcm_mim_vpn_t vpn)
   2318 {
   2319     int vfi, rv, tpid_en, i;
   2320     uint32 vfi_1_entry[SOC_MAX_MEM_WORDS] = {0};
   2321     vfi_entry_t vfi_entry;
   2322     uint32 mpls_entry[SOC_MAX_MEM_WORDS] = {0};
   2323     uint32 egr_vlan_xlate_entry[SOC_MAX_MEM_WORDS];
   2324     soc_mem_t mpls_mem = MPLS_ENTRYm;
   2325     int num_vfi;
   2326     bcm_vpn_t mim_vpn_min=0;
   2327     int ref_count, proto_pkt_idx;
   2328     soc_mem_t egr_xlate_mem;
   2329     soc_mem_t vfi_mem;
   2330     soc_mem_t vfi_1_mem;
   2331     uint32 vfi_entry_data[SOC_MAX_MEM_WORDS] = {0};
   2332     int index;
   2333 
   2334 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   2335     int policer=0;
   2336 #endif 
   2337     MIM_INIT(unit);
   2338     MIM_LOCK(unit);
   2339 
   2340 #if defined(BCM_TRIDENT3_SUPPORT)
   2341     if (soc_feature(unit, soc_feature_base_valid)) {
   2342         egr_xlate_mem = EGR_VLAN_XLATE_1_DOUBLEm;
   2343     } else
   2344 #endif
   2345     {
   2346         egr_xlate_mem = EGR_VLAN_XLATEm;
   2347     }
   2348 
   2349     num_vfi = soc_mem_index_count(unit, VFIm);
   2350     _BCM_MIM_VPN_SET(mim_vpn_min, _BCM_MIM_VPN_TYPE_MIM, 0);
   2351     if ( vpn < mim_vpn_min || vpn > (mim_vpn_min+num_vfi-1) ) {
   2352         MIM_UNLOCK(unit);
   2353         return BCM_E_PARAM;
   2354     }
   2355 
   2356     _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vpn);
   2357     if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   2358         MIM_UNLOCK(unit);
   2359         return BCM_E_NOT_FOUND;
   2360     }
   2361 
   2362     /* Delete all the MIM ports on this VPN */
   2363     rv = bcm_tr2_mim_port_delete_all(unit, vpn);
   2364     if (BCM_FAILURE(rv)) {
   2365         MIM_UNLOCK(unit);
   2366         return rv;
   2367     } 
   2368 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   2369     if (soc_feature(unit, soc_feature_global_meter)) {
   2370         rv = _bcm_esw_get_policer_from_table(unit,
   2371                 VFIm, vfi, &vfi_entry, &policer, 0); 
   2372         if(BCM_SUCCESS(rv)) {
   2373              _bcm_esw_policer_decrement_ref_count(unit, policer);
   2374         } else {
   2375             MIM_UNLOCK(unit);
   2376             return rv;
   2377         }
   2378     }
   2379 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT */
   2380     if (SOC_MEM_FIELD_VALID(unit, VFIm, PROTOCOL_PKT_INDEXf)) {
   2381         rv = READ_VFIm(unit, MEM_BLOCK_ALL, vfi, &vfi_entry);
   2382         if (BCM_FAILURE(rv)) {
   2383             MIM_UNLOCK(unit);
   2384             return rv;
   2385         }
   2386         proto_pkt_idx = soc_VFIm_field32_get(unit, &vfi_entry,
   2387                                              PROTOCOL_PKT_INDEXf);
   2388         rv = _bcm_prot_pkt_ctrl_ref_count_get(unit, proto_pkt_idx,
   2389                                               &ref_count);
   2390         if (BCM_FAILURE(rv)) {
   2391             MIM_UNLOCK(unit);
   2392             return rv;
   2393         }
   2394         if (ref_count > 0) {
   2395             rv = _bcm_prot_pkt_ctrl_delete(unit, proto_pkt_idx);
   2396             if (BCM_FAILURE(rv)) {
   2397                 MIM_UNLOCK(unit);
   2398                 return rv;
   2399             }
   2400         }
   2401     }
   2402 
   2403     if (soc_feature(unit, soc_feature_gport_service_counters)) {
   2404         /* Release Service counter, if any */
   2405         _bcm_esw_flex_stat_handle_free(unit, _bcmFlexStatTypeService,
   2406                                        vpn);
   2407     }
   2408     sal_memset(&mpls_entry, 0, sizeof(mpls_entry));
   2409 #if defined(BCM_TRIUMPH3_SUPPORT)    
   2410     if (SOC_IS_TRIUMPH3(unit)) {
   2411         mpls_mem = MPLS_ENTRY_EXTDm;
   2412         soc_mem_field32_set(unit, mpls_mem, &mpls_entry, KEY_TYPE_0f, 0x18);
   2413         soc_mem_field32_set(unit, mpls_mem, &mpls_entry, KEY_TYPE_1f, 0x18);
   2414         soc_mem_field32_set(unit, mpls_mem, &mpls_entry, VALID_0f, 0x1);
   2415         soc_mem_field32_set(unit, mpls_mem, &mpls_entry, VALID_1f, 0x1);
   2416     } else
   2417 #endif /* BCM_TRIUMPH3_SUPPORT */
   2418     {
   2419         mpls_mem = MPLS_ENTRYm;
   2420         soc_mem_field32_set(unit, mpls_mem, &mpls_entry, KEY_TYPEf, 0x2);
   2421 #if defined(BCM_TRIDENT3_SUPPORT)
   2422         if (soc_feature(unit, soc_feature_base_valid)) {
   2423             soc_mem_field32_set(unit, mpls_mem, &mpls_entry, BASE_VALID_0f, 3);
   2424             soc_mem_field32_set(unit, mpls_mem, &mpls_entry, BASE_VALID_1f, 7);
   2425             soc_mem_field32_set(unit, mpls_mem, &mpls_entry, DATA_TYPEf, 0x2);
   2426         } else
   2427 #endif
   2428         {
   2429             soc_mem_field32_set(unit, mpls_mem, &mpls_entry, VALIDf, 0x1);
   2430         }
   2431 
   2432     }
   2433     soc_mem_field32_set(unit, mpls_mem, &mpls_entry, MIM_ISID__ISIDf, VPN_ISID(unit, vfi));
   2434     rv = soc_mem_delete(unit, mpls_mem, MEM_BLOCK_ANY, &mpls_entry);
   2435     if (BCM_FAILURE(rv)) {
   2436         MIM_UNLOCK(unit);
   2437         return rv;
   2438     } 
   2439 
   2440     sal_memset(egr_vlan_xlate_entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   2441 #if defined(BCM_TRIUMPH3_SUPPORT)    
   2442     if (SOC_IS_TRIUMPH3(unit)) {
   2443         soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, 
   2444                                         KEY_TYPEf, 0x2); /* MIM_ISID */
   2445     } else
   2446 #endif /* BCM_TRIUMPH3_SUPPORT */
   2447     {
   2448 #if defined(BCM_TRIDENT3_SUPPORT)
   2449         if (soc_feature(unit, soc_feature_base_valid)) {
   2450             soc_mem_field32_set(unit, egr_xlate_mem,
   2451                 egr_vlan_xlate_entry, DATA_TYPEf, 0x3);
   2452             soc_mem_field32_set(unit, egr_xlate_mem,
   2453                 egr_vlan_xlate_entry, KEY_TYPEf, 0x3);
   2454         } else
   2455 #endif
   2456         {
   2457             soc_mem_field32_set(unit, egr_xlate_mem,
   2458                 egr_vlan_xlate_entry, ENTRY_TYPEf, 0x3);
   2459         }
   2460     }
   2461 #if defined(BCM_TRIDENT3_SUPPORT)
   2462     if (soc_feature(unit, soc_feature_base_valid)) {
   2463         soc_mem_field32_set(unit, egr_xlate_mem,
   2464                egr_vlan_xlate_entry, BASE_VALID_0f, 0x3);
   2465         soc_mem_field32_set(unit, egr_xlate_mem,
   2466                egr_vlan_xlate_entry, BASE_VALID_1f, 0x7);
   2467     } else
   2468 #endif
   2469     {
   2470         soc_mem_field32_set(unit, egr_xlate_mem,
   2471             egr_vlan_xlate_entry, VALIDf, 0x1);
   2472     }
   2473 
   2474     /* MIIM_ISID key */
   2475     soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, MIM_ISID__VFIf, vfi);
   2476     rv = soc_mem_search(unit, egr_xlate_mem, MEM_BLOCK_ANY, &index,
   2477                         egr_vlan_xlate_entry, egr_vlan_xlate_entry, 0);
   2478     rv = _bcm_tr2_mim_egr_vxlt_sd_tag_actions_delete(unit, egr_vlan_xlate_entry);
   2479     if (BCM_FAILURE(rv)) {
   2480         MIM_UNLOCK(unit);
   2481         return rv;
   2482     }
   2483     rv = soc_mem_delete(unit, egr_xlate_mem, MEM_BLOCK_ANY, egr_vlan_xlate_entry);
   2484     if (BCM_FAILURE(rv)) {
   2485         MIM_UNLOCK(unit);
   2486         return rv;
   2487     } 
   2488 #if defined(BCM_TRIDENT3_SUPPORT)
   2489     if (SOC_MEM_FIELD_VALID(unit, VFIm, SD_TAG_MODEf)) {
   2490         vfi_mem = VFIm;
   2491         vfi_1_mem = VFI_ATTRS_1m;
   2492     } else
   2493 #endif
   2494     {
   2495         vfi_mem = VFI_1m;
   2496         vfi_1_mem = VFI_1m;
   2497     }
   2498     rv = soc_mem_read(unit, vfi_mem, MEM_BLOCK_ANY, vfi, vfi_1_entry);
   2499     if (BCM_FAILURE(rv)) {
   2500         MIM_UNLOCK(unit);
   2501         return rv;
   2502     }
   2503     rv = soc_mem_read(unit, vfi_1_mem, MEM_BLOCK_ANY, vfi, vfi_entry_data);
   2504     if (BCM_FAILURE(rv)) {
   2505         MIM_UNLOCK(unit);
   2506         return rv;
   2507     }
   2508 
   2509     /* Delete TPID if applicable */
   2510     if (soc_mem_field32_get(unit, vfi_mem, vfi_1_entry, SD_TAG_MODEf)) {
   2511         tpid_en = soc_mem_field32_get(unit, vfi_1_mem, vfi_entry_data, TPID_ENABLEf);
   2512         for (i = 0; i < 4; i++) {
   2513             if (tpid_en & (1 << i)) {
   2514                (void)_bcm_fb2_outer_tpid_entry_delete(unit, i);
   2515                 break;
   2516             }
   2517         }
   2518     }
   2519     sal_memset(vfi_1_entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   2520     rv = soc_mem_write(unit, vfi_1_mem, MEM_BLOCK_ALL, vfi, vfi_1_entry);
   2521     if (BCM_FAILURE(rv)) {
   2522         MIM_UNLOCK(unit);
   2523         return rv;
   2524     } 
   2525 
   2526     VPN_ISID(unit, vfi) = 0;
   2527     (void) _bcm_vfi_free(unit, _bcmVfiTypeMim, vfi);
   2528 
   2529 #ifdef BCM_WARM_BOOT_SUPPORT
   2530     SOC_CONTROL_LOCK(unit);
   2531     SOC_CONTROL(unit)->scache_dirty = 1;
   2532     SOC_CONTROL_UNLOCK(unit);
   2533 #endif
   2534 
   2535     MIM_UNLOCK(unit);
   2536     return rv;
   2537 }
   2538 
   2539 STATIC int
   2540 _bcm_tr2_mim_vpn_np_destroy(int unit)
   2541 {
   2542     int vp, rv = BCM_E_NONE;
   2543     uint32 num_vp;
   2544     source_vp_entry_t *psvp;
   2545     uint8 *source_vp_buf = NULL;
   2546     int network_port = 0;
   2547     _bcm_vp_info_t vp_info;
   2548 
   2549     MIM_INIT(unit);
   2550 
   2551     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   2552     source_vp_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, SOURCE_VPm),
   2553                                  "SOURCE_VP buffer");
   2554     if (source_vp_buf == NULL) {
   2555         goto done;
   2556     }
   2557     rv = soc_mem_read_range(unit, SOURCE_VPm, MEM_BLOCK_ANY, 
   2558                            0, num_vp-1, source_vp_buf); 
   2559     if (rv < 0) { 
   2560         goto done; 
   2561     }
   2562 
   2563     for (vp = 0; vp < num_vp; vp++) {
   2564         network_port = FALSE;
   2565         psvp = soc_mem_table_idx_to_pointer 
   2566                 (unit, SOURCE_VPm, source_vp_entry_t *, source_vp_buf, vp);
   2567         if (soc_SOURCE_VPm_field32_get( unit, psvp, ENTRY_TYPEf) != 0) {
   2568             if(_bcm_vp_info_get(unit, vp, &vp_info) == BCM_E_NONE) {
   2569                 if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
   2570                     network_port = TRUE;
   2571                 }
   2572             }
   2573 
   2574             if(network_port) {
   2575                 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   2576                     rv = _bcm_tr2_mim_port_delete(unit, 0, vp);
   2577                     if (rv < 0) {
   2578                         goto done;
   2579                     }
   2580                 }
   2581             }
   2582         }
   2583     }
   2584 done:
   2585     if ( source_vp_buf != NULL ){
   2586         soc_cm_sfree( unit, source_vp_buf); 
   2587     }
   2588     return rv;
   2589 }
   2590 
   2591 /*
   2592  * Function:
   2593  *      bcm_mim_vpn_destroy_all
   2594  * Purpose:
   2595  *      Delete al VPN instances
   2596  * Parameters:
   2597  *      unit - Device Number
   2598  * Returns:
   2599  *      BCM_E_XXX
   2600  */
   2601 int
   2602 bcm_tr2_mim_vpn_destroy_all(int unit)
   2603 {
   2604     int num_vfi, i, rv = BCM_E_NONE;
   2605     bcm_vpn_t vpn;
   2606 
   2607     MIM_INIT(unit);
   2608     num_vfi = soc_mem_index_count(unit, VFIm);
   2609     for (i = 0; i < num_vfi; i++) {
   2610         if (_bcm_vfi_used_get(unit, i, _bcmVfiTypeMim)) {
   2611             _BCM_MIM_VPN_SET(vpn, _BCM_MIM_VPN_TYPE_MIM, i);
   2612             rv = bcm_tr2_mim_vpn_destroy(unit, vpn);
   2613             if (rv < 0) {
   2614                 goto done;
   2615             }
   2616         }
   2617     }
   2618     rv = _bcm_tr2_mim_vpn_np_destroy(unit);
   2619 done:
   2620     return rv;
   2621 }
   2622 
   2623 /*
   2624  * Function:
   2625  *      bcm_mim_vpn_get
   2626  * Purpose:
   2627  *      Get information about a VPN instance
   2628  * Parameters:
   2629  *      unit  - (IN)  Device Number
   2630  *      vpn   - (IN)  VPN instance ID
   2631  *      info  - (OUT) VPN configuration info
   2632  * Returns:
   2633  *      BCM_E_XXX
   2634  */
   2635 int 
   2636 bcm_tr2_mim_vpn_get(int unit, bcm_mim_vpn_t vpn, 
   2637                     bcm_mim_vpn_config_t *info)
   2638 {
   2639     int vfi, tpid_en, i;
   2640     vfi_entry_t vfi_entry;
   2641     uint32 vfi_entry_data[SOC_MAX_MEM_WORDS] = {0};
   2642     uint32 vfi_1_entry[SOC_MAX_MEM_WORDS] = {0};
   2643     int num_vfi;
   2644     bcm_vpn_t mim_vpn_min=0;
   2645     int is_eline = 0;
   2646     int vpn_type;
   2647     int proto_pkt_idx, rv;
   2648     int bc_index = 0;
   2649     int uuc_index = 0;
   2650     int umc_index = 0;
   2651     soc_mem_t vfi_mem;
   2652     soc_mem_t vfi_1_mem;
   2653     soc_mem_t evx_mem = EGR_VLAN_XLATEm;
   2654     uint32 egr_vlan_xlate_entry[SOC_MAX_MEM_WORDS] = {0};
   2655     int index;
   2656     uint8 new_pri = 0;
   2657 
   2658     MIM_INIT(unit);
   2659     num_vfi = soc_mem_index_count(unit, VFIm);
   2660 
   2661     _BCM_MIM_VPN_SET(mim_vpn_min, _BCM_MIM_VPN_TYPE_MIM, 0);
   2662     if ( vpn < mim_vpn_min || vpn > (mim_vpn_min+num_vfi-1) ) {
   2663         return BCM_E_PARAM;
   2664     }
   2665 
   2666     _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vpn);
   2667 
   2668     if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   2669         return BCM_E_NOT_FOUND;
   2670     }
   2671    
   2672     /* Initialize VPN configuration information */
   2673     bcm_mim_vpn_config_t_init(info);
   2674     info->vpn = vpn; 
   2675 
   2676     /* check if ELINE vpn service */
   2677     BCM_IF_ERROR_RETURN(soc_mem_read(unit, VFIm, MEM_BLOCK_ANY, vfi, 
   2678                                      &vfi_entry));
   2679 
   2680     is_eline = soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf);
   2681 
   2682     if (is_eline) {
   2683         vpn_type = BCM_MIM_VPN_ELINE;
   2684     } else {
   2685         vpn_type = BCM_MIM_VPN_MIM;
   2686     }
   2687 
   2688     info->flags |= vpn_type;
   2689 
   2690     /* if point-to_point vpn BC_INDEX, UUC_INDEX, UMC_INDEX not relevant */
   2691     if (!is_eline) {
   2692 #if defined(BCM_TRIDENT3_SUPPORT)
   2693         if (soc_feature(unit, soc_feature_generic_dest)) {
   2694             uint32 dt;
   2695 
   2696             bc_index = soc_mem_field32_dest_get(unit, VFIm,
   2697                             &vfi_entry, BC_DESTINATIONf, &dt);
   2698             if (dt != SOC_MEM_FIF_DEST_IPMC) {
   2699                 return BCM_E_INTERNAL;
   2700             }
   2701 
   2702             uuc_index = soc_mem_field32_dest_get(unit, VFIm,
   2703                             &vfi_entry, UUC_DESTINATIONf, &dt);
   2704             if (dt != SOC_MEM_FIF_DEST_IPMC) {
   2705                 return BCM_E_INTERNAL;
   2706             }
   2707 
   2708             umc_index = soc_mem_field32_dest_get(unit, VFIm,
   2709                             &vfi_entry, UMC_DESTINATIONf, &dt);
   2710             if (dt != SOC_MEM_FIF_DEST_IPMC) {
   2711                 return BCM_E_INTERNAL;
   2712             }
   2713         } else
   2714 #endif
   2715         {
   2716             bc_index = soc_VFIm_field32_get(unit, &vfi_entry, BC_INDEXf);
   2717             uuc_index = soc_VFIm_field32_get(unit, &vfi_entry, UUC_INDEXf);
   2718             umc_index = soc_VFIm_field32_get(unit, &vfi_entry, UMC_INDEXf);
   2719         }
   2720 
   2721         _BCM_MULTICAST_GROUP_SET(info->broadcast_group,
   2722                             _BCM_MULTICAST_TYPE_MIM, bc_index);
   2723         _BCM_MULTICAST_GROUP_SET(info->unknown_unicast_group,
   2724                             _BCM_MULTICAST_TYPE_MIM, uuc_index);
   2725         _BCM_MULTICAST_GROUP_SET(info->unknown_multicast_group,
   2726                             _BCM_MULTICAST_TYPE_MIM, umc_index);
   2727     }
   2728 
   2729 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   2730     if (soc_feature(unit, soc_feature_global_meter)) {
   2731          _bcm_esw_get_policer_from_table(unit, VFIm, vfi, &vfi_entry, 
   2732                                                     &info->policer_id, 1); 
   2733     }
   2734 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT */
   2735     info->lookup_id = VPN_ISID(unit, vfi);
   2736     if (SOC_MEM_FIELD_VALID(unit,VFIm, PROTOCOL_PKT_INDEXf)) {
   2737         proto_pkt_idx = soc_VFIm_field32_get(unit, &vfi_entry,
   2738                                              PROTOCOL_PKT_INDEXf);
   2739         rv = _bcm_xgs3_protocol_pkt_ctrl_get(unit, proto_pkt_idx,
   2740                                              &info->protocol_pkt);
   2741         if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) {
   2742             return rv;
   2743         }
   2744     }
   2745 #if defined(BCM_TRIDENT3_SUPPORT)
   2746     if (SOC_MEM_FIELD_VALID(unit, VFIm, SD_TAG_MODEf)) {
   2747         vfi_mem = VFIm;
   2748         vfi_1_mem = VFI_ATTRS_1m;
   2749         evx_mem = EGR_VLAN_XLATE_1_DOUBLEm;
   2750     } else
   2751 #endif
   2752     {
   2753         vfi_mem = VFI_1m;
   2754         vfi_1_mem = VFI_1m;
   2755     }
   2756 
   2757     BCM_IF_ERROR_RETURN(soc_mem_read(unit, vfi_mem,
   2758                       MEM_BLOCK_ANY, vfi, vfi_entry_data));
   2759     BCM_IF_ERROR_RETURN(soc_mem_read(unit, vfi_1_mem,
   2760                       MEM_BLOCK_ANY, vfi, vfi_1_entry));
   2761     if (soc_mem_field32_get(unit, vfi_mem, vfi_entry_data, SD_TAG_MODEf)) {
   2762         info->flags |= BCM_MIM_VPN_MATCH_SERVICE_VLAN_TPID;
   2763         tpid_en = soc_mem_field32_get(unit, vfi_1_mem, &vfi_1_entry, TPID_ENABLEf);
   2764         for (i = 0; i < 4; i++) {
   2765             if (tpid_en & (1 << i)) {
   2766                 _bcm_fb2_outer_tpid_entry_get(unit, 
   2767                                       &info->match_service_tpid, i);
   2768                 break;
   2769             }
   2770         }
   2771     }
   2772 
   2773     sal_memset(egr_vlan_xlate_entry, 0, sizeof(egr_vlan_xlate_entry));
   2774 #if defined(BCM_TRIUMPH3_SUPPORT)
   2775     if (SOC_IS_TRIUMPH3(unit)) {
   2776         soc_mem_field32_set(unit, evx_mem, egr_vlan_xlate_entry,
   2777                             KEY_TYPEf, 0x2); /* MIM_ISID */
   2778     } else
   2779 #endif /* BCM_TRIUMPH3_SUPPORT */
   2780 #if defined(BCM_TRIDENT3_SUPPORT)
   2781     if (soc_feature(unit, soc_feature_base_valid)) {
   2782         soc_mem_field32_set(unit, evx_mem, egr_vlan_xlate_entry, DATA_TYPEf, 0x3);
   2783         soc_mem_field32_set(unit, evx_mem, egr_vlan_xlate_entry, KEY_TYPEf, 0x3);
   2784     } else
   2785 #endif
   2786     {
   2787         soc_mem_field32_set(unit, evx_mem, egr_vlan_xlate_entry,
   2788                             ENTRY_TYPEf, 0x3);
   2789     }
   2790     if (soc_feature(unit, soc_feature_base_valid)) {
   2791         soc_mem_field32_set(unit, evx_mem, egr_vlan_xlate_entry, BASE_VALID_0f, 0x3);
   2792         soc_mem_field32_set(unit, evx_mem, egr_vlan_xlate_entry, BASE_VALID_1f, 0x7);
   2793     } else {
   2794         soc_mem_field32_set(unit, evx_mem, egr_vlan_xlate_entry, VALIDf, 0x1);
   2795     }
   2796     /* MIIM_ISID key */
   2797     soc_mem_field32_set(unit, evx_mem, egr_vlan_xlate_entry, MIM_ISID__VFIf, vfi);
   2798     rv = soc_mem_search(unit, evx_mem, MEM_BLOCK_ANY, &index,
   2799                         egr_vlan_xlate_entry, egr_vlan_xlate_entry, 0);
   2800     if (rv == SOC_E_NONE)
   2801     {
   2802         new_pri =
   2803             soc_mem_field32_get(unit, evx_mem, &egr_vlan_xlate_entry,
   2804                                             MIM_ISID__NEW_PRIf);
   2805         new_pri |=
   2806             ((soc_mem_field32_get(unit, evx_mem, &egr_vlan_xlate_entry,
   2807                                               MIM_ISID__NEW_CFIf) & 0x1) << 3);
   2808         if (new_pri != 0) {
   2809             if (soc_mem_field32_get(unit, evx_mem, &egr_vlan_xlate_entry,
   2810                MIM_ISID__SD_TAG_ACTION_IF_PRESENTf) == 0) {
   2811                 info->flags |= BCM_MIM_VPN_QOS_ITAG_FIX_PRIORITY;
   2812                 info->int_pri = new_pri;
   2813             }
   2814         }
   2815 
   2816         rv = _bcm_tr2_mim_egr_vxlt_sd_tag_actions_get(unit, NULL, info,
   2817                                                       egr_vlan_xlate_entry);
   2818     }
   2819 
   2820     return rv;
   2821 }
   2822 
   2823 /*
   2824  * Function:
   2825  *      bcm_mim_vpn_traverse
   2826  * Purpose:
   2827  *      Get information about a VPN instance
   2828  * Parameters:
   2829  *      unit  - (IN)  Device Number
   2830  *      cb    - (IN)  User-provided callback
   2831  *      info  - (IN/OUT) Cookie
   2832  * Returns:
   2833  *      BCM_E_XXX
   2834  */
   2835 
   2836 int bcm_tr2_mim_vpn_traverse(int unit, bcm_mim_vpn_traverse_cb cb, 
   2837                              void *user_data)
   2838 {
   2839     int i, index_min, index_max, rv = BCM_E_NONE;
   2840     int vpn;
   2841     bcm_mim_vpn_config_t info;
   2842 
   2843     MIM_INIT(unit);
   2844 
   2845     index_min = soc_mem_index_min(unit, VFIm);
   2846     index_max = soc_mem_index_max(unit, VFIm);
   2847 
   2848     MIM_LOCK(unit);
   2849     for (i = index_min; i <= index_max; i++) {
   2850         if (!_bcm_vfi_used_get(unit, i, _bcmVfiTypeMim)) {
   2851             continue;
   2852         }
   2853         bcm_mim_vpn_config_t_init(&info);
   2854         _BCM_MIM_VPN_SET(vpn, _BCM_MIM_VPN_TYPE_MIM, i);
   2855         rv = bcm_tr2_mim_vpn_get(unit, vpn, &info);
   2856         if (BCM_FAILURE(rv)) {
   2857             MIM_UNLOCK(unit);
   2858             return rv;
   2859         }
   2860         rv = cb(unit, &info, user_data);
   2861         if (BCM_FAILURE(rv)) {
   2862             MIM_UNLOCK(unit); 
   2863             return rv;
   2864         }
   2865     }
   2866     MIM_UNLOCK(unit);
   2867     return rv;
   2868 }
   2869 
   2870 STATIC int
   2871 _bcm_tr2_mim_l3_intf_add(int unit, _bcm_l3_intf_cfg_t *if_info)
   2872 {
   2873     int i, num_intf;
   2874     egr_l3_intf_entry_t egr_intf;
   2875     bcm_mac_t hw_mac;
   2876     num_intf = soc_mem_index_count(unit, EGR_L3_INTFm);
   2877     for (i = 0; i < num_intf; i++) {
   2878         if (_BCM_MIM_INTF_USED_GET(unit, i)) {
   2879             BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_INTFm,  
   2880                                              MEM_BLOCK_ANY, i, &egr_intf));
   2881             soc_mem_mac_addr_get(unit, EGR_L3_INTFm, &egr_intf, 
   2882                                  MAC_ADDRESSf, hw_mac);
   2883             if (SAL_MAC_ADDR_EQUAL(hw_mac, if_info->l3i_mac_addr)) {
   2884                 if_info->l3i_index = i;
   2885                 return BCM_E_NONE;
   2886             }
   2887         }
   2888     }
   2889     /* Create an interface */
   2890     BCM_IF_ERROR_RETURN(bcm_xgs3_l3_intf_create(unit, if_info));
   2891     _BCM_MIM_INTF_USED_SET(unit, if_info->l3i_index);
   2892     return BCM_E_NONE;
   2893 }
   2894 
   2895 typedef struct _bcm_tr2_ing_nh_info_s {
   2896     int      port;
   2897     int      module;
   2898     int      trunk;
   2899     uint32   mtu;
   2900 } _bcm_tr2_ing_nh_info_t;
   2901 
   2902 typedef struct _bcm_tr2_egr_nh_info_s {
   2903     uint8    entry_type;
   2904     uint8    dvp_is_network;
   2905     uint8    sd_tag_action_present;
   2906     uint8    sd_tag_action_not_present;
   2907     int      dvp;
   2908     int      intf_num;
   2909     int      sd_tag_vlan;
   2910     int      sd_tag_pri;
   2911     int      sd_tag_cfi;
   2912     int      macda_index;
   2913     int      tpid_index;
   2914     int      vintf_ctr_idx;
   2915 } _bcm_tr2_egr_nh_info_t;
   2916 
   2917 STATIC int
   2918 _bcm_tr2_mim_egr_sd_tag_actions(int unit, bcm_mim_port_t *mim_port, 
   2919                                 _bcm_tr2_egr_nh_info_t *egr_nh_info)
   2920 {
   2921     int rv = BCM_E_NONE, tpid_index = -1;
   2922     if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_ADD) {
   2923         if (mim_port->egress_service_vlan >= BCM_VLAN_INVALID) { 
   2924             if (soc_feature(unit, soc_feature_vp_sharing)) {
   2925                 egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID;    
   2926             } else {
   2927                 return  BCM_E_PARAM;
   2928             }
   2929         }
   2930 
   2931         if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) {
   2932             egr_nh_info->sd_tag_vlan = mim_port->egress_service_vlan; 
   2933         }
   2934         egr_nh_info->sd_tag_action_not_present = 0x1; /* ADD */
   2935     }
   2936     if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_TPID_REPLACE) {
   2937         if (mim_port->egress_service_vlan >= BCM_VLAN_INVALID) { 
   2938             if (soc_feature(unit, soc_feature_vp_sharing)) {
   2939                 egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID;    
   2940             } else {
   2941                 return  BCM_E_PARAM;
   2942             }
   2943         }
   2944         /* REPLACE_VID_TPID */
   2945         if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) {
   2946             egr_nh_info->sd_tag_vlan = mim_port->egress_service_vlan; 
   2947         }
   2948         egr_nh_info->sd_tag_action_present = 0x1;
   2949     } else if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_REPLACE) {
   2950         if (mim_port->egress_service_vlan >= BCM_VLAN_INVALID) { 
   2951             if (soc_feature(unit, soc_feature_vp_sharing)) {
   2952                 egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID;    
   2953             } else {
   2954                 return  BCM_E_PARAM;
   2955             }
   2956         }
   2957         /* REPLACE_VID_ONLY */
   2958         if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) {
   2959             egr_nh_info->sd_tag_vlan = mim_port->egress_service_vlan; 
   2960         }
   2961         egr_nh_info->sd_tag_action_present = 0x2;
   2962     } else if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_DELETE) {
   2963         egr_nh_info->sd_tag_action_present = 0x3; /* DELETE */
   2964     } else if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_PRI_TPID_REPLACE) {
   2965         if (mim_port->egress_service_vlan >= BCM_VLAN_INVALID) { 
   2966             if (soc_feature(unit, soc_feature_vp_sharing)) {
   2967                 egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID;    
   2968             } else {
   2969                 return  BCM_E_PARAM;
   2970             }
   2971         }
   2972         /*  REPLACE_VID_PRI_TPID */
   2973         if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) {
   2974             egr_nh_info->sd_tag_vlan = mim_port->egress_service_vlan; 
   2975         }
   2976         egr_nh_info->sd_tag_pri = mim_port->egress_service_pri;
   2977         egr_nh_info->sd_tag_cfi = mim_port->egress_service_cfi;
   2978         egr_nh_info->sd_tag_action_present = 0x4;
   2979     } else if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_PRI_REPLACE ) {
   2980         if (mim_port->egress_service_vlan >= BCM_VLAN_INVALID) { 
   2981             if (soc_feature(unit, soc_feature_vp_sharing)) {
   2982                 egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID;    
   2983             } else {
   2984                 return  BCM_E_PARAM;
   2985             }
   2986         }
   2987         /* REPLACE_VID_PRI ONLY */
   2988         if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) {
   2989             egr_nh_info->sd_tag_vlan = mim_port->egress_service_vlan; 
   2990         }
   2991         egr_nh_info->sd_tag_pri = mim_port->egress_service_pri;
   2992         egr_nh_info->sd_tag_cfi = mim_port->egress_service_cfi;
   2993         egr_nh_info->sd_tag_action_present = 0x5;
   2994     }
   2995 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   2996       else if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_PRI_REPLACE) {
   2997         egr_nh_info->sd_tag_pri = mim_port->egress_service_pri;
   2998         egr_nh_info->sd_tag_cfi = mim_port->egress_service_cfi;
   2999         egr_nh_info->sd_tag_action_present = 0x6;
   3000     } else if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_TPID_REPLACE) {
   3001         /* TPID value is used */
   3002         rv = _bcm_fb2_outer_tpid_entry_add(unit, mim_port->egress_service_tpid, 
   3003                                            &tpid_index);
   3004         BCM_IF_ERROR_RETURN(rv);
   3005         egr_nh_info->tpid_index = tpid_index;
   3006         egr_nh_info->sd_tag_action_present = 0x7;
   3007     } 
   3008 #endif
   3009     if ((mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_ADD)
   3010         || (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_TPID_REPLACE)
   3011         || (mim_port->flags &
   3012                         BCM_MIM_PORT_EGRESS_SERVICE_VLAN_PRI_TPID_REPLACE))
   3013     {
   3014         /* TPID value is used */
   3015         rv = _bcm_fb2_outer_tpid_entry_add(unit, mim_port->egress_service_tpid, 
   3016                                            &tpid_index);
   3017         BCM_IF_ERROR_RETURN(rv);
   3018         egr_nh_info->tpid_index = tpid_index;
   3019     }
   3020 
   3021     /* Set fixed priority */
   3022     if (mim_port->flags & BCM_MIM_PORT_FIX_PRIORITY) {
   3023         if (mim_port->flags & BCM_MIM_PORT_TYPE_BACKBONE) {
   3024             egr_nh_info->sd_tag_pri = mim_port->int_pri & 0x7;
   3025             egr_nh_info->sd_tag_cfi = ((mim_port->int_pri >> 0x3) & 0x1);
   3026         }
   3027     }
   3028 
   3029     return rv;
   3030 }
   3031 
   3032 int
   3033 _bcm_tr2_mim_egr_vxlt_sd_tag_actions(int unit, bcm_mim_port_t *mim_port,
   3034                                      bcm_mim_vpn_config_t *vpn_info,
   3035                                      uint32 *evxlt_entry)
   3036 {
   3037     int rv = BCM_E_NONE, tpid_index = -1;
   3038     int sd_default_action = 0, sd_tag_action = 0;
   3039     soc_mem_t egr_xlate_mem;
   3040     
   3041 #if defined(BCM_TRIDENT3_SUPPORT)
   3042         if (soc_feature(unit, soc_feature_base_valid)) {
   3043             egr_xlate_mem = EGR_VLAN_XLATE_1_DOUBLEm;
   3044         } else
   3045 #endif
   3046         {
   3047             egr_xlate_mem = EGR_VLAN_XLATEm;
   3048         }
   3049 
   3050     if (mim_port != NULL) {
   3051         if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_ADD) {
   3052             if (!BCM_VLAN_VALID(mim_port->egress_service_vlan)) {
   3053                 return BCM_E_PARAM;
   3054             }
   3055             soc_mem_field32_set(unit, egr_xlate_mem, evxlt_entry, 
   3056                                         MIM_ISID__SD_TAG_VIDf, 
   3057                                         mim_port->egress_service_vlan);
   3058             sd_default_action = 0x1; /* ADD */
   3059         }
   3060         if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_TPID_REPLACE) {
   3061             if (!BCM_VLAN_VALID(mim_port->egress_service_vlan)) {
   3062                 return BCM_E_PARAM;
   3063             }
   3064             /* REPLACE_VID_TPID */
   3065             soc_mem_field32_set(unit, egr_xlate_mem, evxlt_entry, 
   3066                                         MIM_ISID__SD_TAG_VIDf, 
   3067                                         mim_port->egress_service_vlan); 
   3068             sd_tag_action = 0x1; /* Replace Vid and TPID */
   3069         } else if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_REPLACE) {
   3070             if (!BCM_VLAN_VALID(mim_port->egress_service_vlan)) {
   3071                 return BCM_E_PARAM;
   3072             }
   3073             /* REPLACE_VID_ONLY */
   3074             soc_mem_field32_set(unit, egr_xlate_mem, evxlt_entry, 
   3075                                         MIM_ISID__SD_TAG_VIDf, 
   3076                                         mim_port->egress_service_vlan); 
   3077             sd_tag_action = 0x2; /* Replace Vid only */
   3078         } else if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_DELETE) {
   3079             sd_tag_action = 0x3; /* DELETE */
   3080         } 
   3081 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   3082           else if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_PRI_REPLACE) {
   3083             soc_mem_field32_set(unit, egr_xlate_mem, evxlt_entry,
   3084                                         MIM_ISID__NEW_PRIf,
   3085                                         mim_port->egress_service_pri);
   3086             soc_mem_field32_set(unit, egr_xlate_mem, evxlt_entry,
   3087                                         MIM_ISID__NEW_CFIf,
   3088                                         mim_port->egress_service_cfi);
   3089             sd_tag_action = 0x6;
   3090         } else if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_TPID_REPLACE) {
   3091             /* TPID value is used */
   3092             rv = _bcm_fb2_outer_tpid_entry_add(unit, mim_port->egress_service_tpid, 
   3093                                            &tpid_index);
   3094             BCM_IF_ERROR_RETURN(rv);
   3095             soc_mem_field32_set(unit, egr_xlate_mem, evxlt_entry,
   3096                                         MIM_ISID__SD_TAG_TPID_INDEXf,
   3097                                         tpid_index);
   3098             sd_tag_action = 0x7;
   3099         }
   3100 #endif
   3101         soc_mem_field32_set(unit, egr_xlate_mem, evxlt_entry,
   3102                                     MIM_ISID__SD_TAG_ACTION_IF_NOT_PRESENTf,
   3103                                     sd_default_action);
   3104         soc_mem_field32_set(unit, egr_xlate_mem, evxlt_entry, 
   3105                                     MIM_ISID__SD_TAG_ACTION_IF_PRESENTf, 
   3106                                     sd_tag_action);
   3107 
   3108         if ((mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_ADD) ||
   3109             (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_TPID_REPLACE)) {
   3110         /* TPID value is used */
   3111             rv = _bcm_fb2_outer_tpid_entry_add(unit, mim_port->egress_service_tpid, 
   3112                                            &tpid_index);
   3113             BCM_IF_ERROR_RETURN(rv);
   3114             soc_mem_field32_set(unit, egr_xlate_mem, evxlt_entry, 
   3115                                         MIM_ISID__SD_TAG_TPID_INDEXf, 
   3116                                         tpid_index);
   3117         }
   3118     } else if (vpn_info != NULL) {
   3119         if (vpn_info->flags & BCM_MIM_VPN_EGRESS_SERVICE_TPID_REPLACE) {
   3120             rv = _bcm_fb2_outer_tpid_entry_add(unit, vpn_info->egress_service_tpid,
   3121                                                &tpid_index);
   3122             BCM_IF_ERROR_RETURN(rv);
   3123             soc_mem_field32_set(unit, egr_xlate_mem, evxlt_entry,
   3124                                             MIM_ISID__SD_TAG_TPID_INDEXf,
   3125                                             tpid_index);
   3126 
   3127             /* REPLACE_TPID_ONLY */
   3128             sd_tag_action = 0x7;
   3129             soc_mem_field32_set(unit, egr_xlate_mem, evxlt_entry,
   3130                                             MIM_ISID__SD_TAG_ACTION_IF_PRESENTf,
   3131                                             sd_tag_action);
   3132         }
   3133     }
   3134 
   3135     return rv;
   3136 }
   3137 
   3138 int
   3139 _bcm_tr2_mim_egr_vxlt_sd_tag_actions_delete(
   3140     int unit, uint32 *egr_vlan_xlate_entry)
   3141 {
   3142     int action_present, action_not_present, tpid_idx;
   3143     soc_mem_t egr_xlate_mem;
   3144 
   3145 #if defined(BCM_TRIDENT3_SUPPORT)
   3146     if (soc_feature(unit, soc_feature_base_valid)) {
   3147         egr_xlate_mem = EGR_VLAN_XLATE_1_DOUBLEm;
   3148     } else
   3149 #endif
   3150     {
   3151         egr_xlate_mem = EGR_VLAN_XLATEm;
   3152     }    
   3153 
   3154     /* Populate the API structure */
   3155     action_present =
   3156         soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   3157                                         MIM_ISID__SD_TAG_ACTION_IF_PRESENTf);
   3158     action_not_present =
   3159         soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   3160                                       MIM_ISID__SD_TAG_ACTION_IF_NOT_PRESENTf);
   3161 
   3162     if ((action_not_present == 0x1) || (action_present == 0x1) ||
   3163         ((action_present == 0x7) &&
   3164           soc_feature(unit, soc_feature_evt_replace_tpid_only))) {
   3165         /* If SD tag action is ADD or REPLACE_VID_TPID, the tpid
   3166          * index of the entry is valid. Get the tpid index for later.
   3167          */
   3168         tpid_idx =
   3169             soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   3170                                             MIM_ISID__SD_TAG_TPID_INDEXf);
   3171         /* Delete old TPID */
   3172         if (tpid_idx != -1) {
   3173             (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_idx);
   3174         }
   3175     }
   3176     return BCM_E_NONE;
   3177 }
   3178 
   3179 /*
   3180  * Function:
   3181  *    _bcm_tr2_mim_failover_check
   3182  * Purpose:
   3183  *    Check for failover enable - mim port
   3184  * Parameters:
   3185  *    unit     : (IN) Device Unit Number
   3186  *    mim_port : (IN) mim port information
   3187  * Returns:
   3188  *    BCM_E_XXX
   3189  */
   3190 STATIC int
   3191 _bcm_tr2_mim_failover_check(int unit, bcm_mim_port_t *mim_port)
   3192 {
   3193     int failover_vp = -1;
   3194     int l3mc_index  = -1;
   3195     int vp_min      = -1;
   3196     /* Get egress next-hop index from Failover MPLS gport */
   3197     if (_BCM_MULTICAST_IS_SET(mim_port->failover_mc_group)) {
   3198         l3mc_index = _BCM_MULTICAST_ID_GET(mim_port->failover_mc_group);
   3199         if ((l3mc_index >= 0) &&
   3200             (l3mc_index < soc_mem_index_count(unit, L3_IPMCm))) {
   3201              return BCM_E_NONE;
   3202         } else {
   3203               return BCM_E_PARAM;
   3204         }
   3205     } else {
   3206         failover_vp = BCM_GPORT_MIM_PORT_ID_GET(mim_port->failover_gport_id);
   3207         if (failover_vp == -1) {
   3208              return BCM_E_PARAM;
   3209         }
   3210         if (soc_feature(unit, soc_feature_mim_reserve_default_port) &&
   3211             soc_property_get(unit, spn_RESERVE_MIM_DEFAULT_SVP, 0)) {
   3212             vp_min = 2;
   3213         } else {
   3214             vp_min = 1;
   3215         }
   3216         if ((failover_vp >= vp_min) &&
   3217             (failover_vp < soc_mem_index_count(unit, SOURCE_VPm))) {
   3218              return BCM_E_NONE;
   3219         } else {
   3220              return BCM_E_PARAM;
   3221         }
   3222     }
   3223     return BCM_E_PARAM;
   3224 }
   3225 
   3226 STATIC int
   3227 _bcm_tr2_mim_l2_nh_info_add(int unit, bcm_mim_port_t *mim_port, int vp, int drop,
   3228                            int *nh_index, bcm_port_t *local_port, int *is_local) 
   3229 {
   3230     initial_ing_l3_next_hop_entry_t initial_ing_nh;
   3231     ing_l3_next_hop_entry_t ing_nh;
   3232     egr_l3_next_hop_entry_t egr_nh;
   3233     egr_mac_da_profile_entry_t mac_da_ent;
   3234     void *macda;
   3235     soc_mem_t mem;
   3236     _bcm_tr2_ing_nh_info_t ing_nh_info;
   3237     _bcm_tr2_egr_nh_info_t egr_nh_info;
   3238     bcm_l3_egress_t nh_info;
   3239     _bcm_l3_intf_cfg_t if_info;
   3240     uint32 nh_flags;
   3241     int gport_id, rv;
   3242     bcm_module_t mod_out;
   3243     bcm_port_t port_out;
   3244     bcm_trunk_t trunk_id;
   3245     int action_present, action_not_present;
   3246     int old_tpid_idx = -1, old_macda_idx = -1;
   3247     void *entries[1];
   3248     uint64 temp_mac;
   3249     _bcm_port_info_t *info;
   3250     int failover_nh_index;
   3251     uint32 failover_vp;
   3252     ing_dvp_table_entry_t failover_dvp;
   3253     uint32 protection_flags=0;
   3254     uint32 port_flags;
   3255     int network_group=0;
   3256 #ifdef BCM_TRIUMPH3_SUPPORT
   3257     uint32 mtu_profile_index = 0;
   3258 #endif /* BCM_TRIUMPH3_SUPPORT */
   3259 #if defined(BCM_KATANA2_SUPPORT)
   3260     int my_modid = 0, is_local_subport = FALSE;
   3261     int pp_port;
   3262     int min_subport = SOC_INFO(unit).pp_port_index_min; 
   3263     int max_subport = SOC_INFO(unit).pp_port_index_max;
   3264 #endif
   3265 
   3266     /* Initialize values */
   3267     *local_port = 0;
   3268     *is_local = 0;
   3269     ing_nh_info.mtu = 0x3fff; 
   3270     ing_nh_info.port = -1;
   3271     ing_nh_info.module = -1;
   3272     ing_nh_info.trunk = -1;
   3273 
   3274     egr_nh_info.dvp = vp;
   3275     if (soc_feature(unit,
   3276                 soc_feature_multiple_split_horizon_group)) {
   3277         network_group = mim_port->network_group_id;
   3278         rv = _bcm_validate_splithorizon_network_group(unit,
   3279                 mim_port->flags & BCM_MIM_PORT_TYPE_BACKBONE,
   3280                 &network_group);
   3281         BCM_IF_ERROR_RETURN(rv);
   3282     }
   3283     egr_nh_info.dvp_is_network =
   3284         (mim_port->flags & BCM_MIM_PORT_TYPE_BACKBONE) ? 1 : 0;
   3285 
   3286     egr_nh_info.sd_tag_action_present = 0;
   3287     egr_nh_info.sd_tag_action_not_present = 0;
   3288     egr_nh_info.intf_num = -1;
   3289     egr_nh_info.sd_tag_vlan = -1;
   3290     egr_nh_info.sd_tag_pri = -1;
   3291     egr_nh_info.sd_tag_cfi = -1;
   3292     egr_nh_info.macda_index = -1;
   3293     egr_nh_info.tpid_index = -1;
   3294     egr_nh_info.vintf_ctr_idx = -1;
   3295 
   3296     if (mim_port->flags & BCM_MIM_PORT_REPLACE) {
   3297         if ((*nh_index > soc_mem_index_max(unit, EGR_L3_NEXT_HOPm)) ||
   3298             (*nh_index < soc_mem_index_min(unit, EGR_L3_NEXT_HOPm)))  {
   3299             return BCM_E_PARAM;
   3300         }
   3301         /* Read the existing egress next_hop entry */
   3302         rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
   3303                           *nh_index, &egr_nh);
   3304         BCM_IF_ERROR_RETURN(rv);
   3305     } else {
   3306         /*
   3307          * Allocate a next-hop entry. By calling bcm_xgs3_nh_add()
   3308          * with _BCM_L3_SHR_WRITE_DISABLE flag, a next-hop index is
   3309          * allocated but nothing is written to hardware. The "nh_info"
   3310          * in this case is not used, so just set to all zeros.
   3311          */
   3312          bcm_l3_egress_t_init(&nh_info);
   3313 
   3314         nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE;
   3315         rv = bcm_xgs3_nh_add(unit, nh_flags, &nh_info, nh_index);
   3316         BCM_IF_ERROR_RETURN(rv);
   3317     }
   3318 
   3319     /* Resolve the gport */
   3320     rv = _bcm_esw_gport_resolve(unit, mim_port->port, &mod_out, 
   3321                                 &port_out, &trunk_id, &gport_id);
   3322     BCM_IF_ERROR_RETURN(rv);
   3323 
   3324 #if defined(BCM_KATANA2_SUPPORT)
   3325     if (BCM_GPORT_IS_SET(mim_port->port) &&
   3326         _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit,
   3327             mim_port->port)) {
   3328         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   3329         if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_out) == BCM_E_NONE) {
   3330             rv = _bcm_kt2_modport_to_pp_port_get(
   3331                      unit, mod_out, port_out, &pp_port);
   3332             BCM_IF_ERROR_RETURN(rv);
   3333 #if defined BCM_METROLITE_SUPPORT
   3334             if (soc_feature(unit, soc_feature_discontinuous_pp_port)) {
   3335                 if (_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, pp_port)) {
   3336                     is_local_subport = TRUE;
   3337                     *is_local = 1;
   3338                     *local_port = pp_port;
   3339                 }
   3340             } else
   3341 #endif
   3342             {
   3343                 if ((pp_port >= min_subport) &&
   3344                     (pp_port <= max_subport)) {
   3345                     is_local_subport = TRUE;
   3346                     *is_local = 1;
   3347                     *local_port = pp_port;
   3348                 }
   3349             }
   3350         }
   3351     }
   3352 
   3353 #endif
   3354     if (BCM_GPORT_IS_TRUNK(mim_port->port)) {
   3355         ing_nh_info.module = -1;
   3356         ing_nh_info.port = -1;
   3357         ing_nh_info.trunk = trunk_id;
   3358         MIM_INFO(unit)->port_info[vp].modid = -1;
   3359         MIM_INFO(unit)->port_info[vp].port = -1;
   3360         MIM_INFO(unit)->port_info[vp].tgid = trunk_id;
   3361     } else {
   3362         ing_nh_info.module = mod_out;
   3363         ing_nh_info.port = port_out;
   3364         ing_nh_info.trunk = -1;
   3365         BCM_IF_ERROR_RETURN(
   3366             _bcm_esw_modid_is_local(unit, mod_out, is_local));
   3367 
   3368         if (TRUE == *is_local) {
   3369             /* Indicated to calling function that this is a local port */
   3370             *is_local = 1;
   3371             *local_port = ing_nh_info.port;
   3372         }
   3373 
   3374         MIM_INFO(unit)->port_info[vp].modid = mod_out;
   3375         MIM_INFO(unit)->port_info[vp].port = port_out;
   3376         MIM_INFO(unit)->port_info[vp].tgid = -1;
   3377     }
   3378 
   3379     if ((mim_port->flags & BCM_MIM_PORT_TYPE_BACKBONE) || 
   3380         (mim_port->flags & BCM_MIM_PORT_TYPE_PEER)) {
   3381         /* Deal with backbone/peer ports (ingress and egress) */
   3382         /* Use the MIM view of EGR_L3_NEXT_HOP */
   3383         if (mim_port->flags & BCM_MIM_PORT_REPLACE) {
   3384 
   3385 #if defined(BCM_TRIDENT3_SUPPORT)
   3386             if (SOC_IS_TRIDENT3X(unit)) {
   3387                 egr_nh_info.entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   3388                     &egr_nh, DATA_TYPEf);
   3389             } else
   3390 #endif /* BCM_TRIDENT3_SUPPORT */
   3391             {
   3392                 egr_nh_info.entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   3393                     &egr_nh, ENTRY_TYPEf);
   3394             }
   3395 
   3396             /* Be sure that the existing entry is programmed to MIM */
   3397             if (egr_nh_info.entry_type != 0x3) { /* != MIM */
   3398                 return BCM_E_PARAM;
   3399             }
   3400             /* Remember old MAC DA profile index */
   3401             old_macda_idx = 
   3402                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   3403                                                  MIM__MAC_DA_PROFILE_INDEXf);
   3404             /* Get Flexible Counter index */
   3405             if (SOC_IS_TRIUMPH2(unit) || SOC_IS_VALKYRIE2(unit)
   3406                 || SOC_IS_TRIDENT(unit)) {
   3407                 egr_nh_info.vintf_ctr_idx =
   3408                     soc_EGR_L3_NEXT_HOPm_field32_get
   3409                             (unit, &egr_nh, VINTF_CTR_IDXf);
   3410             }                
   3411         }
   3412         egr_nh_info.entry_type = 0x3;
   3413  
   3414         mem = EGR_MAC_DA_PROFILEm;
   3415         macda = (void *)&mac_da_ent;
   3416         sal_memset(macda, 0, sizeof(egr_mac_da_profile_entry_t));
   3417         /* Add MAC DA profile */
   3418         soc_mem_mac_addr_set(unit, mem, macda, 
   3419                              MAC_ADDRESSf, mim_port->egress_tunnel_dstmac);
   3420 
   3421         entries[0] = macda;
   3422         rv = _bcm_mac_da_profile_entry_add(unit, entries, 1,
   3423                                            (uint32 *) &egr_nh_info.macda_index);
   3424         if (BCM_FAILURE(rv)) {
   3425             goto cleanup;
   3426         }
   3427 
   3428         /* Add MACSA to an L3 interface entry - ref count if exists */
   3429         if (!BCM_VLAN_VALID(mim_port->egress_tunnel_vlan)) {
   3430             rv = BCM_E_PARAM;
   3431             goto cleanup;
   3432         }
   3433         sal_memset(&if_info, 0, sizeof(_bcm_l3_intf_cfg_t));
   3434         SAL_MAC_ADDR_TO_UINT64(mim_port->egress_tunnel_srcmac, temp_mac);
   3435         SAL_MAC_ADDR_FROM_UINT64(if_info.l3i_mac_addr, temp_mac);
   3436         if_info.l3i_vid = mim_port->egress_tunnel_vlan;
   3437         rv = _bcm_tr2_mim_l3_intf_add(unit, &if_info);
   3438         if (BCM_FAILURE(rv)) {
   3439             goto cleanup;
   3440         }
   3441 
   3442         /* Populate the fields of MIM::EGR_l3_NEXT_HOP */
   3443         if (!(mim_port->flags & BCM_MIM_PORT_REPLACE)) {
   3444             sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   3445         }
   3446 #if defined(BCM_TRIDENT3_SUPPORT)
   3447         if (SOC_IS_TRIDENT3X(unit)) {
   3448             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3449                                 DATA_TYPEf, egr_nh_info.entry_type);
   3450         } else
   3451 #endif /* BCM_TRIDENT3_SUPPORT */
   3452         {
   3453             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3454                                 ENTRY_TYPEf, egr_nh_info.entry_type);
   3455         }        
   3456         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3457                             MIM__DVPf, egr_nh_info.dvp);
   3458         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   3459             /* 
   3460              * Setting DVP_IS_ENNI field for PEER type ports and resetting for 
   3461              * BACKBONE ports. Resetting is done to support scenarios where
   3462              * PEER ports are replaced by BACKBONE ports  
   3463              */
   3464             if (!SOC_IS_TRIDENT3X(unit)) {
   3465                 if(mim_port->flags & BCM_MIM_PORT_TYPE_PEER) {
   3466                    soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3467                                    &egr_nh, MIM__DVP_IS_ENNIf, 1);
   3468                 } else {
   3469                    soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3470                                        &egr_nh, MIM__DVP_IS_ENNIf, 0);
   3471                 }
   3472             }    
   3473         } 
   3474         
   3475         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3476                             MIM__BVID_VALIDf, 1);
   3477         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3478                             MIM__INTF_NUMf, if_info.l3i_index);
   3479         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3480                             MIM__BVIDf, mim_port->egress_tunnel_vlan);
   3481         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3482                             MIM__HG_HDR_SELf, 1); /* HG 2 */
   3483         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3484                             MIM__MAC_DA_PROFILE_INDEXf, egr_nh_info.macda_index);
   3485         if (mim_port->flags & BCM_MIM_PORT_TYPE_PEER) {
   3486             if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, MIM__ISID_LOOKUP_TYPEf)) {
   3487                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3488                                 MIM__ISID_LOOKUP_TYPEf, 1); /* Peer */
   3489             }
   3490 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   3491             if (soc_feature(unit, soc_feature_mim_bvid_insertion_control)) {
   3492                 uint32 regval;
   3493                 BCM_IF_ERROR_RETURN(READ_EGR_CONFIGr(unit, &regval));
   3494                 if (soc_reg_field_get(unit, EGR_CONFIGr, regval,
   3495                             HONOR_NEXTHOP_BVID_VALIDf)) {
   3496                     if (mim_port->flags & BCM_MIM_PORT_PEER_NO_BTAG) {
   3497                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3498                                             MIM__BVID_VALIDf, 0);
   3499                     }
   3500                 }
   3501             }
   3502 #endif
   3503         }
   3504         if (mim_port->flags & BCM_MIM_PORT_EGRESS_TUNNEL_DEST_MAC_USE_SERVICE) {
   3505             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3506                                 MIM__ADD_ISID_TO_MACDAf, 1); 
   3507         }
   3508 
   3509         if (mim_port->flags & BCM_MIM_PORT_FIX_PRIORITY) {
   3510             BCM_IF_ERROR_RETURN
   3511                 (_bcm_tr2_mim_egr_sd_tag_actions(unit, mim_port, &egr_nh_info));
   3512             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3513 		                  SD_TAG__SD_TAG_DOT1P_PRI_SELECTf, 0);
   3514             if (egr_nh_info.sd_tag_pri != -1) {
   3515                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3516                                     &egr_nh, SD_TAG__NEW_PRIf, 
   3517                                     egr_nh_info.sd_tag_pri);
   3518             }
   3519             if (egr_nh_info.sd_tag_cfi != -1) {
   3520                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3521                                     &egr_nh, SD_TAG__NEW_CFIf, 
   3522                                     egr_nh_info.sd_tag_cfi);
   3523             }
   3524         }
   3525     } else if (mim_port->flags & BCM_MIM_PORT_TYPE_ACCESS){
   3526         /* Deal with access ports */
   3527         /* Use the SD_TAG view of EGR_L3_NEXT_HOP */
   3528         if (mim_port->flags & BCM_MIM_PORT_REPLACE) {
   3529 #if defined(BCM_TRIDENT3_SUPPORT)
   3530             if (SOC_IS_TRIDENT3X(unit)) {
   3531                 egr_nh_info.entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   3532                     &egr_nh, DATA_TYPEf);
   3533             } else
   3534 #endif /* BCM_TRIDENT3_SUPPORT */
   3535             {
   3536                 egr_nh_info.entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   3537                     &egr_nh, ENTRY_TYPEf);
   3538             }
   3539             /* Be sure that the existing entry is programmed to SD-tag */
   3540             if (egr_nh_info.entry_type != 0x2) { /* != SD-tag */
   3541                 return BCM_E_PARAM;
   3542             }
   3543             action_present = 
   3544                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   3545                                                  SD_TAG__SD_TAG_ACTION_IF_PRESENTf);
   3546             action_not_present = 
   3547                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   3548                                                  SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf);
   3549             if ((action_not_present == 0x1) || (action_present == 0x1)) {
   3550                 /* If SD tag action is ADD or REPLACE_VID_TPID, the tpid
   3551                  * index of the entry getting replaced is valid. Save
   3552                  * the old tpid index to be deleted later.
   3553                  */
   3554                 old_tpid_idx = 
   3555                     soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 
   3556                                                      SD_TAG__SD_TAG_TPID_INDEXf);
   3557                 /* Get Flexible Counter index */
   3558                if (SOC_IS_TRIUMPH2(unit) || SOC_IS_VALKYRIE2(unit)
   3559                    || SOC_IS_TRIDENT(unit)) {
   3560     	  	        egr_nh_info.vintf_ctr_idx =
   3561  	  	                soc_EGR_L3_NEXT_HOPm_field32_get
   3562                                 (unit, &egr_nh, VINTF_CTR_IDXf);
   3563  	  	        }                
   3564             }
   3565         }
   3566         egr_nh_info.entry_type = 0x2; /* SD-tag */
   3567     
   3568         /* Populate SD_TAG::EGR_L3_NEXT_HOP entry */
   3569         if (!(mim_port->flags & BCM_MIM_PORT_REPLACE)) {
   3570             sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   3571         }
   3572 #if defined(BCM_TRIDENT3_SUPPORT)
   3573         if (SOC_IS_TRIDENT3X(unit)) {
   3574             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3575                                 DATA_TYPEf, egr_nh_info.entry_type);
   3576         } else
   3577 #endif /* BCM_TRIDENT3_SUPPORT */
   3578         {
   3579             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3580                                 ENTRY_TYPEf, egr_nh_info.entry_type);
   3581         }
   3582 
   3583         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3584                             SD_TAG__DVPf, egr_nh_info.dvp);
   3585         /* HG header PPD2 */
   3586         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   3587                             SD_TAG__HG_HDR_SELf, 1);
   3588 
   3589         if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_TAGGED) {
   3590             /* Prepare egress SD tag entry (including parameter checks) */
   3591             BCM_IF_ERROR_RETURN
   3592                 (_bcm_tr2_mim_egr_sd_tag_actions(unit, mim_port, &egr_nh_info));
   3593 
   3594             /* Populate SD-TAG attributes in HW */
   3595             if (egr_nh_info.sd_tag_vlan != -1) {
   3596                 if (soc_feature(unit, soc_feature_vp_sharing)) {
   3597                     if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, SD_TAG__SD_TAG_NOT_VALIDf)) {
   3598                         if (egr_nh_info.sd_tag_vlan == BCM_VLAN_INVALID) {
   3599                             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3600                                            &egr_nh, SD_TAG__SD_TAG_NOT_VALIDf, 1);
   3601                         } else {
   3602                             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3603                                            &egr_nh, SD_TAG__SD_TAG_NOT_VALIDf, 0);
   3604                             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3605                                 &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info.sd_tag_vlan);
   3606                         }
   3607                     } else {
   3608                         if (egr_nh_info.sd_tag_vlan < BCM_VLAN_INVALID) {
   3609                             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3610                                 &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info.sd_tag_vlan); 
   3611                         }
   3612                     }
   3613                 } else {
   3614                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3615                                     &egr_nh, SD_TAG__SD_TAG_VIDf, 
   3616                                     egr_nh_info.sd_tag_vlan);
   3617                }
   3618             }
   3619             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3620                             SD_TAG__SD_TAG_ACTION_IF_PRESENTf,
   3621                             egr_nh_info.sd_tag_action_present);
   3622             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   3623                                 SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf,
   3624                                 egr_nh_info.sd_tag_action_not_present);
   3625             if (egr_nh_info.tpid_index != -1) {
   3626                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3627                                     &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf,
   3628                                     egr_nh_info.tpid_index);
   3629             }
   3630 
   3631 
   3632             if (egr_nh_info.sd_tag_pri != -1) {
   3633                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3634                                     &egr_nh, SD_TAG__NEW_PRIf, 
   3635                                     egr_nh_info.sd_tag_pri);
   3636             }
   3637 
   3638             if (egr_nh_info.sd_tag_cfi != -1) {
   3639                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3640                                     &egr_nh, SD_TAG__NEW_CFIf, 
   3641                                     egr_nh_info.sd_tag_cfi);
   3642 
   3643             }
   3644 
   3645 #if defined(BCM_KATANA2_SUPPORT)
   3646             if (is_local_subport) {
   3647                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   3648                             SD_TAG__HG_MODIFY_ENABLEf, 1);
   3649             } else
   3650 #endif
   3651 
   3652             {
   3653                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   3654                             SD_TAG__HG_MODIFY_ENABLEf, (*is_local) ? 1 : 0);
   3655             }
   3656         }
   3657     }
   3658 
   3659     /* Network Group ID can be set irrespective of port type */
   3660     if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   3661         if (!SOC_IS_TRIDENT3X(unit)) {
   3662             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3663                                 &egr_nh, MIM__DVP_NETWORK_GROUPf,
   3664                                 network_group);
   3665         }
   3666     } else {
   3667         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3668                 &egr_nh, MIM__DVP_IS_NETWORK_PORTf,
   3669                 egr_nh_info.dvp_is_network);
   3670     }
   3671     
   3672     /* Write INITIAL_ING_L3_NEXT_HOP entry */
   3673     sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t));
   3674     if (soc_feature(unit, soc_feature_generic_dest)) {
   3675         if (ing_nh_info.trunk == -1) {
   3676             soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh,
   3677                 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
   3678                 ing_nh_info.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_info.port);
   3679         } else {
   3680             soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh,
   3681                 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_info.trunk);
   3682         }
   3683     } else {
   3684         if (ing_nh_info.trunk == -1) {
   3685             soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   3686                                 &initial_ing_nh, PORT_NUMf, ing_nh_info.port);
   3687             soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   3688                                 &initial_ing_nh, MODULE_IDf, ing_nh_info.module);
   3689         } else {
   3690             soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   3691                                 &initial_ing_nh, Tf, 1);
   3692             soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   3693                                 &initial_ing_nh, TGIDf, ing_nh_info.trunk);
   3694             BCM_GPORT_TRUNK_SET(*local_port, ing_nh_info.trunk);
   3695         }
   3696     }
   3697     rv = soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm,
   3698                        MEM_BLOCK_ALL, *nh_index, &initial_ing_nh);
   3699     if (rv < 0) {
   3700         goto cleanup;
   3701     }
   3702 
   3703     /* Configure drop bits */
   3704     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, SD_TAG__BC_DROPf, 
   3705                         drop ? 1 : 0);
   3706     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, SD_TAG__UUC_DROPf, 
   3707                         drop ? 1 : 0);
   3708     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, SD_TAG__UMC_DROPf, 
   3709                         drop ? 1 : 0); 
   3710 
   3711     /* Set Flexible Counter index */
   3712     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_VALKYRIE2(unit)
   3713         || SOC_IS_TRIDENT(unit)) {
   3714         if (egr_nh_info.vintf_ctr_idx != -1) {
   3715             soc_EGR_L3_NEXT_HOPm_field32_set
   3716                     (unit, &egr_nh, VINTF_CTR_IDXf, egr_nh_info.vintf_ctr_idx);
   3717         }
   3718     }                
   3719 
   3720     /* Write EGR_L3_NEXT_HOP entry */
   3721     rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   3722                        MEM_BLOCK_ALL, *nh_index, &egr_nh);
   3723     if (rv < 0) {
   3724         goto cleanup;
   3725     }
   3726 
   3727     /* Write ING_L3_NEXT_HOP entry */
   3728     sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t));
   3729     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, drop);
   3730     if (soc_feature(unit, soc_feature_generic_dest)) {
   3731         if (ing_nh_info.trunk == -1) {
   3732             soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   3733                 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
   3734                 ing_nh_info.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_info.port);
   3735         } else {
   3736             soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   3737                 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_info.trunk);
   3738         }
   3739     } else {
   3740         if (ing_nh_info.trunk == -1) {
   3741             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   3742                                 &ing_nh, PORT_NUMf, ing_nh_info.port);
   3743             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   3744                                 &ing_nh, MODULE_IDf, ing_nh_info.module);
   3745         } else {    
   3746             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   3747                                 &ing_nh, Tf, 1);
   3748             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   3749                                 &ing_nh, TGIDf, ing_nh_info.trunk);
   3750         }
   3751     }
   3752     if (drop) {
   3753         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, drop);
   3754     }
   3755     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   3756                        &ing_nh, ENTRY_TYPEf, 0x2); /* L2 DVP */
   3757     if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) {
   3758         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   3759                 &ing_nh, MTU_SIZEf, 0x3fff);
   3760     }
   3761 #ifdef BCM_TRIUMPH3_SUPPORT
   3762     else if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, 
   3763                  DVP_ATTRIBUTE_1_INDEXf)) {
   3764         BCM_IF_ERROR_RETURN(
   3765           _bcm_tr3_mtu_profile_index_get(unit, 0x3fff, &mtu_profile_index));
   3766         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 
   3767                       DVP_ATTRIBUTE_1_INDEXf, mtu_profile_index);
   3768     }
   3769 #endif /*BCM_TRIUMPH3_SUPPORT */
   3770     rv = soc_mem_write (unit, ING_L3_NEXT_HOPm,
   3771                        MEM_BLOCK_ALL, *nh_index, &ing_nh);
   3772     if (rv < 0) {
   3773         goto cleanup;
   3774     }
   3775 
   3776     /* Update the physical port's SW state */
   3777 #if defined(BCM_KATANA2_SUPPORT)
   3778     if (soc_feature(unit, soc_feature_linkphy_coe) ||
   3779         soc_feature(unit, soc_feature_subtag_coe)) {
   3780         if (is_local_subport) {
   3781             _bcm_port_info_access(unit,
   3782                 MIM_INFO(unit)->port_info[vp].port, &info);
   3783             info->vp_count++;
   3784             rv = bcm_esw_port_vlan_member_get(
   3785                      unit, MIM_INFO(unit)->port_info[vp].port, &port_flags);
   3786             if (rv < 0) {
   3787                 goto cleanup;
   3788             }
   3789             rv = bcm_esw_port_vlan_member_set(
   3790                     unit, MIM_INFO(unit)->port_info[vp].port, port_flags);
   3791             if (rv < 0) {
   3792                 goto cleanup;
   3793             }
   3794         }
   3795     }
   3796 #endif
   3797     if (*is_local) {
   3798         bcm_port_t phys_port = MIM_INFO(unit)->port_info[vp].port; 
   3799         if (soc_feature(unit, soc_feature_sysport_remap)) { 
   3800             BCM_XLATE_SYSPORT_S2P(unit, &phys_port); 
   3801         }
   3802         _bcm_port_info_access(unit, phys_port, &info);
   3803         info->vp_count++;
   3804         rv = bcm_esw_port_vlan_member_get(unit, phys_port, &port_flags);
   3805         if (rv < 0) {
   3806             goto cleanup;
   3807         }
   3808         rv = bcm_esw_port_vlan_member_set(unit, phys_port, port_flags);
   3809         if (rv < 0) {
   3810             goto cleanup;
   3811         }
   3812     }
   3813 
   3814     /* If associated with a trunk, update each local physical port's SW state */
   3815     if (ing_nh_info.trunk != -1) {
   3816 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
   3817         bcm_port_t      local_member_array[SOC_MAX_NUM_PP_PORTS];
   3818         int             max_num_ports = SOC_MAX_NUM_PP_PORTS;
   3819 #else
   3820         bcm_port_t      local_member_array[SOC_MAX_NUM_PORTS];
   3821         int             max_num_ports = SOC_MAX_NUM_PORTS;
   3822 #endif
   3823         int local_member_count;
   3824         int idx;
   3825 
   3826         rv = _bcm_esw_trunk_local_members_get(unit, trunk_id,
   3827                 max_num_ports, local_member_array, &local_member_count);
   3828         if (rv < 0) {
   3829             goto cleanup;
   3830         }
   3831         for (idx = 0; idx < local_member_count; idx++) {
   3832             _bcm_port_info_access(unit, local_member_array[idx], &info);
   3833             info->vp_count++;
   3834             rv = bcm_esw_port_vlan_member_get(
   3835                      unit, local_member_array[idx], &port_flags);
   3836             if (rv < 0) {
   3837                 goto cleanup;
   3838             }
   3839             rv = bcm_esw_port_vlan_member_set(
   3840                      unit, local_member_array[idx], port_flags);
   3841             if (rv < 0) {
   3842                 goto cleanup;
   3843             }
   3844         }
   3845     }
   3846 
   3847 #if defined(BCM_ENDURO_SUPPORT)
   3848     if (!SOC_IS_ENDURO(unit)) {
   3849 #endif
   3850     if (BCM_SUCCESS(_bcm_tr2_mim_failover_check(unit, mim_port))) {
   3851          /* Get egress next-hop index from Failover MIM gport */
   3852          failover_vp = BCM_GPORT_MIM_PORT_ID_GET(mim_port->failover_gport_id);
   3853          rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, failover_vp, 
   3854                                   &failover_dvp);
   3855          if (rv < 0) {
   3856              goto cleanup;
   3857          }
   3858          failover_nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &failover_dvp,
   3859                                                             NEXT_HOP_INDEXf);
   3860          if (_BCM_MULTICAST_IS_SET(mim_port->failover_mc_group)) {
   3861               protection_flags |= _BCM_FAILOVER_1_PLUS_PROTECTION;
   3862          }
   3863          rv = _bcm_esw_failover_prot_nhi_create(unit, protection_flags, (uint32) *nh_index, 
   3864                               failover_nh_index, mim_port->failover_mc_group, mim_port->failover_id);
   3865          if (rv < 0) {
   3866              goto cleanup;
   3867          }
   3868     }
   3869 #if defined(BCM_ENDURO_SUPPORT)
   3870     }
   3871 #endif
   3872     /* Delete old TPID, MAC indexes */
   3873     if (old_macda_idx != -1) {
   3874         rv = _bcm_mac_da_profile_entry_delete(unit, old_macda_idx);
   3875         BCM_IF_ERROR_RETURN(rv);
   3876     }
   3877     if (old_tpid_idx != -1) {
   3878         (void)_bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx);
   3879     }
   3880     return rv;
   3881 
   3882 cleanup:
   3883     if (!(mim_port->flags & BCM_MIM_PORT_REPLACE)) {
   3884         (void) bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, *nh_index);
   3885     }
   3886     if (egr_nh_info.tpid_index != -1) {
   3887         (void) _bcm_fb2_outer_tpid_entry_delete(unit, egr_nh_info.tpid_index);
   3888     }
   3889     if (egr_nh_info.macda_index != -1) {
   3890         (void) _bcm_mac_da_profile_entry_delete(unit, egr_nh_info.macda_index);
   3891     }
   3892     return rv;
   3893 }
   3894 
   3895 STATIC int
   3896 _bcm_tr2_mim_l2_nh_info_delete(int unit, int nh_index)
   3897 {
   3898     int rv, old_macda_idx = -1;
   3899     int action_present, action_not_present, old_tpid_idx = -1;
   3900     initial_ing_l3_next_hop_entry_t initial_ing_nh;
   3901     ing_l3_next_hop_entry_t ing_nh;
   3902     egr_l3_next_hop_entry_t egr_nh;
   3903     int entry_type = 0;
   3904 
   3905     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 
   3906                                   MEM_BLOCK_ANY, nh_index, &egr_nh));
   3907     BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 
   3908                                   MEM_BLOCK_ANY, nh_index, &ing_nh));
   3909     BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_ING_L3_NEXT_HOPm, 
   3910                                   MEM_BLOCK_ANY, nh_index, &initial_ing_nh));
   3911 
   3912 #if defined(BCM_TRIDENT3_SUPPORT)
   3913     if (SOC_IS_TRIDENT3X(unit)) {
   3914         entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   3915             &egr_nh, DATA_TYPEf);
   3916     } else
   3917 #endif /* BCM_TRIDENT3_SUPPORT */
   3918     {
   3919         entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   3920             &egr_nh, ENTRY_TYPEf);
   3921     }
   3922 
   3923     if (entry_type == 0x2) {
   3924         /* Access port */
   3925         action_present =
   3926             soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   3927                                      SD_TAG__SD_TAG_ACTION_IF_PRESENTf);
   3928         action_not_present =
   3929             soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   3930                                      SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf);
   3931         if ((action_not_present == 0x1) || (action_present == 0x1)
   3932 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   3933             || (action_present == 0x7)
   3934 #endif
   3935            ) {
   3936             /* If SD tag action is ADD or REPLACE_VID_TPID, the tpid
   3937              * index of the entry is valid. Save
   3938              * the old tpid index to be deleted later.
   3939              */
   3940             old_tpid_idx =
   3941                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   3942                                              SD_TAG__SD_TAG_TPID_INDEXf);
   3943         }
   3944     } else if (entry_type == 0x3) {
   3945         /* Network or peer port */
   3946         old_macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   3947                                                      MIM__MAC_DA_PROFILE_INDEXf);
   3948     } else {
   3949         return BCM_E_NOT_FOUND;
   3950     }
   3951 
   3952     /* Clear EGR_L3_NEXT_HOP entry */
   3953     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   3954     BCM_IF_ERROR_RETURN (soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   3955                                    MEM_BLOCK_ALL, nh_index, &egr_nh));
   3956 
   3957     /* Clear ING_L3_NEXT_HOP entry */
   3958     sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t));
   3959     BCM_IF_ERROR_RETURN (soc_mem_write (unit, ING_L3_NEXT_HOPm,
   3960                                    MEM_BLOCK_ALL, nh_index, &ing_nh));
   3961 
   3962     /* Clear INITIAL_ING_L3_NEXT_HOP entry */
   3963     sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t));
   3964     BCM_IF_ERROR_RETURN (soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm,
   3965                                    MEM_BLOCK_ALL, nh_index, &initial_ing_nh));
   3966 
   3967 #if defined(BCM_ENDURO_SUPPORT)
   3968     if (!SOC_IS_ENDURO(unit)) {
   3969 #endif
   3970         if (soc_feature(unit, soc_feature_failover))  {
   3971             /* Delete the protection next-hop (if applicable) */
   3972             rv = _bcm_esw_failover_prot_nhi_cleanup(unit, nh_index);
   3973             if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE)) {
   3974                 return rv;
   3975             }
   3976         }
   3977 #if defined(BCM_ENDURO_SUPPORT)
   3978     }
   3979 #endif
   3980     /* Delete old TPID */
   3981     if (old_tpid_idx != -1) {
   3982         (void) _bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx);
   3983     }
   3984 
   3985     /* Delete old MAC profile reference */
   3986     if (old_macda_idx != -1) {
   3987         rv = _bcm_mac_da_profile_entry_delete(unit, old_macda_idx);
   3988         BCM_IF_ERROR_RETURN(rv);
   3989     }
   3990 
   3991     /* Free the next-hop entry. */
   3992     rv = bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, nh_index);
   3993     return rv;
   3994 }
   3995 
   3996 /*
   3997  * Function:
   3998  *      __bcm_tr2_mim_match_trunk_add
   3999  * Purpose:
   4000  *      Assign SVP of an MIM Trunk port
   4001  * Parameters:
   4002  *      unit    - (IN) Device Number
   4003  *      tgid - (IN) Trunk group Id
   4004  *      vp  - (IN) Source Virtual Port
   4005  * Returns:
   4006  *      BCM_E_XXX
   4007  */
   4008 
   4009 int
   4010 _bcm_tr2_mim_match_trunk_add(int unit, bcm_trunk_t tgid, int vp)
   4011 {
   4012     bcm_module_t my_modid;
   4013 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
   4014     bcm_port_t      local_member_array[SOC_MAX_NUM_PP_PORTS];
   4015     int             max_num_ports = SOC_MAX_NUM_PP_PORTS;
   4016 #else
   4017     bcm_port_t      local_member_array[SOC_MAX_NUM_PORTS];
   4018     int             max_num_ports = SOC_MAX_NUM_PORTS;
   4019 #endif
   4020 
   4021     int local_member_count;
   4022     int p;
   4023     int rv = BCM_E_NONE;
   4024     int rv_cleanup;
   4025     int stm_index;
   4026 
   4027 
   4028     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   4029 
   4030     BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid,
   4031                 max_num_ports, local_member_array, &local_member_count));
   4032 
   4033     for (p = 0; p < local_member_count; p++) {
   4034         rv = _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
   4035                 local_member_array[p], &stm_index);
   4036         if (BCM_FAILURE(rv)) {
   4037             goto trunk_cleanup;
   4038         }
   4039         rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
   4040                 stm_index, SOURCE_VPf, vp);
   4041         if (BCM_FAILURE(rv)) {
   4042             goto trunk_cleanup;
   4043         }
   4044 
   4045         if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, SVP_VALIDf)) {
   4046             rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
   4047                                         stm_index, SVP_VALIDf, 1);
   4048             if (BCM_FAILURE(rv)) {
   4049                 goto trunk_cleanup;
   4050             }
   4051         }
   4052 #if defined(BCM_TRIDENT3_SUPPORT)
   4053         if(SOC_IS_TRIDENT3X(unit)) {
   4054             rv = _bcm_esw_port_tab_set(
   4055                      unit, local_member_array[p],
   4056                     _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0x1); /* L2_SVP */
   4057         } else
   4058 #endif
   4059         {
   4060             rv = soc_mem_field32_modify(unit, PORT_TABm, local_member_array[p],
   4061                     PORT_OPERATIONf, 0x1); /* L2_SVP */
   4062         }
   4063         if (BCM_FAILURE(rv)) {
   4064             goto trunk_cleanup;
   4065         }
   4066     }
   4067 
   4068     return BCM_E_NONE;
   4069 
   4070   trunk_cleanup:
   4071     for (;p >= 0; p--) {
   4072         rv_cleanup = _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
   4073                 local_member_array[p], &stm_index);
   4074         if (BCM_SUCCESS(rv_cleanup)) {
   4075             (void) soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
   4076                     stm_index, SOURCE_VPf, 0);
   4077 #if defined(BCM_TRIDENT3_SUPPORT)
   4078             if(SOC_IS_TRIDENT3X(unit)) {
   4079                 (void)_bcm_esw_port_tab_set(
   4080                          unit, local_member_array[p],
   4081                         _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0);
   4082             } else
   4083 #endif
   4084             {
   4085                 (void) soc_mem_field32_modify(unit, PORT_TABm, local_member_array[p],
   4086                         PORT_OPERATIONf, 0);
   4087             }
   4088         }
   4089     }
   4090     return rv;
   4091 }
   4092 
   4093 /*
   4094  * Function:
   4095  *      _bcm_tr_mim_match_trunk_delete
   4096  * Purpose:
   4097  *      Remove SVP of an MIM Trunk port
   4098  * Parameters:
   4099  *      unit    - (IN) Device Number
   4100  *      tgid - (IN) Trunk group Id
   4101  *      vp  - (IN) Source Virtual Port
   4102  * Returns:
   4103  *      BCM_E_XXX
   4104  */
   4105 
   4106 int
   4107 _bcm_tr_mim_match_trunk_delete(int unit, bcm_trunk_t tgid, int vp)
   4108 {
   4109     bcm_module_t my_modid;
   4110 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
   4111     bcm_port_t      local_member_array[SOC_MAX_NUM_PP_PORTS];
   4112     int             max_num_ports = SOC_MAX_NUM_PP_PORTS;
   4113 #else
   4114     bcm_port_t      local_member_array[SOC_MAX_NUM_PORTS];
   4115     int             max_num_ports = SOC_MAX_NUM_PORTS;
   4116 #endif
   4117 
   4118     int local_member_count;
   4119     int p;
   4120     int rv = BCM_E_NONE;
   4121     int rv_cleanup;
   4122     int stm_index;
   4123 
   4124     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   4125 
   4126     BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid,
   4127                 max_num_ports, local_member_array, &local_member_count));
   4128 
   4129     for (p = 0; p < local_member_count; p++) {
   4130         rv = _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
   4131                 local_member_array[p], &stm_index);
   4132         if (BCM_FAILURE(rv)) {
   4133             goto trunk_cleanup;
   4134         }
   4135         rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
   4136                 stm_index, SOURCE_VPf, 0);
   4137         if (BCM_FAILURE(rv)) {
   4138             goto trunk_cleanup;
   4139         }
   4140 
   4141         if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, SVP_VALIDf)) {
   4142             rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
   4143                     stm_index, SVP_VALIDf, 0);
   4144             if (BCM_FAILURE(rv)) {
   4145                 goto trunk_cleanup;
   4146             }
   4147         }
   4148 #if defined(BCM_TRIDENT3_SUPPORT)
   4149         if(SOC_IS_TRIDENT3X(unit)) {
   4150             rv = _bcm_esw_port_tab_set(
   4151                      unit, local_member_array[p],
   4152                     _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0); /* L2_SVP */
   4153         } else
   4154 #endif
   4155         {
   4156             rv = soc_mem_field32_modify(unit, PORT_TABm, local_member_array[p],
   4157                     PORT_OPERATIONf, 0x0); /* L2_SVP */
   4158         }
   4159         if (BCM_FAILURE(rv)) {
   4160             goto trunk_cleanup;
   4161         }
   4162     }
   4163 
   4164     return BCM_E_NONE;
   4165 
   4166   trunk_cleanup:
   4167     for (;p >= 0; p--) {
   4168         rv_cleanup = _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
   4169                 local_member_array[p], &stm_index);
   4170         if (BCM_SUCCESS(rv_cleanup)) {
   4171             (void) soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
   4172                     stm_index, SOURCE_VPf, vp);
   4173 #if defined(BCM_TRIDENT3_SUPPORT)
   4174             if(SOC_IS_TRIDENT3X(unit)) {
   4175                 (void)_bcm_esw_port_tab_set(
   4176                          unit, local_member_array[p],
   4177                         _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 1); /* L2_SVP */
   4178             } else
   4179 #endif
   4180             {
   4181                 (void) soc_mem_field32_modify(unit, PORT_TABm, local_member_array[p],
   4182                         PORT_OPERATIONf, 1);
   4183             }
   4184         }
   4185     }
   4186 
   4187     return rv;
   4188 }
   4189 
   4190 int
   4191 _bcm_tr2_mim_match_add(int unit, bcm_mim_port_t *mim_port,
   4192                                    int vp, bcm_mim_vpn_t vpn)
   4193 {
   4194     int rv = BCM_E_NONE, i, gport_id;
   4195     bcm_module_t mod_out;
   4196     bcm_port_t port_out;
   4197     bcm_trunk_t trunk_id;
   4198 #if defined(BCM_KATANA2_SUPPORT)
   4199     int my_modid = 0, is_local_subport = FALSE, pp_port;
   4200     int min_subport = SOC_INFO(unit).pp_port_index_min;
   4201     int max_subport = SOC_INFO(unit).pp_port_index_max;
   4202 #endif
   4203 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   4204     int    vfi = 0;
   4205     _bcm_vp_info_t vp_info;
   4206 #endif
   4207     soc_mem_t  xlate_mem;
   4208     soc_mem_t port_mem;
   4209 
   4210 #if defined(BCM_TRIDENT3_SUPPORT)
   4211     if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) {
   4212         port_mem = ING_DEVICE_PORTm;
   4213     } else
   4214 #endif
   4215     {
   4216         port_mem = PORT_TABm;
   4217     }
   4218 #if defined(BCM_TRIDENT3_SUPPORT)
   4219     if (soc_feature(unit, soc_feature_base_valid)) {
   4220        xlate_mem = VLAN_XLATE_1_DOUBLEm;
   4221     } else
   4222 #endif
   4223     {
   4224        xlate_mem = VLAN_XLATEm;
   4225     }
   4226 
   4227     if (mim_port->criteria == BCM_MIM_PORT_MATCH_SHARE) {
   4228         /* There is no criteria to be configurated for shared vp,
   4229                * only updating software state to indicate this is a shared vp */
   4230         MIM_INFO(unit)->port_info[vp].flags |= _BCM_MIM_PORT_TYPE_ACCESS_SHARED;
   4231         return BCM_E_NONE;
   4232     }
   4233 
   4234     rv = _bcm_esw_gport_resolve(unit, mim_port->port, &mod_out,
   4235                                 &port_out, &trunk_id, &gport_id);
   4236     BCM_IF_ERROR_RETURN(rv);
   4237 
   4238 #if defined(BCM_KATANA2_SUPPORT)
   4239     if (BCM_GPORT_IS_SET(mim_port->port) &&
   4240         _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit,
   4241             mim_port->port)) {
   4242         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   4243         if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_out) == BCM_E_NONE) {
   4244             rv = _bcm_kt2_modport_to_pp_port_get(
   4245                     unit, mod_out, port_out, &pp_port);
   4246 #if defined BCM_METROLITE_SUPPORT
   4247             if (soc_feature(unit, soc_feature_discontinuous_pp_port)) {
   4248                 if (_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, pp_port)) {
   4249                     is_local_subport = TRUE;
   4250                 }
   4251             } else
   4252 #endif
   4253             {
   4254                 if ((pp_port >= min_subport) &&
   4255                     (pp_port <= max_subport)) {
   4256                     is_local_subport = TRUE;
   4257                 }
   4258             }
   4259         }
   4260     }
   4261 #endif
   4262 
   4263 
   4264     if ((mim_port->criteria == BCM_MIM_PORT_MATCH_PORT_VLAN) ||
   4265         (mim_port->criteria == BCM_MIM_PORT_MATCH_PORT_VLAN_STACKED)) {
   4266         uint32 vent[SOC_MAX_MEM_WORDS];
   4267         int xlate_index = -1;
   4268         uint32 return_vent[SOC_MAX_MEM_WORDS];
   4269 
   4270         sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   4271 #if defined(BCM_TRIDENT3_SUPPORT)
   4272         if (soc_feature(unit, soc_feature_base_valid)) {
   4273             soc_mem_field32_set(unit, xlate_mem,
   4274                          vent, BASE_VALID_0f, 0x3); 
   4275             soc_mem_field32_set(unit, xlate_mem,
   4276                          vent, BASE_VALID_1f, 0x7);
   4277         } else
   4278 #endif
   4279         {
   4280             soc_mem_field32_set(unit, xlate_mem, vent, VALIDf, 1);
   4281         }
   4282         soc_mem_field32_set(unit, xlate_mem, vent, MPLS_ACTIONf, 0x1); /* SVP */
   4283         soc_mem_field32_set(unit, xlate_mem, vent, DISABLE_VLAN_CHECKSf, 1);
   4284         soc_mem_field32_set(unit, xlate_mem, vent, SOURCE_VPf, vp);
   4285 #if defined(BCM_TRIDENT2_SUPPORT)
   4286         if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit) ||
   4287             SOC_IS_TRIDENT3X(unit)) {
   4288             soc_mem_field32_set(unit, xlate_mem, vent, SOURCE_TYPEf, 1);
   4289             soc_mem_field32_set(unit, xlate_mem, vent, VLAN_ACTION_VALIDf, 1);
   4290         }
   4291 #endif /* BCM_TRIDENT2_SUPPORT */
   4292 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   4293         BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
   4294         if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) {
   4295             _BCM_MIM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
   4296             soc_mem_field32_set(unit, xlate_mem, vent, XLATE__VFIf, vfi);
   4297         }
   4298 #endif
   4299 #if defined(BCM_KATANA2_SUPPORT)
   4300         if (SOC_IS_KATANA2(unit)) {
   4301             soc_mem_field32_set(unit, xlate_mem, vent, SOURCE_TYPEf, 1);
   4302         }
   4303 #endif /* BCM_KATANA2_SUPPORT */
   4304 
   4305         if (mim_port->criteria == BCM_MIM_PORT_MATCH_PORT_VLAN) {
   4306             if (!BCM_VLAN_VALID(mim_port->match_vlan)) {
   4307                 return BCM_E_PARAM;
   4308             }
   4309             soc_mem_field32_set(unit, xlate_mem, vent, KEY_TYPEf,
   4310                                 TR_VLXLT_HASH_KEY_TYPE_OVID);
   4311             if (soc_mem_field_valid(unit, xlate_mem, DATA_TYPEf)) {
   4312                 soc_mem_field32_set(unit, xlate_mem, vent, DATA_TYPEf,
   4313                                     TR_VLXLT_HASH_KEY_TYPE_OVID);
   4314             }
   4315             soc_mem_field32_set(unit, xlate_mem, vent, OVIDf,
   4316                                         mim_port->match_vlan);
   4317             if (!(MIM_INFO(unit)->port_info[vp].flags & 
   4318                 _BCM_MIM_PORT_TYPE_ACCESS_SHARED)) {
   4319                 MIM_INFO(unit)->port_info[vp].flags |= 
   4320                                          _BCM_MIM_PORT_TYPE_ACCESS_PORT_VLAN;
   4321                 MIM_INFO(unit)->port_info[vp].match_vlan = mim_port->match_vlan;
   4322             }
   4323         } else {
   4324             if (!BCM_VLAN_VALID(mim_port->match_vlan) || 
   4325                 !BCM_VLAN_VALID(mim_port->match_inner_vlan)) {
   4326                 return BCM_E_PARAM;
   4327             }
   4328             soc_mem_field32_set(unit, xlate_mem, vent, KEY_TYPEf,
   4329                                         TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
   4330             soc_mem_field32_set(unit, xlate_mem, vent, OVIDf,
   4331                                         mim_port->match_vlan);
   4332             soc_mem_field32_set(unit, xlate_mem, vent, IVIDf,
   4333                                         mim_port->match_inner_vlan);
   4334             if (!(MIM_INFO(unit)->port_info[vp].flags & 
   4335                 _BCM_MIM_PORT_TYPE_ACCESS_SHARED)) {
   4336                 MIM_INFO(unit)->port_info[vp].flags |= 
   4337                                  _BCM_MIM_PORT_TYPE_ACCESS_PORT_VLAN_STACKED;
   4338                 MIM_INFO(unit)->port_info[vp].match_vlan = mim_port->match_vlan;
   4339                 MIM_INFO(unit)->port_info[vp].match_inner_vlan = 
   4340                                  mim_port->match_inner_vlan;
   4341             }
   4342         }
   4343 
   4344         if (BCM_GPORT_IS_TRUNK(mim_port->port)) {
   4345             soc_mem_field32_set(unit, xlate_mem, vent, Tf, 1);
   4346             soc_mem_field32_set(unit, xlate_mem, vent, TGIDf, trunk_id);
   4347         } else {
   4348             soc_mem_field32_set(unit, xlate_mem, vent, MODULE_IDf, mod_out);
   4349             soc_mem_field32_set(unit, xlate_mem, vent, PORT_NUMf, port_out);
   4350         }
   4351         rv = soc_mem_search(unit, xlate_mem, MEM_BLOCK_ANY, &xlate_index,
   4352                             vent, return_vent, 0);
   4353         if (BCM_E_NONE == rv) {
   4354             if (mim_port->flags & BCM_MIM_PORT_REPLACE) {
   4355                 BCM_IF_ERROR_RETURN(
   4356                     soc_mem_write(unit,
   4357                                   xlate_mem, MEM_BLOCK_ALL, xlate_index, vent));
   4358             } else {
   4359                 return BCM_E_EXISTS;
   4360             }
   4361         } else if (BCM_E_NOT_FOUND == rv) {
   4362             if (mim_port->flags & BCM_MIM_PORT_REPLACE) {
   4363                 return BCM_E_NOT_FOUND;
   4364             }
   4365             rv = soc_mem_insert(unit, xlate_mem, MEM_BLOCK_ALL, vent);
   4366             BCM_IF_ERROR_RETURN(rv);
   4367             _bcm_tr2_mim_port_match_count_adjust(unit, vp, 1);
   4368         } else {
   4369             return rv;
   4370         }
   4371     } else if (mim_port->criteria == BCM_MIM_PORT_MATCH_PORT) {
   4372         if (mim_port->flags & BCM_MIM_PORT_REPLACE) {
   4373             if (!((MIM_INFO(unit)->port_info[vp].flags & _BCM_MIM_PORT_TYPE_ACCESS_PORT_TRUNK) ||
   4374                 (MIM_INFO(unit)->port_info[vp].flags & _BCM_MIM_PORT_TYPE_ACCESS_PORT))) {
   4375                 BCM_IF_ERROR_RETURN(BCM_E_NOT_FOUND);
   4376             }
   4377 
   4378             if (MIM_INFO(unit)->port_info[vp].flags & _BCM_MIM_PORT_TYPE_ACCESS_PORT_TRUNK) {
   4379                 int trunk_id = 0;;
   4380                 trunk_id = MIM_INFO(unit)->port_info[vp].index;
   4381                 rv = _bcm_tr_mim_match_trunk_delete(unit, trunk_id, vp);
   4382                 BCM_IF_ERROR_RETURN(rv);
   4383             }
   4384 
   4385             if (MIM_INFO(unit)->port_info[vp].flags & _BCM_MIM_PORT_TYPE_ACCESS_PORT) {
   4386                 int port= 0;
   4387                 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 
   4388                                             MIM_INFO(unit)->port_info[vp].index, 
   4389                                             SOURCE_VPf, 0);        
   4390                 BCM_IF_ERROR_RETURN(rv);
   4391 
   4392                 if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, SVP_VALIDf)) {
   4393                     rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
   4394                                                 MIM_INFO(unit)->port_info[vp].index, 
   4395                                                 SVP_VALIDf, 0);
   4396                     BCM_IF_ERROR_RETURN(rv);
   4397                 }
   4398 
   4399                 port = MIM_INFO(unit)->port_info[vp].index & SOC_PORT_ADDR_MAX(unit);
   4400 #if defined(BCM_TRIDENT3_SUPPORT)
   4401                 if(SOC_IS_TRIDENT3X(unit)) {
   4402                     rv = _bcm_esw_port_tab_set(
   4403                          unit, port, _BCM_CPU_TABS_NONE,
   4404                          PORT_OPERATIONf, 0x0); /* NORMAL */
   4405                 } else
   4406 #endif
   4407                 {
   4408                     rv = soc_mem_field32_modify(unit, port_mem, port,
   4409                                             PORT_OPERATIONf, 0x0); /* NORMAL */
   4410                 }
   4411                 BCM_IF_ERROR_RETURN(rv);
   4412             }
   4413         }
   4414 
   4415         if (BCM_GPORT_IS_TRUNK(mim_port->port)) {
   4416             rv = _bcm_tr2_mim_match_trunk_add(unit, trunk_id, vp);
   4417             if (rv >= 0) {
   4418                 MIM_INFO(unit)->port_info[vp].flags |= 
   4419                     _BCM_MIM_PORT_TYPE_ACCESS_PORT_TRUNK;
   4420                 MIM_INFO(unit)->port_info[vp].index = trunk_id;
   4421             }
   4422             BCM_IF_ERROR_RETURN(rv);
   4423         } else {
   4424             int is_local;
   4425 
   4426             BCM_IF_ERROR_RETURN
   4427                 ( _bcm_esw_modid_is_local(unit, mod_out, &is_local));
   4428 
   4429             /* Get index to source trunk map table */
   4430             BCM_IF_ERROR_RETURN(
   4431                 _bcm_esw_src_mod_port_table_index_get(unit, mod_out,
   4432                      port_out, &i));
   4433 
   4434             rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
   4435                                         i, SOURCE_VPf, vp);
   4436             BCM_IF_ERROR_RETURN(rv);
   4437 
   4438             if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, SVP_VALIDf)) {
   4439                 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
   4440                                             i, SVP_VALIDf, 1);
   4441                 BCM_IF_ERROR_RETURN(rv);
   4442             }
   4443 
   4444             if (is_local) {
   4445 #if defined(BCM_TRIDENT3_SUPPORT)
   4446                 if(SOC_IS_TRIDENT3X(unit)) {
   4447                     rv = _bcm_esw_port_tab_set(
   4448                          unit, port_out, _BCM_CPU_TABS_NONE,
   4449                          PORT_OPERATIONf, 0x1); /* L2_SVP2_SVP */
   4450                 } else
   4451 #endif
   4452                 {
   4453                     rv = soc_mem_field32_modify(unit, port_mem, port_out,
   4454                                         PORT_OPERATIONf, 0x1); /* L2_SVP */
   4455                 }
   4456                 BCM_IF_ERROR_RETURN(rv);
   4457             }
   4458 #ifdef BCM_KATANA2_SUPPORT
   4459             if (soc_feature(unit, soc_feature_linkphy_coe) ||
   4460                 soc_feature(unit, soc_feature_linkphy_coe)) {
   4461                 if (is_local_subport) {
   4462                     rv = soc_mem_field32_modify(unit, port_mem, port_out,
   4463                                             PORT_OPERATIONf, 0x1); /* L2_SVP */
   4464                     BCM_IF_ERROR_RETURN(rv);
   4465                 }
   4466             }
   4467 #endif
   4468             MIM_INFO(unit)->port_info[vp].flags |= 
   4469                              _BCM_MIM_PORT_TYPE_ACCESS_PORT;
   4470             MIM_INFO(unit)->port_info[vp].index = i;
   4471         }
   4472 
   4473     } else if ((mim_port->criteria == BCM_MIM_PORT_MATCH_LABEL)) {
   4474         uint32 ment[SOC_MAX_MEM_WORDS];
   4475         int index = -1;
   4476         uint32 return_ment[SOC_MAX_MEM_WORDS];
   4477         soc_mem_t mpls_mem = MPLS_ENTRYm;
   4478 
   4479         sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   4480         if (BCM_GPORT_IS_TRUNK(mim_port->port)) {
   4481             soc_mem_field32_set(unit, mpls_mem, ment, Tf, 1);
   4482             soc_mem_field32_set(unit, mpls_mem, ment, TGIDf, trunk_id);
   4483         } else {
   4484             soc_mem_field32_set(unit, mpls_mem, ment, MODULE_IDf, mod_out);
   4485             soc_mem_field32_set(unit, mpls_mem, ment, PORT_NUMf, port_out);
   4486         }
   4487         soc_mem_field32_set(unit, mpls_mem, ment, MPLS_LABELf,
   4488                                     mim_port->match_label);
   4489 #if defined(BCM_TRIDENT3_SUPPORT)
   4490         if (soc_feature(unit, soc_feature_base_valid)) {
   4491             soc_mem_field32_set(unit, mpls_mem, ment, BASE_VALID_0f, 3); 
   4492             soc_mem_field32_set(unit, mpls_mem, ment, BASE_VALID_1f, 7); 
   4493         } else
   4494 #endif
   4495         {
   4496             soc_mem_field32_set(unit, mpls_mem, ment, VALIDf, 0x1);
   4497         }
   4498         soc_mem_field32_set(unit, mpls_mem, ment, SOURCE_VPf, vp);
   4499         soc_mem_field32_set(unit, mpls_mem, ment, MPLS_ACTION_IF_BOSf,
   4500                                     0x1); /* L2 SVP */
   4501         soc_mem_field32_set(unit, mpls_mem, ment, MPLS_ACTION_IF_NOT_BOSf,
   4502                                     0x0); /* INVALID */
   4503         rv = soc_mem_search(unit, mpls_mem, MEM_BLOCK_ANY, &index,
   4504                             ment, return_ment, 0);
   4505         if (BCM_E_NONE == rv) {
   4506             if (mim_port->flags & BCM_MIM_PORT_REPLACE) {
   4507                 BCM_IF_ERROR_RETURN(
   4508                     soc_mem_write(unit,
   4509                                   mpls_mem, MEM_BLOCK_ALL, index, ment));
   4510             } else {
   4511                 return BCM_E_EXISTS;
   4512             }
   4513         } else if (BCM_E_NOT_FOUND == rv) {
   4514             if (mim_port->flags & BCM_MIM_PORT_REPLACE) {
   4515                 return BCM_E_NOT_FOUND;
   4516             }
   4517             rv = soc_mem_insert(unit, mpls_mem, MEM_BLOCK_ALL, ment);
   4518             BCM_IF_ERROR_RETURN(rv);
   4519         } else {
   4520             return rv;
   4521         }
   4522         MIM_INFO(unit)->port_info[vp].flags |= 
   4523                          _BCM_MIM_PORT_TYPE_ACCESS_LABEL;
   4524         MIM_INFO(unit)->port_info[vp].match_label = mim_port->match_label;
   4525 
   4526     } else if ((mim_port->criteria == BCM_MIM_PORT_MATCH_TUNNEL_VLAN_SRCMAC)) {
   4527         uint32 ment[SOC_MAX_MEM_WORDS];
   4528         uint64 temp_mac;
   4529         int index = -1;
   4530         uint32 return_ment[SOC_MAX_MEM_WORDS];
   4531         soc_mem_t mpls_mem = MPLS_ENTRYm;
   4532 
   4533         if (!BCM_VLAN_VALID(mim_port->match_tunnel_vlan)) {
   4534             return BCM_E_PARAM;
   4535         }
   4536 
   4537         sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   4538         soc_mem_field32_set(unit, mpls_mem, ment, KEY_TYPEf, 1); /* MIM NVP */
   4539 #if defined(BCM_TRIDENT3_SUPPORT)
   4540         if (soc_mem_field_valid(unit, mpls_mem, DATA_TYPEf)) {
   4541             soc_mem_field32_set(unit, mpls_mem, ment, DATA_TYPEf, 1);
   4542         }
   4543 #endif
   4544         if (BCM_GPORT_IS_TRUNK(mim_port->port)) {
   4545             soc_mem_field32_set(unit, mpls_mem, ment, MIM_NVP__Tf, 1);
   4546             soc_mem_field32_set(unit, mpls_mem, ment, MIM_NVP__TGIDf, trunk_id);
   4547         } else {
   4548             soc_mem_field32_set(unit, mpls_mem, ment, MIM_NVP__MODULE_IDf, mod_out);
   4549             soc_mem_field32_set(unit, mpls_mem, ment, MIM_NVP__PORT_NUMf, port_out);
   4550         }
   4551         if (mim_port->flags & BCM_MIM_PORT_TYPE_PEER) {
   4552             soc_mem_field32_set(unit, mpls_mem, ment, 
   4553                                         MIM_NVP__ISID_LOOKUP_TYPEf, 1);
   4554             MIM_INFO(unit)->port_info[vp].flags |= 
   4555                              _BCM_MIM_PORT_TYPE_PEER;
   4556 #if defined(BCM_TRIDENT_SUPPORT)
   4557             if (soc_feature(unit, soc_feature_mim_peer_sharing) &&
   4558                 (mim_port->flags & BCM_MIM_PORT_SHARE)) {
   4559                     MIM_INFO(unit)->port_info[vp].flags |=
   4560                         _BCM_MIM_PORT_TYPE_SHARE;
   4561 
   4562             }
   4563 #endif /* BCM_TRIDENT_SUPPORT */
   4564         } else {
   4565             MIM_INFO(unit)->port_info[vp].flags |= 
   4566                              _BCM_MIM_PORT_TYPE_NETWORK;
   4567         }
   4568 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   4569         if (soc_feature(unit, soc_feature_ingress_failover)) {
   4570             int local_failover_id = 0;
   4571             int prot_type         = 0;
   4572             if (mim_port->flags & BCM_MIM_PORT_FAILOVER_DROP) {
   4573                 soc_mem_field32_set(unit, mpls_mem, ment,
   4574                                             MIM_NVP__DROP_DATA_ENABLEf, 1);
   4575             } else {
   4576                 soc_mem_field32_set(unit, mpls_mem, ment,
   4577                                             MIM_NVP__DROP_DATA_ENABLEf, 0);
   4578             }
   4579 
   4580             if (mim_port->ingress_failover_id != 0) {
   4581                 local_failover_id = mim_port->ingress_failover_id;
   4582                 _BCM_GET_FAILOVER_TYPE(local_failover_id, prot_type);
   4583                 _BCM_GET_FAILOVER_ID(local_failover_id);
   4584 
   4585                 if ((prot_type & _BCM_FAILOVER_INGRESS) &&
   4586                     (BCM_SUCCESS(_bcm_td2p_failover_ingress_id_validate(
   4587                     unit, local_failover_id)))) {
   4588                     soc_mem_field32_set(unit, mpls_mem, ment,
   4589                                                 MIM_NVP__RX_PROT_GROUPf,
   4590                                                 local_failover_id);
   4591                 }
   4592             } else {
   4593                 soc_mem_field32_set(unit, mpls_mem, ment,
   4594                                             MIM_NVP__RX_PROT_GROUPf, 0);
   4595             }
   4596          }
   4597 #endif
   4598 #if defined(BCM_TRIDENT3_SUPPORT)
   4599         if (soc_feature(unit, soc_feature_base_valid)) {
   4600             soc_mem_field32_set(unit, mpls_mem, ment, BASE_VALID_0f, 3); 
   4601             soc_mem_field32_set(unit, mpls_mem, ment, BASE_VALID_1f, 7); 
   4602         } else
   4603 #endif
   4604         {
   4605             soc_mem_field32_set(unit, mpls_mem, ment, VALIDf, 0x1);
   4606         }
   4607         soc_mem_field32_set(unit, mpls_mem, ment, MIM_NVP__SVPf, vp);
   4608         soc_mem_field32_set(unit, mpls_mem, ment, MIM_NVP__BVIDf,
   4609                                     mim_port->match_tunnel_vlan);
   4610         soc_mem_mac_addr_set(unit, mpls_mem, ment, MIM_NVP__BMACSAf, 
   4611                              mim_port->match_tunnel_srcmac);
   4612         rv = soc_mem_search(unit, mpls_mem, MEM_BLOCK_ANY, &index,
   4613                             ment, return_ment, 0);
   4614         if (BCM_E_NONE == rv) {
   4615             if (mim_port->flags & BCM_MIM_PORT_REPLACE) {
   4616                 BCM_IF_ERROR_RETURN(
   4617                     soc_mem_write(unit,
   4618                                   mpls_mem, MEM_BLOCK_ALL, index, ment));
   4619             } else {
   4620                 return BCM_E_EXISTS;
   4621             }
   4622         } else if (BCM_E_NOT_FOUND == rv) {
   4623             if (mim_port->flags & BCM_MIM_PORT_REPLACE) {
   4624                 return BCM_E_NOT_FOUND;
   4625             }
   4626             rv = soc_mem_insert(unit, mpls_mem, MEM_BLOCK_ALL, ment);
   4627             BCM_IF_ERROR_RETURN(rv);
   4628         } else {
   4629             return rv;
   4630         }
   4631         SAL_MAC_ADDR_TO_UINT64(mim_port->match_tunnel_srcmac, temp_mac);
   4632         SAL_MAC_ADDR_FROM_UINT64
   4633            (MIM_INFO(unit)->port_info[vp].match_tunnel_srcmac, temp_mac); 
   4634         MIM_INFO(unit)->port_info[vp].match_tunnel_vlan = 
   4635                          mim_port->match_tunnel_vlan;
   4636     }
   4637     return rv;
   4638 }
   4639 
   4640 int
   4641 _bcm_tr2_mim_match_delete(int unit, int vp, bcm_mim_port_t mim_port)
   4642 {
   4643     int port, rv;
   4644     int is_local;
   4645     bcm_module_t mod_out;
   4646     soc_mem_t  xlate_mem;
   4647     soc_mem_t port_mem;
   4648 
   4649 #if defined(BCM_TRIDENT3_SUPPORT)
   4650     if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) {
   4651         port_mem = ING_DEVICE_PORTm;
   4652     } else
   4653 #endif
   4654     {
   4655         port_mem = PORT_TABm;
   4656     }
   4657 #if defined(BCM_TRIDENT3_SUPPORT)
   4658     if (soc_feature(unit, soc_feature_base_valid)) {
   4659        xlate_mem = VLAN_XLATE_1_DOUBLEm;
   4660     } else
   4661 #endif
   4662     {
   4663        xlate_mem = VLAN_XLATEm;
   4664     }
   4665 
   4666     if (MIM_INFO(unit)->port_info[vp].flags & 
   4667         _BCM_MIM_PORT_TYPE_ACCESS_PORT_VLAN) {
   4668         uint32 vent[SOC_MAX_MEM_WORDS];
   4669         sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   4670 
   4671 #if defined(BCM_TRIDENT3_SUPPORT)
   4672         if (soc_feature(unit, soc_feature_base_valid)) {
   4673             soc_mem_field32_set(unit, xlate_mem,
   4674                          vent, BASE_VALID_0f, 0x3); 
   4675             soc_mem_field32_set(unit, xlate_mem,
   4676                          vent, BASE_VALID_1f, 0x7);
   4677         } else
   4678 #endif
   4679         {
   4680             soc_mem_field32_set(unit, xlate_mem, vent, VALIDf, 1);
   4681         }
   4682 
   4683         soc_mem_field32_set(unit, xlate_mem, vent, KEY_TYPEf, 
   4684                                     TR_VLXLT_HASH_KEY_TYPE_OVID);
   4685         if (soc_mem_field_valid(unit, xlate_mem, DATA_TYPEf)) {
   4686             soc_mem_field32_set(unit, xlate_mem, vent, DATA_TYPEf,
   4687                                 TR_VLXLT_HASH_KEY_TYPE_OVID);
   4688         }
   4689         soc_mem_field32_set(unit, xlate_mem, vent, OVIDf,
   4690                                     MIM_INFO(unit)->port_info[vp].match_vlan);
   4691 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
   4692 
   4693         if (SOC_IS_TRIDENT2X(unit) || SOC_IS_KATANA2(unit) || 
   4694             SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   4695             soc_mem_field32_set(unit, xlate_mem, vent, SOURCE_TYPEf, 1);
   4696         }
   4697 #endif /* BCM_TRIDENT2_SUPPORT  || BCM_KATANA2_SUPPORT */
   4698         if (MIM_INFO(unit)->port_info[vp].modid != -1) {
   4699             soc_mem_field32_set(unit, xlate_mem, vent, MODULE_IDf, 
   4700                                         MIM_INFO(unit)->port_info[vp].modid);
   4701             soc_mem_field32_set(unit, xlate_mem, vent, PORT_NUMf, 
   4702                                         MIM_INFO(unit)->port_info[vp].port);
   4703         } else {
   4704             soc_mem_field32_set(unit, xlate_mem, vent, Tf, 1);
   4705             soc_mem_field32_set(unit, xlate_mem, vent, TGIDf, 
   4706                                         MIM_INFO(unit)->port_info[vp].tgid);
   4707         }
   4708         rv = soc_mem_delete(unit, xlate_mem, MEM_BLOCK_ANY, vent);
   4709         if (rv != BCM_E_NOT_FOUND) {
   4710             _bcm_tr2_mim_port_match_count_adjust(unit, vp, -1);
   4711             return rv; /* Match has been deleted by bcm_port_match_delete */
   4712         }
   4713 
   4714     } else if (MIM_INFO(unit)->port_info[vp].flags & 
   4715                _BCM_MIM_PORT_TYPE_ACCESS_PORT_VLAN_STACKED) {
   4716         uint32 vent[SOC_MAX_MEM_WORDS];
   4717         sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   4718 
   4719         soc_mem_field32_set(unit, xlate_mem, vent, KEY_TYPEf, 
   4720                             TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
   4721         if (soc_mem_field_valid(unit, xlate_mem, DATA_TYPEf)) {
   4722             soc_mem_field32_set(unit, xlate_mem, vent, DATA_TYPEf,
   4723                                 TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
   4724         }
   4725         soc_mem_field32_set(unit, xlate_mem, vent, OVIDf,
   4726                                     MIM_INFO(unit)->port_info[vp].match_vlan);
   4727         soc_mem_field32_set(unit, xlate_mem, vent, IVIDf,
   4728                               MIM_INFO(unit)->port_info[vp].match_inner_vlan);
   4729 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
   4730         soc_mem_field32_set(unit, xlate_mem, vent, SOURCE_TYPEf, 1);
   4731         if (SOC_IS_TRIDENT2X(unit) || SOC_IS_KATANA2(unit) || 
   4732             SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   4733             soc_mem_field32_set(unit, xlate_mem, vent, SOURCE_TYPEf, 1);
   4734         }
   4735 #endif /* BCM_TRIDENT2_SUPPORT  || BCM_KATANA2_SUPPORT */
   4736 
   4737         if (MIM_INFO(unit)->port_info[vp].modid != -1) {
   4738             soc_mem_field32_set(unit, xlate_mem, vent, MODULE_IDf, 
   4739                                         MIM_INFO(unit)->port_info[vp].modid);
   4740             soc_mem_field32_set(unit, xlate_mem, vent, PORT_NUMf, 
   4741                                         MIM_INFO(unit)->port_info[vp].port);
   4742         } else {
   4743             soc_mem_field32_set(unit, xlate_mem, vent, Tf, 1);
   4744             soc_mem_field32_set(unit, xlate_mem, vent, TGIDf, 
   4745                                         MIM_INFO(unit)->port_info[vp].tgid);
   4746         }
   4747         rv = soc_mem_delete(unit, xlate_mem, MEM_BLOCK_ANY, vent);
   4748         BCM_IF_ERROR_RETURN(rv);   
   4749 
   4750     } else if (MIM_INFO(unit)->port_info[vp].flags & 
   4751                _BCM_MIM_PORT_TYPE_ACCESS_PORT) {
   4752         rv = _bcm_esw_src_modid_port_get(unit,
   4753                                          MIM_INFO(unit)->port_info[vp].index,
   4754                                          &mod_out, &port);
   4755         BCM_IF_ERROR_RETURN(rv);
   4756         rv = _bcm_esw_modid_is_local(unit, mod_out, &is_local);
   4757         BCM_IF_ERROR_RETURN(rv);
   4758 
   4759         rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 
   4760                                     MIM_INFO(unit)->port_info[vp].index, 
   4761                                     SOURCE_VPf, 0);        
   4762         BCM_IF_ERROR_RETURN(rv);
   4763 
   4764         if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, SVP_VALIDf)) {
   4765             rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
   4766                                         MIM_INFO(unit)->port_info[vp].index, 
   4767                                         SVP_VALIDf, 0);
   4768 
   4769             BCM_IF_ERROR_RETURN(rv);
   4770         }
   4771 
   4772         if (is_local) {
   4773 #if defined(BCM_TRIDENT3_SUPPORT)
   4774             if(SOC_IS_TRIDENT3X(unit)) {
   4775                 rv = _bcm_esw_port_tab_set(
   4776                      unit, port, _BCM_CPU_TABS_NONE,
   4777                          PORT_OPERATIONf, 0x0); /* NORMAL */
   4778             } else
   4779 #endif
   4780             {
   4781                 rv = soc_mem_field32_modify(unit, port_mem, port,
   4782                                         PORT_OPERATIONf, 0x0); /* NORMAL */
   4783                 BCM_IF_ERROR_RETURN(rv);
   4784            }
   4785         }
   4786 
   4787     } else if(MIM_INFO(unit)->port_info[vp].flags & 
   4788               _BCM_MIM_PORT_TYPE_ACCESS_PORT_TRUNK) {
   4789         int trunk_id;
   4790         trunk_id = MIM_INFO(unit)->port_info[vp].index;
   4791         rv = _bcm_tr_mim_match_trunk_delete(unit, trunk_id, vp);
   4792         BCM_IF_ERROR_RETURN(rv);
   4793     } else if (MIM_INFO(unit)->port_info[vp].flags & 
   4794                _BCM_MIM_PORT_TYPE_ACCESS_LABEL) {
   4795         uint32 ment[SOC_MAX_MEM_WORDS];
   4796         soc_mem_t mpls_mem = MPLS_ENTRYm;
   4797 
   4798         sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   4799         if (MIM_INFO(unit)->port_info[vp].modid != -1) {
   4800             soc_mem_field32_set(unit, mpls_mem, ment, MODULE_IDf, 
   4801                                         MIM_INFO(unit)->port_info[vp].modid);
   4802             soc_mem_field32_set(unit, mpls_mem, ment, PORT_NUMf, 
   4803                                         MIM_INFO(unit)->port_info[vp].port);
   4804         } else {
   4805             soc_mem_field32_set(unit, mpls_mem, ment, Tf, 1);
   4806             soc_mem_field32_set(unit, mpls_mem, ment, TGIDf, 
   4807                                         MIM_INFO(unit)->port_info[vp].tgid);
   4808         }
   4809         soc_mem_field32_set(unit, mpls_mem, ment, MPLS_LABELf,
   4810                                     MIM_INFO(unit)->port_info[vp].match_label);
   4811         rv = soc_mem_delete(unit, mpls_mem, MEM_BLOCK_ANY, ment);
   4812         BCM_IF_ERROR_RETURN(rv);
   4813     } else if (MIM_INFO(unit)->port_info[vp].flags & 
   4814                    _BCM_MIM_PORT_TYPE_ACCESS_SHARED) {
   4815         uint32 vent[SOC_MAX_MEM_WORDS];
   4816         bcm_module_t mod_out = -1;
   4817         bcm_port_t port_out = -1;
   4818         int    gport_id =-1;
   4819         bcm_trunk_t trunk_id;
   4820 
   4821         sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   4822 
   4823         soc_mem_field32_set(unit, xlate_mem, vent, SOURCE_TYPEf, 1);
   4824 #if defined(BCM_TRIDENT3_SUPPORT)
   4825         if (soc_feature(unit, soc_feature_base_valid)) {
   4826             soc_mem_field32_set(unit, xlate_mem,
   4827                          vent, BASE_VALID_0f, 0x3); 
   4828             soc_mem_field32_set(unit, xlate_mem,
   4829                          vent, BASE_VALID_1f, 0x7);
   4830         } else
   4831 #endif
   4832         {
   4833             soc_mem_field32_set(unit, xlate_mem, vent, VALIDf, 1);
   4834         }
   4835         if (BCM_MIM_PORT_MATCH_PORT_VLAN == mim_port.criteria) {
   4836             soc_mem_field32_set(unit, xlate_mem, vent, KEY_TYPEf, 
   4837                                         TR_VLXLT_HASH_KEY_TYPE_OVID);
   4838             soc_mem_field32_set(unit, xlate_mem, vent, XLATE__OVIDf,
   4839                                         mim_port.match_vlan);
   4840         } else if (BCM_MIM_PORT_MATCH_PORT_VLAN_STACKED == mim_port.criteria) {
   4841             soc_mem_field32_set(unit, xlate_mem, vent, KEY_TYPEf, 
   4842                                         TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
   4843             soc_mem_field32_set(unit, xlate_mem, vent, XLATE__OVIDf,
   4844                                         mim_port.match_vlan);
   4845             soc_mem_field32_set(unit, xlate_mem, vent, XLATE__IVIDf,
   4846                                         mim_port.match_inner_vlan);
   4847         } else {
   4848             return BCM_E_UNAVAIL;
   4849         }
   4850 
   4851         rv = _bcm_esw_gport_resolve(unit, mim_port.port, &mod_out,
   4852                                     &port_out, &trunk_id, &gport_id);
   4853         BCM_IF_ERROR_RETURN(rv);
   4854         
   4855         if (BCM_GPORT_IS_TRUNK(mim_port.port)) {
   4856             soc_mem_field32_set(unit, xlate_mem, vent, Tf, 1);
   4857             soc_mem_field32_set(unit, xlate_mem, vent, TGIDf, trunk_id);
   4858         } else {
   4859             soc_mem_field32_set(unit, xlate_mem, vent, MODULE_IDf, mod_out);
   4860             soc_mem_field32_set(unit, xlate_mem, vent, PORT_NUMf, port_out);
   4861         }
   4862 
   4863         rv = soc_mem_delete(unit, xlate_mem, MEM_BLOCK_ANY, vent);
   4864         BCM_IF_ERROR_RETURN(rv);
   4865         _bcm_tr2_mim_port_match_count_adjust(unit, vp, -1);
   4866     } else if (MIM_INFO(unit)->port_info[vp].flags & 
   4867                (_BCM_MIM_PORT_TYPE_NETWORK | _BCM_MIM_PORT_TYPE_PEER)) {
   4868         uint32 ment[SOC_MAX_MEM_WORDS];
   4869         soc_mem_t mpls_mem = MPLS_ENTRYm;
   4870 
   4871         sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   4872         soc_mem_field32_set(unit, mpls_mem, ment, KEY_TYPEf, 1); /* MIM NVP */
   4873 #if defined(BCM_TRIDENT3_SUPPORT)
   4874         if (soc_feature(unit, soc_feature_base_valid)) {
   4875             soc_mem_field32_set(unit, mpls_mem, ment, BASE_VALID_0f, 3); 
   4876             soc_mem_field32_set(unit, mpls_mem, ment, BASE_VALID_1f, 7); 
   4877         } else
   4878 #endif
   4879         {
   4880             soc_mem_field32_set(unit, mpls_mem, ment, VALIDf, 0x1);
   4881         }
   4882         soc_mem_field32_set(unit, mpls_mem, ment, MIM_NVP__BVIDf,
   4883                                MIM_INFO(unit)->port_info[vp].match_tunnel_vlan);
   4884         soc_mem_mac_addr_set(unit, mpls_mem, ment, MIM_NVP__BMACSAf, 
   4885                              MIM_INFO(unit)->port_info[vp].match_tunnel_srcmac);
   4886         rv = soc_mem_delete(unit, mpls_mem, MEM_BLOCK_ALL, ment);
   4887         BCM_IF_ERROR_RETURN(rv);
   4888     }
   4889     return BCM_E_NONE;
   4890 }
   4891 
   4892 STATIC int
   4893 _bcm_tr2_mim_peer_port_config_add(int unit, bcm_mim_port_t *mim_port, 
   4894                                   int vp, bcm_mim_vpn_t vpn) {
   4895     uint32 ment[SOC_MAX_MEM_WORDS];
   4896     uint32 egr_vlan_xlate_entry[SOC_MAX_MEM_WORDS];
   4897     int index, vfi, rv = BCM_E_NONE;
   4898     soc_mem_t egr_xlate_mem;
   4899     soc_mem_t mpls_mem = MPLS_ENTRYm;
   4900 
   4901 #if defined(BCM_TRIDENT3_SUPPORT)
   4902     if (soc_feature(unit, soc_feature_base_valid)) {
   4903         egr_xlate_mem = EGR_VLAN_XLATE_1_DOUBLEm;
   4904     } else
   4905 #endif
   4906     {
   4907         egr_xlate_mem = EGR_VLAN_XLATEm;
   4908     }
   4909 
   4910     /* Need an ISID-SVP entry in MPLS_ENTRY */
   4911     _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vpn);
   4912     sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   4913 
   4914     soc_mem_field32_set(unit, mpls_mem, ment, KEY_TYPEf, 3); /* MIM_ISID_SVP */
   4915 #if defined(BCM_TRIDENT3_SUPPORT)
   4916     if (soc_feature(unit, soc_feature_base_valid)) {
   4917         soc_mem_field32_set(unit, mpls_mem, ment, BASE_VALID_0f, 3); 
   4918         soc_mem_field32_set(unit, mpls_mem, ment, BASE_VALID_1f, 7); 
   4919     } else
   4920 #endif
   4921     {
   4922         soc_mem_field32_set(unit, mpls_mem, ment, VALIDf, 0x1);
   4923     }
   4924     if (mim_port->flags & BCM_MIM_PORT_EGRESS_TUNNEL_SERVICE_REPLACE) {
   4925         soc_mem_field32_set(unit, mpls_mem, ment, MIM_ISID__ISIDf,
   4926             (mim_port->egress_tunnel_service & 0xffffff));
   4927     } else {
   4928         soc_mem_field32_set(unit, mpls_mem, ment, MIM_ISID__ISIDf,
   4929                                     VPN_ISID(unit, vfi));
   4930     }
   4931     soc_mem_field32_set(unit, mpls_mem, ment, MIM_ISID__SVPf, vp);
   4932     soc_mem_field32_set(unit, mpls_mem, ment, MIM_ISID__VFIf, vfi);
   4933     rv = soc_mem_search(unit, mpls_mem, MEM_BLOCK_ANY, &index,
   4934                         ment, ment, 0);
   4935     if (rv == SOC_E_NONE) {
   4936         return BCM_E_EXISTS;
   4937     } else if (rv != SOC_E_NOT_FOUND) {
   4938         return rv;
   4939     }
   4940     BCM_IF_ERROR_RETURN(soc_mem_insert(unit, mpls_mem, MEM_BLOCK_ALL, ment));
   4941 
   4942     /* Also need the reverse entry in the egress */
   4943     sal_memset(egr_vlan_xlate_entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   4944     soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, MIM_ISID__VFIf, 
   4945                                     vfi);
   4946 #if defined(BCM_TRIDENT3_SUPPORT)
   4947     if (soc_feature(unit, soc_feature_base_valid)) {
   4948         soc_mem_field32_set(unit, egr_xlate_mem,
   4949                egr_vlan_xlate_entry, BASE_VALID_0f, 0x3);
   4950         soc_mem_field32_set(unit, egr_xlate_mem,
   4951                egr_vlan_xlate_entry, BASE_VALID_1f, 0x7);
   4952         soc_mem_field32_set(unit, egr_xlate_mem,
   4953             egr_vlan_xlate_entry, DATA_TYPEf, 0x4);
   4954         soc_mem_field32_set(unit, egr_xlate_mem,
   4955             egr_vlan_xlate_entry, KEY_TYPEf, 0x4);
   4956     } else
   4957 #endif
   4958     {
   4959         soc_mem_field32_set(unit, egr_xlate_mem, 
   4960             egr_vlan_xlate_entry, VALIDf, 0x1);
   4961         soc_mem_field32_set(unit, egr_xlate_mem,
   4962             egr_vlan_xlate_entry, ENTRY_TYPEf, 0x4);
   4963     }
   4964 
   4965     if (mim_port->flags & BCM_MIM_PORT_EGRESS_TUNNEL_SERVICE_REPLACE) {
   4966         soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, 
   4967             MIM_ISID__ISIDf,
   4968             (mim_port->egress_tunnel_service & 0xffffff));
   4969     } else {
   4970         soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   4971                             MIM_ISID__ISIDf, VPN_ISID(unit, vfi));
   4972     }
   4973 
   4974     soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, 
   4975                                     MIM_ISID__DVPf, vp);
   4976 
   4977     /* Deal with egress SD tag actions */
   4978     if (mim_port->flags & BCM_MIM_PORT_EGRESS_SERVICE_VLAN_TAGGED) {
   4979         BCM_IF_ERROR_RETURN
   4980             (_bcm_tr2_mim_egr_vxlt_sd_tag_actions(unit, mim_port, NULL,
   4981                                                   egr_vlan_xlate_entry));
   4982     }
   4983 
   4984     rv = soc_mem_search(unit, egr_xlate_mem, MEM_BLOCK_ANY, &index,
   4985                         egr_vlan_xlate_entry, egr_vlan_xlate_entry, 0);
   4986     if (rv == SOC_E_NONE) {
   4987         return BCM_E_EXISTS;
   4988     } else if (rv != SOC_E_NOT_FOUND) {
   4989         return rv;
   4990     }
   4991     rv = soc_mem_insert(unit, egr_xlate_mem, MEM_BLOCK_ALL, egr_vlan_xlate_entry);
   4992     if (rv < 0) {
   4993         return rv;
   4994     }
   4995 #if defined(BCM_TRIDENT_SUPPORT)
   4996     if (soc_feature(unit, soc_feature_mim_peer_sharing) &&
   4997         !(mim_port->flags & BCM_MIM_PORT_REPLACE)) {
   4998         MIM_INFO(unit)->port_info[vp].vfi_count++;
   4999     }
   5000 #endif /* BCM_TRIDENT_SUPPORT */
   5001 
   5002     return BCM_E_NONE;
   5003 }
   5004 
   5005  /* Function:
   5006  *      _bcm_tr2_mim_vpn_is_eline
   5007  * Purpose:
   5008  *      Find if given MIM VPN is ELINE
   5009  * Parameters:
   5010  *      unit     - Device Number
   5011  *      vpn      - MIM VPN
   5012  *      is_eline - Flag 
   5013  * Returns:
   5014  *      BCM_E_XXXX
   5015  * Assumes:
   5016  *      l2vpn is valid
   5017  */
   5018 
   5019 STATIC int
   5020 _bcm_tr2_mim_vpn_is_eline( int unit, bcm_mim_vpn_t vpn, int *is_eline)
   5021 {
   5022     vfi_entry_t vfi_entry;
   5023     bcm_vpn_t mim_vpn_min=0;
   5024     int vfi_index = -1;
   5025     int num_vfi = 0;
   5026 
   5027 
   5028      num_vfi = soc_mem_index_count(unit, VFIm);
   5029 
   5030     _BCM_MIM_VPN_SET(mim_vpn_min, _BCM_MIM_VPN_TYPE_MIM, 0);
   5031 
   5032     if (vpn < mim_vpn_min || vpn > (mim_vpn_min + num_vfi - 1) ) {
   5033         return BCM_E_PARAM;
   5034     }
   5035 
   5036     _BCM_MIM_VPN_GET(vfi_index, _BCM_MIM_VPN_TYPE_MIM, vpn);
   5037 
   5038     if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeMim)) {
   5039         return BCM_E_NOT_FOUND;
   5040     }
   5041 
   5042     /* Read the VFI table to check if point-to-point vpn */
   5043     BCM_IF_ERROR_RETURN
   5044         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
   5045 
   5046     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
   5047         *is_eline = 1;  /* ELINE */
   5048     }
   5049     
   5050     return BCM_E_NONE;
   5051 }
   5052 
   5053  /* Function:
   5054  *      _bcm_tr2_mim_eline_port_add
   5055  * Purpose:
   5056  *      Add a port to VFI table for Point-to-Point(ELINE) service 
   5057  * Parameters:
   5058  *      unit     - Device Number
   5059  *      vpn      - MIM VPN
   5060  *      mim_port - MIM port
   5061  * Returns:
   5062  *      BCM_E_XXXX
   5063  */
   5064 
   5065 STATIC int
   5066 _bcm_tr2_mim_eline_port_add(int unit, 
   5067                             int current_vp,
   5068                             bcm_mim_vpn_t vpn, 
   5069                             bcm_mim_port_t *mim_port)
   5070 {
   5071 
   5072     vfi_entry_t vfi_entry;
   5073     source_vp_entry_t svp0, svp1;
   5074     bcm_vpn_t mim_vpn_min=0;
   5075     int vfi_index = -1;
   5076     int num_vfi = 0;
   5077     int vp0 = -1; /* virtual port 1 */
   5078     int vp1 = -1; /* virtual port 2 */
   5079     uint32 vp0_valid = 0, vp1_valid = 0;
   5080     soc_field_t field = INVALIDf;
   5081     int rv = BCM_E_NONE;
   5082 
   5083 
   5084     /*
   5085      * 1. check if vpn is valid
   5086      * 2. get vfi index
   5087      * 3. Read VFI entry from the VFI table.
   5088      * 4. if PT2PTf is set
   5089      * 5. get VP0 and VP1f fields 
   5090      * 6. If both are set and not REPLACE flag
   5091      *    return error - BCM_E_FULL
   5092      * 7. Add it to vp0 or vp1 
   5093      */
   5094             
   5095      num_vfi = soc_mem_index_count(unit, VFIm);
   5096 
   5097     _BCM_MIM_VPN_SET(mim_vpn_min, _BCM_MIM_VPN_TYPE_MIM, 0);
   5098 
   5099     if (vpn < mim_vpn_min || vpn > (mim_vpn_min + num_vfi - 1) ) {
   5100         return BCM_E_PARAM;
   5101     }
   5102 
   5103     _BCM_MIM_VPN_GET(vfi_index, _BCM_MIM_VPN_TYPE_MIM, vpn);
   5104 
   5105     if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeMim)) {
   5106         return BCM_E_NOT_FOUND;
   5107     }
   5108 
   5109     BCM_IF_ERROR_RETURN
   5110         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
   5111 
   5112     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
   5113         vp0 = soc_VFIm_field32_get(unit, &vfi_entry, VP_0f);
   5114         vp1 = soc_VFIm_field32_get(unit, &vfi_entry, VP_1f);
   5115     } else {
   5116         return BCM_E_PARAM;
   5117     }
   5118 
   5119     if (_bcm_vp_used_get(unit, vp0, _bcmVpTypeMim)) {
   5120         BCM_IF_ERROR_RETURN (
   5121            READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp0, &svp0));
   5122         if (soc_SOURCE_VPm_field32_get(unit, &svp0, ENTRY_TYPEf) == 0x1) {
   5123             vp0_valid = 1;
   5124         }
   5125     }
   5126 
   5127     if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeMim)) {
   5128         BCM_IF_ERROR_RETURN (
   5129            READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp1, &svp1));
   5130         if (soc_SOURCE_VPm_field32_get(unit, &svp1, ENTRY_TYPEf) == 0x1) {
   5131             vp1_valid = 1;
   5132         }
   5133     }
   5134 
   5135     /*
   5136      * if both vp0 and vp1 are valid
   5137      * if port flags PORT_REPLACE is not set.
   5138      * return BCM_E_FULL only 2 ports are required
   5139      * for a point-to-point(ELINE) service    
   5140      */
   5141     if (vp0_valid && vp1_valid) {
   5142         if ((mim_port->flags & BCM_MIM_PORT_REPLACE)) {
   5143             if ((current_vp == vp0) || (current_vp == vp1)) {
   5144                  return BCM_E_NONE;
   5145             } else {
   5146                 return BCM_E_NOT_FOUND;
   5147             }
   5148         } else {
   5149             return BCM_E_FULL;
   5150         } 
   5151     } else if (vp0_valid && !vp1_valid) {
   5152         if (mim_port->flags & BCM_MIM_PORT_REPLACE) {
   5153             if (current_vp != vp0) {
   5154                 return BCM_E_NOT_FOUND;
   5155             }
   5156         }
   5157         field = VP_1f;
   5158     } else if (!vp0_valid && vp1_valid) {
   5159         if (mim_port->flags & BCM_MIM_PORT_REPLACE) {
   5160             if (current_vp != vp1) {
   5161                 return BCM_E_NOT_FOUND;
   5162             }
   5163         }
   5164         field = VP_0f;
   5165     } else if (!vp0_valid && !vp1_valid) {
   5166         if (mim_port->flags & BCM_MIM_PORT_REPLACE) {
   5167             return BCM_E_NOT_FOUND;
   5168         }
   5169         field = VP_0f;
   5170     }        
   5171 
   5172     if (field != INVALIDf) {
   5173         soc_VFIm_field32_set(unit, &vfi_entry, field, current_vp);
   5174         rv =  WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry);
   5175     }
   5176 
   5177     return rv;
   5178 
   5179 }
   5180 
   5181  /* Function:
   5182  *      _bcm_tr2_mim_eline_port_delete
   5183  * Purpose:
   5184  *      Delete a port from VFI table for Point-to-Point(ELINE) service 
   5185  * Parameters:
   5186  *      unit     - Device Number
   5187  *      vpn      - MIM VPN
   5188  *      vp       - MIM virtual port
   5189  * Returns:
   5190  *      BCM_E_XXXX
   5191  */
   5192 
   5193 STATIC int
   5194 _bcm_tr2_mim_eline_port_delete(int unit, 
   5195                                bcm_mim_vpn_t vpn, 
   5196                                int vp)
   5197 {
   5198 
   5199     vfi_entry_t vfi_entry;
   5200     bcm_vpn_t mim_vpn_min=0;
   5201     int vfi_index = -1;
   5202     int num_vfi = 0;
   5203     int vp0 = -1; /* virtual port 1 */
   5204     int vp1 = -1; /* virtual port 2 */
   5205 
   5206 
   5207      num_vfi = soc_mem_index_count(unit, VFIm);
   5208 
   5209     _BCM_MIM_VPN_SET(mim_vpn_min, _BCM_MIM_VPN_TYPE_MIM, 0);
   5210 
   5211     if (vpn < mim_vpn_min || vpn > (mim_vpn_min + num_vfi - 1) ) {
   5212         return BCM_E_PARAM;
   5213     }
   5214 
   5215     _BCM_MIM_VPN_GET(vfi_index, _BCM_MIM_VPN_TYPE_MIM, vpn);
   5216 
   5217     if (!(_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeMim))) {
   5218         return BCM_E_NOT_FOUND;
   5219     }
   5220 
   5221     BCM_IF_ERROR_RETURN
   5222         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
   5223 
   5224     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
   5225         vp0 = soc_VFIm_field32_get(unit, &vfi_entry, VP_0f);
   5226         vp1 = soc_VFIm_field32_get(unit, &vfi_entry, VP_1f);
   5227     } else {
   5228         return BCM_E_PARAM;
   5229     }
   5230 
   5231     if (vp == vp0) {
   5232         soc_VFIm_field32_set(unit, &vfi_entry, VP_0f, 0);
   5233     } else if (vp == vp1) {
   5234         soc_VFIm_field32_set(unit, &vfi_entry, VP_1f, 0);
   5235     } else {
   5236         return BCM_E_PARAM;
   5237     }
   5238 
   5239     return WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry);
   5240 
   5241 }
   5242 
   5243 STATIC int
   5244 _bcm_tr2_mim_peer_port_config_delete(int unit, int vp, bcm_mim_vpn_t vpn)
   5245 {
   5246     uint32 ment[SOC_MAX_MEM_WORDS];
   5247     uint32 egr_vlan_xlate_entry[SOC_MAX_MEM_WORDS];
   5248     int vfi, rv = BCM_E_NONE;
   5249     soc_mem_t egr_xlate_mem;
   5250     soc_mem_t mpls_mem = MPLS_ENTRYm;
   5251     int isid = -1, index = -1;
   5252 
   5253 #if defined(BCM_TRIDENT3_SUPPORT)
   5254     if (soc_feature(unit, soc_feature_base_valid)) {
   5255         egr_xlate_mem = EGR_VLAN_XLATE_1_DOUBLEm;
   5256     } else
   5257 #endif
   5258     {
   5259         egr_xlate_mem = EGR_VLAN_XLATEm;
   5260     }
   5261 
   5262     _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vpn);
   5263 
   5264     sal_memset(egr_vlan_xlate_entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   5265 #if defined(BCM_TRIDENT3_SUPPORT)
   5266     if (soc_feature(unit, soc_feature_base_valid)) {
   5267         soc_mem_field32_set(unit, egr_xlate_mem,
   5268             egr_vlan_xlate_entry, DATA_TYPEf, 0x4);
   5269         soc_mem_field32_set(unit, egr_xlate_mem,
   5270             egr_vlan_xlate_entry, KEY_TYPEf, 0x4);
   5271     } else
   5272 #endif
   5273     {
   5274         soc_mem_field32_set(unit, egr_xlate_mem,
   5275             egr_vlan_xlate_entry, ENTRY_TYPEf, 0x4);
   5276     }
   5277     soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   5278         MIM_ISID__VFIf, vfi);
   5279 #if defined(BCM_TRIDENT3_SUPPORT)
   5280     if (soc_feature(unit, soc_feature_base_valid)) {
   5281         soc_mem_field32_set(unit, egr_xlate_mem,
   5282                egr_vlan_xlate_entry, BASE_VALID_0f, 0x3);
   5283         soc_mem_field32_set(unit, egr_xlate_mem,
   5284                egr_vlan_xlate_entry, BASE_VALID_1f, 0x7);
   5285     } else
   5286 #endif
   5287     {
   5288         soc_mem_field32_set(unit, egr_xlate_mem,
   5289             egr_vlan_xlate_entry, VALIDf, 0x1);
   5290     }
   5291     soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   5292                                     MIM_ISID__DVPf, vp);
   5293 
   5294     rv = soc_mem_search(unit, egr_xlate_mem, MEM_BLOCK_ANY, &index,
   5295                         egr_vlan_xlate_entry, egr_vlan_xlate_entry, 0);
   5296     BCM_IF_ERROR_RETURN(rv);
   5297 
   5298     isid = soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   5299         MIM_ISID__ISIDf);
   5300 
   5301     /* Delete the ISID-SVP entry in MPLS_ENTRY */
   5302     sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   5303     soc_mem_field32_set(unit, mpls_mem, ment, KEY_TYPEf, 3); /* MIM_ISID_SVP */
   5304 #if defined(BCM_TRIDENT3_SUPPORT)
   5305     if (soc_feature(unit, soc_feature_base_valid)) {
   5306         soc_mem_field32_set(unit, mpls_mem, ment, BASE_VALID_0f, 3); 
   5307         soc_mem_field32_set(unit, mpls_mem, ment, BASE_VALID_1f, 7); 
   5308     } else
   5309 #endif
   5310     {
   5311         soc_mem_field32_set(unit, mpls_mem, ment, VALIDf, 0x1);
   5312     }
   5313     soc_mem_field32_set(unit, mpls_mem, ment, MIM_ISID__ISIDf, isid);
   5314     soc_mem_field32_set(unit, mpls_mem, ment, MIM_ISID__SVPf, vp);
   5315     rv = soc_mem_delete(unit, mpls_mem, MEM_BLOCK_ANY, ment);
   5316     BCM_IF_ERROR_RETURN(rv);
   5317 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   5318     /*delete TP_ID from software*/
   5319     BCM_IF_ERROR_RETURN(
   5320         _bcm_tr2_mim_egr_vxlt_sd_tag_actions_delete(unit,
   5321                                                     egr_vlan_xlate_entry));
   5322 #endif
   5323     /* Delete the reverse entry in the egress */
   5324     rv = soc_mem_delete(unit, egr_xlate_mem, MEM_BLOCK_ANY, 
   5325                         egr_vlan_xlate_entry);
   5326 #if defined(BCM_TRIDENT_SUPPORT)
   5327     if (soc_feature(unit, soc_feature_mim_peer_sharing)) {
   5328         MIM_INFO(unit)->port_info[vp].vfi_count--;
   5329     }
   5330 #endif /* BCM_TRIDENT_SUPPORT */
   5331 
   5332     return BCM_E_NONE;
   5333 }
   5334 
   5335 #if defined(BCM_TRIDENT3_SUPPORT)
   5336 /*
   5337  * Function:
   5338  *      _bcm_tr2_mim_dvp_set
   5339  * Purpose:
   5340  *      Set Egress DVP tables
   5341  * Parameters:
   5342  *      IN :  Unit
   5343  *      IN :  vp
   5344  *      IN :  mim_port
   5345  * Returns:
   5346  *      BCM_E_XXX
   5347  */
   5348 STATIC int
   5349 _bcm_tr2_mim_dvp_set(int unit, int vp, bcm_mim_port_t *mim_port)
   5350 {
   5351     int rv = BCM_E_NONE;
   5352     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   5353     int network_group = 0;
   5354     soc_mem_t mem = EGR_DVP_ATTRIBUTEm;
   5355 
   5356     sal_memset(&egr_dvp_attribute, 0, sizeof(egr_dvp_attribute_entry_t));
   5357     rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
   5358     BCM_IF_ERROR_RETURN(rv);
   5359     if (SOC_MEM_FIELD_VALID(unit, mem, COMMON__DVP_NETWORK_GROUPf)) {
   5360 
   5361         network_group = mim_port->network_group_id;
   5362         rv = _bcm_validate_splithorizon_network_group(unit,
   5363                 mim_port->flags & BCM_MIM_PORT_TYPE_BACKBONE, &network_group);
   5364         BCM_IF_ERROR_RETURN(rv);
   5365         soc_mem_field32_set(unit, mem, &egr_dvp_attribute,
   5366                 COMMON__DVP_NETWORK_GROUPf, network_group);
   5367     }
   5368 
   5369     if (SOC_MEM_FIELD_VALID(unit, mem, COMMON__EVXLT_KEY_SELf)) {
   5370         if (mim_port->flags & BCM_MIM_PORT_TYPE_BACKBONE) {
   5371             soc_mem_field32_set(unit, mem, &egr_dvp_attribute,
   5372                     COMMON__EVXLT_KEY_SELf, 0x1);
   5373         } else if (mim_port->flags & BCM_MIM_PORT_TYPE_PEER) {
   5374             soc_mem_field32_set(unit, mem, &egr_dvp_attribute,
   5375                    COMMON__EVXLT_KEY_SELf, 0x2);
   5376         }
   5377     }
   5378 
   5379     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
   5380     BCM_IF_ERROR_RETURN(rv);
   5381 
   5382     return rv;
   5383 }
   5384 
   5385 STATIC int
   5386 _bcm_tr2_mim_dvp_get(int unit, int vp, bcm_mim_port_t *mim_port)
   5387 {
   5388     int rv = BCM_E_NONE;
   5389     soc_mem_t mem = EGR_DVP_ATTRIBUTEm;
   5390     egr_dvp_attribute_entry_t egr_dvp_attribute;
   5391 
   5392     sal_memset(&egr_dvp_attribute, 0, sizeof(egr_dvp_attribute_entry_t));
   5393     rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
   5394     BCM_IF_ERROR_RETURN(rv);
   5395 
   5396     if (SOC_MEM_FIELD_VALID(unit, mem, COMMON__EVXLT_KEY_SELf)) {
   5397         if (soc_mem_field32_get(unit, mem, &egr_dvp_attribute,
   5398                                  COMMON__EVXLT_KEY_SELf) == 0x1) {
   5399             mim_port->flags |= BCM_MIM_PORT_TYPE_BACKBONE;
   5400         } else if (soc_mem_field32_get(unit, mem, &egr_dvp_attribute,
   5401                                         COMMON__EVXLT_KEY_SELf) == 0x2) {
   5402             mim_port->flags |= BCM_MIM_PORT_TYPE_PEER;
   5403         }
   5404     }
   5405 
   5406     return rv;
   5407 }
   5408 #endif
   5409 
   5410 /*
   5411  * Function:
   5412  *      bcm_mim_port_add
   5413  * Purpose:
   5414  *      Create a VPN instance
   5415  * Parameters:
   5416  *      unit  - (IN)  Device Number
   5417  *      vpn   - (IN)  VPN id
   5418  *      mim_port  - (IN/OUT) MIM port configuration info
   5419  * Returns:
   5420  *      BCM_E_XXX
   5421  */
   5422 int 
   5423 bcm_tr2_mim_port_add(int unit, bcm_mim_vpn_t vpn, bcm_mim_port_t *mim_port)
   5424 {
   5425     int drop, mode, is_local = 0, rv = BCM_E_PARAM, nh_index = 0;
   5426     int old_tpid_enable = 0, tpid_enable = 0, tpid_index;
   5427     bcm_port_t local_port;
   5428     int i, vp, num_vp, ipmc_id, vfi = -1;
   5429     source_vp_entry_t svp;
   5430     ing_dvp_table_entry_t dvp;
   5431     vfi_entry_t vfi_entry;
   5432     bcm_multicast_t mc_group = 0;
   5433     int failover_vp = 0;
   5434     int cml_default_enable=0, cml_default_new=0, cml_default_move=0;
   5435     ing_pri_cng_map_entry_t imap;
   5436     ing_untagged_phb_entry_t phb;
   5437     int is_eline = 0;
   5438     int network_group=0;
   5439 #if defined(BCM_KATANA2_SUPPORT)
   5440     int my_modid = 0, mod_out =0, id = -1;
   5441     bcm_port_t port_out = -1;
   5442     bcm_trunk_t trunk_id = -1;
   5443     int is_local_subport = FALSE;
   5444     int min_subport = SOC_INFO(unit).pp_port_index_min; 
   5445     int max_subport = SOC_INFO(unit).pp_port_index_max;
   5446 #endif
   5447     bcm_mim_vpn_config_t vpn_info;
   5448     int mim_use_default_reserve_svp = 0;
   5449     _bcm_vp_info_t vp_info;
   5450 #if defined(BCM_TRIDENT3_SUPPORT)
   5451     uint32 svp1[SOC_MAX_MEM_WORDS] = {0};
   5452 #endif
   5453 
   5454     _bcm_vp_info_init(&vp_info);
   5455     vp_info.vp_type = _bcmVpTypeMim;
   5456 
   5457     MIM_INIT(unit);
   5458 
   5459     rv = bcm_xgs3_l3_egress_mode_get(unit, &mode);
   5460     BCM_IF_ERROR_RETURN(rv);
   5461     if (!mode) {
   5462         LOG_INFO(BSL_LS_BCM_L3,
   5463                  (BSL_META_U(unit,
   5464                              "L3 egress mode must be set first\n")));
   5465         return BCM_E_DISABLED;
   5466     }
   5467 
   5468     if (!(mim_port->flags & BCM_MIM_PORT_TYPE_BACKBONE)) {
   5469         if (!_BCM_MIM_VPN_IS_SET(vpn)) {
   5470             return BCM_E_PARAM;
   5471         }
   5472     }
   5473 
   5474     if ((SOC_IS_TRIUMPH2(unit) ||
   5475         SOC_IS_TRIDENT3(unit) )&&
   5476         !(mim_port->flags & BCM_MIM_PORT_TYPE_BACKBONE)) {
   5477         /* check if ELINE vpn service */
   5478         BCM_IF_ERROR_RETURN(_bcm_tr2_mim_vpn_is_eline(unit, vpn, &is_eline));
   5479     }
   5480 
   5481     /* BCM_MIM_PORT_DEFAULT is used on TR2 B0, setting mim_port_id to
   5482      * _BCM_MIM_DEFAULT_PORT
   5483      */
   5484      if (soc_feature(unit, soc_feature_mim_reserve_default_port) &&
   5485         soc_property_get(unit, spn_RESERVE_MIM_DEFAULT_SVP, 0) &&
   5486         (mim_port->flags & BCM_MIM_PORT_DEFAULT)) {
   5487 
   5488         BCM_GPORT_MIM_PORT_ID_SET(mim_port->mim_port_id,
   5489                                 _BCM_MIM_DEFAULT_PORT);
   5490         vp = BCM_GPORT_MIM_PORT_ID_GET(mim_port->mim_port_id);
   5491         mim_use_default_reserve_svp = 1;
   5492      }
   5493 
   5494     /* Allocate a new VP or use provided one */
   5495     if (mim_port->criteria == BCM_MIM_PORT_MATCH_SHARE) {
   5496         if (!soc_feature(unit, soc_feature_vp_sharing)) {
   5497             return BCM_E_UNAVAIL;
   5498         }
   5499         if (mim_port->flags & BCM_MIM_PORT_TYPE_ACCESS) {
   5500             vp_info.flags |= _BCM_VP_INFO_SHARED_PORT;
   5501         } else {
   5502             return BCM_E_UNAVAIL;
   5503         }
   5504     }
   5505 
   5506     if (mim_port->flags & BCM_MIM_PORT_SHARE) {
   5507         if (!soc_feature(unit, soc_feature_mim_peer_sharing)) {
   5508             return BCM_E_UNAVAIL;
   5509         }
   5510 #if defined(BCM_TRIDENT_SUPPORT)
   5511         else if (!(mim_port->flags & BCM_MIM_PORT_TYPE_PEER)) {
   5512             return BCM_E_PARAM;
   5513         }
   5514 #endif /* BCM_TRIDENT_SUPPORT */
   5515     }
   5516 
   5517     MIM_LOCK(unit);
   5518 
   5519     if (mim_port->flags & BCM_MIM_PORT_WITH_ID) {
   5520         if (!BCM_GPORT_IS_MIM_PORT((mim_port->mim_port_id))) {
   5521             MIM_UNLOCK(unit);
   5522             return BCM_E_PARAM;
   5523         }
   5524         vp = BCM_GPORT_MIM_PORT_ID_GET(mim_port->mim_port_id);
   5525         if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) {
   5526             MIM_UNLOCK(unit);
   5527             return BCM_E_PARAM;
   5528         }
   5529         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMim) &&
   5530            (!mim_use_default_reserve_svp)) {
   5531             if (!(mim_port->flags & BCM_MIM_PORT_REPLACE)) {
   5532 #if defined(BCM_TRIDENT_SUPPORT)
   5533                 if (soc_feature(unit, soc_feature_mim_peer_sharing) &&
   5534                     (mim_port->flags & BCM_MIM_PORT_TYPE_PEER)) {
   5535                     if (!(MIM_INFO(unit)->port_info[vp].flags &
   5536                         _BCM_MIM_PORT_TYPE_SHARE)) {
   5537                         MIM_UNLOCK(unit);
   5538                         return BCM_E_EXISTS;
   5539                     }
   5540 
   5541                     /* for share peer vp */
   5542                     rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp);
   5543                     if (rv < 0) {
   5544                         MIM_UNLOCK(unit);
   5545                         return rv;
   5546                     }
   5547                     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
   5548                                                               NEXT_HOP_INDEXf);
   5549 
   5550                     rv = _bcm_tr2_mim_peer_port_config_add(unit, mim_port,
   5551                                                            vp, vpn);
   5552                     if (rv < 0) {
   5553                         MIM_UNLOCK(unit);
   5554                         return rv;
   5555                     }
   5556 
   5557                     mim_port->encap_id = nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   5558 
   5559                     goto port_cleanup;
   5560                  } else
   5561 #endif /* BCM_TRIDENT_SUPPORT */
   5562                  {
   5563                     MIM_UNLOCK(unit);
   5564                     return BCM_E_EXISTS;
   5565                  }
   5566             }
   5567         } else {
   5568             if ((mim_port->flags & BCM_MIM_PORT_TYPE_ACCESS) || 
   5569                     (mim_port->flags & BCM_MIM_PORT_TYPE_PEER)) {
   5570                 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
   5571             } else {
   5572                 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
   5573             }
   5574 
   5575             rv = _bcm_vp_used_set(unit, vp, vp_info);
   5576             if (rv < 0) {
   5577                 MIM_UNLOCK(unit);
   5578                 return rv;
   5579             }
   5580         }
   5581     } else if (!mim_use_default_reserve_svp) {
   5582         /* allocate a new VP index */
   5583         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   5584         if ((mim_port->flags & BCM_MIM_PORT_TYPE_ACCESS) || 
   5585                 (mim_port->flags & BCM_MIM_PORT_TYPE_PEER)) {
   5586             vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
   5587         } else {
   5588             vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
   5589         }
   5590 
   5591         rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp);
   5592         if (rv < 0) {
   5593             MIM_UNLOCK(unit);
   5594             return rv;
   5595         }
   5596     }
   5597 
   5598     /* Deal with the different kinds of VPs */
   5599     if (mim_port->flags & BCM_MIM_PORT_TYPE_ACCESS) {
   5600         /* Deal with access VPs */
   5601         if (vpn == _BCM_MIM_VPN_INVALID) {
   5602             MIM_UNLOCK(unit);
   5603             return BCM_E_PARAM;
   5604         }
   5605         _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vpn);
   5606 
   5607         if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   5608             MIM_UNLOCK(unit);
   5609             return BCM_E_NOT_FOUND;
   5610         }
   5611     } else if (mim_port->flags & BCM_MIM_PORT_TYPE_PEER) {
   5612         /* Deal with peer VPs - tunnel and associated VPN */
   5613         if (vpn == _BCM_MIM_VPN_INVALID) {
   5614             MIM_UNLOCK(unit);
   5615             return BCM_E_PARAM;
   5616         }
   5617          _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vpn);
   5618         if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   5619             MIM_UNLOCK(unit);
   5620             return BCM_E_NOT_FOUND;
   5621         }
   5622     }
   5623 
   5624     /* Program, the next hop, matching and egress tables */
   5625     if (mim_port->flags & BCM_MIM_PORT_REPLACE) {
   5626         /* For existing access ports, NH entry already exists */
   5627 #if defined(BCM_TRIDENT3_SUPPORT)
   5628         if (SOC_IS_TRIDENT3X(unit)) {
   5629             rv = READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, &svp1);
   5630             if (rv < 0) {
   5631                 MIM_UNLOCK(unit);
   5632                 return rv;
   5633             }
   5634         }
   5635 #endif
   5636         rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
   5637         if (rv < 0) {
   5638             MIM_UNLOCK(unit);
   5639             return rv;
   5640         }
   5641         rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp);
   5642         if (rv < 0) {
   5643             MIM_UNLOCK(unit);
   5644             return rv;
   5645         }
   5646         nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
   5647                                                   NEXT_HOP_INDEXf);
   5648         if (soc_SOURCE_VPm_field32_get(unit, &svp, SD_TAG_MODEf)) {
   5649             /* SD-tag mode, save the old TPID enable bits */
   5650 #if defined(BCM_TRIDENT3_SUPPORT)
   5651             if (SOC_IS_TRIDENT3X(unit)) {
   5652                 old_tpid_enable = soc_SVP_ATTRS_1m_field32_get(unit, &svp1,
   5653                                                             TPID_ENABLEf);
   5654             } else
   5655 #endif
   5656             {
   5657                 old_tpid_enable = soc_SOURCE_VPm_field32_get(unit, &svp,
   5658                                                          TPID_ENABLEf);
   5659             }
   5660         }
   5661     } else {
   5662         sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   5663         sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t));
   5664     }
   5665 
   5666     /* if ELINE service check if it valid to add the port */
   5667     if (is_eline) { 
   5668         rv = _bcm_tr2_mim_eline_port_add(unit, vp, vpn, mim_port);
   5669         if (rv < 0) {
   5670             MIM_UNLOCK(unit);
   5671             return rv;
   5672         }
   5673 
   5674     }
   5675 
   5676     /* Program next hop entry using existing or new index */
   5677     drop = (mim_port->flags & BCM_MIM_PORT_DROP) ? 1 : 0;
   5678     rv = _bcm_tr2_mim_l2_nh_info_add(unit, mim_port, vp, drop,
   5679                                     &nh_index, &local_port, &is_local);
   5680     if (rv < 0) {
   5681         goto port_cleanup;
   5682     }
   5683 
   5684     bcm_mim_vpn_config_t_init(&vpn_info);
   5685     rv = bcm_tr2_mim_vpn_get(unit, vpn, &vpn_info);
   5686     if (rv < 0 && !((rv == BCM_E_NOT_FOUND) && (mim_port->flags &
   5687         BCM_MIM_PORT_TYPE_BACKBONE))) {
   5688         goto port_cleanup;
   5689     }
   5690     /* Program the VP tables */
   5691     if (mim_port->flags & BCM_MIM_PORT_MATCH_SERVICE_VLAN_TPID) {
   5692         rv = _bcm_fb2_outer_tpid_entry_add(unit, mim_port->match_service_tpid,
   5693                 &tpid_index);
   5694         if (rv < 0) {
   5695             goto port_cleanup;
   5696         }
   5697         tpid_enable = (1 << tpid_index);
   5698         soc_SOURCE_VPm_field32_set(unit, &svp, SD_TAG_MODEf, 1);
   5699 #if defined(BCM_TRIDENT3_SUPPORT)
   5700         if (SOC_IS_TRIDENT3X(unit)) {
   5701             soc_SVP_ATTRS_1m_field32_set(unit, &svp1, TPID_ENABLEf, tpid_enable);
   5702         } else
   5703 #endif
   5704         {
   5705             soc_SOURCE_VPm_field32_set(unit, &svp, TPID_ENABLEf, tpid_enable);
   5706         }
   5707     } else {
   5708         if (mim_port->flags & BCM_MIM_PORT_TYPE_BACKBONE) {
   5709             soc_SOURCE_VPm_field32_set(unit, &svp, SD_TAG_VFI_ENABLEf, 1);
   5710 #if defined(BCM_TRIDENT2_SUPPORT)
   5711             if (soc_mem_field_valid(unit, SOURCE_VPm, TPID_SOURCEf)) {
   5712                 soc_SOURCE_VPm_field32_set(unit, &svp, TPID_SOURCEf, 1);
   5713             }
   5714 #endif /* BCM_TRIDENT2_SUPPORT */
   5715         } else {
   5716             soc_SOURCE_VPm_field32_set(unit, &svp, SD_TAG_MODEf, 0);
   5717         }
   5718     }
   5719     soc_SOURCE_VPm_field32_set(unit, &svp, CLASS_IDf,
   5720                                mim_port->if_class);
   5721     if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TRUST_OUTER_DOT1Pf)) {
   5722         soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_OUTER_DOT1Pf, 1);
   5723     }
   5724 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
   5725                                                 defined(BCM_APACHE_SUPPORT)
   5726     if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit)) {
   5727         rv = _bcm_esw_add_policer_to_table(unit, mim_port->policer_id,
   5728                                          SOURCE_VPm, 0 , &svp);
   5729         BCM_IF_ERROR_RETURN(rv);
   5730     }
   5731 #endif /* BCM_KATANA_SUPPORT  or BCM_TRIUMPH3_SUPPORT or BCM_APACHE_SUPPORT */
   5732 
   5733     if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   5734         network_group = mim_port->network_group_id;
   5735         rv = _bcm_validate_splithorizon_network_group(unit,
   5736                 mim_port->flags & BCM_MIM_PORT_TYPE_BACKBONE,
   5737                 &network_group);
   5738         BCM_IF_ERROR_RETURN(rv);
   5739         soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf,
   5740                                    network_group);
   5741     } else {
   5742        if ((mim_port->flags & BCM_MIM_PORT_TYPE_ACCESS) || 
   5743            (mim_port->flags & BCM_MIM_PORT_TYPE_PEER)) {
   5744             soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 0);
   5745        } else {
   5746             soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 1);
   5747        }
   5748     }
   5749 
   5750     /* Assign fixed internal priority per VP or trust inner tag */
   5751     if ((mim_port->flags & BCM_MIM_PORT_FIX_PRIORITY) &&
   5752         (mim_port->flags & BCM_MIM_PORT_TYPE_ACCESS)) {
   5753     
   5754         sal_memset(&imap, 0, sizeof(ing_pri_cng_map_entry_t));
   5755         sal_memset(&phb, 0, sizeof(ing_untagged_phb_entry_t));
   5756         if (SOC_IS_ENDURO(unit) || SOC_IS_TRIUMPH2(unit)) {
   5757             soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_DOT1P_PTRf,
   5758                                 mim_port->int_pri + 16);
   5759             soc_SOURCE_VPm_field32_set(unit, &svp, USE_INNER_PRIf, 0);
   5760             soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_OUTER_DOT1Pf, 0);
   5761 
   5762             BCM_IF_ERROR_RETURN(READ_ING_PRI_CNG_MAPm(unit, MEM_BLOCK_ANY,
   5763                                         1024 + mim_port->int_pri, &imap));
   5764             soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, &imap, PRIf,
   5765                                 mim_port->int_pri);
   5766             BCM_IF_ERROR_RETURN(WRITE_ING_PRI_CNG_MAPm(unit, MEM_BLOCK_ANY,
   5767                                          1024 + mim_port->int_pri, &imap)); 
   5768         }
   5769         
   5770         if (SOC_IS_TRIUMPH3(unit)) {
   5771             soc_mem_field32_set(unit, ING_UNTAGGED_PHBm,
   5772                                 &phb, PRIf, mim_port->int_pri);
   5773             BCM_IF_ERROR_RETURN(WRITE_ING_UNTAGGED_PHBm(unit, MEM_BLOCK_ANY,
   5774                                                   mim_port->int_pri, &phb));
   5775             soc_SOURCE_VPm_field32_set(unit, &svp, USE_INNER_PRIf, 1);
   5776             soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_DOT1P_PTRf,
   5777                                                    mim_port->int_pri);
   5778         }
   5779     }
   5780 
   5781     if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   5782 #ifdef BCM_RIOT_SUPPORT
   5783         /* Not setting dvp as network port for RIOT as all
   5784          * routed packet gets dropped if overlay SVP and DVP
   5785          * both are network ports.
   5786          * SVP and DVP as network ports is a valid used case
   5787          * but reg file says that this field
   5788          * is set when DVP is a TRILL port */
   5789         if ((BCMI_RIOT_IS_ENABLED(unit)) &&
   5790                 ((mim_port->flags & BCM_MIM_PORT_TYPE_BACKBONE) ||
   5791                  (mim_port->flags & BCM_MIM_PORT_TYPE_PEER))) {
   5792             /* explicitly setting it to zero. */
   5793             if(!(soc_property_get(unit, spn_USE_ALL_SPLITHORIZON_GROUPS, 0))) {
   5794                 network_group = 0;
   5795             }
   5796         }
   5797 #endif
   5798         if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_GROUPf)) {
   5799             soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf,
   5800                                            network_group);
   5801         }
   5802 #if defined(BCM_TRIDENT3_SUPPORT)
   5803         if(SOC_IS_TRIDENT3X(unit)) {
   5804             rv = _bcm_tr2_mim_dvp_set(unit, vp, mim_port);
   5805 
   5806             if (rv < 0) {
   5807                 goto port_cleanup;
   5808             }
   5809         }
   5810 #endif
   5811     }
   5812 
   5813 
   5814     /* Program the matching criteria */
   5815     if (mim_port->flags & BCM_MIM_PORT_REPLACE) {
   5816 #if defined(BCM_TRIDENT3_SUPPORT)
   5817         if (SOC_IS_TRIDENT3X(unit)) {
   5818             rv = WRITE_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, &svp1);
   5819             if (rv < 0) {
   5820                 goto port_cleanup;
   5821             }
   5822         }
   5823 #endif
   5824         rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
   5825         if (rv < 0) {
   5826             goto port_cleanup;
   5827         }
   5828 
   5829         if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) {
   5830 #ifdef BCM_RIOT_SUPPORT
   5831             if (BCMI_RIOT_IS_ENABLED(unit)) {
   5832                 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 0);
   5833             } else
   5834 #endif
   5835             {
   5836                 soc_ING_DVP_TABLEm_field32_set(
   5837                     unit, &dvp, NETWORK_PORTf,
   5838                     (mim_port->flags & BCM_MIM_PORT_TYPE_BACKBONE) ? 1 : 0);
   5839             }
   5840         }
   5841 
   5842         rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp);
   5843         if (rv < 0) {
   5844             goto port_cleanup;
   5845         }
   5846 
   5847         rv = _bcm_vp_ing_dvp_to_ing_dvp2_2(unit, &dvp, vp, network_group);
   5848         if (rv < 0) {
   5849             goto port_cleanup;
   5850         }
   5851 
   5852         BCM_IF_ERROR_RETURN(
   5853             _bcm_tr2_mim_match_add(unit, mim_port, vp, vpn));
   5854     } else {
   5855         /* Link in the newly allocated next-hop entry */
   5856         soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NEXT_HOP_INDEXf,
   5857                                        nh_index);
   5858 
   5859         if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) {
   5860 #ifdef BCM_RIOT_SUPPORT
   5861             if (BCMI_RIOT_IS_ENABLED(unit)) {
   5862                 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 0);
   5863             } else
   5864 #endif
   5865             {
   5866                 soc_ING_DVP_TABLEm_field32_set(
   5867                     unit, &dvp, NETWORK_PORTf,
   5868                     (mim_port->flags & BCM_MIM_PORT_TYPE_BACKBONE) ? 1 : 0);
   5869             }
   5870         }
   5871 
   5872         rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp);
   5873         if (rv < 0) {
   5874             goto port_cleanup;
   5875         }
   5876 
   5877         rv = _bcm_vp_ing_dvp_to_ing_dvp2_2(unit, &dvp, vp, network_group);
   5878         if (rv < 0) {
   5879             goto port_cleanup;
   5880         }
   5881 
   5882         /* Initialize the SVP parameters */
   5883         soc_SOURCE_VPm_field32_set(unit, &svp,
   5884                                    ENTRY_TYPEf, 0x1); /* L2 VP */
   5885         if ((vfi != -1) && (mim_port->criteria != BCM_MIM_PORT_MATCH_SHARE)) {
   5886             soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, vfi);
   5887         }
   5888 
   5889 
   5890         /*
   5891          * if ELINE VPN service and the port type is access 
   5892          * learning to be disabled
   5893          */
   5894         if (!((mim_port->flags & BCM_MIM_PORT_TYPE_ACCESS) && is_eline)) {
   5895             /* Set the CML */
   5896             rv = _bcm_vp_default_cml_mode_get (unit, 
   5897                                &cml_default_enable, &cml_default_new, 
   5898                                &cml_default_move);
   5899              if (rv < 0) {
   5900                  goto port_cleanup;
   5901              }
   5902 
   5903             if (cml_default_enable) {
   5904                 /* Set the CML to default values */
   5905                 soc_SOURCE_VPm_field32_set(unit, &svp, 
   5906                                            CML_FLAGS_NEWf, cml_default_new);
   5907                 soc_SOURCE_VPm_field32_set(unit, &svp,
   5908                                            CML_FLAGS_MOVEf, cml_default_move);
   5909             } else {
   5910                 /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */
   5911                 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, 0x8);
   5912                 soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, 0x8);
   5913             }
   5914         }
   5915 
   5916         if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) {
   5917             if (!soc_feature(unit, soc_feature_vlan_vfi_membership)) {
   5918                 soc_SOURCE_VPm_field32_set(unit, &svp, DISABLE_VLAN_CHECKSf, 1);
   5919             }
   5920         }
   5921 #if defined(BCM_TRIDENT3_SUPPORT)
   5922         if (SOC_IS_TRIDENT3X(unit)) {
   5923             rv = WRITE_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, &svp1);
   5924             if (rv < 0) {
   5925                 goto port_cleanup;
   5926             }
   5927         }
   5928 #endif
   5929         rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
   5930         if (rv < 0) {
   5931             goto port_cleanup;
   5932         }
   5933 
   5934 #if defined(BCM_TRIDENT3_SUPPORT)
   5935         if (SOC_IS_TRIDENT3X(unit)) {
   5936             if ((vpn != _BCM_MIM_VPN_INVALID) &&
   5937                 (mim_port->flags & BCM_MIM_PORT_TYPE_BACKBONE)) {
   5938                 if ( BCM_E_NONE != soc_cancun_app_dest_entry_set (unit,
   5939                     SOURCE_VPm, vp, ENTRY_TYPEf,
   5940                     CANCUN_APP__SOURCE_VP__No_Control_Word, 0x1)) {
   5941                     LOG_ERROR(BSL_LS_BCM_MIM,
   5942                        (BSL_META_U(unit,"SOURCE_VP cancun app cfg error\n")));
   5943                 }
   5944             }
   5945         }
   5946 #endif
   5947 
   5948         /* Add the port to the VFI broadcast replication list */
   5949 #if defined(BCM_KATANA2_SUPPORT)
   5950         if (soc_feature(unit, soc_feature_linkphy_coe) ||
   5951             soc_feature(unit, soc_feature_subtag_coe)) {
   5952             rv  =_bcm_esw_gport_resolve(unit, mim_port->port, &mod_out, 
   5953                                    &port_out, &trunk_id, &id);
   5954             if (rv < 0) {
   5955                 goto port_cleanup;
   5956             }
   5957             rv = bcm_esw_stk_my_modid_get(unit, &my_modid);
   5958             if (rv < 0) {
   5959                 goto port_cleanup;
   5960             }
   5961             if (BCM_GPORT_IS_SET(mim_port->port) &&
   5962                 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit,
   5963                     mim_port->port)) {
   5964                 if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_out) == BCM_E_NONE) {
   5965                     rv = _bcm_kt2_modport_to_pp_port_get(
   5966                              unit, mod_out, port_out, &port_out);
   5967                     if (rv < 0) {
   5968                         goto port_cleanup;
   5969                     }
   5970 #if defined BCM_METROLITE_SUPPORT
   5971                     if (soc_feature(unit, soc_feature_discontinuous_pp_port)) {
   5972                         if (_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, port_out)) {
   5973                             is_local_subport = TRUE;
   5974                         }
   5975                     } else
   5976 #endif
   5977                     {
   5978                         if ((port_out >= min_subport ) &&
   5979                             (port_out <= max_subport)) {
   5980                             is_local_subport = TRUE;
   5981                         }
   5982                     }
   5983                 }
   5984             }
   5985             if ((is_local_subport) && (vfi != -1)) {
   5986                 /* Get IPMC index from HW */
   5987                 rv = READ_VFIm(unit, MEM_BLOCK_ANY, vfi, &vfi_entry);
   5988                 if (rv < 0) {
   5989                     goto port_cleanup;
   5990                 }
   5991 #if defined(BCM_TRIDENT3_SUPPORT)
   5992                 if (soc_feature(unit, soc_feature_generic_dest)) {
   5993                     uint32 dt = SOC_MEM_FIF_DEST_INVALID;
   5994                     ipmc_id = soc_mem_field32_dest_get(unit, VFIm,
   5995                             &vfi_entry, BC_DESTINATIONf, &dt);
   5996                     if (dt != SOC_MEM_FIF_DEST_IPMC) {
   5997                         rv = BCM_E_INTERNAL;
   5998                         goto port_cleanup;
   5999                     }
   6000                 } else
   6001 #endif
   6002                 {
   6003                     ipmc_id = soc_VFIm_field32_get(unit,
   6004                         &vfi_entry, BC_INDEXf);
   6005                 }
   6006                 _BCM_MULTICAST_GROUP_SET(mc_group,
   6007                     _BCM_MULTICAST_TYPE_MIM, ipmc_id);
   6008                 rv = bcm_esw_multicast_egress_add(unit, mc_group,
   6009                                              mim_port->port, nh_index + 
   6010                                              BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   6011                 if (rv < 0) {
   6012                     goto port_cleanup;
   6013                 }
   6014             }
   6015         }
   6016 #endif
   6017         if ((is_local || BCM_GPORT_IS_TRUNK(mim_port->port)) && 
   6018             (vfi != -1) && (!is_eline)) {
   6019             bcm_gport_t local_gport;
   6020 
   6021             /* Get IPMC index from HW */
   6022             rv = READ_VFIm(unit, MEM_BLOCK_ANY, vfi, &vfi_entry);
   6023             if (rv < 0) {
   6024                 goto port_cleanup;
   6025             }
   6026 #if defined(BCM_TRIDENT3_SUPPORT)
   6027             if (soc_feature(unit, soc_feature_generic_dest)) {
   6028                 uint32 dt = SOC_MEM_FIF_DEST_INVALID;
   6029                 ipmc_id = soc_mem_field32_dest_get(unit, VFIm,
   6030                             &vfi_entry, BC_DESTINATIONf, &dt);
   6031                 if (dt != SOC_MEM_FIF_DEST_IPMC) {
   6032                     rv = BCM_E_INTERNAL;
   6033                     goto port_cleanup;
   6034                 }
   6035             } else
   6036 #endif
   6037             {
   6038                 ipmc_id = soc_VFIm_field32_get(unit,
   6039                     &vfi_entry, BC_INDEXf);
   6040             }
   6041             _BCM_MULTICAST_GROUP_SET(mc_group, _BCM_MULTICAST_TYPE_MIM, ipmc_id);
   6042             if (is_local) {
   6043                 /* Convert system local_port to physical local_port */
   6044                 if (soc_feature(unit, soc_feature_sysport_remap)) {
   6045                     BCM_XLATE_SYSPORT_S2P(unit, &local_port);
   6046                 }
   6047                 rv = bcm_esw_port_gport_get(unit, local_port, &local_gport);
   6048                 if (BCM_FAILURE(rv)) {
   6049                     goto port_cleanup;
   6050                 }
   6051             } else {
   6052                 local_gport = mim_port->port; /* Trunk gport */
   6053             }
   6054 #if defined(BCM_ENDURO_SUPPORT)
   6055             if (SOC_IS_ENDURO(unit)) {
   6056                 rv = bcm_esw_multicast_egress_add(unit, mc_group,
   6057                                              local_gport, nh_index);
   6058             } else 
   6059 #endif /* BCM_ENDURO_SUPPORT */
   6060             {
   6061                 rv = bcm_esw_multicast_egress_add(unit, mc_group,
   6062                                              local_gport, nh_index + 
   6063                                              BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   6064             }
   6065             if (rv < 0) {
   6066                 goto port_cleanup;
   6067             }
   6068         }
   6069 
   6070         /* Configure failover VP */
   6071         if (BCM_SUCCESS(_bcm_tr2_mim_failover_check(unit, mim_port))) {
   6072             failover_vp = BCM_GPORT_MIM_PORT_ID_GET(mim_port->failover_gport_id);
   6073             if (failover_vp == vp) {
   6074                 rv = BCM_E_PORT;
   6075                 goto port_cleanup;
   6076             }
   6077             if (!_bcm_vp_used_get(unit, failover_vp, _bcmVpTypeMim)) {
   6078                 /* coverity[assigned_value] */
   6079                 rv = BCM_E_NOT_FOUND;
   6080             }
   6081         }
   6082 
   6083         /*
   6084          * Match entries cannot be replaced, instead, callers
   6085          * need to delete the existing entry and re-add with the
   6086          * new match parameters.
   6087          */
   6088 #if defined(BCM_TRIUMPH3_SUPPORT)    
   6089         if (SOC_IS_TRIUMPH3(unit)) {
   6090             rv = _bcm_tr3_mim_match_add(unit, mim_port, vp);
   6091         } else
   6092 #endif /* BCM_TRIUMPH3_SUPPORT */
   6093         {
   6094             rv = _bcm_tr2_mim_match_add(unit, mim_port, vp, vpn);
   6095         }
   6096 
   6097         if (rv < 0) {
   6098             bcm_gport_t local_gport;
   6099             if (is_local && !is_eline) {
   6100                 (void) bcm_esw_port_gport_get(unit, local_port, &local_gport);
   6101 #if defined(BCM_ENDURO_SUPPORT)
   6102                 if (SOC_IS_ENDURO(unit)) {
   6103                     (void) bcm_esw_multicast_egress_delete(unit, mc_group, 
   6104                                                        local_gport, nh_index);
   6105                 } else 
   6106 #endif /* BCM_ENDURO_SUPPORT */
   6107                 {
   6108                     (void) bcm_esw_multicast_egress_delete(unit, mc_group, 
   6109                                                        local_gport, nh_index + 
   6110                                                        BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   6111                 }
   6112             }
   6113 #if defined(BCM_KATANA2_SUPPORT)
   6114             if (soc_feature(unit, soc_feature_linkphy_coe) ||
   6115                 soc_feature(unit, soc_feature_subtag_coe)) {
   6116                 if (is_local_subport) {
   6117                     (void) bcm_esw_multicast_egress_delete(unit, mc_group, 
   6118                                                mim_port->port, nh_index + 
   6119                                                BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   6120                 }
   6121             }
   6122 #endif
   6123         } else {
   6124             /* For peer ports, create entries in ingress and egress 
   6125                VLAN translate tables */
   6126             if (mim_port->flags & BCM_MIM_PORT_TYPE_PEER) {
   6127 #if defined(BCM_TRIUMPH3_SUPPORT)
   6128                 if (SOC_IS_TRIUMPH3(unit)) {
   6129                     rv = _bcm_tr3_mim_peer_port_config_add(unit, mim_port,
   6130                                                            vp, vpn);
   6131                 } else 
   6132 #endif /* BCM_TRIUMPH3_SUPPORT */
   6133                 {
   6134                     rv = _bcm_tr2_mim_peer_port_config_add(unit, mim_port, 
   6135                                                            vp, vpn);
   6136                 }
   6137             }
   6138             /* Set the MIM port ID */
   6139             BCM_GPORT_MIM_PORT_ID_SET(mim_port->mim_port_id, vp);
   6140             mim_port->encap_id = nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   6141         }
   6142     }
   6143 
   6144 #ifdef BCM_WARM_BOOT_SUPPORT
   6145     SOC_CONTROL_LOCK(unit);
   6146     SOC_CONTROL(unit)->scache_dirty = 1;
   6147     SOC_CONTROL_UNLOCK(unit);
   6148 #endif
   6149 
   6150 port_cleanup:
   6151     if (rv < 0) {
   6152         if (tpid_enable) {
   6153             (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   6154         }
   6155         if (!(mim_port->flags & BCM_MIM_PORT_REPLACE)) {
   6156             if (!mim_use_default_reserve_svp) {
   6157                 (void) _bcm_vp_free(unit, _bcmVpTypeMim, 1, vp);
   6158             }
   6159             _bcm_tr2_mim_l2_nh_info_delete(unit, nh_index);
   6160         }
   6161         if (vp > 0) {
   6162 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
   6163                                                     defined(BCM_APACHE_SUPPORT)
   6164             if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit)) {
   6165             /* reset the policer entry to 0 and decrement reference count */
   6166                 _bcm_esw_reset_policer_from_table(unit, mim_port->policer_id, 
   6167                                                SOURCE_VPm, vp, &svp); 
   6168             }
   6169 #endif /* BCM_KATANA_SUPPORT  or BCM_TRIUMPH3_SUPPORT or BCM_APACHE_SUPPORT */
   6170             sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   6171             (void)WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
   6172 #if defined(BCM_TRIDENT3_SUPPORT)
   6173             sal_memset(&svp1, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   6174             if (SOC_IS_TRIDENT3X(unit)) {
   6175                 (void)WRITE_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, &svp1);
   6176             }
   6177 #endif
   6178             (void)_bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigClear, vp,
   6179                     ING_DVP_CONFIG_INVALID_VP_TYPE, 
   6180                     ING_DVP_CONFIG_INVALID_INTF_ID, 
   6181                     ING_DVP_CONFIG_INVALID_PORT_TYPE);
   6182         }
   6183     }
   6184     if (old_tpid_enable) {
   6185         for (i = 0; i < 4; i++) {
   6186             if (old_tpid_enable & (1 << i)) {
   6187                 (void) _bcm_fb2_outer_tpid_entry_delete(unit, i);
   6188                 break;
   6189             }
   6190         }
   6191     }
   6192     MIM_UNLOCK(unit);
   6193     return rv;
   6194 }
   6195 
   6196 /*
   6197  * Function:
   6198  *      _bcm_tr2_mim_egress_dvp_reset
   6199  * Purpose:
   6200  *      Reet Egress DVP tables
   6201  * Parameters:
   6202  *      IN :  Unit
   6203  *           IN :  vp
   6204  * Returns:
   6205  *      BCM_E_XXX
   6206  */
   6207 
   6208 STATIC int
   6209 _bcm_tr2_mim_egress_dvp_reset(int unit, int vp)
   6210 {
   6211     int rv=BCM_E_NONE;
   6212     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   6213     egr_dvp_attribute_1_entry_t  egr_dvp_attribute_1;
   6214 
   6215     if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) {
   6216         sal_memset(&egr_dvp_attribute, 0, sizeof(egr_dvp_attribute_entry_t));
   6217         rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTEm,
   6218                                       MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
   6219         BCM_IF_ERROR_RETURN(rv);
   6220     }
   6221 
   6222     if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTE_1m)) {
   6223         sal_memset(&egr_dvp_attribute_1, 0, sizeof(egr_dvp_attribute_1_entry_t));
   6224         rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTE_1m,
   6225                                       MEM_BLOCK_ALL, vp, &egr_dvp_attribute_1);
   6226     }
   6227 
   6228     return rv;
   6229 }
   6230 
   6231 
   6232 STATIC int
   6233 _bcm_tr2_mim_port_delete(int unit, bcm_vpn_t vpn, int vp)
   6234 {
   6235     int rv = BCM_E_NONE;
   6236     int nh_index = 0, vfi, ipmc_id, is_local = FALSE;
   6237     source_vp_entry_t svp;
   6238     ing_dvp_table_entry_t dvp;
   6239     ing_l3_next_hop_entry_t ing_nh;
   6240     vfi_entry_t vfi_entry;
   6241     bcm_module_t modid;
   6242     bcm_port_t port;
   6243     bcm_trunk_t tgid;
   6244     bcm_multicast_t mc_group = 0;
   6245     bcm_gport_t local_gport = BCM_GPORT_INVALID;
   6246     _bcm_port_info_t *info;
   6247 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   6248     int policer_id=0;
   6249 #endif
   6250 #if defined(BCM_KATANA2_SUPPORT)
   6251     bcm_port_t pp_port = -1;
   6252     int is_local_subport = FALSE;
   6253     int min_subport = SOC_INFO(unit).pp_port_index_min;
   6254     int max_subport = SOC_INFO(unit).pp_port_index_max;
   6255 #endif
   6256     int is_eline = 0;
   6257     int mim_reserve_svp_delete = 0;
   6258     int old_tpid_enable, i;
   6259     bcm_mim_port_t mim_port;
   6260     uint32 port_flags;
   6261     int is_trunk = 0;
   6262 #if defined(BCM_TRIDENT3_SUPPORT)
   6263     uint32 svp1[SOC_MAX_MEM_WORDS] = {0};
   6264 #endif
   6265     int tpid_enable_length = 0;
   6266 
   6267     /* We can not delete shared VP's match in this API, so if the
   6268      * VP is using by match, do not delete this vp */
   6269     if (MIM_INFO(unit)->port_info[vp].flags & _BCM_MIM_PORT_TYPE_ACCESS_SHARED) {
   6270         if(MIM_INFO(unit)->port_info[vp].match_count >= 1) {
   6271             return BCM_E_BUSY;
   6272         }
   6273     } else {
   6274         if(MIM_INFO(unit)->port_info[vp].match_count > 1) {
   6275             return BCM_E_BUSY;
   6276         }
   6277     }
   6278 
   6279 #if defined(BCM_TRIDENT_SUPPORT)
   6280     if (soc_feature(unit, soc_feature_mim_peer_sharing) &&
   6281         (MIM_INFO(unit)->port_info[vp].flags & _BCM_MIM_PORT_TYPE_SHARE)) {
   6282         if (MIM_INFO(unit)->port_info[vp].vfi_count > 1) {
   6283             rv = _bcm_tr2_mim_peer_port_config_delete(unit, vp, vpn);
   6284             return rv;
   6285         }
   6286     }
   6287 #endif /* BCM_TRIDENT_SUPPORT */
   6288 
   6289     _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vpn);
   6290 
   6291     if (!(MIM_INFO(unit)->port_info[vp].flags & _BCM_MIM_PORT_TYPE_NETWORK)) {
   6292         if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   6293             return BCM_E_NOT_FOUND;
   6294         }
   6295     }
   6296 
   6297     if (SOC_IS_TRIUMPH2(unit) && (!(MIM_INFO(unit)->port_info[vp].flags & _BCM_MIM_PORT_TYPE_NETWORK))) {
   6298         /* check if point-to-point vpn */
   6299         BCM_IF_ERROR_RETURN(_bcm_tr2_mim_vpn_is_eline(unit, vpn, &is_eline));
   6300     }
   6301     rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp);
   6302     BCM_IF_ERROR_RETURN(rv);
   6303     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
   6304 
   6305 #if defined(BCM_TRIUMPH3_SUPPORT)    
   6306     if (SOC_IS_TRIUMPH3(unit)) {
   6307         rv = _bcm_tr3_mim_match_delete(unit, vp);
   6308     } else
   6309 #endif /* BCM_TRIUMPH3_SUPPORT */
   6310     {
   6311         _bcm_vp_info_t vp_info;
   6312         BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
   6313         if (!(vp_info.flags & _BCM_VP_INFO_SHARED_PORT)) {
   6314             rv = _bcm_tr2_mim_match_delete(unit, vp, mim_port);
   6315         }
   6316     }
   6317 
   6318     if (rv < 0) {
   6319         return rv;
   6320     }
   6321 
   6322     /* Check if this port is on the local unit */
   6323     rv = soc_mem_read(unit, ING_L3_NEXT_HOPm,
   6324                       MEM_BLOCK_ANY, nh_index, &ing_nh);
   6325     BCM_IF_ERROR_RETURN(rv);
   6326 
   6327     if (!(MIM_INFO(unit)->port_info[vp].flags & _BCM_MIM_PORT_TYPE_NETWORK)) {
   6328         if (soc_feature(unit, soc_feature_generic_dest)) {
   6329             uint32 dt, dv;
   6330             dv = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm,
   6331                     &ing_nh, DESTINATIONf, &dt);
   6332             if (dt == SOC_MEM_FIF_DEST_LAG) {
   6333                 /* Trunk group */
   6334                 tgid = dv & SOC_MEM_FIF_DGPP_TGID_MASK;
   6335                 is_trunk = 1;
   6336             } else {
   6337                 port = dv & SOC_MEM_FIF_DGPP_PORT_MASK;
   6338                 modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
   6339                           SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
   6340             }
   6341         } else {
   6342             if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
   6343                 tgid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf);
   6344                 is_trunk = 1;
   6345             } else {
   6346                 modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
   6347                 port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf);
   6348             }
   6349         }
   6350 
   6351         if (!is_trunk) {
   6352             BCM_IF_ERROR_RETURN(
   6353                 _bcm_esw_modid_is_local(unit, modid, &is_local));
   6354             if (TRUE == is_local) {
   6355                 /* Convert system port to physical port */
   6356                 if (soc_feature(unit, soc_feature_sysport_remap)) {
   6357                     BCM_XLATE_SYSPORT_S2P(unit, &port);
   6358                 }
   6359                 BCM_IF_ERROR_RETURN(
   6360                     bcm_esw_port_gport_get(unit, port, &local_gport));
   6361             }
   6362 #if defined(BCM_KATANA2_SUPPORT)
   6363             if (soc_feature(unit, soc_feature_linkphy_coe) ||
   6364                 soc_feature(unit, soc_feature_subtag_coe)) {
   6365                 /* For LinkPHY/SubportPktTag pp_ports, check if the mod is a valid one */
   6366                 if (_bcm_kt2_mod_is_coe_mod_check(unit, modid) == BCM_E_NONE) {
   6367                     BCM_IF_ERROR_RETURN(
   6368                         _bcm_kt2_modport_to_pp_port_get(unit, modid,
   6369                             port, &pp_port));
   6370 #if defined BCM_METROLITE_SUPPORT
   6371                     if (soc_feature(unit, soc_feature_discontinuous_pp_port)) {
   6372                         if (_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, pp_port)) {
   6373                             _BCM_KT2_SUBPORT_PORT_ID_SET(local_gport, pp_port);
   6374                             if (BCM_PBMP_MEMBER(
   6375                                         SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) {
   6376                                 _BCM_KT2_SUBPORT_PORT_TYPE_SET(local_gport,
   6377                                         _BCM_KT2_SUBPORT_TYPE_LINKPHY);
   6378                             } else if (BCM_PBMP_MEMBER(
   6379                                         SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) {
   6380                                 _BCM_KT2_SUBPORT_PORT_TYPE_SET(local_gport,
   6381                                         _BCM_KT2_SUBPORT_TYPE_SUBTAG);
   6382                             } else {
   6383                                 return BCM_E_PORT;
   6384                             }
   6385                             /* If this port is on the local unit and is not a network port,
   6386                              *                              *remove from replication list
   6387                              *                                                           * Get IPMC index from HW */
   6388                             BCM_IF_ERROR_RETURN(
   6389                                     READ_VFIm(unit, MEM_BLOCK_ANY, vfi, &vfi_entry));
   6390                             ipmc_id =
   6391                                 soc_VFIm_field32_get(unit, &vfi_entry, BC_INDEXf);
   6392                             _BCM_MULTICAST_GROUP_SET(mc_group,
   6393                                     _BCM_MULTICAST_TYPE_MIM, ipmc_id);
   6394 
   6395                             BCM_IF_ERROR_RETURN(
   6396                                     bcm_esw_multicast_egress_delete(unit, mc_group,
   6397                                         local_gport,
   6398                                         nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit)));
   6399                             is_local_subport = TRUE;
   6400                         }
   6401                     } else
   6402 #endif
   6403                         /*For KT2, pp_port >=42 are used for LinkPHY/SubportPktTag subport.
   6404                          * Get the subport info associated with the pp_port and form the
   6405                          * subport_gport */
   6406                     {
   6407                         if ((pp_port >= min_subport) &&
   6408                             (pp_port <= max_subport)) {
   6409                             _BCM_KT2_SUBPORT_PORT_ID_SET(local_gport, pp_port);
   6410                             if (BCM_PBMP_MEMBER(
   6411                                         SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) {
   6412                                 _BCM_KT2_SUBPORT_PORT_TYPE_SET(local_gport,
   6413                                         _BCM_KT2_SUBPORT_TYPE_LINKPHY);
   6414                             } else if (BCM_PBMP_MEMBER(
   6415                                         SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) {
   6416                                 _BCM_KT2_SUBPORT_PORT_TYPE_SET(local_gport,
   6417                                         _BCM_KT2_SUBPORT_TYPE_SUBTAG);
   6418                             } else {
   6419                                 return BCM_E_PORT;
   6420                             }
   6421                             /* If this port is on the local unit and is not a network port, 
   6422                              *remove from replication list 
   6423                              * Get IPMC index from HW */
   6424                             BCM_IF_ERROR_RETURN(
   6425                                     READ_VFIm(unit, MEM_BLOCK_ANY, vfi, &vfi_entry));
   6426                             ipmc_id =
   6427                                 soc_VFIm_field32_get(unit, &vfi_entry, BC_INDEXf);
   6428                             _BCM_MULTICAST_GROUP_SET(mc_group,
   6429                                     _BCM_MULTICAST_TYPE_MIM, ipmc_id);
   6430 
   6431                             BCM_IF_ERROR_RETURN(
   6432                                     bcm_esw_multicast_egress_delete(unit, mc_group, 
   6433                                         local_gport,
   6434                                         nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit)));
   6435                             is_local_subport = TRUE;
   6436                         }
   6437                         /* If this port is on the local unit and is not a network port, 
   6438                         *remove from replication list 
   6439                         * Get IPMC index from HW */
   6440                         BCM_IF_ERROR_RETURN(
   6441                             READ_VFIm(unit, MEM_BLOCK_ANY, vfi, &vfi_entry));
   6442 #if defined(BCM_TRIDENT3_SUPPORT)
   6443                         if (soc_feature(unit, soc_feature_generic_dest)) {
   6444                             uint32 dt = SOC_MEM_FIF_DEST_INVALID;
   6445                             ipmc_id = soc_mem_field32_dest_get(unit, VFIm,
   6446                                     &vfi_entry, BC_DESTINATIONf, &dt);
   6447                             if (dt != SOC_MEM_FIF_DEST_IPMC) {
   6448                                   return BCM_E_INTERNAL;
   6449                             }
   6450                         } else
   6451 #endif
   6452                         {
   6453                             ipmc_id = soc_VFIm_field32_get(unit,
   6454                                           &vfi_entry, BC_INDEXf);
   6455                         }
   6456                         ipmc_id = soc_VFIm_field32_get(unit,
   6457                                 &vfi_entry, BC_INDEXf);
   6458                         _BCM_MULTICAST_GROUP_SET(mc_group,
   6459                             _BCM_MULTICAST_TYPE_MIM, ipmc_id);
   6460 
   6461                         BCM_IF_ERROR_RETURN(
   6462                             bcm_esw_multicast_egress_delete(unit, mc_group, 
   6463                                 local_gport,
   6464                                 nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit)));
   6465                         is_local_subport = TRUE;
   6466                     }
   6467                 }
   6468             }
   6469 #endif /* BCM_KATANA2_SUPPORT */
   6470         } else {
   6471             BCM_GPORT_TRUNK_SET(local_gport, tgid);
   6472         }
   6473        /*
   6474         *  If point-to-point vpn service, BC_INDEXf
   6475         *  UC_INDEXf are overlaid with VP_0f, VP_1f. 
   6476         *  and are not relevant. skip multicast operations
   6477         *  If this port is on the local unit and is not  
   6478         *  a network port, remove from replication list
   6479         */    
   6480 
   6481         if (((TRUE == is_local) || BCM_GPORT_IS_TRUNK(local_gport)) && 
   6482             (!is_eline)) {
   6483             /* Get IPMC index from HW */
   6484             rv = READ_VFIm(unit, MEM_BLOCK_ANY, vfi, &vfi_entry);
   6485             BCM_IF_ERROR_RETURN(rv);
   6486 #if defined(BCM_TRIDENT3_SUPPORT)
   6487             if (soc_feature(unit, soc_feature_generic_dest)) {
   6488                  uint32 dt = SOC_MEM_FIF_DEST_INVALID;
   6489                  ipmc_id = soc_mem_field32_dest_get(unit, VFIm,
   6490                             &vfi_entry, BC_DESTINATIONf, &dt);
   6491                  if (dt != SOC_MEM_FIF_DEST_IPMC) {
   6492                       return BCM_E_INTERNAL;
   6493                  }
   6494             } else
   6495 #endif
   6496             {
   6497                 ipmc_id = soc_VFIm_field32_get(unit,
   6498                     &vfi_entry, BC_INDEXf);
   6499             }
   6500             _BCM_MULTICAST_GROUP_SET(mc_group, _BCM_MULTICAST_TYPE_MIM, ipmc_id);
   6501 #if defined(BCM_ENDURO_SUPPORT)            
   6502             if (SOC_IS_ENDURO(unit)) {
   6503                 rv = bcm_esw_multicast_egress_delete(unit, mc_group, 
   6504                                                      local_gport, nh_index);
   6505             } else 
   6506 #endif /* BCM_ENDURO_SUPPORT */
   6507             {
   6508                 rv = bcm_esw_multicast_egress_delete(unit, mc_group, 
   6509                                                      local_gport, 
   6510                                        nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   6511             }
   6512             BCM_IF_ERROR_RETURN(rv);
   6513         }
   6514     }
   6515 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   6516     if (soc_feature(unit, soc_feature_global_meter)) {
   6517         rv = _bcm_esw_get_policer_from_table(unit, SOURCE_VPm, vp, &svp, 
   6518                                                       &policer_id, 0); 
   6519         if(BCM_SUCCESS(rv)) {
   6520              _bcm_esw_policer_decrement_ref_count(unit, policer_id);
   6521         } else {
   6522              return rv;
   6523         }
   6524     }
   6525 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT */
   6526 
   6527     /* if Point-to-Point vpn, clear the vp in VFI table */
   6528     if (is_eline) {
   6529         rv = _bcm_tr2_mim_eline_port_delete(unit, vpn, vp); 
   6530         BCM_IF_ERROR_RETURN(rv);
   6531     }
   6532  
   6533     /* Clear the SVP and DVP table entries */
   6534     BCM_IF_ERROR_RETURN
   6535         (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
   6536 
   6537 #if defined(BCM_TRIDENT3_SUPPORT)
   6538     if (SOC_IS_TRIDENT3X(unit)) {
   6539         BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit,
   6540                           MEM_BLOCK_ANY, vp, &svp1));
   6541         old_tpid_enable = soc_SVP_ATTRS_1m_field32_get(unit, &svp1,
   6542                                            TPID_ENABLEf);
   6543         tpid_enable_length = soc_mem_field_length(unit,
   6544                              SVP_ATTRS_1m, TPID_ENABLEf);
   6545     } else
   6546 #endif
   6547     {
   6548         old_tpid_enable = soc_SOURCE_VPm_field32_get(unit, &svp,
   6549                                          TPID_ENABLEf);
   6550         tpid_enable_length = soc_mem_field_length(unit,
   6551                              SOURCE_VPm, TPID_ENABLEf);
   6552     }
   6553 
   6554     if (old_tpid_enable) {
   6555         for (i= 0; i < tpid_enable_length; i++) {
   6556             if (old_tpid_enable & (1 << i)) {
   6557                 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_delete(unit, i));
   6558             }
   6559         }
   6560     }
   6561     sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   6562     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
   6563     BCM_IF_ERROR_RETURN(rv);
   6564 
   6565 #if defined(BCM_TRIDENT3_SUPPORT)
   6566     if (SOC_IS_TRIDENT3X(unit)) {
   6567         sal_memset(&svp1, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   6568         BCM_IF_ERROR_RETURN(WRITE_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, &svp1));
   6569     }
   6570 #endif
   6571 
   6572     sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t));
   6573     rv = _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigClear, vp,
   6574             ING_DVP_CONFIG_INVALID_VP_TYPE, 
   6575             ING_DVP_CONFIG_INVALID_INTF_ID, 
   6576             ING_DVP_CONFIG_INVALID_PORT_TYPE);
   6577     BCM_IF_ERROR_RETURN(rv);
   6578 
   6579     /* Clear the next-hop table entries */
   6580     rv = _bcm_tr2_mim_l2_nh_info_delete(unit, nh_index);
   6581     BCM_IF_ERROR_RETURN(rv);
   6582 
   6583     /* For peer ports, delete entries in ingress and egress 
   6584        VLAN translate tables */
   6585     if (MIM_INFO(unit)->port_info[vp].flags & _BCM_MIM_PORT_TYPE_PEER) {
   6586 #if defined(BCM_TRIUMPH3_SUPPORT)
   6587         if (SOC_IS_TRIUMPH3(unit)) {
   6588             rv = _bcm_tr3_mim_peer_port_config_delete(unit, vp, vpn);
   6589         } else
   6590 #endif /* BCM_TRIUMPH3_SUPPORT */
   6591         {
   6592             rv = _bcm_tr2_mim_peer_port_config_delete(unit, vp, vpn);
   6593         }
   6594         BCM_IF_ERROR_RETURN(rv);
   6595     }
   6596 
   6597     /* Update the physical port's SW state */
   6598 #if defined(BCM_KATANA2_SUPPORT)
   6599     if (soc_feature(unit, soc_feature_linkphy_coe) ||
   6600         soc_feature(unit, soc_feature_subtag_coe)) {
   6601 
   6602         if (is_local_subport && (MIM_INFO(unit)->port_info[vp].tgid == -1)) {
   6603             _bcm_port_info_access(unit,
   6604                 MIM_INFO(unit)->port_info[vp].port, &info);
   6605             info->vp_count--;
   6606             BCM_IF_ERROR_RETURN(
   6607                 bcm_esw_port_vlan_member_get(
   6608                     unit, MIM_INFO(unit)->port_info[vp].port, &port_flags));
   6609             BCM_IF_ERROR_RETURN(
   6610                 bcm_esw_port_vlan_member_set(
   6611                     unit, MIM_INFO(unit)->port_info[vp].port, port_flags));
   6612         }
   6613     }
   6614 #endif
   6615     if (soc_feature(unit, soc_feature_generic_dest)) {
   6616         uint32 dt, dv;
   6617         dv = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm,
   6618                 &ing_nh, DESTINATIONf, &dt);
   6619         if (dt == SOC_MEM_FIF_DEST_DGPP) {
   6620             modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
   6621                         SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
   6622             BCM_IF_ERROR_RETURN(
   6623                 _bcm_esw_modid_is_local(unit, modid, &is_local));
   6624         }
   6625     } else {
   6626         if (!soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
   6627             modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
   6628             BCM_IF_ERROR_RETURN(
   6629                 _bcm_esw_modid_is_local(unit, modid, &is_local));
   6630         }
   6631     }
   6632     if (is_local && (MIM_INFO(unit)->port_info[vp].tgid == -1)) {
   6633         bcm_port_t phys_port = MIM_INFO(unit)->port_info[vp].port; 
   6634         if (soc_feature(unit, soc_feature_sysport_remap)) { 
   6635             BCM_XLATE_SYSPORT_S2P(unit, &phys_port); 
   6636         }
   6637         _bcm_port_info_access(unit, phys_port, &info);
   6638         info->vp_count--;
   6639         BCM_IF_ERROR_RETURN(
   6640             bcm_esw_port_vlan_member_get(unit, phys_port, &port_flags));
   6641         BCM_IF_ERROR_RETURN(
   6642             bcm_esw_port_vlan_member_set(unit, phys_port, port_flags));
   6643     }
   6644 
   6645     /* If associated with a trunk, update each local physical port's SW state */
   6646     if (MIM_INFO(unit)->port_info[vp].tgid != -1) {
   6647         int idx;
   6648 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
   6649         bcm_port_t      local_member_array[SOC_MAX_NUM_PP_PORTS];
   6650         int             max_num_ports = SOC_MAX_NUM_PP_PORTS;
   6651 #else
   6652         bcm_port_t      local_member_array[SOC_MAX_NUM_PORTS];
   6653         int             max_num_ports = SOC_MAX_NUM_PORTS;
   6654 #endif
   6655         int local_member_count;
   6656 
   6657         bcm_trunk_t trunk_id = MIM_INFO(unit)->port_info[vp].tgid;
   6658         BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, trunk_id,
   6659                     max_num_ports, local_member_array, &local_member_count));
   6660         for (idx = 0; idx < local_member_count; idx++) {
   6661             _bcm_port_info_access(unit, local_member_array[idx], &info);
   6662             info->vp_count--;
   6663             BCM_IF_ERROR_RETURN(
   6664                 bcm_esw_port_vlan_member_get(
   6665                     unit, local_member_array[idx], &port_flags));
   6666             BCM_IF_ERROR_RETURN(
   6667                 bcm_esw_port_vlan_member_set(
   6668                     unit, local_member_array[idx], port_flags));
   6669         }
   6670     }
   6671 
   6672     /* Clear the SW state */
   6673     sal_memset(&(MIM_INFO(unit)->port_info[vp]), 0, 
   6674                sizeof(_bcm_tr2_mim_port_info_t));
   6675 
   6676     if (soc_feature(unit, soc_feature_gport_service_counters)) {
   6677         bcm_gport_t gport;
   6678 
   6679         /* Release Service counter, if any */
   6680         BCM_GPORT_MIM_PORT_ID_SET(gport, vp);
   6681         _bcm_esw_flex_stat_handle_free(unit, _bcmFlexStatTypeGport, gport);
   6682     }
   6683 
   6684     /* if spn_RESERVE_MIM_DEFAULT_SVP is set, mim svp 1 memory is already
   6685      * allocated during init time, skipping svp 1 memory free
   6686      */
   6687     if(soc_feature(unit, soc_feature_mim_reserve_default_port) &&
   6688        soc_property_get(unit, spn_RESERVE_MIM_DEFAULT_SVP, 0) &&
   6689        (vp == _BCM_MIM_DEFAULT_PORT)) {
   6690        mim_reserve_svp_delete = 1;
   6691     }
   6692 
   6693     if (!mim_reserve_svp_delete) {
   6694         BCM_IF_ERROR_RETURN(_bcm_tr2_mim_egress_dvp_reset(unit, vp));
   6695         /* Free the VP */
   6696         (void) _bcm_vp_free(unit, _bcmVpTypeMim, 1, vp);
   6697     }
   6698     return rv;
   6699 }
   6700 
   6701 /*
   6702  * Function:
   6703  *      bcm_mim_port_delete
   6704  * Purpose:
   6705  *      Delete an mim port from a VPN
   6706  * Parameters:
   6707  *      unit       - (IN) Device Number
   6708  *      vpn        - (IN) VPN instance ID
   6709  *      mim_port_id - (IN) mim port information
   6710  * Returns:
   6711  *      BCM_E_XXX
   6712  */
   6713 int
   6714 bcm_tr2_mim_port_delete(int unit, bcm_vpn_t vpn, bcm_gport_t mim_port_id)
   6715 {
   6716     int vp, rv;
   6717 
   6718     MIM_INIT(unit);
   6719     if (!BCM_GPORT_IS_MIM_PORT(mim_port_id)) {
   6720         return BCM_E_PORT;
   6721     }
   6722     vp = BCM_GPORT_MIM_PORT_ID_GET(mim_port_id);
   6723     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   6724         return BCM_E_NOT_FOUND;
   6725     }
   6726     if (!(MIM_INFO(unit)->port_info[vp].flags & _BCM_MIM_PORT_TYPE_NETWORK)) {
   6727         if (!_BCM_MIM_VPN_IS_SET(vpn)) {
   6728             return BCM_E_PARAM;
   6729         }
   6730     }
   6731     MIM_LOCK(unit);
   6732     rv = _bcm_tr2_mim_port_delete(unit, vpn, vp);
   6733 
   6734 #ifdef BCM_WARM_BOOT_SUPPORT
   6735     SOC_CONTROL_LOCK(unit);
   6736     SOC_CONTROL(unit)->scache_dirty = 1;
   6737     SOC_CONTROL_UNLOCK(unit);
   6738 #endif
   6739 
   6740     MIM_UNLOCK(unit);
   6741     return rv;
   6742 }
   6743 
   6744 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   6745 /*
   6746   * Function:
   6747   *      _bcm_mim_share_vp_get
   6748   * Purpose:
   6749   *      Get shared VPs info per VPN
   6750   * Parameters:
   6751   *      unit       - (IN) Device Number
   6752   *      vpn        - (IN) VPN that shared vp belong to
   6753   *      vp_bitmap  - (OUT) shared vp bitmap
   6754   * Returns:
   6755   *      BCM_E_XXX
   6756   */
   6757 int
   6758 _bcm_mim_share_vp_get(int unit, bcm_vpn_t vpn, SHR_BITDCL *vp_bitmap)
   6759 {
   6760     void *vent;
   6761     soc_mem_t mem;
   6762     int index_min = 0;
   6763     int index_max = 0;
   6764     uint8 *xlate_buf = NULL;
   6765     int buf_size = 0;
   6766     int i = 0;
   6767     int rv = BCM_E_NONE;
   6768     int vfi = -1;
   6769     int vp = -1;
   6770 
   6771 #if defined(BCM_TRIDENT3_SUPPORT)
   6772     if (soc_feature(unit, soc_feature_base_valid)) {
   6773        mem = VLAN_XLATE_1_DOUBLEm;
   6774     } else
   6775 #endif
   6776     {
   6777        mem = VLAN_XLATEm;
   6778     }
   6779 
   6780     if(NULL == vp_bitmap) {
   6781         return BCM_E_PARAM;
   6782     }
   6783 
   6784     if (!_BCM_MIM_VPN_IS_SET(vpn)) {
   6785         return BCM_E_PARAM;
   6786     }
   6787 
   6788     _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vpn);
   6789     if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   6790         return BCM_E_NOT_FOUND;
   6791     }
   6792 
   6793     index_min = soc_mem_index_min(unit, mem);
   6794     index_max = soc_mem_index_max(unit, mem);
   6795 
   6796     buf_size = SOC_MEM_TABLE_BYTES(unit, mem);
   6797     xlate_buf = soc_cm_salloc(unit, buf_size, "VLAN_XLATE buffer");
   6798     if (NULL == xlate_buf) {
   6799         return BCM_E_MEMORY;
   6800     }
   6801     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, xlate_buf);
   6802     if (rv < 0) {
   6803         soc_cm_sfree(unit, xlate_buf);
   6804         return rv;
   6805     }
   6806 
   6807     for (i = index_min; i <= index_max; i++) {
   6808         vent = soc_mem_table_idx_to_pointer(unit,
   6809             mem, void *, xlate_buf, i);
   6810 #if defined(BCM_TRIDENT3_SUPPORT)
   6811         if (soc_feature(unit, soc_feature_base_valid)) {
   6812             if (soc_mem_field32_get(unit, mem,
   6813                          vent, BASE_VALID_0f) != 3) {
   6814                 continue;
   6815             }
   6816             if (soc_mem_field32_get(unit, mem,
   6817                          vent, BASE_VALID_1f) != 7) {
   6818                 continue;
   6819             }
   6820         } else
   6821 #endif
   6822         {
   6823             if (soc_mem_field32_get(unit, mem,
   6824                          vent, VALIDf) == 0) {
   6825                 continue;
   6826             }
   6827         }
   6828 
   6829         if (soc_mem_field32_get(unit, mem, vent, XLATE__MPLS_ACTIONf) != 0x1) {
   6830             continue;
   6831         }
   6832 
   6833         if (soc_mem_field32_get(unit, mem, vent, XLATE__VFIf) != vfi) {
   6834             continue;
   6835         }
   6836 
   6837         vp = soc_mem_field32_get(unit, mem, vent, XLATE__SOURCE_VPf);
   6838         SHR_BITSET(vp_bitmap, vp);
   6839     }
   6840 
   6841     (void)soc_cm_sfree(unit, xlate_buf);
   6842 
   6843     return BCM_E_NONE;
   6844 }
   6845 
   6846 /*
   6847  * Function:
   6848  *      _bcm_mim_share_vp_delete
   6849  * Purpose:
   6850  *      Delete match criteria of shared VPs
   6851  * Parameters:
   6852  *      unit    - (IN) Device Number
   6853  *      vpn     - (IN) VPN that shared vp belong to
   6854  *      vp      - (IN) Source Virtual Port
   6855  * Returns:
   6856  *      BCM_E_XXX
   6857  */
   6858 int
   6859 _bcm_mim_share_vp_delete(int unit, bcm_vpn_t vpn, int vp)
   6860 {
   6861     void *vent;
   6862     soc_mem_t mem;
   6863     int index_min = 0;
   6864     int index_max = 0;
   6865     uint8 *xlate_buf = NULL;
   6866     int buf_size = 0;
   6867     int i = 0;
   6868     int rv = BCM_E_NONE;
   6869     int vfi = -1;
   6870     int source_vp = -1;
   6871 
   6872     if (!_BCM_MIM_VPN_IS_SET(vpn)) {
   6873         return BCM_E_PARAM;
   6874     }
   6875 
   6876     _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vpn);
   6877     if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   6878         return BCM_E_NOT_FOUND;
   6879     }
   6880 
   6881 #if defined(BCM_TRIDENT3_SUPPORT)
   6882     if (soc_feature(unit, soc_feature_base_valid)) {
   6883        mem = VLAN_XLATE_1_DOUBLEm;
   6884     } else
   6885 #endif
   6886     {
   6887        mem = VLAN_XLATEm;
   6888     }
   6889 
   6890     index_min = soc_mem_index_min(unit, mem);
   6891     index_max = soc_mem_index_max(unit, mem);
   6892 
   6893     buf_size = SOC_MEM_TABLE_BYTES(unit, mem);
   6894     xlate_buf = soc_cm_salloc(unit, buf_size, "VLAN_XLATE buffer");
   6895     if (NULL == xlate_buf) {
   6896         return BCM_E_MEMORY;
   6897     }
   6898     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, xlate_buf);
   6899     if (rv < 0) {
   6900         soc_cm_sfree(unit, xlate_buf);
   6901         return rv;
   6902     }
   6903 
   6904     for (i = index_min; i <= index_max; i++) {
   6905         vent = soc_mem_table_idx_to_pointer(unit,
   6906             mem, void *, xlate_buf, i);
   6907 #if defined(BCM_TRIDENT3_SUPPORT)
   6908         if (soc_feature(unit, soc_feature_base_valid)) {
   6909             if (soc_mem_field32_get(unit, mem,
   6910                          vent, BASE_VALID_0f) != 3) {
   6911                 continue;
   6912             }
   6913             if (soc_mem_field32_get(unit, mem,
   6914                          vent, BASE_VALID_1f) != 7) {
   6915                 continue;
   6916             }
   6917         } else
   6918 #endif
   6919         {
   6920             if (soc_mem_field32_get(unit, mem,
   6921                          vent, VALIDf) == 0) {
   6922                 continue;
   6923             }
   6924         }
   6925 
   6926         if (soc_mem_field32_get(unit, mem, vent, XLATE__MPLS_ACTIONf) != 0x1) {
   6927             continue;
   6928         }
   6929 
   6930         if (soc_mem_field32_get(unit, mem, vent, XLATE__VFIf) != vfi) {
   6931             continue;
   6932         }
   6933 
   6934         source_vp = soc_mem_field32_get(unit, mem, vent, XLATE__SOURCE_VPf);
   6935         if (vp != source_vp) {
   6936             continue;
   6937         }
   6938 
   6939         rv = soc_mem_delete_index(unit, mem, MEM_BLOCK_ALL, i);
   6940         if (rv < 0) {
   6941             soc_cm_sfree(unit, xlate_buf);
   6942             return rv;
   6943         }
   6944         _bcm_tr2_mim_port_match_count_adjust(unit, source_vp, -1);
   6945     }
   6946 
   6947     (void)soc_cm_sfree(unit, xlate_buf);
   6948 
   6949     return BCM_E_NONE;
   6950 }
   6951 #endif
   6952 
   6953 /*
   6954  * Function:
   6955  *      bcm_mim_port_delete_all
   6956  * Purpose:
   6957  *      Delete all mim ports from a VPN
   6958  * Parameters:
   6959  *      unit - Device Number
   6960  *      vpn - VPN instance ID
   6961  * Returns:
   6962  *      BCM_E_XXX
   6963  */
   6964 int
   6965 bcm_tr2_mim_port_delete_all(int unit, bcm_vpn_t vpn)
   6966 {
   6967     int rv = BCM_E_NONE;
   6968     uint32 vfi, vp, num_vp;
   6969     source_vp_entry_t *psvp; 
   6970     uint8 *source_vp_buf = NULL; 
   6971     int network_port = 0;
   6972     _bcm_vp_info_t vp_info;
   6973 
   6974     MIM_INIT(unit);
   6975 
   6976     if (!_BCM_MIM_VPN_IS_SET(vpn)) {
   6977         return BCM_E_PARAM;
   6978     }
   6979 
   6980     _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vpn);
   6981     if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   6982         rv =  BCM_E_NOT_FOUND;
   6983         goto done;
   6984     }
   6985     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   6986 
   6987     source_vp_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, SOURCE_VPm), 
   6988                                  "SOURCE_VP buffer");
   6989      
   6990     if (NULL == source_vp_buf) { 
   6991         return BCM_E_MEMORY; 
   6992     } 
   6993 
   6994     rv = soc_mem_read_range(unit, SOURCE_VPm, MEM_BLOCK_ANY, 
   6995                            0, num_vp-1, source_vp_buf); 
   6996     if (rv < 0) { 
   6997         goto done; 
   6998     } 
   6999 
   7000     for (vp = 0; vp < num_vp; vp++) { 
   7001         network_port = FALSE;
   7002         psvp = soc_mem_table_idx_to_pointer 
   7003                 (unit, SOURCE_VPm, source_vp_entry_t *, source_vp_buf, vp); 
   7004         if (soc_SOURCE_VPm_field32_get(unit, psvp, ENTRY_TYPEf) != 0) {
   7005             /* Network ports do not belong to a certain VPN uniquely,
   7006              * it should be ignored. */
   7007             BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
   7008             if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
   7009                 network_port = TRUE;
   7010             }
   7011             /* Shared access ports do not belong to a certain VPN uniquely,
   7012                       * Remove both software and hardware status of the given VPN. */
   7013 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7014             if ((!network_port) && (vp_info.flags & _BCM_VP_INFO_SHARED_PORT)) {
   7015                 if (MIM_INFO(unit)->port_info[vp].match_count > 0) {
   7016                     BCM_IF_ERROR_RETURN(_bcm_mim_share_vp_delete(unit, vpn, vp));
   7017                 }
   7018             }
   7019 #endif
   7020             if((vfi == soc_SOURCE_VPm_field32_get(unit, psvp, VFIf)) &&
   7021                (!network_port)) { 
   7022                 rv = _bcm_tr2_mim_port_delete(unit, vpn, vp); 
   7023             }
   7024             if (rv < 0) { 
   7025                 goto done; 
   7026             } 
   7027         }
   7028     } 
   7029 
   7030     done: 
   7031     if ( source_vp_buf != NULL ){
   7032         soc_cm_sfree( unit, source_vp_buf); 
   7033     }
   7034     return rv; 
   7035 }
   7036 
   7037 STATIC int
   7038 _bcm_tr2_mim_l2_nh_info_get(int unit, bcm_mim_port_t *mim_port, int nh_index)
   7039 {
   7040     ing_l3_next_hop_entry_t ing_nh;
   7041     egr_l3_next_hop_entry_t egr_nh, failover_egr_nh;
   7042     egr_l3_intf_entry_t egr_intf;
   7043     egr_mac_da_profile_entry_t macda;
   7044     int action_present, action_not_present;
   7045     int intf_num = -1, macda_idx = -1, tpid_idx = -1;
   7046     bcm_module_t mod_out, mod_in;
   7047     bcm_port_t port_out, port_in;
   7048     bcm_trunk_t trunk_id;
   7049     bcm_failover_t failover_id;
   7050     int failover_nh_index = 0;
   7051     int failover_vp;
   7052     bcm_multicast_t  failover_mc_group = 0;
   7053 #if defined(BCM_KATANA2_SUPPORT)
   7054     int is_local_subport = 0;
   7055     bcm_port_t pp_port;
   7056     int min_subport = SOC_INFO(unit).pp_port_index_min;
   7057     int max_subport = SOC_INFO(unit).pp_port_index_max;
   7058 #endif
   7059     int entry_type = 0;
   7060     int is_trunk = 0;
   7061 
   7062     /* Read the HW entries */
   7063     BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
   7064                                       nh_index, &ing_nh));
   7065     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
   7066                                       nh_index, &egr_nh));
   7067 
   7068     if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, 
   7069                                                 ENTRY_TYPEf) == 0x2) {
   7070         if (soc_feature(unit, soc_feature_generic_dest)) {
   7071             uint32 dt, dv;
   7072             dv = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm,
   7073                     &ing_nh, DESTINATIONf, &dt);
   7074             if (dt == SOC_MEM_FIF_DEST_LAG) {
   7075                 /* Trunk group */
   7076                 trunk_id = dv & SOC_MEM_FIF_DGPP_TGID_MASK;
   7077                 is_trunk = 1;
   7078             } else {
   7079                 port_in = dv & SOC_MEM_FIF_DGPP_PORT_MASK;
   7080                 mod_in = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
   7081                           SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
   7082             }
   7083         } else {
   7084             if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
   7085                 trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf);
   7086                 is_trunk = 1;
   7087             } else {
   7088                 mod_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
   7089                 port_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf);
   7090             }
   7091         }
   7092 
   7093         if (is_trunk) {
   7094             BCM_GPORT_TRUNK_SET(mim_port->port, trunk_id);
   7095         } else {
   7096 #if defined(BCM_KATANA2_SUPPORT)
   7097             is_local_subport = 0;
   7098             if (soc_feature(unit, soc_feature_linkphy_coe) ||
   7099                 soc_feature(unit, soc_feature_subtag_coe)) {
   7100                 if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_in) == BCM_E_NONE) {
   7101                     BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(
   7102                         unit, mod_in, port_in, &pp_port));
   7103 #if defined BCM_METROLITE_SUPPORT
   7104                     if (soc_feature(unit, soc_feature_discontinuous_pp_port)) {
   7105                         if (_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, pp_port)) {
   7106                             is_local_subport = 1;
   7107                         }
   7108                     } else
   7109 #endif
   7110                     {
   7111                         if ((pp_port >= min_subport) &&
   7112                             (pp_port <= max_subport)) {
   7113                             is_local_subport = 1;
   7114                         }
   7115                     }
   7116                 }
   7117             }
   7118             if (is_local_subport) {
   7119                 _BCM_KT2_SUBPORT_PORT_ID_SET(mim_port->port, pp_port);
   7120                 if (BCM_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm,
   7121                     pp_port)) {
   7122                     _BCM_KT2_SUBPORT_PORT_TYPE_SET(mim_port->port,
   7123                         _BCM_KT2_SUBPORT_TYPE_LINKPHY);
   7124                 } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm,
   7125                     pp_port)) {
   7126                     _BCM_KT2_SUBPORT_PORT_TYPE_SET(mim_port->port,
   7127                         _BCM_KT2_SUBPORT_TYPE_SUBTAG);
   7128                 } else {
   7129                     return BCM_E_PORT;
   7130                 }
   7131             } else
   7132 #endif
   7133             {
   7134                 SOC_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit,
   7135                     BCM_STK_MODMAP_GET, mod_in, port_in, &mod_out, &port_out));
   7136                 BCM_GPORT_MODPORT_SET(mim_port->port, mod_out, port_out);
   7137             }
   7138         }
   7139     } else {
   7140         return BCM_E_NOT_FOUND;
   7141     }
   7142 
   7143 #if defined(BCM_TRIDENT3_SUPPORT)
   7144         if (SOC_IS_TRIDENT3X(unit)) {
   7145             entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   7146                 &egr_nh, DATA_TYPEf);
   7147         } else
   7148 #endif /* BCM_TRIDENT3_SUPPORT */
   7149         {
   7150             entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   7151                 &egr_nh, ENTRY_TYPEf);
   7152         }
   7153 
   7154     if (entry_type == 0x2) {
   7155         action_present =
   7156             soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   7157                                      SD_TAG__SD_TAG_ACTION_IF_PRESENTf);
   7158         if (action_present) {
   7159             mim_port->flags |= BCM_MIM_PORT_EGRESS_SERVICE_VLAN_TAGGED;
   7160         }
   7161         action_not_present =
   7162             soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   7163                                      SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf);
   7164 
   7165         if ((action_not_present == 0x1) || (action_present == 0x1)) {
   7166             /* If SD tag action is ADD or REPLACE_VID_TPID, the tpid
   7167              * index of the entry is valid. Get the tpid index for later.
   7168              */
   7169             tpid_idx =
   7170                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   7171                                                  SD_TAG__SD_TAG_TPID_INDEXf);
   7172             mim_port->egress_service_vlan =
   7173                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, SD_TAG__SD_TAG_VIDf);
   7174             if (action_not_present) {
   7175                 mim_port->flags |= BCM_MIM_PORT_EGRESS_SERVICE_VLAN_ADD;
   7176             }
   7177             if (action_present) {
   7178                 mim_port->flags |= 
   7179                     BCM_MIM_PORT_EGRESS_SERVICE_VLAN_TPID_REPLACE;
   7180             }
   7181             _bcm_fb2_outer_tpid_entry_get(unit, &mim_port->egress_service_tpid, tpid_idx);
   7182         } else if (action_present == 0x2) { /* REPLACE_VID_ONLY */
   7183             mim_port->flags |= BCM_MIM_PORT_EGRESS_SERVICE_VLAN_REPLACE;
   7184             mim_port->egress_service_vlan =
   7185                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, SD_TAG__SD_TAG_VIDf);
   7186         } else if (action_present == 0x3) { /* DELETE */
   7187             mim_port->flags |= BCM_MIM_PORT_EGRESS_SERVICE_VLAN_DELETE;
   7188         } else if (action_present == 0x4) { /* REPLACE VID TPID PRI ONLY */
   7189             mim_port->flags |= 
   7190                 BCM_MIM_PORT_EGRESS_SERVICE_VLAN_PRI_TPID_REPLACE;
   7191             mim_port->egress_service_vlan =
   7192                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, SD_TAG__SD_TAG_VIDf);
   7193             mim_port->egress_service_pri =
   7194                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, SD_TAG__NEW_PRIf);
   7195             mim_port->egress_service_cfi =
   7196                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, SD_TAG__NEW_CFIf);
   7197             tpid_idx =
   7198                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   7199                                                  SD_TAG__SD_TAG_TPID_INDEXf);
   7200             _bcm_fb2_outer_tpid_entry_get(unit, &mim_port->egress_service_tpid, tpid_idx);
   7201         } else if (action_present == 0x5) { /* REPLACE VID PRI ONLY */
   7202             mim_port->flags |= 
   7203                 BCM_MIM_PORT_EGRESS_SERVICE_VLAN_PRI_REPLACE;
   7204             mim_port->egress_service_vlan =
   7205                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, SD_TAG__SD_TAG_VIDf);
   7206             mim_port->egress_service_pri =
   7207                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, SD_TAG__NEW_PRIf);
   7208             mim_port->egress_service_cfi =
   7209                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, SD_TAG__NEW_CFIf);
   7210         }
   7211 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   7212           else if (action_present == 0x6) {
   7213             mim_port->flags |= 
   7214                 BCM_MIM_PORT_EGRESS_SERVICE_PRI_REPLACE;
   7215             mim_port->egress_service_pri =
   7216                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, SD_TAG__NEW_PRIf);
   7217             mim_port->egress_service_cfi =
   7218                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, SD_TAG__NEW_CFIf);
   7219         } else if (action_present == 0x7){
   7220             mim_port->flags |= 
   7221                     BCM_MIM_PORT_EGRESS_SERVICE_TPID_REPLACE;
   7222             tpid_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   7223                                                  SD_TAG__SD_TAG_TPID_INDEXf);
   7224             _bcm_fb2_outer_tpid_entry_get(unit, &mim_port->egress_service_tpid, tpid_idx); 
   7225         }
   7226 #endif
   7227     } else if (entry_type == 0x3) {
   7228         /* Backbone / peer VP */
   7229         /* Get the tunnel encap attributes */
   7230         mim_port->egress_tunnel_vlan =
   7231                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, MIM__BVIDf);
   7232         intf_num = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 
   7233                                                     MIM__INTF_NUMf);
   7234         macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 
   7235                                                     MIM__MAC_DA_PROFILE_INDEXf);
   7236         BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_INTFm, MEM_BLOCK_ANY, 
   7237                                           intf_num, &egr_intf));
   7238         BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_MAC_DA_PROFILEm,  
   7239                                          MEM_BLOCK_ANY, macda_idx, &macda));
   7240         soc_mem_mac_addr_get(unit, EGR_L3_INTFm, &egr_intf, MAC_ADDRESSf, 
   7241                              mim_port->egress_tunnel_srcmac); 
   7242         soc_mem_mac_addr_get(unit, EGR_MAC_DA_PROFILEm, &macda, MAC_ADDRESSf, 
   7243                              mim_port->egress_tunnel_dstmac);
   7244         if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, MIM__ISID_LOOKUP_TYPEf)) {
   7245             if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   7246                                                  MIM__ISID_LOOKUP_TYPEf) == 0) {
   7247                 mim_port->flags |= BCM_MIM_PORT_TYPE_BACKBONE;
   7248             } else {
   7249                 mim_port->flags |= BCM_MIM_PORT_TYPE_PEER;
   7250             }
   7251         }
   7252         if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   7253                                              MIM__ADD_ISID_TO_MACDAf) == 1) {
   7254             mim_port->flags |= BCM_MIM_PORT_EGRESS_TUNNEL_DEST_MAC_USE_SERVICE;
   7255         }
   7256     }
   7257 
   7258     if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, DROPf)) {
   7259         mim_port->flags |= BCM_MIM_PORT_DROP;
   7260     }
   7261 
   7262 #if defined(BCM_ENDURO_SUPPORT)
   7263     if (!SOC_IS_ENDURO(unit)) {
   7264 #endif 
   7265     /* Get failover info */
   7266     BCM_IF_ERROR_RETURN(
   7267          _bcm_esw_failover_prot_nhi_get (unit, nh_index, 
   7268                     &failover_id, &failover_nh_index, &failover_mc_group));
   7269 
   7270     mim_port->failover_id = failover_id;
   7271     if (failover_mc_group != 0) {
   7272         _BCM_MULTICAST_GROUP_SET(mim_port->failover_mc_group,
   7273                                  _BCM_MULTICAST_TYPE_MIM,
   7274                                  _BCM_MULTICAST_ID_GET(failover_mc_group));
   7275     }
   7276     if (failover_nh_index > 0) {
   7277         BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
   7278                                          failover_nh_index, &failover_egr_nh));
   7279 #if defined(BCM_TRIDENT3_SUPPORT)
   7280         if (SOC_IS_TRIDENT3X(unit)) {
   7281             entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   7282                 &failover_egr_nh, DATA_TYPEf);
   7283         } else
   7284 #endif /* BCM_TRIDENT3_SUPPORT */
   7285         {
   7286             entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   7287                 &failover_egr_nh, ENTRY_TYPEf);
   7288         }
   7289 
   7290         if (entry_type == 0x3) {
   7291             failover_vp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 
   7292                                                            &failover_egr_nh, 
   7293                                                            MIM__DVPf);
   7294         } else if (entry_type == 0x2) {
   7295             failover_vp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 
   7296                                                            &failover_egr_nh, 
   7297                                                            SD_TAG__DVPf);
   7298         } else {
   7299             return BCM_E_INTERNAL; /* should not get here */
   7300         }
   7301         BCM_GPORT_MIM_PORT_ID_SET(mim_port->failover_gport_id, failover_vp);
   7302     }
   7303 
   7304 #if defined(BCM_ENDURO_SUPPORT)
   7305     }
   7306 #endif
   7307     return BCM_E_NONE;
   7308 }
   7309 
   7310 STATIC int
   7311 _bcm_tr2_mim_match_get(int unit, bcm_mim_port_t *mim_port, int vp)
   7312 {
   7313     int modid_count, rv = BCM_E_NONE;
   7314     bcm_module_t mod_in, mod_out;
   7315     bcm_port_t port_in, port_out;
   7316     bcm_trunk_t trunk_id;
   7317     uint64 temp_mac;
   7318 
   7319     if ((MIM_INFO(unit)->port_info[vp].flags & 
   7320          _BCM_MIM_PORT_TYPE_ACCESS_PORT_VLAN) || 
   7321         (MIM_INFO(unit)->port_info[vp].flags & 
   7322          _BCM_MIM_PORT_TYPE_ACCESS_PORT_VLAN_STACKED)) {
   7323 
   7324         if (MIM_INFO(unit)->port_info[vp].match_count == 0) {
   7325             return BCM_E_NONE;
   7326         }
   7327         mim_port->flags |= BCM_MIM_PORT_TYPE_ACCESS;
   7328         mim_port->match_vlan = MIM_INFO(unit)->port_info[vp].match_vlan;
   7329 
   7330         if ((MIM_INFO(unit)->port_info[vp].flags & 
   7331              _BCM_MIM_PORT_TYPE_ACCESS_PORT_VLAN_STACKED)) {
   7332             mim_port->match_inner_vlan = 
   7333                 MIM_INFO(unit)->port_info[vp].match_inner_vlan;
   7334             mim_port->criteria = BCM_MIM_PORT_MATCH_PORT_VLAN_STACKED; 
   7335         } else {
   7336             mim_port->criteria = BCM_MIM_PORT_MATCH_PORT_VLAN;
   7337         }
   7338 
   7339         if ((MIM_INFO(unit)->port_info[vp].tgid != -1)) {
   7340             trunk_id = MIM_INFO(unit)->port_info[vp].tgid;
   7341             BCM_GPORT_TRUNK_SET(mim_port->port, trunk_id);
   7342         } else {
   7343             mod_in = MIM_INFO(unit)->port_info[vp].modid;
   7344             port_in = MIM_INFO(unit)->port_info[vp].port;
   7345 
   7346             rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   7347                                     mod_in, port_in, &mod_out, &port_out);
   7348             BCM_GPORT_MODPORT_SET(mim_port->port, mod_out, port_out);
   7349         }
   7350 
   7351     } else if (MIM_INFO(unit)->port_info[vp].flags & 
   7352                _BCM_MIM_PORT_TYPE_ACCESS_PORT) {
   7353         mim_port->flags |= (BCM_MIM_PORT_TYPE_ACCESS);
   7354         mim_port->criteria = BCM_MIM_PORT_MATCH_PORT;
   7355         modid_count = SOC_MODID_MAX(unit) + 1;
   7356 
   7357         if ( SOC_IS_TRIUMPH3(unit) ) {
   7358             int src_trk_idx=0; /*Source Trunk table index.*/
   7359             source_trunk_map_modbase_entry_t modbase_entry;
   7360         
   7361             BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &mod_in));
   7362             src_trk_idx = MIM_INFO(unit)->port_info[vp].index % modid_count;
   7363         
   7364             BCM_IF_ERROR_RETURN
   7365                 (soc_mem_read(unit, SOURCE_TRUNK_MAP_MODBASEm,
   7366             MEM_BLOCK_ANY, mod_in, &modbase_entry));
   7367         
   7368             port_in = src_trk_idx - soc_mem_field32_get(unit,
   7369                     SOURCE_TRUNK_MAP_MODBASEm,
   7370                     &modbase_entry, BASEf);
   7371         } else {
   7372             port_in = MIM_INFO(unit)->port_info[vp].index % modid_count;
   7373             mod_in = MIM_INFO(unit)->port_info[vp].index / modid_count;
   7374         }
   7375 
   7376         rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   7377                                 mod_in, port_in, &mod_out, &port_out);
   7378         BCM_GPORT_MODPORT_SET(mim_port->port, mod_out, port_out);
   7379 
   7380     } else if (MIM_INFO(unit)->port_info[vp].flags & 
   7381                _BCM_MIM_PORT_TYPE_ACCESS_LABEL) {
   7382         mim_port->flags |= (BCM_MIM_PORT_TYPE_ACCESS);
   7383         mim_port->criteria = BCM_MIM_PORT_MATCH_LABEL;
   7384         mim_port->match_label = MIM_INFO(unit)->port_info[vp].match_label;
   7385 
   7386         if ((MIM_INFO(unit)->port_info[vp].tgid != -1)) {
   7387             trunk_id = MIM_INFO(unit)->port_info[vp].tgid;
   7388             BCM_GPORT_TRUNK_SET(mim_port->port, trunk_id);
   7389         } else {
   7390             mod_in = MIM_INFO(unit)->port_info[vp].modid;
   7391             port_in = MIM_INFO(unit)->port_info[vp].port;
   7392 
   7393             rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   7394                                     mod_in, port_in, &mod_out, &port_out);
   7395             BCM_GPORT_MODPORT_SET(mim_port->port, mod_out, port_out);
   7396         }
   7397 
   7398     } else if (MIM_INFO(unit)->port_info[vp].flags & 
   7399                (_BCM_MIM_PORT_TYPE_NETWORK | _BCM_MIM_PORT_TYPE_PEER)) {
   7400         mim_port->criteria = BCM_MIM_PORT_MATCH_TUNNEL_VLAN_SRCMAC;
   7401         if (MIM_INFO(unit)->port_info[vp].flags & _BCM_MIM_PORT_TYPE_PEER) {
   7402             mim_port->flags |= BCM_MIM_PORT_TYPE_PEER;
   7403 #if defined(BCM_TRIDENT_SUPPORT)
   7404             if (soc_feature(unit, soc_feature_mim_peer_sharing) &&
   7405                 (MIM_INFO(unit)->port_info[vp].flags &
   7406                  _BCM_MIM_PORT_TYPE_SHARE)) {
   7407                     mim_port->flags |= BCM_MIM_PORT_SHARE;
   7408             }
   7409 #endif /* BCM_TRIDENT_SUPPORT */
   7410         } else {
   7411             mim_port->flags |= BCM_MIM_PORT_TYPE_BACKBONE;
   7412         }
   7413 
   7414         SAL_MAC_ADDR_TO_UINT64
   7415            (MIM_INFO(unit)->port_info[vp].match_tunnel_srcmac, temp_mac);
   7416         SAL_MAC_ADDR_FROM_UINT64(mim_port->match_tunnel_srcmac, temp_mac);
   7417         mim_port->match_tunnel_vlan = 
   7418             MIM_INFO(unit)->port_info[vp].match_tunnel_vlan; 
   7419 
   7420         if ((MIM_INFO(unit)->port_info[vp].tgid != -1)) {
   7421             trunk_id = MIM_INFO(unit)->port_info[vp].tgid;
   7422             BCM_GPORT_TRUNK_SET(mim_port->port, trunk_id);
   7423         } else {
   7424             mod_in = MIM_INFO(unit)->port_info[vp].modid;
   7425             port_in = MIM_INFO(unit)->port_info[vp].port;
   7426 
   7427             rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   7428                                     mod_in, port_in, &mod_out, &port_out);
   7429             BCM_GPORT_MODPORT_SET(mim_port->port, mod_out, port_out);
   7430         }
   7431 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7432         if (soc_feature(unit, soc_feature_ingress_failover)) {
   7433             uint32 ment[SOC_MAX_MEM_WORDS];
   7434             int                index = -1;
   7435             soc_mem_t mpls_mem = MPLS_ENTRYm;
   7436 
   7437             sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   7438             soc_mem_field32_set(unit, mpls_mem, ment, KEY_TYPEf, 1);
   7439 #if defined(BCM_TRIDENT3_SUPPORT)
   7440             if (soc_feature(unit, soc_feature_base_valid)) {
   7441                 soc_mem_field32_set(unit, mpls_mem, ment, BASE_VALID_0f, 3); 
   7442                 soc_mem_field32_set(unit, mpls_mem, ment, BASE_VALID_1f, 7); 
   7443             } else
   7444 #endif
   7445             {
   7446                 soc_mem_field32_set(unit, mpls_mem, ment, VALIDf, 0x1);
   7447             }
   7448             soc_mem_field32_set(unit, mpls_mem, ment, MIM_NVP__BVIDf,
   7449                 MIM_INFO(unit)->port_info[vp].match_tunnel_vlan);
   7450             soc_mem_mac_addr_set(unit, mpls_mem, ment, MIM_NVP__BMACSAf,
   7451                 MIM_INFO(unit)->port_info[vp].match_tunnel_srcmac);
   7452             BCM_IF_ERROR_RETURN(soc_mem_search(unit, mpls_mem, MEM_BLOCK_ANY,
   7453                                                &index, ment, ment, 0));
   7454             if (soc_mem_field32_get(unit, mpls_mem, ment,
   7455                                             MIM_NVP__DROP_DATA_ENABLEf)) {
   7456                 mim_port->flags |= BCM_MIM_PORT_FAILOVER_DROP;
   7457             }
   7458             mim_port->ingress_failover_id =
   7459                 soc_mem_field32_get(unit, mpls_mem, ment,
   7460                                             MIM_NVP__RX_PROT_GROUPf);
   7461             if (mim_port->ingress_failover_id != 0) {
   7462                 _BCM_ENCAP_TYPE_IN_FAILOVER_ID(mim_port->ingress_failover_id,
   7463                                                _BCM_FAILOVER_INGRESS);
   7464             }
   7465          }
   7466 #endif
   7467     } else if (MIM_INFO(unit)->port_info[vp].flags & 
   7468                _BCM_MIM_PORT_TYPE_ACCESS_SHARED) {
   7469         mim_port->flags |= BCM_MIM_PORT_TYPE_ACCESS;
   7470         mim_port->criteria = BCM_MIM_PORT_MATCH_SHARE;
   7471     }
   7472     return rv;
   7473 }
   7474 
   7475 STATIC int
   7476 _bcm_tr2_mim_egr_vxlt_sd_tag_actions_get(
   7477     int unit, bcm_mim_port_t *mim_port, bcm_mim_vpn_config_t *vpn_info,
   7478     uint32 *egr_vlan_xlate_entry)
   7479 {
   7480     int action_present, action_not_present, tpid_idx;
   7481     soc_mem_t egr_xlate_mem;
   7482 
   7483 #if defined(BCM_TRIDENT3_SUPPORT)
   7484     if (soc_feature(unit, soc_feature_base_valid)) {
   7485         egr_xlate_mem = EGR_VLAN_XLATE_1_DOUBLEm;
   7486     } else
   7487 #endif
   7488     {
   7489         egr_xlate_mem = EGR_VLAN_XLATEm;
   7490     }
   7491 
   7492     /* Populate the API structure */
   7493     action_present =
   7494         soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   7495                                         MIM_ISID__SD_TAG_ACTION_IF_PRESENTf);
   7496     action_not_present =
   7497         soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   7498                                        MIM_ISID__SD_TAG_ACTION_IF_NOT_PRESENTf);
   7499     if (mim_port != NULL) {
   7500         if (action_present) {
   7501             mim_port->flags |= BCM_MIM_PORT_EGRESS_SERVICE_VLAN_TAGGED;
   7502         }
   7503 
   7504     if ((action_not_present == 0x1) || (action_present == 0x1)) {
   7505         /* If SD tag action is ADD or REPLACE_VID_TPID, the tpid
   7506          * index of the entry is valid. Get the tpid index for later.
   7507          */
   7508         tpid_idx =
   7509             soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   7510                                             MIM_ISID__SD_TAG_TPID_INDEXf);
   7511         mim_port->egress_service_vlan =
   7512             soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate_entry, 
   7513                                             MIM_ISID__SD_TAG_VIDf);
   7514         if (action_not_present) {
   7515             mim_port->flags |= BCM_MIM_PORT_EGRESS_SERVICE_VLAN_ADD;
   7516         }
   7517         if (action_present) {
   7518             mim_port->flags |= 
   7519                 BCM_MIM_PORT_EGRESS_SERVICE_VLAN_TPID_REPLACE;
   7520         }
   7521         _bcm_fb2_outer_tpid_entry_get(unit, &mim_port->egress_service_tpid, tpid_idx);
   7522     } else if (action_present == 0x2) { /* REPLACE_VID_ONLY */
   7523         mim_port->flags |= BCM_MIM_PORT_EGRESS_SERVICE_VLAN_REPLACE;
   7524         mim_port->egress_service_vlan =
   7525             soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate_entry, 
   7526                                             MIM_ISID__SD_TAG_VIDf);
   7527     } else if (action_present == 0x3) { /* DELETE */
   7528         mim_port->flags |= BCM_MIM_PORT_EGRESS_SERVICE_VLAN_DELETE;
   7529     }
   7530 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   7531       else if (action_present == 0x6) {
   7532         mim_port->flags |= 
   7533                 BCM_MIM_PORT_EGRESS_SERVICE_PRI_REPLACE;
   7534         mim_port->egress_service_pri =
   7535             soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   7536                                 MIM_ISID__NEW_PRIf);
   7537         mim_port->egress_service_cfi =
   7538             soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   7539                                 MIM_ISID__NEW_CFIf);
   7540     } else if (action_present == 0x7) {
   7541         mim_port->flags |= 
   7542                     BCM_MIM_PORT_EGRESS_SERVICE_TPID_REPLACE;
   7543         tpid_idx = soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   7544                                        MIM_ISID__SD_TAG_TPID_INDEXf);
   7545         _bcm_fb2_outer_tpid_entry_get(unit, &mim_port->egress_service_tpid, tpid_idx);
   7546     }
   7547 #endif
   7548     } else if (vpn_info != NULL) {
   7549         if (action_present == 0x7) {
   7550             vpn_info->flags |= BCM_MIM_VPN_EGRESS_SERVICE_TPID_REPLACE;
   7551             tpid_idx = soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   7552                                            MIM_ISID__SD_TAG_TPID_INDEXf);
   7553             _bcm_fb2_outer_tpid_entry_get(unit, &vpn_info->egress_service_tpid,
   7554                                           tpid_idx);
   7555         }
   7556     }
   7557 
   7558     return BCM_E_NONE;
   7559 }
   7560 
   7561 /*
   7562  * Function:
   7563  *      _bcm_tr2_mim_peer_port_config_get
   7564  * Purpose:
   7565  *      Get the information of peer port
   7566  * Parameters:
   7567  *      unit     - (IN) Device Number
   7568  *      mim_port - (IN/OUT) MIM port information
   7569  *      vp       - (IN) Virtual Port
   7570  *      vpn      - (IN) VPN instance ID
   7571  */
   7572 STATIC int
   7573 _bcm_tr2_mim_peer_port_config_get(int unit, bcm_mim_port_t *mim_port,
   7574                                   int vp, bcm_mim_vpn_t vpn)
   7575 {
   7576     uint32 egr_vlan_xlate_entry[SOC_MAX_MEM_WORDS];
   7577     int index = -1;
   7578     int vfi   = -1;
   7579     int isid  = -1;
   7580     int rv    = BCM_E_NONE;
   7581     soc_mem_t egr_xlate_mem;
   7582 
   7583 #if defined(BCM_TRIDENT3_SUPPORT)
   7584     if (soc_feature(unit, soc_feature_base_valid)) {
   7585         egr_xlate_mem = EGR_VLAN_XLATE_1_DOUBLEm;
   7586     } else
   7587 #endif
   7588     {
   7589         egr_xlate_mem = EGR_VLAN_XLATEm;
   7590     }
   7591 
   7592     _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vpn);
   7593 
   7594     sal_memset(egr_vlan_xlate_entry, 0, sizeof(egr_vlan_xlate_entry));
   7595     soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, ENTRY_TYPEf, 0x4);
   7596     soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, MIM_ISID__VFIf, vfi);
   7597     if (soc_feature(unit, soc_feature_base_valid)) {
   7598         soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, BASE_VALID_0f, 0x3);
   7599         soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, BASE_VALID_1f, 0x7);
   7600     } else {
   7601         soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, VALIDf, 0x1);
   7602     }
   7603     soc_mem_field32_set(unit, egr_xlate_mem, egr_vlan_xlate_entry, MIM_ISID__DVPf, vp);
   7604 
   7605     rv = soc_mem_search(unit, egr_xlate_mem, MEM_BLOCK_ANY, &index,
   7606                         egr_vlan_xlate_entry, egr_vlan_xlate_entry, 0);
   7607     BCM_IF_ERROR_RETURN(rv);
   7608 
   7609     isid = soc_mem_field32_get(unit, egr_xlate_mem, egr_vlan_xlate_entry,
   7610                                MIM_ISID__ISIDf);
   7611     if (isid != -1) {
   7612         mim_port->egress_tunnel_service = isid;
   7613         mim_port->flags |= BCM_MIM_PORT_EGRESS_TUNNEL_SERVICE_REPLACE;
   7614     }
   7615 
   7616     BCM_IF_ERROR_RETURN(
   7617         _bcm_tr2_mim_egr_vxlt_sd_tag_actions_get(unit, mim_port, NULL,
   7618                                                  egr_vlan_xlate_entry));
   7619 
   7620     return rv;
   7621 }
   7622 
   7623 STATIC int
   7624 _bcm_tr2_mim_port_get(int unit, bcm_vpn_t vpn, int vp,
   7625                         bcm_mim_port_t *mim_port)
   7626 {
   7627     int i, nh_index, tpid_enable = 0, rv = BCM_E_NONE;
   7628     ing_dvp_table_entry_t dvp;
   7629     source_vp_entry_t svp;
   7630 #if defined(BCM_TRIDENT3_SUPPORT)
   7631     uint32 svp1[SOC_MAX_MEM_WORDS] = {0};
   7632 #endif
   7633 
   7634     /* Initialize the structure */
   7635     bcm_mim_port_t_init(mim_port);
   7636     BCM_GPORT_MIM_PORT_ID_SET(mim_port->mim_port_id, vp);
   7637 
   7638     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   7639     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
   7640 
   7641     if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   7642         if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_GROUPf)) {
   7643             mim_port->network_group_id = soc_ING_DVP_TABLEm_field32_get(
   7644                     unit, &dvp, NETWORK_GROUPf);
   7645         }
   7646     }
   7647 
   7648     /* Get the match parameters */
   7649     rv = _bcm_tr2_mim_match_get(unit, mim_port, vp);
   7650     BCM_IF_ERROR_RETURN(rv);
   7651 
   7652     /* Get the next-hop parameters */
   7653     rv = _bcm_tr2_mim_l2_nh_info_get(unit, mim_port, nh_index);
   7654     BCM_IF_ERROR_RETURN(rv);
   7655 
   7656 #if defined(BCM_TRIDENT3_SUPPORT)
   7657     if (SOC_IS_TRIDENT3X(unit)) {
   7658         rv = _bcm_tr2_mim_dvp_get(unit, vp, mim_port);
   7659         BCM_IF_ERROR_RETURN(rv);
   7660     }
   7661 #endif
   7662 
   7663     mim_port->encap_id = nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   7664 
   7665     /* For peer ports, get the peer information if configured */
   7666     if (MIM_INFO(unit)->port_info[vp].flags & _BCM_MIM_PORT_TYPE_PEER) {
   7667         if (!SOC_IS_TRIUMPH3(unit)) {
   7668             rv = _bcm_tr2_mim_peer_port_config_get(unit, mim_port, vp, vpn);
   7669             BCM_IF_ERROR_RETURN(rv);
   7670         }
   7671     }
   7672 
   7673     /* Fill in SVP parameters */
   7674     BCM_IF_ERROR_RETURN (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
   7675 #if defined(BCM_TRIDENT3_SUPPORT)
   7676     if (SOC_IS_TRIDENT3X(unit)) {
   7677         BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, &svp1));
   7678 
   7679         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   7680             if (soc_mem_field_valid(unit, SOURCE_VPm, NETWORK_GROUPf)) {
   7681                 mim_port->network_group_id = soc_SOURCE_VPm_field32_get(unit,
   7682                     &svp, NETWORK_GROUPf);
   7683             }
   7684         }
   7685     }
   7686 #endif
   7687     mim_port->if_class = soc_SOURCE_VPm_field32_get(unit, &svp, CLASS_IDf);
   7688     if (soc_SOURCE_VPm_field32_get(unit, &svp, SD_TAG_MODEf)) {
   7689 #if defined(BCM_TRIDENT3_SUPPORT)
   7690         if (SOC_IS_TRIDENT3X(unit)) {
   7691             tpid_enable = soc_SVP_ATTRS_1m_field32_get(unit, &svp1, TPID_ENABLEf);
   7692         } else
   7693 #endif
   7694         {
   7695             tpid_enable = soc_SOURCE_VPm_field32_get(unit, &svp, TPID_ENABLEf);
   7696         }
   7697         if (tpid_enable) {
   7698             mim_port->flags |= BCM_MIM_PORT_MATCH_SERVICE_VLAN_TPID;
   7699             for (i = 0; i < 4; i++) {
   7700                 if (tpid_enable & (1 << i)) {
   7701                     _bcm_fb2_outer_tpid_entry_get(unit, 
   7702                         &mim_port->match_service_tpid, i);
   7703                 }
   7704             }
   7705         }
   7706     }
   7707 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   7708     if (soc_feature(unit, soc_feature_global_meter)) {
   7709         rv = _bcm_esw_get_policer_from_table(unit, SOURCE_VPm, vp, &svp, 
   7710                                                       &mim_port->policer_id, 1);
   7711     }
   7712 #endif
   7713     return rv;
   7714 }
   7715 
   7716 /*
   7717  * Function:
   7718  *      bcm_mim_port_get
   7719  * Purpose:
   7720  *      Get an mim port
   7721  * Parameters:
   7722  *      unit       - (IN) Device Number
   7723  *      vpn        - (IN) VPN instance ID
   7724  *      mim_port  - (IN/OUT) mim port information
   7725  */
   7726 int
   7727 bcm_tr2_mim_port_get(int unit, bcm_vpn_t vpn, bcm_mim_port_t *mim_port)
   7728 {
   7729     int vp;
   7730 
   7731     MIM_INIT(unit);
   7732 
   7733     if (!_BCM_MIM_VPN_IS_SET(vpn)) {
   7734         return BCM_E_PARAM;
   7735     }
   7736     if (!BCM_GPORT_IS_MIM_PORT(mim_port->mim_port_id)) {
   7737         return BCM_E_PORT;
   7738     }
   7739     vp = BCM_GPORT_MIM_PORT_ID_GET(mim_port->mim_port_id);
   7740     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   7741         return BCM_E_NOT_FOUND;
   7742     }
   7743     return _bcm_tr2_mim_port_get(unit, vpn, vp, mim_port);
   7744 }
   7745 
   7746 /*
   7747  * Function:
   7748  *      bcm_mim_port_get_all
   7749  * Purpose:
   7750  *      Get all the mim ports from a VPN
   7751  * Parameters:
   7752  *      unit     - (IN) Device Number
   7753  *      vpn      - (IN) VPN instance ID
   7754  *      port_max   - (IN) Maximum number of interfaces in array
   7755  *      port_array - (OUT) Array of mpls ports
   7756  *      port_count - (OUT) Number of interfaces returned in array
   7757  */
   7758 int
   7759 bcm_tr2_mim_port_get_all(int unit, bcm_vpn_t vpn, int port_max,
   7760                         bcm_mim_port_t *port_array, int *port_count)
   7761 {
   7762     int vp = 0, rv = BCM_E_NONE;
   7763     uint32 vfi = -1, num_vp = 0;
   7764     source_vp_entry_t svp;
   7765     int network_port = 0;
   7766     _bcm_vp_info_t vp_info;
   7767     SHR_BITDCL *share_vp_bitmap = NULL;
   7768 
   7769     MIM_INIT(unit);
   7770 
   7771     if (!_BCM_MIM_VPN_IS_SET(vpn)) {
   7772         return BCM_E_PARAM;
   7773     }
   7774 
   7775     *port_count = 0;
   7776 
   7777     _BCM_MIM_VPN_GET(vfi, _BCM_MIM_VPN_TYPE_MIM, vpn);
   7778 
   7779     if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMim)) {
   7780         rv = BCM_E_NOT_FOUND;
   7781         goto done;
   7782     }
   7783 
   7784     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   7785     share_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "share_vp_bitmap");
   7786     if (share_vp_bitmap == NULL) {
   7787         return BCM_E_MEMORY;
   7788     }
   7789     sal_memset(share_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
   7790 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7791     if (soc_feature(unit, soc_feature_vp_sharing)) {
   7792         rv = _bcm_mim_share_vp_get(unit, vpn, share_vp_bitmap);
   7793         if (rv < 0) {
   7794             goto done;
   7795         }
   7796     }
   7797 #endif
   7798 
   7799     for (vp = 0; vp < num_vp; vp++) {
   7800         if (*port_count == port_max) {
   7801             break;
   7802         }
   7803         rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
   7804         if (rv < 0) {
   7805             goto done;
   7806         }
   7807 
   7808         if (soc_SOURCE_VPm_field32_get( unit, &svp, ENTRY_TYPEf) == 1) {
   7809             /* Network ports do not belong to a certain VPN uniquely, 
   7810              * it should be ignored. */
   7811             BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
   7812             if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
   7813                 network_port = TRUE;
   7814             }
   7815 
   7816             if(((vfi == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf)) &&
   7817                 (!network_port))
   7818 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7819                 || (SHR_BITGET(share_vp_bitmap, vp)
   7820                     && (vp_info.flags & _BCM_VP_INFO_SHARED_PORT))
   7821 #endif
   7822                ) {
   7823                 rv = _bcm_tr2_mim_port_get(unit, vpn, vp, 
   7824                                         &port_array[*port_count]);
   7825                 if ((rv < 0) && rv != BCM_E_NOT_FOUND) {
   7826                     goto done;
   7827                 }
   7828                 if (rv != BCM_E_NOT_FOUND) {
   7829                     BCM_GPORT_MIM_PORT_ID_SET
   7830                         (port_array[*port_count].mim_port_id, vp);
   7831                     (*port_count)++;
   7832                 }
   7833             }
   7834         }
   7835     }
   7836 done:
   7837     if(share_vp_bitmap != NULL) {
   7838         sal_free(share_vp_bitmap);
   7839     }
   7840     return (*port_count > 0)? BCM_E_NONE:rv;
   7841 }
   7842 
   7843 /*
   7844  * Function:
   7845  *      _bcm_tr2_mim_port_resolve
   7846  * Purpose:
   7847  *      Get the modid, port, trunk values for a MIM port
   7848  * Returns:
   7849  *      BCM_E_XXX
   7850  */
   7851 int
   7852 _bcm_tr2_mim_port_resolve(int unit, bcm_gport_t mim_port_id,
   7853                           bcm_module_t *modid, bcm_port_t *port,
   7854                           bcm_trunk_t *trunk_id, int *id)
   7855 
   7856 {
   7857     int rv = BCM_E_NONE, nh_index, vp;
   7858     ing_l3_next_hop_entry_t ing_nh;
   7859     ing_dvp_table_entry_t dvp;
   7860 
   7861     MIM_INIT(unit);
   7862 
   7863     if (!BCM_GPORT_IS_MIM_PORT(mim_port_id)) {
   7864         return (BCM_E_BADID);
   7865     }
   7866 
   7867     vp = BCM_GPORT_MIM_PORT_ID_GET(mim_port_id);
   7868     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   7869         return BCM_E_NOT_FOUND;
   7870     }
   7871     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   7872     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
   7873                                               NEXT_HOP_INDEXf);
   7874     BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   7875                                       nh_index, &ing_nh));
   7876 
   7877     if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf) != 0x2) {
   7878         /* Entry type is not L2 DVP */
   7879         return BCM_E_NOT_FOUND;
   7880     }
   7881 
   7882     if (soc_feature(unit, soc_feature_generic_dest)) {
   7883         uint32 dt, dv;
   7884         dv = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm,
   7885                 &ing_nh, DESTINATIONf, &dt);
   7886         if (dt == SOC_MEM_FIF_DEST_LAG) {
   7887             /* Trunk group */
   7888             *trunk_id = dv & SOC_MEM_FIF_DGPP_TGID_MASK;
   7889         } else {
   7890             *port = dv & SOC_MEM_FIF_DGPP_PORT_MASK;
   7891             *modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
   7892                       SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
   7893         }
   7894     } else {
   7895         if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
   7896             *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf);
   7897         } else {
   7898             *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
   7899             *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf);
   7900         }
   7901     }
   7902     *id = vp;
   7903     return rv;
   7904 }
   7905 
   7906 /*
   7907  * Function:
   7908  *      bcm_tr2_mim_port_learn_get
   7909  * Purpose:
   7910  *      Get the CML bits for an mim port
   7911  * Returns:
   7912  *      BCM_E_XXX
   7913  */
   7914 int
   7915 bcm_tr2_mim_port_learn_get(int unit, bcm_gport_t mim_port_id, uint32 *flags)
   7916 {
   7917     int rv, vp, cml = 0;
   7918     source_vp_entry_t svp;
   7919 
   7920     MIM_INIT(unit);
   7921 
   7922     /* Get the VP index from the gport */
   7923     vp = BCM_GPORT_MIM_PORT_ID_GET(mim_port_id);
   7924     if (vp == -1) {
   7925         return BCM_E_PARAM;
   7926     }
   7927 
   7928     MEM_LOCK(unit, SOURCE_VPm);
   7929     /* Be sure the entry is used and is set for VPLS */
   7930     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeAny)) {
   7931         MEM_UNLOCK(unit, SOURCE_VPm);
   7932         return BCM_E_NOT_FOUND;
   7933     }
   7934     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
   7935     if (rv < 0) {
   7936         MEM_UNLOCK(unit, SOURCE_VPm);
   7937         return rv;
   7938     }
   7939     if (soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) != 1) { /* L2 VP */
   7940         MEM_UNLOCK(unit, SOURCE_VPm);
   7941         return BCM_E_NOT_FOUND;
   7942     }
   7943     MEM_UNLOCK(unit, SOURCE_VPm);
   7944     cml = soc_SOURCE_VPm_field32_get(unit, &svp, CML_FLAGS_NEWf);
   7945 
   7946     *flags = 0;
   7947     if (!(cml & (1 << 0))) {
   7948        *flags |= BCM_PORT_LEARN_FWD;
   7949     }
   7950     if (cml & (1 << 1)) {
   7951        *flags |= BCM_PORT_LEARN_CPU;
   7952     }
   7953     if (cml & (1 << 2)) {
   7954        *flags |= BCM_PORT_LEARN_PENDING;
   7955     }
   7956     if (cml & (1 << 3)) {
   7957        *flags |= BCM_PORT_LEARN_ARL;
   7958     }
   7959     return BCM_E_NONE;
   7960 }
   7961 
   7962 /*
   7963  * Function:
   7964  *      bcm_tr2_mim_port_learn_set
   7965  * Purpose:
   7966  *      Set the CML bits for an mim port.
   7967  * Returns:
   7968  *      BCM_E_XXX
   7969  */
   7970 int
   7971 bcm_tr2_mim_port_learn_set(int unit, bcm_gport_t mim_port_id, uint32 flags)
   7972 {
   7973     int vp, cml = 0, rv = BCM_E_NONE;
   7974     source_vp_entry_t svp;
   7975 
   7976     MIM_INIT(unit);
   7977 
   7978     cml = 0;
   7979     if (!(flags & BCM_PORT_LEARN_FWD)) {
   7980        cml |= (1 << 0);
   7981     }
   7982     if (flags & BCM_PORT_LEARN_CPU) {
   7983        cml |= (1 << 1);
   7984     }
   7985     if (flags & BCM_PORT_LEARN_PENDING) {
   7986        cml |= (1 << 2);
   7987     }
   7988     if (flags & BCM_PORT_LEARN_ARL) {
   7989        cml |= (1 << 3);
   7990     }
   7991 
   7992     /* Get the VP index from the gport */
   7993     vp = BCM_GPORT_MIM_PORT_ID_GET(mim_port_id);
   7994     if (vp == -1) {
   7995         return BCM_E_PARAM;
   7996     }
   7997 
   7998     MEM_LOCK(unit, SOURCE_VPm);
   7999     /* Be sure the entry is used and is set for MIM */
   8000     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeAny)) {
   8001         MEM_UNLOCK(unit, SOURCE_VPm);
   8002         return BCM_E_NOT_FOUND;
   8003     }
   8004     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
   8005     if (rv < 0) {
   8006         MEM_UNLOCK(unit, SOURCE_VPm);
   8007         return rv;
   8008     }
   8009     if (soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) != 1) { /* L2 VP */
   8010         MEM_UNLOCK(unit, SOURCE_VPm);
   8011         return BCM_E_NOT_FOUND;
   8012     }
   8013     soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml);
   8014     soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml);
   8015     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
   8016     MEM_UNLOCK(unit, SOURCE_VPm);
   8017     return rv;
   8018 }
   8019 
   8020 int
   8021 _bcm_esw_mim_flex_stat_index_set(int unit, bcm_gport_t port, int fs_idx,
   8022                                  uint32 flags)
   8023 {
   8024     int rv, vp, nh_index;
   8025     source_vp_entry_t svp;
   8026     ing_dvp_table_entry_t dvp;
   8027     egr_l3_next_hop_entry_t next_hop;
   8028 
   8029     vp = BCM_GPORT_MIM_PORT_ID_GET(port);
   8030     if (vp == -1) {
   8031         return BCM_E_PARAM;
   8032     }
   8033 
   8034     rv = BCM_E_NONE;
   8035 
   8036     MIM_LOCK(unit);
   8037     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   8038         MIM_UNLOCK(unit);
   8039         return BCM_E_NOT_FOUND;
   8040     } else {
   8041         /* Ingress side */
   8042         if (flags & _BCM_FLEX_STAT_HW_INGRESS) {
   8043             rv = soc_mem_read(unit, SOURCE_VPm, MEM_BLOCK_ANY, vp, &svp);
   8044             if (BCM_SUCCESS(rv)) {
   8045                 if (soc_mem_field_valid(unit, SOURCE_VPm, USE_VINTF_CTR_IDXf)) {
   8046                     soc_mem_field32_set(unit, SOURCE_VPm, &svp, USE_VINTF_CTR_IDXf,
   8047                                         fs_idx > 0 ? 1 : 0);
   8048                 }
   8049                 soc_mem_field32_set(unit, SOURCE_VPm, &svp, VINTF_CTR_IDXf,
   8050                                 fs_idx);
   8051                 rv = soc_mem_write(unit, SOURCE_VPm, MEM_BLOCK_ALL, vp, &svp);
   8052             }
   8053         }
   8054         if (flags & _BCM_FLEX_STAT_HW_EGRESS) {
   8055             if (BCM_SUCCESS(rv)) {
   8056                 /* Egress side */
   8057                 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp);
   8058             }
   8059             if (BCM_SUCCESS(rv)) {
   8060                 nh_index = soc_mem_field32_get(unit, ING_DVP_TABLEm, &dvp,
   8061                                                NEXT_HOP_INDEXf);
   8062                 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   8063                                   nh_index, &next_hop);
   8064                 if (BCM_SUCCESS(rv)) {
   8065                     if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
   8066                                             USE_VINTF_CTR_IDXf)) {
   8067                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &next_hop,
   8068                                             USE_VINTF_CTR_IDXf,
   8069                                             fs_idx > 0 ? 1 : 0);
   8070                     }
   8071                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &next_hop,
   8072                                     VINTF_CTR_IDXf, fs_idx);
   8073                     rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL,
   8074                                        nh_index, &next_hop);
   8075                 }
   8076             }
   8077         }
   8078     }
   8079 
   8080     MIM_UNLOCK(unit);
   8081     return rv;
   8082 }
   8083 
   8084 int
   8085 _bcm_tr2_mim_svp_field_set(int unit, bcm_gport_t vp, 
   8086                            soc_field_t field, int value)
   8087 {
   8088     int rv = BCM_E_NONE;
   8089     source_vp_entry_t svp;
   8090 
   8091     MIM_LOCK(unit);
   8092     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
   8093     if (rv < 0) {
   8094         MIM_UNLOCK(unit);
   8095         return rv;
   8096     }
   8097     if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, field)) {
   8098         soc_SOURCE_VPm_field32_set(unit, &svp, field, value);
   8099     } else {
   8100         MIM_UNLOCK(unit);
   8101         return BCM_E_UNAVAIL;
   8102     }
   8103     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
   8104     MIM_UNLOCK(unit);
   8105     return rv;
   8106 }
   8107 
   8108 int 
   8109 _bcm_tr2_mim_port_phys_gport_get(int unit, int vp, bcm_gport_t *gp)
   8110 {
   8111     if (MIM_INFO(unit)->port_info[vp].modid != -1) {
   8112         BCM_GPORT_MODPORT_SET(*gp, MIM_INFO(unit)->port_info[vp].modid, 
   8113                               MIM_INFO(unit)->port_info[vp].port);
   8114     } else {
   8115         BCM_GPORT_TRUNK_SET(*gp, MIM_INFO(unit)->port_info[vp].tgid);
   8116     }
   8117     return BCM_E_NONE;
   8118 }
   8119 
   8120 void 
   8121 _bcm_tr2_mim_port_match_count_adjust(int unit, int vp, int step)
   8122 {
   8123     MIM_INFO(unit)->port_info[vp].match_count += step;
   8124 }
   8125 
   8126 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
   8127 /*
   8128  * Function:
   8129  *     _bcm_mim_sw_dump
   8130  * Purpose:
   8131  *     Displays mim information maintained by software.
   8132  * Parameters:
   8133  *     unit - Device unit number
   8134  * Returns:
   8135  *     None
   8136  */
   8137 void
   8138 _bcm_mim_sw_dump(int unit)
   8139 {
   8140     int i, num_vp, num_vfi;
   8141     uint32 mac[2];
   8142 
   8143     LOG_CLI((BSL_META_U(unit,
   8144                         "\nSW Information MIM - Unit %d\n"), unit));
   8145     LOG_CLI((BSL_META_U(unit,
   8146                         "  VPN Info    : \n")));
   8147 
   8148     num_vfi = soc_mem_index_count(unit, VFIm);
   8149     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   8150 
   8151     for (i = 0; i < num_vfi; i++) {
   8152         if (VPN_ISID(unit, i) != 0) {
   8153             LOG_CLI((BSL_META_U(unit,
   8154                                 "VFI = %x    ISID=%x\n"), i, VPN_ISID(unit, i)));
   8155         }
   8156     }
   8157 
   8158     LOG_CLI((BSL_META_U(unit,
   8159                         "\n  Port Info    : \n")));
   8160     for (i = 0; i < num_vp; i++) {
   8161         if ((MIM_INFO(unit)->port_info[i].tgid == 0) && 
   8162             (MIM_INFO(unit)->port_info[i].modid == 0) &&
   8163             (MIM_INFO(unit)->port_info[i].port == 0)) {
   8164             continue;
   8165         }
   8166         LOG_CLI((BSL_META_U(unit,
   8167                             "\n  MiM port vp = %d\n"), i));
   8168         LOG_CLI((BSL_META_U(unit,
   8169                             "Flags = %x\n"), MIM_INFO(unit)->port_info[i].flags));
   8170         LOG_CLI((BSL_META_U(unit,
   8171                             "Index = %x\n"), MIM_INFO(unit)->port_info[i].index));
   8172         LOG_CLI((BSL_META_U(unit,
   8173                             "TGID = %d\n"), MIM_INFO(unit)->port_info[i].tgid));
   8174         LOG_CLI((BSL_META_U(unit,
   8175                             "Modid = %d\n"), MIM_INFO(unit)->port_info[i].modid));
   8176         LOG_CLI((BSL_META_U(unit,
   8177                             "Port = %d\n"), MIM_INFO(unit)->port_info[i].port));
   8178         LOG_CLI((BSL_META_U(unit,
   8179                             "Match VLAN = %d\n"), 
   8180                  MIM_INFO(unit)->port_info[i].match_vlan));
   8181         LOG_CLI((BSL_META_U(unit,
   8182                             "Match Inner VLAN = %d\n"), 
   8183                  MIM_INFO(unit)->port_info[i].match_inner_vlan));
   8184         LOG_CLI((BSL_META_U(unit,
   8185                             "Match Label = %d\n"), 
   8186                  MIM_INFO(unit)->port_info[i].match_label));
   8187 	SAL_MAC_ADDR_TO_UINT32
   8188             (MIM_INFO(unit)->port_info[i].match_tunnel_srcmac, mac);
   8189 	LOG_CLI((BSL_META_U(unit,
   8190                             "Match tunnel SrcMac = %x %x\n"), mac[1], mac[0]));
   8191         LOG_CLI((BSL_META_U(unit,
   8192                             "Match tunnel VLAN = %d\n"), 
   8193                  MIM_INFO(unit)->port_info[i].match_tunnel_vlan));
   8194         LOG_CLI((BSL_META_U(unit,
   8195                             "Match Count = %d\n"), 
   8196                  MIM_INFO(unit)->port_info[i].match_count));
   8197         LOG_CLI((BSL_META_U(unit,
   8198                             "Vfi Count = %d\n"),
   8199                  MIM_INFO(unit)->port_info[i].vfi_count));
   8200 
   8201     }
   8202     return;
   8203 }
   8204 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */
   8205 
   8206 #ifdef BCM_WARM_BOOT_SUPPORT
   8207 /*
   8208  * Function:
   8209  *      _bcm_chunk_memory_alloc
   8210  * Purpose: 
   8211  *      Allocate Chunk memory for set of memory entries.
   8212  *      Chunk memory is allocated with offset at the beginning of the
   8213  *      memory block.
   8214  *
   8215  *      +--------------+ [0]
   8216  *      |  entry offset|
   8217  *      +--------------+ [4]
   8218  *      |  memory      |
   8219  *      |     entries  |
   8220  *      |              |
   8221  *      +--------------+ [MEM_CHUNK_MAX_ENTRY * mem_entry size]
   8222  * Parameters: 
   8223  *      unit       - (IN) bcm device
   8224  *      mem        - (IN) table memory
   8225  *      mem_buffer - (OUT) Allocated memory chunk buffer
   8226  *
   8227  * Returns:
   8228  *      BCM_E_NONE - Success
   8229  *      BCM_E_XXX
   8230  * Notes:
   8231  */
   8232 STATIC int
   8233 _bcm_chunk_memory_alloc(int unit, soc_mem_t mem, void **mem_buf)
   8234 {
   8235     int entry_size;
   8236 
   8237     /* Validate parameters */
   8238     if (!SOC_MEM_IS_VALID(unit, mem)) {
   8239         return BCM_E_PARAM;
   8240     }
   8241  
   8242     /* Allocate chunk memory */ 
   8243     entry_size = soc_mem_entry_words(unit, mem) * sizeof(uint32);
   8244     *mem_buf = soc_cm_salloc(unit, ((entry_size * MEM_CHUNK_MAX_ENTRY) +
   8245                            sizeof(int32*)), "Memory Chunk Buffer");
   8246     if (NULL == *mem_buf) {
   8247         return BCM_E_MEMORY;
   8248     }
   8249 
   8250     /* Initialize offset */
   8251     _BCM_CHUNK_SET_INDEX_OFFSET(*mem_buf, -1); 
   8252 
   8253     return BCM_E_NONE;
   8254 }
   8255 
   8256 /*
   8257  * Function:
   8258  *      bcm_chunk_memory_read
   8259  * Purpose: 
   8260  *      Read and replenish chunk buffer for range of memory indexes
   8261  *
   8262  * Parameters: 
   8263  *      unit       - (IN) bcm device
   8264  *      mem        - (IN) table memory
   8265  *      chunk      - (IN) chunk
   8266  *      chunk_buf  - (IN) memory chunk buffer
   8267  *
   8268  * Returns:
   8269  *      BCM_E_NONE - Success
   8270  *      BCM_E_XXX
   8271  * Notes:
   8272  *    For generic usage, add atomic memory locks to update chunk buffer.
   8273  */
   8274 STATIC int
   8275 _bcm_chunk_memory_read(int unit, soc_mem_t mem, int chunk, void *chunk_buf)
   8276 {
   8277     int rv, entry_index_min, entry_index_max;
   8278     void *mem_buf = _BCM_CHUNK_GET_MEM_BUFFER(chunk_buf);
   8279 
   8280     /* clear chunk buffer before refill */    
   8281     sal_memset(chunk_buf, 0, ((soc_mem_entry_words(unit, mem) * sizeof(uint32) * 
   8282                                MEM_CHUNK_MAX_ENTRY) + sizeof(int32*)));
   8283 
   8284     /* Read chunk of entries */
   8285     entry_index_min = chunk * MEM_CHUNK_MAX_ENTRY;
   8286     entry_index_max = entry_index_min + MEM_CHUNK_MAX_ENTRY - 1;
   8287     if (entry_index_max > soc_mem_index_max(unit, mem)) {
   8288         entry_index_max = soc_mem_index_max(unit, mem);
   8289     }
   8290 
   8291     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   8292                             entry_index_min, entry_index_max, mem_buf);
   8293     if (BCM_FAILURE(rv)) {
   8294         return rv;   
   8295     }
   8296     
   8297     _BCM_CHUNK_SET_INDEX_OFFSET(chunk_buf, entry_index_min); 
   8298 
   8299     return BCM_E_NONE;
   8300 }
   8301 
   8302 /*
   8303  * Function:
   8304  *      _bcm_chunk_get_mem_entry
   8305  * Purpose: 
   8306  *      Get memory entry from the memory chunk buffer. For the given index, memory chunk buffer is
   8307  *      refilled with the range of memory index entries.
   8308  *
   8309  * Parameters: 
   8310  *      unit       - (IN) bcm device
   8311  *      mem        - (IN) table memory
   8312  *      index      - (IN) index
   8313  *      mem_buffer - (OUT) Allocated memory chunk buffer
   8314  *
   8315  * Returns:
   8316  *      BCM_E_NONE - Success
   8317  *      BCM_E_XXX
   8318  * Notes:
   8319  */
   8320 STATIC int
   8321 _bcm_chunk_get_mem_entry(int unit, soc_mem_t mem, int index, 
   8322                          void *chunk_buf, void **mem_entry)
   8323 {
   8324     int rv, chunk, offset;
   8325     void *mem_buf;
   8326 
   8327     /* Validate parameters */
   8328     if (!SOC_MEM_IS_VALID(unit, mem) || (NULL == chunk_buf)) {
   8329         return BCM_E_PARAM;
   8330     }
   8331 
   8332     chunk = index / MEM_CHUNK_MAX_ENTRY;
   8333 
   8334     offset = _BCM_CHUNK_GET_INDEX_OFFSET(chunk_buf);
   8335 
   8336     if ((offset == -1) || 
   8337         !(index >=  offset && index < (offset + MEM_CHUNK_MAX_ENTRY))) {
   8338          /* Replenish chunk buffer*/
   8339          rv = _bcm_chunk_memory_read(unit, mem, chunk, chunk_buf);
   8340         if (BCM_FAILURE(rv)) {
   8341             return rv;   
   8342         }
   8343     }
   8344     mem_buf = _BCM_CHUNK_GET_MEM_BUFFER(chunk_buf);
   8345 
   8346     *mem_entry = soc_mem_table_idx_to_pointer(unit, mem, void*, mem_buf, 
   8347                     _BCM_CHUNK_GET_INDEX(unit, mem, index));
   8348 
   8349     return BCM_E_NONE;
   8350 }
   8351 #endif /* BCM_WARM_BOOT_SUPPORT */
   8352 
   8353 #if defined(BCM_TRIDENT2_SUPPORT)
   8354 /*
   8355  * Function:
   8356  *      _bcm_td2_mim_match_vp_replace
   8357  * Purpose:
   8358  *      Replace VP value in MIM VP's match entry.
   8359  * Parameters:
   8360  *      unit   - (IN) SOC unit number.
   8361  *      vp     - (IN) MIM VP whose match entry is being replaced.
   8362  *      new_vp - (IN) New VP value.
   8363  *      old_vp - (OUT) Old VP value.
   8364  * Returns:
   8365  *      BCM_X_XXX
   8366  */
   8367 STATIC int
   8368 _bcm_td2_mim_match_vp_replace(int unit, int vp, int new_vp, int *old_vp)
   8369 {
   8370     int                rv = BCM_E_NONE;
   8371     soc_mem_t          mem;
   8372     int                key_type = bcmVlanTranslateKeyInvalid;
   8373     uint32             svp_valid;
   8374     int                entry_index;
   8375     int                port, my_modid, stm_idx, i;
   8376     int                local_port[SOC_MAX_NUM_PORTS];
   8377     int                local_port_count = 0;
   8378     uint32 vent[SOC_MAX_MEM_WORDS], old_vent[SOC_MAX_MEM_WORDS];
   8379     source_trunk_map_table_entry_t stm_entry;
   8380     uint32 ment[SOC_MAX_MEM_WORDS], old_ment[SOC_MAX_MEM_WORDS];
   8381     _bcm_tr2_mim_port_info_t *mkey = NULL;
   8382 
   8383     mkey = &(MIM_INFO(unit)->port_info[vp]);
   8384 
   8385     switch (mkey->flags) {
   8386         case _BCM_MIM_PORT_TYPE_ACCESS_PORT_VLAN:
   8387             if (key_type == bcmVlanTranslateKeyInvalid) {
   8388                 key_type = bcmVlanTranslateKeyPortOuter;
   8389             }
   8390             /* Fall through */
   8391         case _BCM_MIM_PORT_TYPE_ACCESS_PORT_VLAN_STACKED:
   8392             if (key_type == bcmVlanTranslateKeyInvalid) {
   8393                 key_type = bcmVlanTranslateKeyPortDouble;
   8394             }
   8395 
   8396 #if defined(BCM_TRIDENT3_SUPPORT)
   8397             if (soc_feature(unit, soc_feature_base_valid)) {
   8398                mem = VLAN_XLATE_1_DOUBLEm;
   8399             } else
   8400 #endif
   8401             {
   8402                mem = VLAN_XLATEm;
   8403             }
   8404 
   8405             if (mkey->modid != -1) {
   8406                 BCM_GPORT_MODPORT_SET(port, mkey->modid, mkey->port);
   8407             } else {
   8408                 BCM_GPORT_TRUNK_SET(port, mkey->tgid);
   8409             }
   8410             /* Construct lookup key */
   8411             sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   8412             rv = _bcm_trx_vlan_translate_entry_assemble(
   8413                      unit, vent, port, key_type,
   8414                      mkey->match_inner_vlan, mkey->match_vlan);
   8415             if (BCM_FAILURE(rv)) {
   8416                 return rv;
   8417             }
   8418             soc_mem_lock(unit, mem);
   8419             /* Lookup existing entry */
   8420             rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL,
   8421                                 &entry_index, vent, old_vent, 0);
   8422             if (BCM_FAILURE(rv)) {
   8423                 soc_mem_unlock(unit, mem);
   8424                 return rv;
   8425             }
   8426             /* Replace entry's VP value */
   8427             *old_vp = soc_mem_field32_get(unit, mem, old_vent, SOURCE_VPf);
   8428             soc_mem_field32_set(unit, mem, old_vent, SOURCE_VPf, new_vp);
   8429 
   8430             /* Insert new entry */
   8431             rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, old_vent);
   8432             if (rv == SOC_E_EXISTS) {
   8433                 rv = BCM_E_NONE;
   8434             } else {
   8435                 soc_mem_unlock(unit, mem);
   8436                 return BCM_E_INTERNAL;
   8437             }
   8438             soc_mem_unlock(unit, mem);
   8439             break;
   8440         case _BCM_MIM_PORT_TYPE_ACCESS_PORT:
   8441             mem = SOURCE_TRUNK_MAP_TABLEm;
   8442 
   8443             soc_mem_lock(unit, mem);
   8444 
   8445             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   8446                               mkey->index, &stm_entry);
   8447             if (BCM_FAILURE(rv)) {
   8448                 soc_mem_unlock(unit, mem);
   8449                 return rv;
   8450             }
   8451             /* Resolve SVP Mode */
   8452             if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) {
   8453                 svp_valid = soc_mem_field32_get(unit, mem,
   8454                                                 &stm_entry, SVP_VALIDf);
   8455                 if (svp_valid == 0) {
   8456                     soc_mem_unlock(unit, mem);
   8457                     return BCM_E_INTERNAL;
   8458                 }
   8459             }
   8460             *old_vp = soc_mem_field32_get(unit, mem, &stm_entry, SOURCE_VPf);
   8461             rv = soc_mem_field32_modify(unit, mem, mkey->index,
   8462                                         SOURCE_VPf, new_vp);
   8463             soc_mem_unlock(unit, mem);
   8464             break;
   8465         case _BCM_MIM_PORT_TYPE_ACCESS_PORT_TRUNK:
   8466             mem = SOURCE_TRUNK_MAP_TABLEm;
   8467 
   8468             /* Get module id for unit. */
   8469             rv = bcm_esw_stk_my_modid_get(unit, &my_modid);
   8470             if (BCM_FAILURE(rv)) {
   8471                 return rv;
   8472             }
   8473 
   8474             rv = _bcm_esw_trunk_local_members_get(
   8475                      unit, mkey->tgid, SOC_MAX_NUM_PORTS,
   8476                      local_port, &local_port_count);
   8477             if (BCM_FAILURE(rv)) {
   8478                 return rv;
   8479             }
   8480 
   8481             soc_mem_lock(unit, mem);
   8482             for (i = 0; i < local_port_count; i++) {
   8483                 /* Get index to source trunk map table */
   8484                 rv = _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
   8485                                                            local_port[i],
   8486                                                            &stm_idx);
   8487                 if (BCM_FAILURE(rv)) {
   8488                     soc_mem_unlock(unit, mem);
   8489                     return rv;
   8490                 }
   8491 
   8492                 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   8493                                   stm_idx, &stm_entry);
   8494                 if (BCM_FAILURE(rv)) {
   8495                     soc_mem_unlock(unit, mem);
   8496                     return rv;
   8497                 }
   8498 
   8499                 /* Resolve SVP Mode */
   8500                 if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) {
   8501                     svp_valid = soc_mem_field32_get(unit, mem,
   8502                                                     &stm_entry, SVP_VALIDf);
   8503                     if (svp_valid == 0) {
   8504                         soc_mem_unlock(unit, mem);
   8505                         return BCM_E_INTERNAL;
   8506                     }
   8507                 }
   8508                 *old_vp = soc_mem_field32_get(unit, mem,
   8509                                               &stm_entry, SOURCE_VPf);
   8510                 rv = soc_mem_field32_modify(unit, mem, stm_idx,
   8511                                             SOURCE_VPf, new_vp);
   8512                 if (BCM_FAILURE(rv)) {
   8513                     soc_mem_unlock(unit, mem);
   8514                     return rv;
   8515                 }
   8516             }
   8517 
   8518             soc_mem_unlock(unit, mem);
   8519             break;
   8520         case _BCM_MIM_PORT_TYPE_ACCESS_LABEL:
   8521             mem = MPLS_ENTRYm;
   8522             sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   8523             sal_memset(old_ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   8524             soc_mem_lock(unit, mem);
   8525             if (mkey->modid != -1) {
   8526                 soc_mem_field32_set(unit, mem, ment, MODULE_IDf, mkey->modid);
   8527                 soc_mem_field32_set(unit, mem, ment, PORT_NUMf, mkey->port);
   8528             } else {
   8529                 soc_mem_field32_set(unit, mem, ment, Tf, 1);
   8530                 soc_mem_field32_set(unit, mem, ment, TGIDf, mkey->tgid);
   8531             }
   8532             soc_mem_field32_set(
   8533                 unit, mem, ment, MPLS_LABELf, mkey->match_label);
   8534             rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &entry_index,
   8535                                 ment, old_ment, 0);
   8536             if (rv == BCM_E_NOT_FOUND) {
   8537                 rv = BCM_E_PARAM;
   8538             }
   8539             if (BCM_FAILURE(rv)) {
   8540                 soc_mem_unlock(unit, mem);
   8541                 return rv;
   8542             }
   8543 #if defined(BCM_TRIDENT3_SUPPORT)
   8544             if (soc_feature(unit, soc_feature_base_valid)) {
   8545                 if (soc_mem_field32_get(unit, mem, old_ment, BASE_VALID_0f) != 3) {
   8546                     soc_mem_unlock(unit, mem);
   8547                     return BCM_E_INTERNAL;
   8548                 }
   8549                 if (soc_mem_field32_get(unit, mem, old_ment, BASE_VALID_1f) != 7) {
   8550                     soc_mem_unlock(unit, mem);
   8551                     return BCM_E_INTERNAL;
   8552                 }
   8553             } else
   8554 #endif
   8555             {
   8556                 if (!soc_mem_field32_get(unit, mem, old_ment, VALIDf)) {
   8557                     soc_mem_unlock(unit, mem);
   8558                     return BCM_E_INTERNAL;
   8559                 }
   8560 
   8561             }
   8562 
   8563             /* Replace entry's VP value */
   8564             *old_vp = soc_mem_field32_get(unit, mem, old_ment,
   8565                                                   SOURCE_VPf);
   8566             soc_mem_field32_set(unit, mem, old_ment,
   8567                                         SOURCE_VPf, new_vp);
   8568             /* Insert new entry */
   8569             rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, old_ment);
   8570             if (rv == SOC_E_EXISTS) {
   8571                 rv = BCM_E_NONE;
   8572             } else {
   8573                 soc_mem_unlock(unit, mem);
   8574                 return BCM_E_INTERNAL;
   8575             }
   8576             soc_mem_unlock(unit, mem);
   8577             break;
   8578         case _BCM_MIM_PORT_TYPE_NETWORK:
   8579         case _BCM_MIM_PORT_TYPE_PEER:
   8580             mem = MPLS_ENTRYm;
   8581             sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   8582             sal_memset(old_ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   8583 
   8584             soc_mem_lock(unit, mem);
   8585 
   8586             soc_mem_field32_set(unit, mem, ment, KEY_TYPEf, 0x1);/* MIM NVP */
   8587             if (soc_mem_field_valid(unit, mem, DATA_TYPEf)) {
   8588                 soc_mem_field32_set(unit, mem, ment, DATA_TYPEf, 0x1);
   8589             }
   8590             soc_mem_field32_set(unit, mem, ment, MIM_NVP__BVIDf,
   8591                                         mkey->match_tunnel_vlan);
   8592             soc_mem_mac_addr_set(unit, mem, ment, MIM_NVP__BMACSAf,
   8593                                  mkey->match_tunnel_srcmac);
   8594             rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY,
   8595                                 &entry_index, ment, old_ment, 0);
   8596             if (rv == BCM_E_NOT_FOUND) {
   8597                 rv = BCM_E_PARAM;
   8598             }
   8599 
   8600             if (BCM_FAILURE(rv)) {
   8601                 soc_mem_unlock(unit, mem);
   8602                 return rv;
   8603             }
   8604 
   8605 #if defined(BCM_TRIDENT3_SUPPORT)
   8606             if (soc_feature(unit, soc_feature_base_valid)) {
   8607                 if (soc_mem_field32_get(unit, mem, old_ment, BASE_VALID_0f) != 3) {
   8608                     soc_mem_unlock(unit, mem);
   8609                     return BCM_E_INTERNAL;
   8610                 }
   8611                 if (soc_mem_field32_get(unit, mem, old_ment, BASE_VALID_1f) != 7) {
   8612                     soc_mem_unlock(unit, mem);
   8613                     return BCM_E_INTERNAL;
   8614                 }
   8615             } else
   8616 #endif
   8617             {
   8618                 if (!soc_mem_field32_get(unit, mem, old_ment, VALIDf)) {
   8619                     soc_mem_unlock(unit, mem);
   8620                     return BCM_E_INTERNAL;
   8621                 }
   8622 
   8623             }
   8624             /* Replace entry's VP value */
   8625             *old_vp = soc_mem_field32_get(unit, mem, old_ment,
   8626                                                   MIM_NVP__SVPf);
   8627             soc_mem_field32_set(unit, mem, old_ment,
   8628                                         MIM_NVP__SVPf, new_vp);
   8629             /* Insert new entry */
   8630             rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, old_ment);
   8631             if (rv == SOC_E_EXISTS) {
   8632                 rv = BCM_E_NONE;
   8633             } else {
   8634                 soc_mem_unlock(unit, mem);
   8635                 return BCM_E_INTERNAL;
   8636             }
   8637 
   8638             soc_mem_unlock(unit, mem);
   8639             break;
   8640         default:
   8641             return BCM_E_PARAM;
   8642     }
   8643 
   8644     return rv;
   8645 }
   8646 
   8647 /*
   8648  * Function:
   8649  *      _bcm_td2_mim_port_source_vp_lag_set
   8650  * Purpose:
   8651  *      Set source VP LAG for a MIM virtual port.
   8652  * Parameters:
   8653  *      unit      - (IN) SOC unit number.
   8654  *      gport     - (IN) MIM virtual port GPORT ID.
   8655  *      vp_lag_vp - (IN) VP representing the VP LAG.
   8656  * Returns:
   8657  *      BCM_X_XXX
   8658  */
   8659 STATIC int
   8660 _bcm_td2_mim_port_source_vp_lag_set(int unit, bcm_gport_t gport,
   8661                                     int vp_lag_vp)
   8662 {
   8663     int vp, old_vp;
   8664     int rv = BCM_E_NONE;
   8665 
   8666     if (!BCM_GPORT_IS_MIM_PORT(gport)) {
   8667         return BCM_E_PARAM;
   8668     }
   8669 
   8670     vp = BCM_GPORT_MIM_PORT_ID_GET(gport);
   8671     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   8672         return BCM_E_PARAM;
   8673     }
   8674 
   8675     /* Set source VP LAG by replacing the SVP field in MIM VP's
   8676      * match entry with the VP value representing the VP LAG.
   8677      */
   8678     rv = _bcm_td2_mim_match_vp_replace(unit, vp, vp_lag_vp, &old_vp);
   8679     if (BCM_FAILURE(rv)) {
   8680         return rv;
   8681     }
   8682 
   8683     return BCM_E_NONE;
   8684 }
   8685 
   8686 /*
   8687  * Function:
   8688  *      bcm_td2_mim_port_source_vp_lag_set
   8689  * Purpose:
   8690  *      Set source VP LAG for a MIM virtual port.
   8691  * Parameters:
   8692  *      unit      - (IN) SOC unit number.
   8693  *      gport     - (IN) MIM virtual port GPORT ID.
   8694  *      vp_lag_vp - (IN) VP representing the VP LAG.
   8695  * Returns:
   8696  *      BCM_X_XXX
   8697  */
   8698 int
   8699 bcm_td2_mim_port_source_vp_lag_set(int unit, bcm_gport_t gport,
   8700                                    int vp_lag_vp)
   8701 {
   8702     int rv = BCM_E_NONE;
   8703 
   8704     MIM_INIT(unit);
   8705     MIM_LOCK(unit);
   8706     rv = _bcm_td2_mim_port_source_vp_lag_set(unit, gport, vp_lag_vp);
   8707     MIM_UNLOCK(unit);
   8708 
   8709     return rv;
   8710 }
   8711 
   8712 /*
   8713  * Function:
   8714  *      _bcm_td2_mim_port_source_vp_lag_clear
   8715  * Purpose:
   8716  *      Clear source VP LAG for a MIM virtual port.
   8717  * Parameters:
   8718  *      unit      - (IN) SOC unit number.
   8719  *      gport     - (IN) MIM virtual port GPORT ID.
   8720  *      vp_lag_vp - (IN) VP representing the VP LAG.
   8721  * Returns:
   8722  *      BCM_X_XXX
   8723  */
   8724 STATIC int
   8725 _bcm_td2_mim_port_source_vp_lag_clear(int unit, bcm_gport_t gport,
   8726                                       int vp_lag_vp)
   8727 {
   8728     int vp, old_vp;
   8729     int rv = BCM_E_NONE;
   8730 
   8731     if (!BCM_GPORT_IS_MIM_PORT(gport)) {
   8732         return BCM_E_PARAM;
   8733     }
   8734 
   8735     vp = BCM_GPORT_MIM_PORT_ID_GET(gport);
   8736     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   8737         return BCM_E_PARAM;
   8738     }
   8739 
   8740     /* Clear source VP LAG by replacing the SVP field in MIM VP's
   8741      * match entry with the original VP value.
   8742      */
   8743     rv = _bcm_td2_mim_match_vp_replace(unit, vp, vp, &old_vp);
   8744     if (BCM_FAILURE(rv)) {
   8745         return rv;
   8746     }
   8747 
   8748     /* Check that the old VP value matches the VP value representing
   8749      * the VP LAG or has been restored.
   8750      */
   8751     if ((old_vp != vp_lag_vp) && (old_vp != vp)) {
   8752         return BCM_E_INTERNAL;
   8753     }
   8754 
   8755     return BCM_E_NONE;
   8756 }
   8757 
   8758 /*
   8759  * Function:
   8760  *      bcm_td2_mim_port_source_vp_lag_clear
   8761  * Purpose:
   8762  *      Clear source VP LAG for a MIM virtual port.
   8763  * Parameters:
   8764  *      unit      - (IN) SOC unit number.
   8765  *      gport     - (IN) MIM virtual port GPORT ID.
   8766  *      vp_lag_vp - (IN) VP representing the VP LAG.
   8767  * Returns:
   8768  *      BCM_X_XXX
   8769  */
   8770 int
   8771 bcm_td2_mim_port_source_vp_lag_clear(int unit, bcm_gport_t gport,
   8772                                      int vp_lag_vp)
   8773 {
   8774     int rv = BCM_E_NONE;
   8775 
   8776     MIM_INIT(unit);
   8777     MIM_LOCK(unit);
   8778     rv = _bcm_td2_mim_port_source_vp_lag_clear(unit, gport, vp_lag_vp);
   8779     MIM_UNLOCK(unit);
   8780 
   8781     return rv;
   8782 }
   8783 
   8784 
   8785 /*
   8786  * Function:
   8787  *      _bcm_td2_mim_port_source_vp_lag_get
   8788  * Purpose:
   8789  *      Get source VP LAG for a MIM virtual port.
   8790  * Parameters:
   8791  *      unit      - (IN) SOC unit number.
   8792  *      gport     - (IN) MIM virtual port GPORT ID.
   8793  *      vp_lag_vp - (OUT) VP representing the VP LAG.
   8794  * Returns:
   8795  *      BCM_X_XXX
   8796  */
   8797 STATIC int
   8798 _bcm_td2_mim_port_source_vp_lag_get(int unit, bcm_gport_t gport,
   8799                                     int *vp_lag_vp)
   8800 {
   8801     int                rv = BCM_E_NONE;
   8802     soc_mem_t          mem;
   8803     int                key_type = bcmVlanTranslateKeyInvalid;
   8804     bcm_gport_t        vp;
   8805     uint32             svp_valid;
   8806     int                entry_index;
   8807     int                port, my_modid, stm_idx;
   8808     int                local_port[SOC_MAX_NUM_PORTS];
   8809     int                local_port_count = 0;
   8810     uint32 vent[SOC_MAX_MEM_WORDS], old_vent[SOC_MAX_MEM_WORDS];
   8811     source_trunk_map_table_entry_t stm_entry;
   8812     uint32 ment[SOC_MAX_MEM_WORDS], old_ment[SOC_MAX_MEM_WORDS];
   8813     _bcm_tr2_mim_port_info_t *mkey = NULL;
   8814 
   8815 
   8816     if (!BCM_GPORT_IS_MIM_PORT(gport)) {
   8817         return BCM_E_PARAM;
   8818     }
   8819 
   8820     vp = BCM_GPORT_MIM_PORT_ID_GET(gport);
   8821     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMim)) {
   8822         return BCM_E_PARAM;
   8823     }
   8824 
   8825     mkey = &(MIM_INFO(unit)->port_info[vp]);
   8826 
   8827     switch(mkey->flags) {
   8828         case _BCM_MIM_PORT_TYPE_ACCESS_PORT_VLAN:
   8829             if (key_type == bcmVlanTranslateKeyInvalid) {
   8830                 key_type = bcmVlanTranslateKeyPortOuter;
   8831             }
   8832             /* Fall through */
   8833         case _BCM_MIM_PORT_TYPE_ACCESS_PORT_VLAN_STACKED:
   8834             if (key_type == bcmVlanTranslateKeyInvalid) {
   8835                 key_type = bcmVlanTranslateKeyPortDouble;
   8836             }
   8837 
   8838 #if defined(BCM_TRIDENT3_SUPPORT)
   8839             if (soc_feature(unit, soc_feature_base_valid)) {
   8840                mem = VLAN_XLATE_1_DOUBLEm;
   8841             } else
   8842 #endif
   8843             {
   8844                mem = VLAN_XLATEm;
   8845             }
   8846 
   8847             if (mkey->modid != -1) {
   8848                 BCM_GPORT_MODPORT_SET(port, mkey->modid, mkey->port);
   8849             } else {
   8850                 BCM_GPORT_TRUNK_SET(port, mkey->tgid);
   8851             }
   8852             /* Construct lookup key */
   8853             sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   8854             rv = _bcm_trx_vlan_translate_entry_assemble(
   8855                      unit, vent, port, key_type,
   8856                      mkey->match_inner_vlan, mkey->match_vlan);
   8857             if (BCM_FAILURE(rv)) {
   8858                 return rv;
   8859             }
   8860             /* Lookup existing entry */
   8861             rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL,
   8862                                 &entry_index, vent, old_vent, 0);
   8863             if (BCM_FAILURE(rv)) {
   8864                 return rv;
   8865             }
   8866             /* Get VP value representing VP LAG */
   8867             *vp_lag_vp = soc_mem_field32_get(unit, mem, old_vent,
   8868                                                      SOURCE_VPf);
   8869             break;
   8870         case _BCM_MIM_PORT_TYPE_ACCESS_PORT:
   8871             mem = SOURCE_TRUNK_MAP_TABLEm;
   8872 
   8873             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   8874                               mkey->index, &stm_entry);
   8875             if (BCM_FAILURE(rv)) {
   8876                 return rv;
   8877             }
   8878             /* Resolve SVP Mode */
   8879             if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) {
   8880                 svp_valid = soc_mem_field32_get(unit, mem,
   8881                                                 &stm_entry, SVP_VALIDf);
   8882                 if (svp_valid == 0) {
   8883                     return BCM_E_INTERNAL;
   8884                 }
   8885             }
   8886             /* Get VP value representing VP LAG */
   8887             *vp_lag_vp = soc_mem_field32_get(unit, mem,
   8888                                              &stm_entry, SOURCE_VPf);
   8889             break;
   8890         case _BCM_MIM_PORT_TYPE_ACCESS_PORT_TRUNK:
   8891             mem = SOURCE_TRUNK_MAP_TABLEm;
   8892 
   8893             /* Get module id for unit. */
   8894             rv = bcm_esw_stk_my_modid_get(unit, &my_modid);
   8895             if (BCM_FAILURE(rv)) {
   8896                 return rv;
   8897             }
   8898 
   8899             rv = _bcm_esw_trunk_local_members_get(
   8900                      unit, mkey->tgid, SOC_MAX_NUM_PORTS,
   8901                      local_port, &local_port_count);
   8902             if (BCM_FAILURE(rv)) {
   8903                 return rv;
   8904             }
   8905 
   8906             /* Get index to source trunk map table,
   8907              * Only get it from the first member in LAG
   8908              */
   8909             rv = _bcm_esw_src_mod_port_table_index_get(
   8910                      unit, my_modid, local_port[0], &stm_idx);
   8911             if (BCM_FAILURE(rv)) {
   8912                 return rv;
   8913             }
   8914 
   8915             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, stm_idx, &stm_entry);
   8916             if (BCM_FAILURE(rv)) {
   8917                 return rv;
   8918             }
   8919 
   8920             /* Resolve SVP Mode */
   8921             if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) {
   8922                 svp_valid = soc_mem_field32_get(unit, mem,
   8923                                                 &stm_entry, SVP_VALIDf);
   8924                 if (svp_valid == 0) {
   8925                     return BCM_E_INTERNAL;
   8926                 }
   8927             }
   8928             /* Get VP value representing VP LAG */
   8929             *vp_lag_vp = soc_mem_field32_get(unit, mem,
   8930                                              &stm_entry, SOURCE_VPf);
   8931             break;
   8932         case _BCM_MIM_PORT_TYPE_ACCESS_LABEL:
   8933             mem = MPLS_ENTRYm;
   8934             sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   8935             sal_memset(old_ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   8936             if (mkey->modid != -1) {
   8937                 soc_mem_field32_set(unit, mem, ment, MODULE_IDf, mkey->modid);
   8938                 soc_mem_field32_set(unit, mem, ment, PORT_NUMf, mkey->port);
   8939             } else {
   8940                 soc_mem_field32_set(unit, mem, ment, Tf, 1);
   8941                 soc_mem_field32_set(unit, mem, ment, TGIDf, mkey->tgid);
   8942             }
   8943             soc_mem_field32_set(
   8944                 unit, mem, ment, MPLS_LABELf, mkey->match_label);
   8945             rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &entry_index,
   8946                                 ment, old_ment, 0);
   8947             if (rv == BCM_E_NOT_FOUND) {
   8948                 rv = BCM_E_PARAM;
   8949             }
   8950 
   8951             if (BCM_FAILURE(rv)) {
   8952                 return rv;
   8953             }
   8954 #if defined(BCM_TRIDENT3_SUPPORT)
   8955             if (soc_feature(unit, soc_feature_base_valid)) {
   8956                 if (soc_mem_field32_get(unit, mem, old_ment, BASE_VALID_0f) != 3) {
   8957                     return BCM_E_INTERNAL;
   8958                 }
   8959                 if (soc_mem_field32_get(unit, mem, old_ment, BASE_VALID_1f) != 7) {
   8960                     return BCM_E_INTERNAL;
   8961                 }
   8962             } else
   8963 #endif
   8964             {
   8965                 if (!soc_mem_field32_get(unit, mem, old_ment, VALIDf)) {
   8966                     return BCM_E_INTERNAL;
   8967                 }
   8968             }
   8969             /* Get VP value representing VP LAG */
   8970             *vp_lag_vp = soc_mem_field32_get(unit, mem,
   8971                                              old_ment, SOURCE_VPf);
   8972             break;
   8973         case _BCM_MIM_PORT_TYPE_NETWORK:
   8974         case _BCM_MIM_PORT_TYPE_PEER:
   8975             mem = MPLS_ENTRYm;
   8976             sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   8977             sal_memset(old_ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   8978 
   8979             soc_mem_field32_set(unit, mem, ment, KEY_TYPEf, 0x1);/* MIM NVP */
   8980 
   8981             soc_mem_field32_set(unit, mem, ment, MIM_NVP__BVIDf,
   8982                                         mkey->match_tunnel_vlan);
   8983             soc_mem_mac_addr_set(unit, mem, ment, MIM_NVP__BMACSAf,
   8984                                  mkey->match_tunnel_srcmac);
   8985             rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY,
   8986                                 &entry_index, ment, old_ment, 0);
   8987             if (rv == BCM_E_NOT_FOUND) {
   8988                 rv = BCM_E_PARAM;
   8989             }
   8990 
   8991             if (BCM_FAILURE(rv)) {
   8992                 return rv;
   8993             }
   8994 
   8995             if (!soc_mem_field32_get(unit, mem, old_ment, VALIDf)) {
   8996                 return BCM_E_INTERNAL;
   8997             }
   8998             /* Get VP value representing VP LAG */
   8999             *vp_lag_vp = soc_mem_field32_get(unit, mem,
   9000                                              old_ment, MIM_NVP__SVPf);
   9001 
   9002             break;
   9003         default:
   9004             return BCM_E_PARAM;
   9005     }
   9006 
   9007     if (!_bcm_vp_used_get(unit, *vp_lag_vp, _bcmVpTypeVpLag)) {
   9008         return BCM_E_INTERNAL;
   9009     }
   9010 
   9011     return rv;
   9012 }
   9013 
   9014 /*
   9015  * Function:
   9016  *      bcm_td2_mim_port_source_vp_lag_get
   9017  * Purpose:
   9018  *      Get source VP LAG for a MIM virtual port.
   9019  * Parameters:
   9020  *      unit      - (IN) SOC unit number.
   9021  *      gport     - (IN) MIM virtual port GPORT ID.
   9022  *      vp_lag_vp - (OUT) VP representing the VP LAG.
   9023  * Returns:
   9024  *      BCM_X_XXX
   9025  */
   9026 int
   9027 bcm_td2_mim_port_source_vp_lag_get(int unit, bcm_gport_t gport,
   9028                                    int *vp_lag_vp)
   9029 {
   9030     int rv = BCM_E_NONE;
   9031 
   9032     MIM_INIT(unit);
   9033     MIM_LOCK(unit);
   9034     rv = _bcm_td2_mim_port_source_vp_lag_get(unit, gport, vp_lag_vp);
   9035     MIM_UNLOCK(unit);
   9036 
   9037     return rv;
   9038 }
   9039 
   9040 #endif /* BCM_TRIDENT2_SUPPORT */
   9041 
   9042 #endif /* BCM_TRIUMPH2_SUPPORT */