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

mpls.c (1109296B)


      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:    mpls.c
      8  * Purpose: Manages MPLS functions
      9  */
     10 #include <soc/defs.h>
     11 #include <sal/core/libc.h>
     12 #include <shared/bsl.h>
     13 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) && \
     14     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 #include <soc/format.h>
     22 #include <bcm/error.h>
     23 #include <bcm/mpls.h>
     24 
     25 
     26 #include <bcm_int/esw/mbcm.h>
     27 #include <bcm_int/esw/l3.h>
     28 #include <bcm_int/esw/firebolt.h>
     29 #include <bcm_int/esw/triumph.h>
     30 #include <bcm_int/esw/trx.h>
     31 #include <bcm_int/esw/xgs3.h>
     32 #include <bcm_int/esw/mpls.h>
     33 #include <bcm_int/esw/stack.h>
     34 #include <bcm_int/common/multicast.h>
     35 #include <bcm_int/esw/virtual.h>
     36 #include <bcm_int/esw/port.h>
     37 #if defined(BCM_TOMAHAWK_SUPPORT)
     38 #include <bcm_int/esw/ecn.h>
     39 #endif
     40 #include <bcm_int/esw/vlan.h>
     41 #ifdef BCM_TRIUMPH2_SUPPORT
     42 #include <bcm_int/esw/triumph2.h>
     43 #endif
     44 #if defined(BCM_TRIUMPH3_SUPPORT)
     45 #include <bcm_int/esw/triumph3.h>
     46 #endif /* BCM_TRIUMPH3_SUPPORT*/
     47 #ifdef BCM_KATANA2_SUPPORT
     48 #include <bcm_int/esw/katana2.h>
     49 #include <soc/katana2.h>
     50 #endif
     51 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
     52 #include <bcm_int/esw/trident2plus.h>
     53 #endif
     54 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
     55 #include <bcm_int/esw/xgs5.h>
     56 #endif
     57 #if defined(BCM_SABER2_SUPPORT)
     58 #include <soc/saber2.h>
     59 #endif /* BCM_SABER2_SUPPORT */
     60 #if defined(BCM_TRIDENT3_SUPPORT)
     61 #include <bcm_int/esw/trident3.h>
     62 #endif
     63 
     64 #include <bcm_int/esw_dispatch.h>
     65 #include <bcm_int/api_xlate_port.h>
     66 #include <bcm_int/esw/failover.h>
     67 
     68 #if defined(BCM_TOMAHAWK3_SUPPORT)
     69 #include <bcm_int/esw/tomahawk3.h>
     70 #endif
     71 extern uint32 nh_entry_type_field[SOC_MAX_NUM_DEVICES];
     72 extern void _bcm_vp_vfi_set(int unit, int vp, int vfi);
     73 #ifdef BCM_WARM_BOOT_SUPPORT
     74 #include <bcm_int/esw/switch.h>
     75 
     76 #define BCM_WB_VERSION_1_13               SOC_SCACHE_VERSION(1,13)
     77 #define BCM_WB_VERSION_1_12               SOC_SCACHE_VERSION(1,12)
     78 #define BCM_WB_VERSION_1_11               SOC_SCACHE_VERSION(1,11)
     79 #define BCM_WB_VERSION_1_10               SOC_SCACHE_VERSION(1,10)
     80 #define BCM_WB_VERSION_1_9                SOC_SCACHE_VERSION(1,9)
     81 #define BCM_WB_VERSION_1_8                SOC_SCACHE_VERSION(1,8)
     82 #define BCM_WB_VERSION_1_7                SOC_SCACHE_VERSION(1,7)
     83 #define BCM_WB_VERSION_1_6                SOC_SCACHE_VERSION(1,6)
     84 #define BCM_WB_VERSION_1_5                SOC_SCACHE_VERSION(1,5)
     85 #define BCM_WB_VERSION_1_4                SOC_SCACHE_VERSION(1,4)
     86 #define BCM_WB_VERSION_1_3                SOC_SCACHE_VERSION(1,3)
     87 #define BCM_WB_VERSION_1_2                SOC_SCACHE_VERSION(1,2)
     88 #define BCM_WB_VERSION_1_1                SOC_SCACHE_VERSION(1,1)
     89 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
     90 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_13
     91 #endif /* BCM_WARM_BOOT_SUPPORT */
     92 
     93 #define MPLS_VPWS_VP_NUM  3
     94 
     95 #if defined(BCM_KATANA_SUPPORT)
     96 #include <bcm_int/esw/katana.h>
     97 #endif
     98 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
     99 #include <bcm_int/esw/policer.h>
    100 #include <bcm_int/esw/flex_ctr.h>
    101 #endif
    102 #if defined(BCM_TRIDENT3_SUPPORT)
    103 #include <bcm_int/esw/trident3.h>
    104 #include <soc/esw/cancun.h>
    105 #include <soc/esw/cancun_enums.h>
    106 #endif
    107 
    108 #ifdef BCM_SPECIAL_LABEL_SUPPORT
    109 char *label_type_array[5] = { "special_label_type_NONE",
    110                                   "Special_label_type_GAL",
    111                                   "Special_label_type_RAL",
    112                                   "Special_label_type_SPECIAL",
    113                                   "Special_label_type_ELI"};
    114 #endif
    115 
    116 #if (defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT))
    117 #define ECN_MAP_ID_INVALID 0xffffffff
    118 #endif
    119 
    120 
    121 _bcm_tr_mpls_bookkeeping_t  _bcm_tr_mpls_bk_info[BCM_MAX_NUM_UNITS] = {{ 0 }};
    122 STATIC _bcm_mpls_egr_nhopList_t  *_bcm_tr_mpls_nhop_headPtr[BCM_MAX_NUM_UNITS][_BCM_TR_MPLS_HASH_ELEMENTS];
    123 bcm_tr_mpls_vc_swap_table_hash_t *bcmi_vc_swap_label_hash[SOC_MAX_NUM_DEVICES];
    124 
    125 #define MPLS_INFO(_unit_)   (&_bcm_tr_mpls_bk_info[_unit_])
    126 #define L3_INFO(_unit_)   (&_bcm_l3_bk_info[_unit_])
    127 
    128 /* for _bcm_tr_mpls_get_vc_and_swap_table_index() function */
    129 #define ENTRIES_PER_CHUNK  0x400
    130 #define CHUNK_NUM(_ix) (((_ix) - imin)/ENTRIES_PER_CHUNK)
    131 
    132 #define SOC_VC_SWAP_LABLE_FIELD(m, f) soc_field_info_t * m##f
    133 #define SOC_VC_SWAP_LABLE_FIELD_ASSIGN(m_u, s, m, f) \
    134                 (s)->m##f = soc_mem_fieldinfo_get(m_u, m, f)
    135 
    136 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_APACHE_SUPPORT)
    137 #define _BCM_QOS_MAP_TYPE_MASK                     0x3ff
    138 #define _BCM_QOS_MAP_SHIFT                            10
    139 #define _BCM_QOS_MAP_TYPE_ING_QUEUE_OFFSET_MAP_TABLE   5
    140 #define _BCM_QOS_MAP_ING_QUEUE_OFFSET_MAX              7
    141 #define EH_TAG_TYPE_NONE                               0
    142 #define EH_TAG_TYPE_EXPLICT_QUEUE                      1
    143 #define EH_TAG_TYPE_ING_QUEUE_MAP                      2
    144 
    145 #endif
    146 
    147 #ifdef BCM_APACHE_SUPPORT
    148 #define _BCM_MPLS_FWD_LABEL1_PHB_FROM_TOS            0
    149 #define _BCM_MPLS_FWD_LABEL2_PHB_FROM_TOS            1
    150 #define _BCM_MPLS_FWD_LABEL3_PHB_FROM_TOS            2
    151 #endif
    152 
    153 typedef struct soc_emvasltm_field_cache_s {
    154     SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_LABELf);
    155     SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_LABEL_ACTIONf);
    156     SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_TTLf);
    157     SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, CW_INSERT_FLAGf);
    158     SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_EXPf);
    159     SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, NEW_PRIf);
    160     SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, NEW_CFIf);
    161     SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, SD_TAG_VIDf);
    162     SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, SD_TAG_ACTION_IF_PRESENTf);
    163     SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, SD_TAG_ACTION_IF_NOT_PRESENTf);
    164     SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_EXP_SELECTf);
    165     SOC_VC_SWAP_LABLE_FIELD(EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_EXP_MAPPING_PTRf);
    166 } soc_emvasltm_field_cache_t;
    167 
    168 STATIC soc_emvasltm_field_cache_t soc_emvasltm_field_cache[SOC_MAX_NUM_DEVICES];
    169 
    170 static soc_field_t _tnl_push_action_f[] =
    171 { MPLS_PUSH_ACTION_0f, MPLS_PUSH_ACTION_1f,
    172   MPLS_PUSH_ACTION_2f, MPLS_PUSH_ACTION_3f,
    173   MPLS_PUSH_ACTION_4f, MPLS_PUSH_ACTION_5f,
    174   MPLS_PUSH_ACTION_6f, MPLS_PUSH_ACTION_7f };
    175 
    176 #define SOC_MEM_VC_SWAP_F32_GET(m_unit, m_mem, m_entry_data, m_field) \
    177         soc_meminfo_fieldinfo_field32_get((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), \
    178 	 (soc_emvasltm_field_cache[(m_unit)].m_mem##m_field))
    179 
    180 #define SOC_MEM_VC_SWAP_F32_SET(m_unit, m_mem, m_entry_data, m_field, m_val) \
    181         soc_meminfo_fieldinfo_field32_set((&SOC_MEM_INFO(m_unit, m_mem)), (m_entry_data), \
    182 	(soc_emvasltm_field_cache[(m_unit)].m_mem##m_field), (m_val))
    183 
    184 
    185 #define SOC_MEM_VC_SWAP_FIELD_VALID(m_unit, m_mem, m_field) \
    186                 ((soc_emvasltm_field_cache[(m_unit)].m_mem##m_field) != NULL)
    187 
    188 #define VC_AND_SWAP_TABLE_RESV_INDEX 0
    189 
    190 #define _BCM_MPLS_MEPID_IN_VALID_RANGE(mep_id) (mep_id > 0 && mep_id < 8192)
    191 
    192 STATIC int _bcm_tr_mpls_add_vp_nh(int unit, bcm_if_t  egr_if, int nh_index);
    193 STATIC int _bcm_tr_mpls_add_egrNhop ( int unit, bcm_if_t egress_if);
    194 STATIC void  _bcm_tr_mpls_cleanup_egrNhop (int unit);
    195 STATIC int  _bcm_tr_mpls_l2_nh_info_delete(int unit, int nh_index);
    196 STATIC void _bcm_tr_mpls_vpws_vp_map_clear (int unit, bcm_vpn_t vpn);
    197 STATIC void  _bcm_tr_mpls_egr_tunnel_ref_count_adjust (int unit, int index, int step);
    198 #ifdef BCM_KATANA_SUPPORT
    199 STATIC void _bcm_tr_mpls_ing_queue_map_ref_count_adjust (int unit, int index, int step);
    200 #endif /* BCM_KATANA_SUPPORT */
    201 STATIC void bcmi_tr_mpls_vc_swap_hash_cleanup(int unit);
    202 STATIC int _bcm_tr_mpls_port_get(int unit, bcm_vpn_t vpn, int vp, bcm_mpls_port_t *mpls_port);
    203 #if defined(BCM_TRIUMPH3_SUPPORT)
    204 STATIC int _bcm_tr_mpls_vc_and_swap_hash_nhop_add (int unit, int vc_swap_index,
    205                                                    int nh_index);
    206 #endif
    207 
    208 STATIC int bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(int unit);
    209 STATIC int
    210 bcmi_td3_soc_mem_fields32_modify(int unit, soc_mem_t mem, int index,
    211                         soc_field_t field, uint32 value);
    212 
    213 #if defined(BCM_TRIDENT3_SUPPORT)
    214 STATIC int
    215 bcmi_egr_dvp_attribute_nwgroup_get(int unit, int vp, int *nw_group);
    216 #endif /* BCM_TRIDENT3_SUPPORT */
    217 
    218 #if defined(BCM_TRIDENT3_SUPPORT)
    219 #define EXP_MAP_DSCP_INVALID 0xff
    220 #endif
    221 
    222 STATIC int
    223 bcmi_cmh_svp_attributes_set(int unit, int entry_type, int svp, int set_flag,
    224         int mpls_flags)
    225 {
    226     int rv = BCM_E_NONE;
    227     uint32 svp_attrs_0_prof_idx = 0;
    228     uint32 svp_attrs_1_prof_idx = 0;
    229     uint32 flow_sel_ctrl_id_0 = 0;
    230     source_vp_2_entry_t svpattrs_0;
    231     svp_attrs_1_entry_t svpattrs_1;
    232 
    233     /*VPWS or VPLS SVP ATTRIBUTES*/
    234     if ((entry_type == 1) || (entry_type == 2)) {
    235         if((set_flag == TRUE) && (mpls_flags & BCM_MPLS_PORT_EGRESS_TUNNEL)) {
    236             svp_attrs_0_prof_idx = 2;
    237             flow_sel_ctrl_id_0 = 1;
    238 
    239             if(mpls_flags & BCM_MPLS_PORT_CONTROL_WORD ||
    240                mpls_flags & BCM_MPLS_PORT_SEQUENCED) {
    241                 svp_attrs_1_prof_idx = 2;
    242             } else {
    243                 svp_attrs_1_prof_idx = 1;
    244             }
    245         }
    246     }
    247 
    248     /*Write SVP_ATTR_0,SVP_ATTRS_1 tables*/
    249     BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ALL,
    250                 svp,&svpattrs_1));
    251     soc_SVP_ATTRS_1m_field_set(unit, &svpattrs_1,
    252             CTRL_PROFILE_IDXf, &svp_attrs_1_prof_idx);
    253     rv = WRITE_SVP_ATTRS_1m(unit, MEM_BLOCK_ALL, svp, &svpattrs_1);
    254     if( rv != BCM_E_NONE) {
    255         return rv;
    256     }
    257 
    258     BCM_IF_ERROR_RETURN(READ_SOURCE_VP_2m(unit, MEM_BLOCK_ALL,
    259                 svp,&svpattrs_0));
    260     soc_SOURCE_VP_2m_field_set(unit, &svpattrs_0,
    261             CTRL_PROFILE_IDXf, &svp_attrs_0_prof_idx);
    262     soc_SOURCE_VP_2m_field_set(unit, &svpattrs_0,
    263             PKT_FLOW_SELECT_CTRL_ID_0f, &flow_sel_ctrl_id_0);
    264     rv = WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, svp, &svpattrs_0);
    265     if( rv != BCM_E_NONE) {
    266         return rv;
    267     }
    268 
    269     return rv;
    270 }
    271 
    272 #if defined(BCM_TRIDENT3_SUPPORT)
    273 STATIC int
    274 bcmi_cmh_vfi_profile_set(int unit, uint32 *vfi_profile_idx)
    275 {
    276     int rv = BCM_E_NONE;
    277     uint32 pkt_flow_sel_ctrl_id_2 = 4;
    278     uint32 en_ifilter = 1;
    279     vfi_profile_entry_t vfi_profile;
    280     void *entries[1];
    281 
    282     sal_memset(&vfi_profile, 0, sizeof(vfi_profile_entry_t));
    283     soc_VFI_PROFILEm_field_set(unit, &vfi_profile,
    284             PKT_FLOW_SELECT_CTRL_ID_2f, &pkt_flow_sel_ctrl_id_2);
    285     soc_VFI_PROFILEm_field_set(unit, &vfi_profile,
    286             EN_IFILTERf, &en_ifilter);
    287     entries[0] = &vfi_profile;
    288     rv = _bcm_vfi_profile_entry_add(unit, entries, 1, vfi_profile_idx);
    289 
    290     return rv;
    291 }
    292 #endif
    293 
    294 STATIC int
    295 bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(int unit)
    296 {
    297     int num_exp_map = 0;
    298 
    299 #if defined(BCM_TRIDENT3_SUPPORT)
    300     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
    301         num_exp_map = soc_mem_index_count(unit,
    302                 EGR_MPLS_PRI_MAPPINGm) / 64;
    303     } else
    304 #endif
    305     {
    306         num_exp_map = soc_mem_index_count(unit,
    307                 EGR_MPLS_EXP_PRI_MAPPINGm) / 8;
    308     }
    309 
    310     return num_exp_map;
    311 }
    312 
    313 STATIC int
    314 bcmi_td3_soc_mem_fields32_modify(int unit, soc_mem_t mem, int index,
    315                         soc_field_t field, uint32 value)
    316 {
    317     uint32 buf[SOC_MAX_MEM_WORDS];       /* Buffer to read memory entry. */
    318     int rv;                              /* Operation return status.     */
    319     uint32 ret_val = 0,dest_type = 0;
    320     int value_changed = 0;               /* Flag of value changed comparing
    321                                             between input and current reading*/
    322 
    323     /* Check that memory is a valid one for this unit. */
    324     if (!SOC_MEM_IS_VALID(unit, mem)) {
    325         return (SOC_E_UNAVAIL);
    326     }
    327 
    328     /* Check entry index range. */
    329     if ((index > soc_mem_index_max(unit, mem)) ||
    330         (index < soc_mem_index_min(unit, mem))) {
    331         return (SOC_E_PARAM);
    332     }
    333 
    334     /* Make sure value fits into memory field. */
    335     SOC_IF_ERROR_RETURN
    336         (soc_mem_field32_fit(unit, mem, field, value));
    337 
    338     /* Lock the memory. */
    339     soc_mem_lock(unit, mem);
    340     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, buf);
    341     if (SOC_FAILURE(rv)) {
    342         soc_mem_unlock(unit, mem);
    343         return (rv);
    344     }
    345 
    346     /* Set updated values in the buffer. */
    347     if (field == DESTINATIONf) {
    348         ret_val = soc_mem_field32_dest_get(unit, mem, buf,
    349                     DESTINATIONf, &dest_type);
    350 
    351         if ((dest_type == SOC_MEM_FIF_DEST_DVP) &&
    352                 (value != ret_val)) {
    353             soc_mem_field32_dest_set(unit, mem, buf,
    354                         DESTINATIONf, SOC_MEM_FIF_DEST_DVP, value);
    355             value_changed = 1;
    356         }
    357     } else {
    358         if(value != soc_mem_field32_get(unit, mem, buf, field)) {
    359                 value_changed = 1;
    360                 soc_mem_field32_set(unit, mem, buf, field, value);
    361         }
    362     }
    363 
    364     /* Write buffer back to memory. */
    365     if(value_changed) {
    366         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, buf);
    367     }
    368 
    369     soc_mem_unlock(unit, mem);
    370     return (rv);
    371 }
    372 
    373 #if defined(BCM_TRIDENT3_SUPPORT)
    374 STATIC int
    375 bcmi_egr_dvp_attribute_nwgroup_get(int unit, int vp, int *nw_group)
    376 {
    377     int rv=BCM_E_UNAVAIL;
    378     egr_dvp_attribute_entry_t  egr_dvp_attribute;
    379 
    380     rv = soc_mem_read(unit, EGR_DVP_ATTRIBUTEm,
    381             MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
    382     if (BCM_SUCCESS(rv)) {
    383         if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
    384                     &egr_dvp_attribute, COMMON__DVP_NETWORK_GROUPf)) {
    385             *nw_group =  soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
    386                     &egr_dvp_attribute, COMMON__DVP_NETWORK_GROUPf);
    387         }
    388     }
    389     return rv;
    390 }
    391 #endif /* BCM_TRIDENT3_SUPPORT */
    392 
    393 int _bcm_tr_get_ing_mpls_index_size(int unit)
    394 {
    395     int num_ing_exp_map;
    396 
    397     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
    398         num_ing_exp_map = 32;
    399     } else {
    400         num_ing_exp_map = soc_mem_index_count(unit, ING_MPLS_EXP_MAPPINGm) / 8;
    401     }
    402 
    403     return num_ing_exp_map;
    404 }
    405 
    406 /*
    407  * Function:
    408  *      bcm_mpls_enable
    409  * Purpose:
    410  *      Enable/disable MPLS function.
    411  * Parameters:
    412  *      unit - SOC unit number.
    413  *      enable - TRUE: enable MPLS support; FALSE: disable MPLS support.
    414  * Returns:
    415  *      BCM_E_XXX.
    416  */
    417 STATIC int
    418 bcm_tr_mpls_enable(int unit, int enable)
    419 {
    420     int port, rv = BCM_E_NONE;
    421     bcm_pbmp_t port_pbmp;
    422 
    423     BCM_PBMP_CLEAR(port_pbmp);
    424     BCM_PBMP_ASSIGN(port_pbmp, PBMP_PORT_ALL(unit));
    425 #ifdef BCM_KATANA2_SUPPORT
    426     if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) {
    427         BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &port_pbmp));
    428     }
    429     if (soc_feature(unit, soc_feature_linkphy_coe) ||
    430         soc_feature(unit, soc_feature_subtag_coe)) {
    431         _bcm_kt2_subport_pbmp_update(unit, &port_pbmp);
    432     }
    433 #endif
    434 
    435     PBMP_ITER(port_pbmp, port) {
    436         /* No mpls lookup on stacking ports. */
    437         if (IS_ST_PORT(unit, port)) {
    438             continue;
    439         }
    440         BCM_IF_ERROR_RETURN
    441             (bcm_esw_port_control_set(unit, port, bcmPortControlMpls, 
    442                                       (enable) ? 1 : 0));
    443     }
    444     return rv;
    445 }
    446 
    447 /*
    448  * Function:
    449  *      _bcm_tr_mpls_free_resource
    450  * Purpose:
    451  *      Free all allocated tables and memory
    452  * Parameters:
    453  *      unit - SOC unit number
    454  * Returns:
    455  *      Nothing
    456  */
    457 STATIC void
    458 _bcm_tr_mpls_free_resource(int unit, _bcm_tr_mpls_bookkeeping_t *mpls_info)
    459 {
    460     if (!mpls_info) {
    461         return;
    462     }
    463 
    464     if (mpls_info->vrf_bitmap) {
    465         sal_free(mpls_info->vrf_bitmap);
    466         mpls_info->vrf_bitmap = NULL;
    467     }
    468 
    469     if (mpls_info->vpws_bitmap) {
    470         sal_free(mpls_info->vpws_bitmap);
    471         mpls_info->vpws_bitmap = NULL;
    472     }
    473 
    474     if (mpls_info->vpws_vp_map) {
    475         sal_free(mpls_info->vpws_vp_map);
    476         mpls_info->vpws_vp_map = NULL;
    477     }
    478 
    479     if (mpls_info->trunk_vp_map) {
    480         sal_free(mpls_info->trunk_vp_map);
    481         mpls_info->trunk_vp_map = NULL;
    482     }
    483 
    484     if (mpls_info->vc_c_bitmap) {
    485         sal_free(mpls_info->vc_c_bitmap);
    486         mpls_info->vc_c_bitmap = NULL;
    487     }
    488 
    489     if (mpls_info->vc_nc_bitmap) {
    490         sal_free(mpls_info->vc_nc_bitmap);
    491         mpls_info->vc_nc_bitmap = NULL;
    492     }
    493 
    494     if (mpls_info->pw_term_bitmap) {
    495         sal_free(mpls_info->pw_term_bitmap);
    496         mpls_info->pw_term_bitmap = NULL;
    497     }
    498 
    499     if (mpls_info->pw_init_bitmap) {
    500         sal_free(mpls_info->pw_init_bitmap);
    501         mpls_info->pw_init_bitmap = NULL;
    502     }
    503 
    504     if (mpls_info->match_key) {
    505         sal_free(mpls_info->match_key);
    506         mpls_info->match_key = NULL;
    507     }
    508 
    509     if (mpls_info->tnl_bitmap) {
    510         sal_free(mpls_info->tnl_bitmap);
    511         mpls_info->tnl_bitmap = NULL;
    512     }
    513 
    514     if (mpls_info->ip_tnl_bitmap) {
    515         sal_free(mpls_info->ip_tnl_bitmap);
    516         mpls_info->ip_tnl_bitmap = NULL;
    517     }
    518 
    519     if (mpls_info->egr_mpls_bitmap) {
    520         sal_free(mpls_info->egr_mpls_bitmap);
    521         mpls_info->egr_mpls_bitmap = NULL;
    522     }
    523     if (mpls_info->egr_mpls_hw_idx) {
    524         sal_free(mpls_info->egr_mpls_hw_idx);
    525         mpls_info->egr_mpls_hw_idx = NULL;
    526     }
    527 
    528     if (mpls_info->ing_exp_map_bitmap) {
    529         sal_free(mpls_info->ing_exp_map_bitmap);
    530         mpls_info->ing_exp_map_bitmap = NULL;
    531     }
    532 
    533     if (mpls_info->egr_l2_exp_map_bitmap) {
    534         sal_free(mpls_info->egr_l2_exp_map_bitmap);
    535         mpls_info->egr_l2_exp_map_bitmap = NULL;
    536     }
    537 #ifdef BCM_APACHE_SUPPORT
    538     if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) {
    539         if (mpls_info->ing_exp_to_phb_cng_map_bitmap) {
    540             sal_free(mpls_info->ing_exp_to_phb_cng_map_bitmap);
    541             mpls_info->ing_exp_to_phb_cng_map_bitmap = NULL;
    542         }
    543 
    544         if (mpls_info->egr_exp_to_phb_cng_map_bitmap) {
    545             sal_free(mpls_info->egr_exp_to_phb_cng_map_bitmap);
    546             mpls_info->egr_exp_to_phb_cng_map_bitmap = NULL;
    547         }
    548     }
    549 #endif
    550     if (mpls_info->vc_swap_ref_count) {
    551         sal_free(mpls_info->vc_swap_ref_count);
    552         mpls_info->vc_swap_ref_count = NULL;
    553     }
    554 
    555     if (mpls_info->egr_tunnel_ref_count) {
    556         sal_free(mpls_info->egr_tunnel_ref_count);
    557         mpls_info->egr_tunnel_ref_count = NULL;
    558     }
    559 
    560     if (mpls_info->ing_qmap_ref_count) {
    561         sal_free(mpls_info->ing_qmap_ref_count);
    562         mpls_info->ing_qmap_ref_count = NULL;
    563     }
    564 
    565     if (mpls_info->svp_profile_set_bitmap) {
    566         sal_free(mpls_info->svp_profile_set_bitmap);
    567         mpls_info->svp_profile_set_bitmap = NULL;
    568     }
    569 
    570     if (mpls_info->network_vp_bitmap) {
    571         sal_free(mpls_info->network_vp_bitmap);
    572         mpls_info->network_vp_bitmap = NULL;
    573     }
    574 
    575     if (mpls_info->failover_vp) {
    576         sal_free(mpls_info->failover_vp);
    577         mpls_info->failover_vp = NULL;
    578     }
    579 
    580     (void) _bcm_tr_mpls_cleanup_egrNhop(unit);
    581     if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
    582         bcmi_tr_mpls_vc_swap_hash_cleanup(unit);
    583     }
    584 #if defined(BCM_APACHE_SUPPORT) || defined(BCM_TOMAHAWK2_SUPPORT)  \
    585     || defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
    586     if (soc_feature(unit, soc_feature_egr_ip_tnl_mpls_double_wide) ||
    587         (soc_feature(unit, soc_feature_th3_style_simple_mpls))) {
    588         bcmi_egr_ip_tunnel_mpls_sw_cleanup(unit);
    589     }
    590 #endif
    591 
    592 #ifdef BCM_TRIDENT3_SUPPORT
    593     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
    594         if (mpls_info->egr_vc_swap_lbl_action) {
    595             sal_free(mpls_info->egr_vc_swap_lbl_action);
    596             mpls_info->egr_vc_swap_lbl_action = NULL;
    597         }
    598     }
    599 #endif
    600 
    601 #if defined(BCM_SPECIAL_LABEL_SUPPORT)
    602     if (soc_feature(unit, soc_feature_mpls_special_label)) {
    603         (void) bcmi_mpls_special_label_deinit(unit);
    604     }
    605 #endif
    606 
    607 }
    608 
    609 /*
    610  * Function:
    611  *      bcm_tr_mpls_check_init
    612  * Purpose:
    613  *      Check if MPLS is initialized
    614  * Parameters:
    615  *      unit     - Device Number
    616  * Returns:
    617  *      BCM_E_XXX
    618  */
    619 
    620 STATIC int 
    621 _bcm_tr_mpls_check_init (int unit)
    622 {
    623     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
    624         return BCM_E_UNIT;
    625     }
    626 
    627     if (!_bcm_tr_mpls_bk_info[unit].initialized) { 
    628         return BCM_E_INIT;
    629     } else {
    630         return BCM_E_NONE;
    631     }
    632 }
    633 
    634 /*
    635  * Function:
    636  *      bcm_tr_mpls_lock
    637  * Purpose:
    638  *      Take the MPLS software module Lock Sempahore
    639  * Parameters:
    640  *      unit     - Device Number
    641  * Returns:
    642  *      BCM_E_XXX
    643  */
    644 
    645 int 
    646 bcm_tr_mpls_lock (int unit)
    647 {
    648    int rv;
    649 
    650    rv = _bcm_tr_mpls_check_init (unit);
    651    
    652    if ( rv == BCM_E_NONE ) {
    653         sal_mutex_take(MPLS_INFO((unit))->mpls_mutex, sal_mutex_FOREVER);
    654    }
    655    return rv; 
    656 }
    657 
    658 
    659 /*
    660  * Function:
    661  *      bcm_tr_mpls_unlock
    662  * Purpose:
    663  *      Release  the MPLS software module Lock Semaphore
    664  * Parameters:
    665  *      unit     - Device Number
    666  * Returns:
    667  *      BCM_E_XXX
    668  */
    669 
    670 void
    671 bcm_tr_mpls_unlock(int unit)
    672 {
    673     int rv;
    674 
    675     rv = _bcm_tr_mpls_check_init (unit);
    676 
    677     if ( rv == BCM_E_NONE ) {
    678         sal_mutex_give(MPLS_INFO((unit))->mpls_mutex);
    679     }
    680 }
    681 
    682 /*
    683  * Function:
    684  *      bcm_tr_mpls_stat_clear
    685  * Purpose:
    686  *      Clear L2 MPLS PW Stats
    687  * Parameters:
    688  *      unit   - (IN) SOC unit #
    689  * Returns:
    690  *      BCM_E_XXX
    691  */     
    692 
    693 STATIC int
    694 _bcm_tr_mpls_stat_clear(int unit)
    695 {
    696     int num_pw_term, num_pw_init;
    697     int index, rv=BCM_E_NONE;
    698     ing_pw_term_counters_entry_t cent;
    699     ing_pw_term_seq_num_entry_t  snent;
    700     egr_pw_init_counters_entry_t pw_init_entry;
    701     egr_pw_init_counters_x_entry_t pw_init_entry_x;
    702     egr_pw_init_counters_y_entry_t pw_init_entry_y;
    703 
    704     if (SOC_HW_RESET(unit)) {
    705         return BCM_E_NONE;
    706     }
    707     num_pw_term = 0;
    708     if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) {
    709         num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm);
    710         /* Clear the ING Counters */
    711         sal_memset(&cent, 0, sizeof(ing_pw_term_counters_entry_t));
    712         for (index=0; index<num_pw_term; index++) {
    713             rv = WRITE_ING_PW_TERM_COUNTERSm(unit, MEM_BLOCK_ANY, index, &cent);
    714             if (rv < 0) {
    715                 return rv;
    716             }
    717         }
    718     }
    719 
    720     if (SOC_MEM_IS_VALID(unit,  ING_PW_TERM_SEQ_NUMm)) {
    721         num_pw_term = soc_mem_index_count(unit,  ING_PW_TERM_SEQ_NUMm);
    722         /* Clear the ING Counters */
    723         sal_memset(&snent, 0, sizeof(ing_pw_term_seq_num_entry_t));
    724         for (index = 0; index < num_pw_term; index++) {
    725             rv = WRITE_ING_PW_TERM_SEQ_NUMm(unit, MEM_BLOCK_ANY, index, &snent);
    726             if (rv < 0) {
    727                 return rv;
    728             }
    729         }
    730     }
    731 
    732     num_pw_init = 0;
    733 #if defined(BCM_TRIDENT3_SUPPORT)
    734     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
    735         egr_sequence_number_table_entry_t td3_pw_init_entry;
    736         num_pw_init = soc_mem_index_count(unit, EGR_SEQUENCE_NUMBER_TABLEm);
    737         /* Clear the EGR Counters */
    738         sal_memset(&td3_pw_init_entry, 0, sizeof(egr_sequence_number_table_entry_t));
    739         for (index = 0; index < num_pw_init; index++) {
    740             rv = WRITE_EGR_SEQUENCE_NUMBER_TABLEm(unit, MEM_BLOCK_ANY, index,
    741                     &td3_pw_init_entry);
    742             if (rv < 0) {
    743                 return rv;
    744             }
    745         }
    746     } else
    747 #endif
    748     {
    749     if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERSm)) {
    750         num_pw_init = soc_mem_index_count(unit, EGR_PW_INIT_COUNTERSm);
    751         /* Clear the EGR Counters */
    752         sal_memset(&pw_init_entry, 0, sizeof(egr_pw_init_counters_entry_t));    
    753         for (index = 0; index < num_pw_init; index++) {
    754             rv = WRITE_EGR_PW_INIT_COUNTERSm(unit, MEM_BLOCK_ANY, index, 
    755                                              &pw_init_entry);
    756             if (rv < 0) {
    757                 return rv;
    758             }
    759         }
    760         if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERS_Xm)) {
    761             num_pw_init = soc_mem_index_count(unit, EGR_PW_INIT_COUNTERS_Xm);
    762             sal_memset(&pw_init_entry_x, 0, sizeof(egr_pw_init_counters_x_entry_t));
    763             for (index = 0; index < num_pw_init; index++) {
    764                 rv = WRITE_EGR_PW_INIT_COUNTERS_Xm(unit, MEM_BLOCK_ANY, index, 
    765                                                    &pw_init_entry_x);
    766                 if (rv < 0) {
    767                     return rv;
    768                 }
    769             }
    770         }
    771         if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERS_Ym)) {
    772             num_pw_init = soc_mem_index_count(unit, EGR_PW_INIT_COUNTERS_Ym);
    773             sal_memset(&pw_init_entry_y, 0, sizeof(egr_pw_init_counters_y_entry_t));
    774             for (index = 0; index < num_pw_init; index++) {
    775                 rv = WRITE_EGR_PW_INIT_COUNTERS_Ym(unit, MEM_BLOCK_ANY, index, 
    776                                                    &pw_init_entry_y);
    777                 if (rv < 0) {
    778                     return rv;
    779                 }
    780             }
    781         }
    782     }
    783     }
    784     return rv;
    785 }
    786 
    787 
    788 /*
    789 * Purpose:
    790 *	   Entry-0 VC-AND-SWAP Entry is reserved for default
    791 * Parameters:
    792 *	   unit 	 -	(IN) StrataSwitch #.
    793 * Returns:
    794 *	   BCM_E_XXX
    795 */
    796 STATIC int
    797 _bcm_tr_mpls_default_entry_setup(int unit)
    798 {
    799     egr_mpls_vc_and_swap_label_table_entry_t  vc_entry;
    800     int rv = BCM_E_NONE;
    801     uint32 vc_swap_index = VC_AND_SWAP_TABLE_RESV_INDEX;
    802 
    803     sal_memset(&vc_entry, 0,
    804               sizeof(egr_mpls_vc_and_swap_label_table_entry_t));
    805 
    806     _BCM_MPLS_VC_COUNT_USED_SET(unit, vc_swap_index);
    807 
    808 #if defined(BCM_SWAP_TO_SELF_SUPPORT)
    809     if (soc_feature(unit, soc_feature_mpls_swap_label_preserve)) {
    810 
    811         soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
    812                             &vc_entry, MPLS_LABEL_ACTIONf,
    813                             _BCM_MPLS_ACTION_NOOP);
    814 
    815     } else
    816 #endif
    817     {
    818         soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
    819                             &vc_entry, MPLS_LABEL_ACTIONf,
    820                             _BCM_MPLS_ACTION_RESERVED);
    821     }
    822 
    823     rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
    824               MEM_BLOCK_ALL, vc_swap_index,
    825               &vc_entry);
    826 
    827     return rv;
    828 }
    829 
    830 /*
    831  * Function:
    832  *      bcm_tr_mpls_vrf_used_get
    833  */     
    834 
    835 int
    836 bcm_tr_mpls_vrf_used_get(int unit, int vrf)
    837 {
    838     return _BCM_MPLS_VRF_USED_GET(unit, vrf);
    839 }
    840 
    841 /*
    842  * Function:
    843  *      bcm_tr_mpls_pw_used_clear
    844  */     
    845 
    846 void
    847 bcm_tr_mpls_pw_used_clear(int unit, int pw_cnt)
    848 {
    849     _BCM_MPLS_PW_TERM_USED_CLR(unit, pw_cnt);
    850 }
    851 
    852 /*
    853  * Function:
    854  *      bcm_tr_mpls_pw_used_get
    855  */     
    856 int
    857 bcm_tr_mpls_pw_used_get(int unit, int pw_cnt)
    858 {
    859    return _BCM_MPLS_PW_TERM_USED_GET(unit, pw_cnt);
    860 }
    861 
    862 /*
    863  * Function:
    864  *      bcm_tr_mpls_pw_used_set
    865  */     
    866 void
    867 bcm_tr_mpls_pw_used_set(int unit, int pw_cnt)
    868 {
    869     _BCM_MPLS_PW_TERM_USED_SET(unit, pw_cnt);
    870 }
    871 /*
    872  * Function:
    873  *      bcm_tr_mpls_port_independent_range
    874  * Purpose:
    875  *      Check if the incoming Label is within the Port Independent Range
    876  * Parameters:
    877  *      label - Label
    878  * Returns:
    879  *      BCM_E_XXX
    880  */
    881 
    882 int
    883 bcm_tr_mpls_port_independent_range (int unit, bcm_mpls_label_t label, bcm_gport_t port )
    884 {
    885    uint32 reg_val;         /* Register value */
    886    uint32 label_1_low=0, label_1_high=0;
    887    uint32 label_2_low=0, label_2_high=0;
    888 
    889 
    890     if (SOC_REG_IS_VALID(unit, GLOBAL_MPLS_RANGE_1_LOWERr)) {
    891         BCM_IF_ERROR_RETURN(READ_GLOBAL_MPLS_RANGE_1_LOWERr(unit, &reg_val));
    892         label_1_low =
    893             soc_reg_field_get(unit, GLOBAL_MPLS_RANGE_1_LOWERr, reg_val, LABELf);
    894     }
    895 
    896     if (SOC_REG_IS_VALID(unit, GLOBAL_MPLS_RANGE_1_UPPERr)) {
    897         BCM_IF_ERROR_RETURN(READ_GLOBAL_MPLS_RANGE_1_UPPERr(unit, &reg_val));
    898         label_1_high =
    899             soc_reg_field_get(unit, GLOBAL_MPLS_RANGE_1_UPPERr, reg_val, LABELf);
    900     }
    901 
    902     if (SOC_REG_IS_VALID(unit, GLOBAL_MPLS_RANGE_2_LOWERr)) {
    903         BCM_IF_ERROR_RETURN(READ_GLOBAL_MPLS_RANGE_2_LOWERr(unit, &reg_val));
    904         label_2_low =
    905             soc_reg_field_get(unit, GLOBAL_MPLS_RANGE_2_LOWERr, reg_val, LABELf);
    906     }
    907 
    908     if (SOC_REG_IS_VALID(unit, GLOBAL_MPLS_RANGE_2_UPPERr)) {
    909         BCM_IF_ERROR_RETURN(READ_GLOBAL_MPLS_RANGE_2_UPPERr(unit, &reg_val));
    910         label_2_high =
    911             soc_reg_field_get(unit, GLOBAL_MPLS_RANGE_2_UPPERr, reg_val, LABELf);
    912     }
    913 
    914     if (  (( label >= label_1_low) && ( label <= label_1_high)) || 
    915           ((  label >= label_2_low) && ( label <= label_2_high)) ){
    916         if (port == BCM_GPORT_INVALID) {
    917             return BCM_E_NONE;
    918         } else {
    919             return BCM_E_CONFIG;
    920         }
    921     } else {
    922         if (port == BCM_GPORT_INVALID) {
    923             return BCM_E_CONFIG;
    924         } else {
    925             return BCM_E_NONE;
    926         }
    927     }
    928 }
    929 
    930 
    931 
    932 #ifdef BCM_WARM_BOOT_SUPPORT
    933 
    934 int
    935 _bcm_tr_mpls_scache_size_get(int unit, int *size)
    936 {
    937     int num_vp = 0, num_vc = 0;
    938     int num_vrf, num_ip_tnl, num_mpls_map;
    939     int num_ing_exp_map, num_egr_l2_exp_map, num_pw_term, num_pw_init;
    940 #ifdef BCM_APACHE_SUPPORT
    941     int num_ing_mpls_exp_map1 = 0, num_egr_mpls_exp_map3 = 0;
    942 #endif
    943     int num_nh, alloc_sz = 0;
    944     soc_mem_t mem;
    945 
    946     num_vrf = SOC_CONTROL(unit)->max_vrf_id + 1;
    947     if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) {
    948         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    949     }
    950     if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) {
    951         num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
    952     }
    953 #if defined(BCM_TRIDENT3_SUPPORT)
    954     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
    955         mem = EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm;
    956     } else
    957 #endif
    958     {
    959         mem = EGR_IP_TUNNEL_MPLSm;
    960     }
    961     num_ip_tnl = soc_mem_index_count(unit, mem);
    962     /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */
    963     num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
    964     num_ing_exp_map = _bcm_tr_get_ing_mpls_index_size(unit);
    965 #ifdef BCM_APACHE_SUPPORT
    966     if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) {
    967         num_ing_mpls_exp_map1 = soc_mem_index_count(unit, 
    968                 ING_MPLS_EXP_MAPPING_1m) / 16;
    969         num_egr_mpls_exp_map3 = soc_mem_index_count(unit, 
    970                 EGR_MPLS_EXP_MAPPING_3m) / 8;
    971     }
    972 #endif
    973 
    974     num_egr_l2_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit);
    975     num_pw_term = 0;
    976     if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) {
    977         num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm);
    978     }
    979     num_pw_init = 0;
    980 #if defined(BCM_TRIDENT3_SUPPORT)
    981     if(soc_feature(unit, soc_feature_td3_style_mpls)) {
    982         mem = EGR_SEQUENCE_NUMBER_TABLEm; 
    983     } else
    984 #endif
    985     {
    986         mem = EGR_PW_INIT_COUNTERSm;
    987     }
    988     if (SOC_MEM_IS_VALID(unit, mem)) {
    989         num_pw_init = soc_mem_index_count(unit, mem);
    990     }
    991     num_nh = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
    992 
    993     alloc_sz = 0;
    994     alloc_sz += SOC_WB_SCACHE_CONTROL_SIZE; /* For version number */
    995     alloc_sz += SHR_BITALLOCSIZE(num_vrf);
    996     alloc_sz += SHR_BITALLOCSIZE(num_vp / 2);
    997     alloc_sz += SHR_BITALLOCSIZE(num_vc) * 2;
    998     alloc_sz += SHR_BITALLOCSIZE(num_pw_term);
    999     alloc_sz += SHR_BITALLOCSIZE(num_pw_init);
   1000     alloc_sz += SHR_BITALLOCSIZE(num_mpls_map);
   1001     alloc_sz += SHR_BITALLOCSIZE(num_ing_exp_map);
   1002     alloc_sz += SHR_BITALLOCSIZE(num_egr_l2_exp_map);
   1003     alloc_sz += SHR_BITALLOCSIZE(num_ip_tnl *
   1004             _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit));
   1005     alloc_sz += SHR_BITALLOCSIZE(num_ip_tnl);
   1006 
   1007     alloc_sz += sizeof(uint32) * (num_nh + 1);
   1008 #ifdef BCM_APACHE_SUPPORT
   1009     if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) {
   1010         alloc_sz += SHR_BITALLOCSIZE(num_ing_mpls_exp_map1);
   1011         alloc_sz += SHR_BITALLOCSIZE(num_egr_mpls_exp_map3);
   1012     }
   1013 #endif
   1014     if (size != NULL) {
   1015         *size = alloc_sz;
   1016     }
   1017 
   1018     return BCM_E_NONE;
   1019 }
   1020 
   1021 /* 
   1022  * Function:
   1023  *      _bcm_tr_mpls_unsynchronized_reinit
   1024  * Purpose:
   1025  *      - Recover MPLS related state from h/w.
   1026  *      - For MPLS module, the case where limited scache is 
   1027  *          available is the same as unsynchronized init.
   1028  *      - In Cold Boot sequence, just returns to calling func.
   1029  * Parameters:
   1030  *      unit    : (IN) Device Unit Number
   1031  * Returns:
   1032  *      BCM_E_XXX
   1033  */
   1034 STATIC int
   1035 _bcm_tr_mpls_unsynchronized_reinit(int unit) 
   1036 {
   1037     int rv = BCM_E_NONE;
   1038     if (!SOC_WARM_BOOT(unit)) {
   1039         return rv; 
   1040     }
   1041     
   1042     return rv;
   1043 }
   1044 
   1045 /* 
   1046  * Function:
   1047  *      _bcm_tr_mpls_limited_reinit
   1048  * Purpose:
   1049  *      This is called when only limited scache space 
   1050  *      is available. Please see comments for func
   1051  *      '_bcm_tr_mpls_ingexpbitmap_sync' in relation to this.
   1052  * Parameters:
   1053  *      unit    : (IN) Device Unit Number
   1054  * Returns:
   1055  *      BCM_E_XXX
   1056  */
   1057 STATIC int
   1058 _bcm_tr_mpls_limited_reinit(int unit)
   1059 {
   1060     int    rv = BCM_E_NONE;
   1061     int    stable_size;
   1062     uint8  *mpls_state;
   1063     int    num_ing_exp_map;
   1064     soc_scache_handle_t scache_handle;
   1065     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   1066 
   1067     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MPLS, 0);
   1068 
   1069     if (SOC_WARM_BOOT(unit)) {
   1070     /* Warm Boot */
   1071         SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   1072 
   1073         if (stable_size > sizeof(int32)) {
   1074             rv = _bcm_esw_scache_ptr_get(unit, scache_handle,
   1075                                     FALSE, sizeof(int32), &mpls_state,
   1076                                     BCM_WB_DEFAULT_VERSION, NULL);
   1077     
   1078             if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1079                 return rv;
   1080             }
   1081 
   1082             if (NULL == mpls_state) {
   1083                 return BCM_E_MEMORY;
   1084             }
   1085             num_ing_exp_map = _bcm_tr_get_ing_mpls_index_size(unit);
   1086             SHR_BITCOPY_RANGE(mpls_info->ing_exp_map_bitmap, 0,
   1087                               (SHR_BITDCL *)mpls_state, 0, num_ing_exp_map);
   1088         }
   1089     } else {
   1090     /* Cold Boot */
   1091         rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
   1092                                      sizeof(int32), &mpls_state, 
   1093                                      BCM_WB_DEFAULT_VERSION, NULL);
   1094         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1095             return rv;
   1096         }
   1097     }
   1098     
   1099     return BCM_E_NONE;
   1100 }
   1101 
   1102 #ifdef BCM_TRIUMPH2_SUPPORT
   1103 /* 
   1104  * Function:
   1105  *      _bcm_tr_mpls_flex_stat_recover
   1106  * Purpose:
   1107  *      - Recover flex stats for given VP
   1108  * Parameters:
   1109  *      unit    : (IN) Device Unit Number
   1110  *      vp      : (IN) Index into SOURCE_VPm table
   1111  * Returns:
   1112  *      BCM_E_XXX
   1113  */
   1114 int
   1115 _bcm_tr_mpls_flex_stat_recover(int unit, int vp)
   1116 {
   1117     int fs_index;
   1118     bcm_gport_t gport;
   1119     source_vp_entry_t svp_entry;
   1120 
   1121     SOC_IF_ERROR_RETURN(soc_mem_read(unit, SOURCE_VPm,
   1122                                   MEM_BLOCK_ANY, vp, &svp_entry));
   1123 
   1124     if (soc_mem_field_valid(unit, SOURCE_VPm, VINTF_CTR_IDXf)) {
   1125         fs_index = soc_SOURCE_VPm_field32_get(unit, &svp_entry,
   1126                                                 VINTF_CTR_IDXf);
   1127         if (fs_index) {
   1128             BCM_GPORT_MPLS_PORT_ID_SET(gport, vp);
   1129             _bcm_esw_flex_stat_reinit_add(unit,
   1130                                         _bcmFlexStatTypeGport, fs_index, gport);
   1131         }
   1132     }
   1133 
   1134     return BCM_E_NONE;
   1135 }
   1136 
   1137 /* 
   1138  * Function:
   1139  *      _bcm_tr_mpls_flex_stat_recover
   1140  * Purpose:
   1141  *      - Recover flex stats for given VP
   1142  * Parameters:
   1143  *      unit    : (IN) Device Unit Number
   1144  *      ment    : (IN) Pointer to MPLS_ENTRYm table entry
   1145  * Returns:
   1146  *      BCM_E_XXX
   1147  */
   1148 void
   1149 _bcm_tr_mpls_label_flex_stat_recover(int unit, mpls_entry_entry_t *ment)
   1150 {
   1151     int fs_index;
   1152     _bcm_flex_stat_handle_t mpls_fsh;
   1153     mpls_entry_entry_t fs_ment;
   1154     uint32 key[2];
   1155 
   1156     fs_index = soc_MPLS_ENTRYm_field32_get(unit, ment,
   1157                                            VINTF_CTR_IDXf);
   1158 
   1159     if ((0 != soc_MPLS_ENTRYm_field32_get(unit, ment,
   1160                                           USE_VINTF_CTR_IDXf)) &&
   1161         (0 != fs_index)) {
   1162         sal_memset(&fs_ment, 0, sizeof(fs_ment));
   1163         /* Construct key-only entry, copy to FS handle */
   1164         soc_MPLS_ENTRYm_field32_set(unit, &fs_ment, VALIDf,
   1165                  soc_MPLS_ENTRYm_field32_get(unit, ment, VALIDf));
   1166         soc_mem_field_get(unit, MPLS_ENTRYm, (uint32 *) ment,
   1167                           KEYf, (uint32 *) key);
   1168         soc_mem_field_set(unit, MPLS_ENTRYm, (uint32 *) &fs_ment,
   1169                           KEYf, (uint32 *) key);
   1170         /* Technically, we should copy the KEY_TYPE field here,
   1171          * but the rest of the MPLS code appears to abuse the fact that
   1172          * the key type value is 0, so it was handled when we
   1173          * cleared the entry above.
   1174          */
   1175 
   1176         _BCM_FLEX_STAT_HANDLE_CLEAR(mpls_fsh);
   1177         _BCM_FLEX_STAT_HANDLE_COPY(mpls_fsh, fs_ment);
   1178 
   1179         _bcm_esw_flex_stat_ext_reinit_add(unit,
   1180                                           _bcmFlexStatTypeMplsLabel,
   1181                                           fs_index, mpls_fsh);
   1182     }
   1183 }
   1184 
   1185 int
   1186 _bcm_tr_mpls_source_vp_recover(int unit)
   1187 {
   1188     source_vp_entry_t svp;
   1189     int rv = BCM_E_NONE;
   1190     int value = 0, vp;
   1191     int dscp_map_chunk = 0, ing_pri_cng_chunk = 0;
   1192     int vp_count = 0;
   1193     soc_mem_t port_tbl;
   1194 
   1195 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1196     if (SOC_IS_TOMAHAWK3(unit)) {
   1197         return BCM_E_NONE;
   1198     }
   1199 #endif
   1200 #if defined(BCM_TRIDENT3_SUPPORT)
   1201     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   1202         ing_pri_cng_chunk = 64;
   1203         dscp_map_chunk = 64;
   1204     } else
   1205 #endif
   1206     {
   1207         ing_pri_cng_chunk = 16;
   1208         dscp_map_chunk = 64;
   1209     }
   1210 
   1211     vp_count = soc_mem_index_count(unit, SOURCE_VPm);
   1212     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   1213         port_tbl = LPORT_TABm;
   1214     } else {
   1215         port_tbl = PORT_TABm;
   1216     }
   1217 
   1218     for (vp = 0; vp < vp_count; vp++) {
   1219         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
   1220             continue;
   1221         }
   1222 
   1223         if (_BCM_MPLS_SVP_PROFILE_SET_USED_GET(unit, vp)) {
   1224             /*  Read PORT Table */
   1225             if (!soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DSCP_PTRf) ||
   1226                 !soc_mem_field_valid(unit, port_tbl, TRUST_DOT1P_PTRf) ||
   1227                 !soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DOT1P_PTRf))  {
   1228                 return BCM_E_NONE;
   1229             }
   1230 
   1231             rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 
   1232             if (rv < 0) {
   1233                 return rv;
   1234             }
   1235             if (soc_feature(unit, soc_feature_dscp_map_per_port)) {
   1236                 if (soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DSCP_PTRf)) {
   1237                     value = soc_SOURCE_VPm_field32_get(unit, 
   1238                                                        &svp, 
   1239                                                        TRUST_DSCP_PTRf);
   1240                     rv = _bcm_dscp_table_entry_reference(unit, 
   1241                                                          (value * dscp_map_chunk),
   1242                                                          dscp_map_chunk);
   1243                     if (rv != BCM_E_NONE) {
   1244                         return rv;
   1245                     } else {
   1246                         rv = BCM_E_NONE;
   1247                     }
   1248                 }
   1249             }
   1250             if (soc_feature(unit, soc_feature_color_prio_map_profile)) {
   1251                 if (soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DOT1P_PTRf)) {
   1252                     value = soc_SOURCE_VPm_field32_get(unit, 
   1253                                                        &svp, 
   1254                                                        TRUST_DOT1P_PTRf);
   1255                     rv = _bcm_ing_pri_cng_map_entry_reference(
   1256                                             unit,
   1257                                             (value * ing_pri_cng_chunk),
   1258                                             ing_pri_cng_chunk);
   1259                     if (rv != BCM_E_NONE) {
   1260                         return rv;
   1261                     } else {
   1262                         rv = BCM_E_NONE;
   1263                     }
   1264                 } 
   1265             }
   1266         }
   1267     }
   1268     return rv;
   1269 }
   1270 #endif /* BCM_TRIUMPH2_SUPPORT */
   1271 
   1272 /* 
   1273  * Function:
   1274  *      _bcm_tr_mpls_source_vp_tpid_recover
   1275  * Purpose:
   1276  *      - Recover SVP TPIDs
   1277  * Parameters:
   1278  *      unit    : (IN) Device Unit Number
   1279  *      vp      : (IN) Index into SOURCE_VPm table
   1280  * Returns:
   1281  *      BCM_E_XXX
   1282  */
   1283 int
   1284 _bcm_tr_mpls_source_vp_tpid_recover(int unit, int vp)
   1285 {
   1286     int index, tpid_enable;
   1287     source_vp_entry_t svp_entry;
   1288 
   1289     SOC_IF_ERROR_RETURN(soc_mem_read(unit, SOURCE_VPm,
   1290                                   MEM_BLOCK_ANY, vp, &svp_entry));
   1291     if (soc_SOURCE_VPm_field32_get(unit, &svp_entry, SD_TAG_MODEf) == 1) {
   1292 #if defined(BCM_TRIDENT3_SUPPORT)
   1293         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   1294             uint32 svp_attrs_1[SOC_MAX_MEM_WORDS];
   1295 
   1296             BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit,
   1297                         MEM_BLOCK_ANY, vp, svp_attrs_1));
   1298             soc_SVP_ATTRS_1m_field_get(unit,
   1299                     &svp_attrs_1, TPID_ENABLEf, (uint32 *)&tpid_enable);
   1300         } else
   1301 #endif
   1302         {
   1303         tpid_enable = soc_SOURCE_VPm_field32_get(unit, &svp_entry,
   1304                                                               TPID_ENABLEf);
   1305         }
   1306         for (index = 0; index < 4; index++) {
   1307             if (tpid_enable & (1 << index)) {
   1308                 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_tab_ref_count_add(
   1309                                                            unit, index, 1));
   1310                 break;
   1311             }
   1312         }
   1313     }
   1314 
   1315     return BCM_E_NONE;
   1316 }
   1317 
   1318 int
   1319 _bcm_tr_mpls_associated_data_recover(int unit)
   1320 {
   1321     int macda_idx;
   1322     int i, idx_min, idx_max;
   1323     egr_l3_next_hop_entry_t nh_entry;
   1324 
   1325     idx_min = soc_mem_index_min(unit, EGR_L3_NEXT_HOPm);
   1326     idx_max = soc_mem_index_max(unit, EGR_L3_NEXT_HOPm);
   1327 
   1328     for (i = idx_min; i <= idx_max; i++) {
   1329         SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm,
   1330                                          MEM_BLOCK_ANY, i, &nh_entry));
   1331         if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &nh_entry, nh_entry_type_field[unit]) != 1) {
   1332             continue; /* MPLS entries only */
   1333         }
   1334 
   1335         /* Get Index to MAC-DA-PROFILEm */
   1336         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   1337              macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get
   1338                               (unit, &nh_entry, MPLS__MAC_DA_PROFILE_INDEXf);
   1339         } else {
   1340              macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get
   1341                               (unit, &nh_entry, MAC_DA_PROFILE_INDEXf);
   1342         }
   1343 
   1344         _bcm_common_profile_mem_ref_cnt_update(unit, EGR_MAC_DA_PROFILEm, 
   1345                                                macda_idx, 1);
   1346     }
   1347 
   1348     return BCM_E_NONE;
   1349 }
   1350 
   1351 /*
   1352  * Function:
   1353  *       bcmi_tr_mpls_vc_swap_hash_dump 
   1354  * Purpose:
   1355  *       dumps the whole hash table
   1356  * Parameters:
   1357  *           IN :  Unit
   1358  * Returns:
   1359  *        void
   1360  */
   1361 void bcmi_tr_mpls_vc_swap_hash_dump(int unit)
   1362 {   
   1363 
   1364     bcm_tr_mpls_vc_swap_table_hash_entry_t *temp;
   1365     bcm_tr_mpls_vc_swap_table_hash_t *hash;
   1366     int i, count = 0;
   1367 
   1368 
   1369     LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
   1370         "printing VC and SWAP hash table\n")));
   1371 
   1372     if (bcmi_vc_swap_label_hash[unit] != NULL) {
   1373         for (i=0; i< BCM_TR_MPLS_VC_SWAP_HASH_BUCKETS ; i++) {
   1374             hash =  &(bcmi_vc_swap_label_hash[unit][i]);
   1375             temp = hash->head_link;
   1376             if (temp != NULL) {
   1377                 while (temp != NULL) {
   1378                     LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
   1379                         "hash index = %d : table index = %d \n"), 
   1380                         i, temp->index));
   1381                     temp = temp->link;
   1382                     count++;
   1383                 }
   1384             }
   1385         }
   1386         LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit,"\ntotal counts = %d\n"),
   1387              count));
   1388     }
   1389 }
   1390 
   1391 /* 
   1392  * Function:
   1393  *     bcmi_tr_mpls_egr_vc_and_swap_table_hash_recover 
   1394  * Purpose:
   1395  *      - Recover MPLS VC Label table sw state.
   1396  * Parameters:
   1397  *      unit    : (IN) Device Unit Number
   1398  * Returns:
   1399  *      BCM_E_XXX
   1400  */
   1401 STATIC int 
   1402 bcmi_tr_mpls_egr_vc_and_swap_table_hash_recover(int unit)
   1403 {
   1404     int idx, hash_idx, vc_swap_index, table_idx;
   1405     int imin, num_vc;
   1406     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
   1407     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   1408     int action = 0;
   1409 
   1410     imin = soc_mem_index_min(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
   1411     num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
   1412     num_vc /= 2;
   1413     /* we are diving the table in half to manage counted and non-counted entries. */
   1414     for (idx = imin; idx < num_vc + imin; idx++) {
   1415         if ((!_BCM_MPLS_VC_COUNT_USED_GET(unit, idx - imin)) &&
   1416             (!_BCM_MPLS_VC_NON_COUNT_USED_GET(unit, idx - imin))) {
   1417             continue;
   1418         }
   1419 
   1420         table_idx = idx;
   1421          if (_BCM_MPLS_VC_NON_COUNT_USED_GET(unit, idx - imin)) {
   1422             table_idx += num_vc;
   1423         }
   1424 
   1425         if (mpls_info->vc_swap_ref_count[table_idx - imin] <= 0) {
   1426             continue;
   1427         }
   1428 
   1429         BCM_IF_ERROR_RETURN(soc_mem_read(unit,
   1430             EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
   1431             MEM_BLOCK_ALL, table_idx, &vc_entry));
   1432     
   1433 #if defined(BCM_TRIDENT3_SUPPORT)
   1434         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   1435             action = MPLS_INFO(unit)->egr_vc_swap_lbl_action[table_idx];
   1436         } else
   1437 #endif
   1438         {
   1439             action = 0;
   1440         }
   1441         BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_index_get(unit, 
   1442             NULL , action, NULL, NULL, &vc_entry, &hash_idx));
   1443  
   1444         BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_insert(unit, 
   1445             &(bcmi_vc_swap_label_hash[unit][hash_idx]), 
   1446             table_idx, NULL, NULL, NULL, NULL, 0, &vc_swap_index, FALSE));
   1447     }
   1448     return BCM_E_NONE;
   1449 }
   1450 #if defined(BCM_TRIUMPH3_SUPPORT)
   1451 STATIC int
   1452 _bcm_tr_mpls_egr_vc_and_swap_table_hash_nhop_recover(int unit)
   1453 {
   1454     egr_l3_next_hop_entry_t egr_nh;
   1455     int nh_count, idx, entry_type, vc_swap_idx, vc_count;
   1456     int rv = BCM_E_NONE;
   1457     soc_field_t vc_swap_idxf;
   1458 
   1459     if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   1460         vc_swap_idxf = MPLS__VC_AND_SWAP_INDEXf ;
   1461     } else {
   1462         vc_swap_idxf = VC_AND_SWAP_INDEXf;
   1463     }
   1464 
   1465     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   1466     nh_count = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   1467     vc_count = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
   1468 
   1469     for (idx = 0; idx < nh_count; idx++) {
   1470         BCM_IF_ERROR_RETURN (
   1471             soc_mem_read(unit, EGR_L3_NEXT_HOPm,
   1472                          MEM_BLOCK_ANY,  idx, &egr_nh));
   1473         entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   1474                                                       &egr_nh, ENTRY_TYPEf);
   1475         if (entry_type == 0x1) {
   1476             vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   1477                                                            vc_swap_idxf);
   1478             if ((vc_swap_idx) && (vc_swap_idx < vc_count)) {
   1479                 (void)_bcm_tr_mpls_vc_and_swap_hash_nhop_add (unit,
   1480                                                               vc_swap_idx,
   1481                                                               idx);
   1482             }
   1483         }
   1484     }
   1485     return rv;
   1486 }
   1487 #endif
   1488 /* 
   1489  * Function:
   1490  *      _bcm_tr_mpls_vc_refcount_recover
   1491  * Purpose:
   1492  *      - Recover MPLS VC Label Reference Count  from HW
   1493  * Parameters:
   1494  *      unit    : (IN) Device Unit Number
   1495  * Returns:
   1496  *      BCM_E_XXX
   1497  */
   1498 
   1499 STATIC int
   1500 _bcm_tr_mpls_vc_refcount_recover (int unit)
   1501 {
   1502     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   1503     egr_l3_next_hop_entry_t egr_nh;
   1504     int nh_count, idx, entry_type, vc_swap_idx, vc_count;
   1505     int rv=BCM_E_NONE;
   1506     soc_field_t vc_swap_idxf;    
   1507 
   1508     if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   1509         vc_swap_idxf = MPLS__VC_AND_SWAP_INDEXf ;
   1510     } else {
   1511         vc_swap_idxf = VC_AND_SWAP_INDEXf;
   1512     }
   1513 
   1514     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   1515     nh_count = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   1516     vc_count = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
   1517 
   1518     for (idx=0; idx<nh_count; idx++) {
   1519          BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm,
   1520                                       MEM_BLOCK_ANY,  idx, &egr_nh));
   1521          entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, 
   1522                                       &egr_nh, nh_entry_type_field[unit]);
   1523          if (entry_type == 0x1) {
   1524              vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   1525                                                             vc_swap_idxf);
   1526             if ((vc_swap_idx) && (vc_swap_idx < vc_count)) {
   1527                mpls_info->vc_swap_ref_count[vc_swap_idx]++;
   1528             }
   1529          }
   1530     }
   1531     return rv;
   1532 }
   1533 
   1534 
   1535 /* 
   1536  * Function:
   1537  *      _bcm_tr_mpls_egr_tunnel_refcount_recover
   1538  * Purpose:
   1539  *      - Recover MPLS Egress Tunnel-Label Reference Count  from HW
   1540  * Parameters:
   1541  *      unit    : (IN) Device Unit Number
   1542  * Returns:
   1543  *      BCM_E_XXX
   1544  */
   1545 
   1546 STATIC int
   1547 _bcm_tr_mpls_egr_tunnel_refcount_recover (int unit)
   1548 {
   1549     egr_ip_tunnel_mpls_entry_t tnl_entry;
   1550     egr_l3_intf_entry_t if_entry;
   1551     int intf_count, idx;
   1552     int mpls_index, tnl_index;
   1553     int offset, push_action;
   1554     int rv=BCM_E_NONE;
   1555 
   1556     sal_memset(&if_entry, 0, sizeof(egr_l3_intf_entry_t));
   1557     intf_count = soc_mem_index_count(unit, EGR_L3_INTFm);
   1558 
   1559     for (idx=0; idx<intf_count; idx++) {
   1560          BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_INTFm,
   1561                                       MEM_BLOCK_ANY,  idx, &if_entry));
   1562          mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry, 
   1563                                               MPLS_TUNNEL_INDEXf);
   1564          tnl_index = mpls_index / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit);
   1565 #if defined(BCM_TRIDENT3_SUPPORT)
   1566          if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   1567              egr_ip_tunnel_mpls_double_wide_entry_t tnl_entry_dbl;
   1568              rv = READ_EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm(unit, MEM_BLOCK_ANY,
   1569                      tnl_index, &tnl_entry_dbl);
   1570              if (rv < 0) {
   1571                  return rv;
   1572              }
   1573              if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm,
   1574                          &tnl_entry_dbl, DATA_TYPEf) == 0x14) {
   1575                  /* Increment Ref count */
   1576                  _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit,
   1577                          mpls_index, 1);
   1578              }
   1579          } else
   1580 #endif
   1581          {
   1582          rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 
   1583                                       tnl_index, &tnl_entry);
   1584          if (rv < 0) {
   1585             return rv;
   1586          }
   1587          if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
   1588                                 ENTRY_TYPEf) == 0x3) {
   1589              /* Increment Ref count */
   1590              _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 
   1591                                                    mpls_index, 1);
   1592 
   1593                  offset = mpls_index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit);
   1594                  push_action = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
   1595                                                    _tnl_push_action_f[offset]);
   1596                  if (push_action == 2) {
   1597                      _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit,
   1598                              mpls_index+1, 1);
   1599                 }
   1600         }
   1601     }
   1602     }
   1603     return rv;
   1604 }
   1605 
   1606 /* 
   1607  * Function:
   1608  *      _bcm_tr_mpls_match_key_recover
   1609  * Purpose:
   1610  *      - Recover MPLS match key from h/w tables
   1611  * Parameters:
   1612  *      unit    : (IN) Device Unit Number
   1613  * Returns:
   1614  *      BCM_E_XXX
   1615  */
   1616 int
   1617 _bcm_tr_mpls_match_key_recover(int unit)
   1618 {
   1619     int i, vp, port_type;
   1620     int index_min, index_max;
   1621     mpls_entry_entry_t mpls_entry;
   1622     source_trunk_map_table_entry_t trunk_entry;
   1623     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   1624     uint32 vent[SOC_MAX_MEM_WORDS];
   1625     soc_mem_t mem;
   1626 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1627     if (SOC_IS_TOMAHAWK3(unit)) {
   1628         /* Recover misc associated data */
   1629         BCM_IF_ERROR_RETURN(_bcm_tr_mpls_associated_data_recover(unit));
   1630         return BCM_E_NONE;
   1631     }
   1632 #endif
   1633     sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   1634 #if defined(BCM_TRIDENT3_SUPPORT)
   1635     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   1636         mem = VLAN_XLATE_1_DOUBLEm;
   1637     } else
   1638 #endif
   1639     {
   1640         mem = VLAN_XLATEm;
   1641     }
   1642     
   1643     /* Recover match keys from VLAN_XLATEm table */
   1644     index_min = soc_mem_index_min(unit, mem);
   1645     index_max = soc_mem_index_max(unit, mem);
   1646     for (i = index_min; i <= index_max; i++) {
   1647         SOC_IF_ERROR_RETURN(soc_mem_read(unit,
   1648                                          mem, MEM_BLOCK_ANY, i, vent));
   1649         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   1650             if ((soc_mem_field32_get(unit, mem, vent, BASE_VALID_0f) == 0) ||
   1651                     (soc_mem_field32_get(unit, mem, vent, BASE_VALID_1f) == 0)) {
   1652             continue;
   1653         }
   1654         } else {
   1655             if (soc_mem_field32_get(unit, mem, vent, VALIDf) == 0) {
   1656                 continue;
   1657             }
   1658         }
   1659 
   1660         if ((soc_mem_field32_get(unit, mem, vent, MPLS_ACTIONf) & 0x1) != 0x1) {
   1661             continue;
   1662         }    
   1663 
   1664         vp = soc_mem_field32_get(unit, mem, vent, SOURCE_VPf);
   1665 
   1666         /* Proceed only if this VP belongs to MPLS */
   1667         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
   1668 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1669             _bcm_vp_info_t vp_info;
   1670             BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
   1671 
   1672             if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) {
   1673                 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_SHARE;
   1674                 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
   1675                 continue;
   1676             }
   1677 #endif
   1678             if (soc_mem_field32_get(unit, mem, vent, KEY_TYPEf) ==
   1679              TR_VLXLT_HASH_KEY_TYPE_OVID) {
   1680 
   1681                 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN;
   1682                 mpls_info->match_key[vp].match_vlan =
   1683                     soc_mem_field32_get(unit, mem, vent, OVIDf);
   1684                 if (soc_mem_field32_get(unit, mem, vent, GLPf) !=
   1685                     SOC_VLAN_XLATE_GLP_WILDCARD(unit)) {
   1686                     if (soc_mem_field32_get(unit, mem, vent, Tf) == 0x1) {
   1687                         mpls_info->match_key[vp].trunk_id =
   1688                             soc_mem_field32_get(unit, mem, vent, TGIDf);
   1689                     } else {
   1690                         mpls_info->match_key[vp].port =
   1691                             soc_mem_field32_get(unit, mem, vent, PORT_NUMf);
   1692                         mpls_info->match_key[vp].modid =
   1693                             soc_mem_field32_get(unit, mem, vent, MODULE_IDf);
   1694                     }
   1695                 }
   1696                 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
   1697         } else if (soc_mem_field32_get(unit, mem, vent, KEY_TYPEf) ==
   1698              TR_VLXLT_HASH_KEY_TYPE_IVID) {
   1699 
   1700                 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN;
   1701                 mpls_info->match_key[vp].match_inner_vlan =
   1702                     soc_mem_field32_get(unit, mem, vent, IVIDf);
   1703                 if (soc_mem_field32_get(unit, mem, vent, Tf) == 0x1) {
   1704                     mpls_info->match_key[vp].trunk_id = 
   1705                               soc_mem_field32_get(unit, mem, vent, TGIDf);
   1706                 } else {
   1707                     mpls_info->match_key[vp].port = 
   1708                             soc_mem_field32_get(unit, mem, vent, PORT_NUMf);
   1709                     mpls_info->match_key[vp].modid = 
   1710                            soc_mem_field32_get(unit, mem, vent, MODULE_IDf);
   1711                 }
   1712                 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
   1713             } else if (soc_mem_field32_get(unit, mem, vent, KEY_TYPEf) == 
   1714                 TR_VLXLT_HASH_KEY_TYPE_IVID_OVID) {
   1715 
   1716                 mpls_info->match_key[vp].flags =
   1717                                          _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED;
   1718                 mpls_info->match_key[vp].match_vlan =
   1719                               soc_mem_field32_get(unit, mem, vent, OVIDf);
   1720                 mpls_info->match_key[vp].match_inner_vlan = 
   1721                               soc_mem_field32_get(unit, mem, vent, IVIDf);
   1722                 if (soc_mem_field32_get(unit, mem, vent, Tf) == 0x1) {
   1723                     mpls_info->match_key[vp].trunk_id =
   1724                               soc_mem_field32_get(unit, mem, vent, TGIDf);
   1725                 } else {
   1726                     mpls_info->match_key[vp].port = 
   1727                             soc_mem_field32_get(unit, mem, vent, PORT_NUMf);
   1728                     mpls_info->match_key[vp].modid =
   1729                            soc_mem_field32_get(unit, mem, vent, MODULE_IDf);
   1730                 }
   1731                 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
   1732             } 
   1733 #ifdef BCM_KATANA2_SUPPORT
   1734             else if ((soc_mem_field32_get(unit, mem, vent, KEY_TYPEf) ==
   1735                 KT2_PT_XLT_KEY_TYPE_LLVID) && soc_feature(unit, soc_feature_lltag)) {
   1736 
   1737                 mpls_info->match_key[vp].flags =
   1738                                          _BCM_MPLS_PORT_MATCH_TYPE_PORT_SUBPORT_PKT_VID;
   1739                 mpls_info->match_key[vp].match_subport_pkt_vid =
   1740                               soc_mem_field32_get(unit, mem, vent,
   1741                               LLTAG__LLVIDf);
   1742                
   1743                 if (soc_mem_field32_get(unit, mem, vent, Tf) == 0x1) {
   1744                     mpls_info->match_key[vp].trunk_id =
   1745                               soc_mem_field32_get(unit, mem, vent, TGIDf);
   1746                 } else {
   1747                     mpls_info->match_key[vp].port = 
   1748                             soc_mem_field32_get(unit, mem, vent, PORT_NUMf);
   1749                     mpls_info->match_key[vp].modid =
   1750                            soc_mem_field32_get(unit, mem, vent, MODULE_IDf);
   1751                 }
   1752                 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
   1753             } else if (soc_mem_field32_get(unit, mem, vent, KEY_TYPEf) ==
   1754                 KT2_PT_XLT_KEY_TYPE_LLVID_IVID && soc_feature(unit, soc_feature_lltag)) {
   1755 
   1756                 mpls_info->match_key[vp].flags =
   1757                                          _BCM_MPLS_PORT_MATCH_TYPE_PORT_SUBPORT_PKT_VID_INNER_VLAN;
   1758                 mpls_info->match_key[vp].match_subport_pkt_vid =
   1759                               soc_mem_field32_get(unit, mem, vent,
   1760                               LLTAG__LLVIDf);
   1761                 mpls_info->match_key[vp].match_inner_vlan = 
   1762                               soc_mem_field32_get(unit, mem, vent, LLTAG__IVIDf);
   1763                 if (soc_mem_field32_get(unit, mem, vent, Tf) == 0x1) {
   1764                     mpls_info->match_key[vp].trunk_id =
   1765                               soc_mem_field32_get(unit, mem, vent, TGIDf);
   1766                 } else {
   1767                     mpls_info->match_key[vp].port = 
   1768                             soc_mem_field32_get(unit, mem, vent, PORT_NUMf);
   1769                     mpls_info->match_key[vp].modid =
   1770                             soc_mem_field32_get(unit, mem, vent, MODULE_IDf);
   1771                 }
   1772                 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
   1773             } else if (soc_mem_field32_get(unit, mem, vent, KEY_TYPEf) == 
   1774                 KT2_PT_XLT_KEY_TYPE_LLVID_OVID && soc_feature(unit, soc_feature_lltag)) {
   1775 
   1776                 mpls_info->match_key[vp].flags =
   1777                                          _BCM_MPLS_PORT_MATCH_TYPE_PORT_SUBPORT_PKT_VID_OUTER_VLAN;
   1778                 mpls_info->match_key[vp].match_subport_pkt_vid =
   1779                               soc_mem_field32_get(unit, mem, vent, 
   1780                               LLTAG__LLVIDf);
   1781                 mpls_info->match_key[vp].match_vlan = 
   1782                               soc_mem_field32_get(unit, mem, vent, LLTAG__OVIDf);
   1783                 if (soc_mem_field32_get(unit, mem, vent, Tf) == 0x1) {
   1784                     mpls_info->match_key[vp].trunk_id =
   1785                               soc_mem_field32_get(unit, mem, vent, TGIDf);
   1786                 } else {
   1787                     mpls_info->match_key[vp].port = 
   1788                             soc_mem_field32_get(unit, mem, vent, PORT_NUMf);
   1789                     mpls_info->match_key[vp].modid =
   1790                            soc_mem_field32_get(unit, mem, vent, MODULE_IDf);
   1791                 }
   1792                 bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
   1793             }
   1794 #endif /* BCM_KATANA2_SUPPORT */ 
   1795 
   1796 #ifdef BCM_TRIUMPH2_SUPPORT    /* Recover flex stats */
   1797             if (soc_feature(unit, soc_feature_gport_service_counters)) {
   1798                 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_flex_stat_recover(unit, vp));
   1799             }
   1800 #endif /* BCM_TRIUMPH2_SUPPORT */
   1801 
   1802             /* Recover TPID ref count */
   1803             BCM_IF_ERROR_RETURN(_bcm_tr_mpls_source_vp_tpid_recover(unit, vp));
   1804         }
   1805     }
   1806 
   1807     /* Recover misc associated data */
   1808     BCM_IF_ERROR_RETURN(_bcm_tr_mpls_associated_data_recover(unit));
   1809 
   1810     /* Recover match keys from SOURCE_TRUNK_MAP_TABLEm table */
   1811     index_min = soc_mem_index_min(unit, SOURCE_TRUNK_MAP_TABLEm);
   1812     index_max = soc_mem_index_max(unit, SOURCE_TRUNK_MAP_TABLEm);
   1813     for (i = index_min; i <= index_max; i++) {
   1814         SOC_IF_ERROR_RETURN(soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm,
   1815                                                MEM_BLOCK_ANY, i, &trunk_entry));
   1816 
   1817         vp = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit,
   1818                                              &trunk_entry, SOURCE_VPf);
   1819 
   1820         /* Proceed only if this VP belongs to MPLS */
   1821         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
   1822 
   1823             port_type = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit,
   1824                                                      &trunk_entry, PORT_TYPEf); 
   1825             if (0 == port_type) { /* Normal port */
   1826                 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_PORT;
   1827                 mpls_info->match_key[vp].index = i;
   1828             } else if(1 == port_type) { /* Trunk port */
   1829                 mpls_info->match_key[vp].flags =_BCM_MPLS_PORT_MATCH_TYPE_TRUNK;
   1830                 mpls_info->match_key[vp].trunk_id = 
   1831                 soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &trunk_entry,
   1832                                                                          TGIDf);
   1833                 mpls_info->trunk_vp_map[mpls_info->match_key[vp].trunk_id] = vp;
   1834             }
   1835 
   1836 #ifdef BCM_TRIUMPH2_SUPPORT    /* Recover flex stats */
   1837             if (soc_feature(unit, soc_feature_gport_service_counters)) {
   1838                 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_flex_stat_recover(unit, vp));
   1839             }
   1840 #endif /* BCM_TRIUMPH2_SUPPORT */
   1841 
   1842             /* Recover TPID ref count */
   1843             BCM_IF_ERROR_RETURN(_bcm_tr_mpls_source_vp_tpid_recover(unit, vp));
   1844         }
   1845     }
   1846 
   1847     /* Recover match keys from MPLS_ENTRYm table */
   1848     index_min = soc_mem_index_min(unit, MPLS_ENTRYm);
   1849     index_max = soc_mem_index_max(unit, MPLS_ENTRYm);
   1850     for (i = index_min; i <= index_max; i++) {
   1851         SOC_IF_ERROR_RETURN(soc_mem_read(unit, MPLS_ENTRYm,
   1852                                                 MEM_BLOCK_ANY, i, &mpls_entry));
   1853 
   1854         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   1855             if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, BASE_VALID_0f) == 0) ||
   1856                     (soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, BASE_VALID_1f) == 0)) {
   1857                 continue;
   1858             }
   1859         } else {
   1860         if (soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf) == 0) {
   1861             continue;
   1862         }
   1863         }
   1864         if ((soc_MPLS_ENTRYm_field32_get(unit,
   1865                &mpls_entry, MPLS_ACTION_IF_BOSf) != 0x1) || 
   1866             (soc_MPLS_ENTRYm_field32_get(unit,
   1867                &mpls_entry, MPLS_ACTION_IF_NOT_BOSf) != 0x0)) {
   1868 #if defined(BCM_SABER2_SUPPORT)
   1869             /* SB2: IF not BOS field is set for VCCV type 4.
   1870              * It needs to be recovered.
   1871              */
   1872             if (!(SOC_IS_SABER2(unit) &&
   1873                 (soc_MPLS_ENTRYm_field32_get(unit,
   1874                 &mpls_entry, MPLS_ACTION_IF_NOT_BOSf) == 0x5)))
   1875 #endif
   1876             {
   1877                 continue;
   1878             }
   1879         }
   1880 
   1881         vp = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, SOURCE_VPf);
   1882 
   1883         /* Proceed only if this VP belongs to MPLS */
   1884         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
   1885             bcm_module_t  modid;
   1886             bcm_port_t    local_port;
   1887             bcm_trunk_t   trunk_id;
   1888             int           local_id;
   1889             bcm_gport_t   mpls_port_id;
   1890             bcm_trunk_t   mpls_tid = 0;
   1891             bcm_port_t    mpls_local_port = 0;
   1892             int           mpls_local_modid = 0;
   1893             int           rv;
   1894 
   1895             BCM_GPORT_MPLS_PORT_ID_SET(mpls_port_id,vp);
   1896             rv = _bcm_esw_gport_resolve(unit, mpls_port_id, &modid,
   1897                                            &local_port, &trunk_id,
   1898                                            &local_id);
   1899             if (rv != BCM_E_NONE) {
   1900                 continue;
   1901             }
   1902 
   1903             if (soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, Tf) == 0x1) {
   1904                 mpls_tid = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, TGIDf);
   1905                 if (mpls_tid == trunk_id) {
   1906                     mpls_info->match_key[vp].trunk_id = mpls_tid;
   1907                 } else {
   1908                     mpls_info->match_key[vp].fo_trunk_id = mpls_tid;
   1909                 }
   1910                 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT;
   1911             } else {
   1912                 mpls_local_port =
   1913                         soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, PORT_NUMf);
   1914                 mpls_local_modid =
   1915                            soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, MODULE_IDf);
   1916                
   1917                 if ((mpls_local_port == 0) && (mpls_local_modid == 0)) {
   1918                     mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_LABEL;
   1919                     mpls_info->match_key[vp].port  = mpls_local_port;
   1920                     mpls_info->match_key[vp].modid = mpls_local_modid;
   1921                 } else {
   1922                     mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT;
   1923                     if (mpls_local_port == local_port && mpls_local_modid == modid) {
   1924                         mpls_info->match_key[vp].port  = mpls_local_port;
   1925                         mpls_info->match_key[vp].modid = mpls_local_modid;
   1926                     } else {
   1927                         mpls_info->match_key[vp].fo_port  = mpls_local_port;
   1928                         mpls_info->match_key[vp].fo_modid = mpls_local_modid;
   1929                     }
   1930                 }
   1931             } 
   1932             mpls_info->match_key[vp].match_label = 
   1933                     soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, MPLS_LABELf);
   1934             
   1935 #ifdef BCM_TRIUMPH2_SUPPORT    /* Recover flex stats */
   1936             if (soc_feature(unit, soc_feature_gport_service_counters)) {
   1937                 BCM_IF_ERROR_RETURN
   1938                     (_bcm_tr_mpls_flex_stat_recover(unit, vp));
   1939                 _bcm_tr_mpls_label_flex_stat_recover(unit, &mpls_entry);
   1940             }
   1941 #endif /* BCM_TRIUMPH2_SUPPORT */
   1942 
   1943             /* Recover TPID ref count */
   1944             BCM_IF_ERROR_RETURN(_bcm_tr_mpls_source_vp_tpid_recover(unit, vp));
   1945         }
   1946     }
   1947 
   1948 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   1949     index_min = soc_mem_index_min(unit, SOURCE_VPm);
   1950     index_max = soc_mem_index_max(unit, SOURCE_VPm);
   1951     for (i = index_min; i <= index_max; i++) {
   1952         if (_bcm_vp_used_get(unit, i, _bcmVpTypeMpls)) {
   1953             _bcm_vp_info_t vp_info;
   1954             BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, i, &vp_info));
   1955 
   1956             if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) {
   1957                 mpls_info->match_key[i].flags = _BCM_MPLS_PORT_MATCH_TYPE_SHARE;
   1958             }
   1959         }
   1960     }
   1961 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   1962 
   1963 #ifdef BCM_TRIUMPH2_SUPPORT    /* Recover flex stats */
   1964     if (soc_feature(unit, soc_feature_gport_service_counters)) {
   1965         index_min = soc_mem_index_min(unit, SOURCE_VPm);
   1966         index_max = soc_mem_index_max(unit, SOURCE_VPm);
   1967         for (i = index_min; i <= index_max; i++) {
   1968             if ((!_bcm_vp_used_get(unit, i, _bcmVpTypeMpls)) ||
   1969                 (mpls_info->match_key[i].flags != 0)){
   1970                 continue;
   1971             }
   1972 
   1973             BCM_IF_ERROR_RETURN(_bcm_tr_mpls_flex_stat_recover(unit, i));
   1974         }
   1975     }
   1976 #endif /* BCM_TRIUMPH2_SUPPORT */
   1977 
   1978     return BCM_E_NONE;
   1979 }
   1980 
   1981 /* 
   1982  * Function:
   1983  *      _bcm_tr_mpls_vpws_vp_map_recover
   1984  * Purpose: 
   1985  *     Reconstruct the VPWS VP to VPN mapping info 
   1986  *     from h/w by traversing the source VP table.
   1987  *     NOTE: This is possible oly for sdk versions 
   1988  *     where the VPWS VPS are vp and vp+1.
   1989  * Parameters:
   1990  *      unit    : (IN) Device Unit Number
   1991  * Returns:
   1992  *      BCM_E_XXX
   1993  */
   1994 STATIC int
   1995 _bcm_tr_mpls_vpws_vp_map_recover(int unit)
   1996 {
   1997     int i, idx_min, idx_max;
   1998     source_vp_entry_t svp_entry; 
   1999     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   2000 
   2001     idx_min = soc_mem_index_min(unit, SOURCE_VPm);
   2002     idx_max = soc_mem_index_max(unit, SOURCE_VPm);
   2003 
   2004     for (i = idx_min; i <=idx_max; i++) {
   2005         SOC_IF_ERROR_RETURN(soc_mem_read(unit,
   2006                             SOURCE_VPm, MEM_BLOCK_ANY, i, &svp_entry));
   2007         if (soc_SOURCE_VPm_field32_get(unit, &svp_entry, ENTRY_TYPEf) != 2) {
   2008             continue; /* Looking for VPWS VPs only */
   2009         }
   2010         mpls_info->vpws_vp_map[(i>>1)].vp1 = i;
   2011         mpls_info->vpws_vp_map[(i>>1)].vp2 = (i+1);
   2012         i++; /* Skip past the immediate next VP as it belongs to this VPWS */
   2013     }
   2014     return BCM_E_NONE;
   2015 }
   2016 
   2017 /* 
   2018  * Function:
   2019  *      _bcm_tr_mpls_extended_reinit
   2020  * Purpose:
   2021  *      - Called when persistent memory adequate for
   2022  *            MPLS state recover is available.
   2023  *      - In Cold Boot sequence, scache space is allocated 
   2024  *            in persistent memory.
   2025  *      - In Warm Boot sequence, state stored in persistent 
   2026  *            memory is retrieved to reconstrunct MPLS 
   2027  *            book keeping structure.       
   2028  * Parameters:
   2029  *      unit    : (IN) Device Unit Number
   2030  * Returns:
   2031  *      BCM_E_XXX
   2032  */
   2033 STATIC int
   2034 _bcm_tr_mpls_extended_reinit(int unit)
   2035 {
   2036     int       i, rv = BCM_E_NONE;
   2037     int       stable_size, alloc_sz;
   2038     int       num_pw_term, num_pw_init;
   2039     int       num_ip_tnl, num_mpls_map, num_nh;
   2040     int       num_vrf, num_vp = 0, num_vc = 0;
   2041     int       num_ing_exp_map, num_egr_l2_exp_map;
   2042 #ifdef BCM_APACHE_SUPPORT
   2043     int       num_ing_exp_to_phb_cng_map = 0, num_egr_exp_to_phb_cng_map = 0;
   2044 #endif
   2045     int       vpws_vp_map_size;
   2046     int       idx_min, idx_max;
   2047     uint8     *mpls_state, *mpls_state_marker;
   2048     uint16    recovered_ver;
   2049     soc_scache_handle_t scache_handle;
   2050     uint8*    egr_nh_tbl_buf = NULL;
   2051     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   2052     uint32 nh_if, primary_nh_if, bitmask;
   2053     int       additional_scache_sz = 0;
   2054     int vp3_recovery_reqd = 0;
   2055     uint32 recovered_sz = 0;
   2056     int alloc_ver1_3_sz = 0;
   2057     int        old_num_vp = 0;
   2058 #if defined(BCM_SABER2_SUPPORT)
   2059     uint32     source_vp_sb2_5626x = 0;
   2060 #endif /* BCM_SABER2_SUPPORT */
   2061     soc_mem_t mem;
   2062 
   2063     num_mpls_map = soc_mem_index_count(unit,
   2064                         EGR_MPLS_EXP_MAPPING_1m) / 64;
   2065 
   2066     if (SOC_WARM_BOOT(unit)) {
   2067     /* Warm Boot */
   2068         alloc_sz = 0;
   2069         alloc_ver1_3_sz = 0;
   2070         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MPLS, 0);
   2071         BCM_IF_ERROR_RETURN(_bcm_tr_mpls_scache_size_get(unit, &alloc_sz));
   2072         if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1)  {
   2073             /* Although the sync and recover is changed to individual fields,
   2074              * we are still allocating full structure to start with.
   2075              * At this point, we do not know from which version we are 
   2076              * coming from so if we are coming from a version which had
   2077              * more space then we will reduce alloc space here.
   2078              * We will anyways reduce the space when we will recover
   2079              * each field based on versions below.
   2080              */
   2081             if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) {
   2082                 alloc_sz += sizeof(_bcm_mpls_vpws_vp_map_info_t) *
   2083                          (soc_mem_index_count(unit, SOURCE_VPm)/2);
   2084             }
   2085         }
   2086 
   2087         if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_2) {
   2088             alloc_sz += SHR_BITALLOCSIZE(num_mpls_map);
   2089         }
   2090 
   2091         if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_3) {
   2092             alloc_sz += (num_mpls_map * sizeof(uint32) -
   2093                          SHR_BITALLOCSIZE(num_mpls_map));
   2094         }
   2095         alloc_ver1_3_sz = alloc_sz;
   2096 
   2097         SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   2098         SOC_IF_ERROR_RETURN(soc_scache_ptr_get(unit, scache_handle,
   2099                                                 &mpls_state, &recovered_sz));
   2100         recovered_sz -= SOC_WB_SCACHE_CONTROL_SIZE;
   2101         vp3_recovery_reqd = (recovered_sz == alloc_ver1_3_sz) ? 1 : 0;
   2102 
   2103         if (stable_size > alloc_sz) {
   2104             rv = _bcm_esw_scache_ptr_get(unit,
   2105                                     scache_handle, FALSE,
   2106                                     alloc_sz, &mpls_state,
   2107                                     BCM_WB_DEFAULT_VERSION, &recovered_ver);
   2108 
   2109             if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   2110                 return rv;
   2111             }
   2112 
   2113             if (NULL == mpls_state) {
   2114                 return BCM_E_MEMORY;
   2115             }
   2116    
   2117             /* Maximum virtual port supported on saber2 5626x devices are 4K
   2118              * This fix is related to scaling down of vpn from 8K to 4K
   2119              */
   2120 #if defined(BCM_SABER2_SUPPORT)
   2121             if (soc_sb2_5626x_devtype(unit)) {
   2122                 sal_memcpy(&source_vp_sb2_5626x, mpls_state,
   2123                         sizeof(source_vp_sb2_5626x));
   2124                 if (source_vp_sb2_5626x == 0xFED5ABC7) {
   2125                     mpls_state += sizeof(source_vp_sb2_5626x);
   2126                 } else {
   2127                     old_num_vp = 1;
   2128                 }
   2129             }
   2130 #endif /* BCM_SABER2_SUPPORT */
   2131             num_vrf = SOC_CONTROL(unit)->max_vrf_id + 1;
   2132             if (!SOC_IS_TOMAHAWK3(unit)) {
   2133                 num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   2134                 num_vc = soc_mem_index_count(unit,
   2135                                              EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
   2136             }
   2137 #if  defined(BCM_TRIDENT3_SUPPORT)
   2138             if(soc_feature(unit, soc_feature_td3_style_mpls)) {
   2139                 num_ip_tnl = soc_mem_index_count(unit,
   2140                         EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm);
   2141             } else
   2142 #endif
   2143             {
   2144             num_ip_tnl = soc_mem_index_count(unit, EGR_IP_TUNNEL_MPLSm);
   2145             }
   2146 
   2147             /*EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri <<2) + cng)*/
   2148             num_ing_exp_map = _bcm_tr_get_ing_mpls_index_size(unit);
   2149             num_egr_l2_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit);
   2150 #ifdef BCM_APACHE_SUPPORT
   2151             if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) {
   2152                 num_ing_exp_to_phb_cng_map = soc_mem_index_count(unit,
   2153                         ING_MPLS_EXP_MAPPING_1m) / 16;
   2154                 num_egr_exp_to_phb_cng_map = soc_mem_index_count(unit,
   2155                         EGR_MPLS_EXP_MAPPING_3m) / 8;
   2156             }
   2157 #endif
   2158             num_pw_term = 0;
   2159             if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) {
   2160                 num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm);
   2161             }
   2162             num_pw_init = 0;
   2163 #if defined(BCM_TRIDENT3_SUPPORT)
   2164             if(soc_feature(unit, soc_feature_td3_style_mpls)) {
   2165                 mem = EGR_SEQUENCE_NUMBER_TABLEm; 
   2166             } else
   2167 #endif
   2168             {
   2169                 mem = EGR_PW_INIT_COUNTERSm;
   2170             }
   2171             if (SOC_MEM_IS_VALID(unit, mem)) {
   2172                 num_pw_init = soc_mem_index_count(unit, mem);
   2173             }
   2174             num_nh = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   2175             SHR_BITCOPY_RANGE(mpls_info->vrf_bitmap, 0,
   2176                               (SHR_BITDCL *)mpls_state, 0, num_vrf);
   2177             mpls_state += SHR_BITALLOCSIZE(num_vrf);
   2178             SHR_BITCOPY_RANGE(mpls_info->vpws_bitmap, 0,
   2179                               (SHR_BITDCL *)mpls_state, 0, (num_vp/2));
   2180             if (old_num_vp) {
   2181                 mpls_state += SHR_BITALLOCSIZE(num_vp);
   2182             } else {
   2183                 mpls_state += SHR_BITALLOCSIZE(num_vp/2);
   2184             }
   2185             SHR_BITCOPY_RANGE(mpls_info->vc_c_bitmap, 0,
   2186                               (SHR_BITDCL *)mpls_state, 0, num_vc);
   2187             mpls_state += SHR_BITALLOCSIZE(num_vc);
   2188             SHR_BITCOPY_RANGE(mpls_info->vc_nc_bitmap, 0,
   2189                               (SHR_BITDCL *)mpls_state, 0, num_vc);
   2190             mpls_state += SHR_BITALLOCSIZE(num_vc);
   2191             if (num_pw_term) {
   2192                 SHR_BITCOPY_RANGE(mpls_info->pw_term_bitmap, 0,
   2193                                   (SHR_BITDCL *)mpls_state, 0, num_pw_term);
   2194                 mpls_state += SHR_BITALLOCSIZE(num_pw_term);
   2195             }
   2196          
   2197             if (num_pw_init) {
   2198                 SHR_BITCOPY_RANGE(mpls_info->pw_init_bitmap, 0,
   2199                                   (SHR_BITDCL *)mpls_state, 0, num_pw_init); 
   2200                 mpls_state += SHR_BITALLOCSIZE(num_pw_init);
   2201             }
   2202             SHR_BITCOPY_RANGE(mpls_info->egr_mpls_bitmap, 0,
   2203                               (SHR_BITDCL *)mpls_state, 0, num_mpls_map);
   2204             mpls_state += SHR_BITALLOCSIZE(num_mpls_map);
   2205             SHR_BITCOPY_RANGE(mpls_info->ing_exp_map_bitmap, 0,
   2206                               (SHR_BITDCL *)mpls_state, 0, num_ing_exp_map);
   2207             mpls_state += SHR_BITALLOCSIZE(num_ing_exp_map);
   2208             SHR_BITCOPY_RANGE(mpls_info->egr_l2_exp_map_bitmap, 0,
   2209                               (SHR_BITDCL *)mpls_state, 0, num_egr_l2_exp_map);
   2210             mpls_state += SHR_BITALLOCSIZE(num_egr_l2_exp_map);
   2211             
   2212             SHR_BITCOPY_RANGE(mpls_info->tnl_bitmap, 0,
   2213                               (SHR_BITDCL *)mpls_state, 0, (num_ip_tnl *
   2214                                   _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)));
   2215             mpls_state += SHR_BITALLOCSIZE(num_ip_tnl *
   2216                     _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit));
   2217             SHR_BITCOPY_RANGE(mpls_info->ip_tnl_bitmap, 0,
   2218                               (SHR_BITDCL *)mpls_state, 0, num_ip_tnl);
   2219             mpls_state += SHR_BITALLOCSIZE(num_ip_tnl);
   2220             mpls_state_marker = mpls_state;
   2221        
   2222             /* Reconstruct match_index by reading tables */
   2223             rv = _bcm_esw_mpls_match_key_recover(unit);
   2224             if (BCM_FAILURE(rv)) {
   2225                 return rv;
   2226             }
   2227 
   2228             if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
   2229                 /* Reconstruct VC RefCount */
   2230                 rv = _bcm_tr_mpls_vc_refcount_recover(unit);
   2231                 if (BCM_FAILURE(rv)) {
   2232                     return rv;
   2233                 }
   2234             }
   2235 
   2236             /* Reconstruct Egress MPLS Tunnel-Label RefCount */
   2237             rv = _bcm_tr_mpls_egr_tunnel_refcount_recover(unit);
   2238             if (BCM_FAILURE(rv)) {
   2239                 return rv;
   2240             }
   2241 
   2242 #if defined(BCM_TRIDENT3_SUPPORT)
   2243              /*Recover VCSWAP Label Actions in TD3 first, for hash recover depend on it*/
   2244             if (recovered_ver >= BCM_WB_VERSION_1_12) {
   2245                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   2246                     int num_sl = soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm);
   2247                     int lbl_action_offset = sizeof(uint32) * num_nh + sizeof(int) +
   2248                                             (num_vp/2) * 3 * sizeof(int) +
   2249                                             num_mpls_map * sizeof(uint32) +
   2250                                             2 * SHR_BITALLOCSIZE(num_vp) +
   2251                                             num_vp * sizeof(uint32) +
   2252                                             num_sl * 2 *sizeof(int);
   2253                     sal_memcpy(mpls_info->egr_vc_swap_lbl_action, mpls_state + lbl_action_offset,
   2254                             num_vc * sizeof(int));
   2255                 }
   2256             }
   2257 #endif
   2258             if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
   2259                 /* Reconstruct hash for egr VC and swap table */
   2260                 rv = bcmi_tr_mpls_egr_vc_and_swap_table_hash_recover(unit);
   2261                 if (BCM_FAILURE(rv)) {
   2262                     return rv;
   2263                 }
   2264             }
   2265 #if defined(BCM_TRIUMPH3_SUPPORT)
   2266             /* Reconstruct intf hash for egr VC and swap table */
   2267             if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) {
   2268                 rv = _bcm_tr_mpls_egr_vc_and_swap_table_hash_nhop_recover(unit);
   2269                 if (BCM_FAILURE(rv)) {
   2270                     return rv;
   2271                 }
   2272             }
   2273 #endif
   2274 #if defined(BCM_APACHE_SUPPORT) || defined(BCM_TOMAHAWK2_SUPPORT) \
   2275            || defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
   2276             if (soc_feature(unit, soc_feature_egr_ip_tnl_mpls_double_wide) ||
   2277                 (soc_feature(unit, soc_feature_th3_style_simple_mpls))) {
   2278                 rv = bcmi_xgs5_mpls_tunnel_initiator_reinit(unit);
   2279                 if (BCM_FAILURE(rv)) {
   2280                     return rv;
   2281                 }
   2282             }
   2283 #endif
   2284             /* reconstruct the hash and linked lists */
   2285             idx_min = soc_mem_index_min(unit, EGR_L3_NEXT_HOPm);
   2286             idx_max = soc_mem_index_max(unit, EGR_L3_NEXT_HOPm);
   2287             egr_nh_tbl_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit,
   2288                                            EGR_L3_NEXT_HOPm),
   2289                                            "egr_l3_next_hop");
   2290             if (egr_nh_tbl_buf == NULL) {
   2291                 return BCM_E_MEMORY;
   2292             }
   2293                                             
   2294             rv = soc_mem_read_range(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   2295                             idx_min, idx_max, egr_nh_tbl_buf);
   2296             if (SOC_FAILURE(rv)) {
   2297                 goto cleanup;
   2298             }
   2299 
   2300             primary_nh_if = 0;
   2301             bitmask = 1 << ((8 * sizeof(uint32)) - 1);
   2302             sal_memcpy(&nh_if, mpls_state, sizeof(uint32));
   2303             while (nh_if != 0xdeadbeef) {
   2304                 if (nh_if & bitmask) {
   2305                     primary_nh_if = (nh_if & ~bitmask);
   2306                 }
   2307                 if (primary_nh_if != (nh_if & ~bitmask)) {
   2308                     BCM_IF_ERROR_RETURN(_bcm_tr_mpls_add_egrNhop(unit, primary_nh_if));
   2309                     BCM_IF_ERROR_RETURN(_bcm_tr_mpls_add_vp_nh(unit, primary_nh_if, nh_if));
   2310                     BCM_XGS3_L3_ENT_REF_CNT_INC(BCM_XGS3_L3_TBL_PTR(unit, next_hop),
   2311                        (primary_nh_if) ? (primary_nh_if - BCM_XGS3_EGRESS_IDX_MIN(unit)) : 0,
   2312                                                                      _BCM_SINGLE_WIDE);
   2313                 }
   2314                 mpls_state += sizeof(uint32);
   2315                 sal_memcpy(&nh_if, mpls_state, sizeof(uint32));
   2316             }
   2317             mpls_state = mpls_state_marker + (sizeof(uint32) * num_nh);
   2318 
   2319             /* Reconstruct VPWS VP map from the scache */
   2320             if (recovered_ver >= BCM_WB_VERSION_1_1) {
   2321                 mpls_state += sizeof(int);
   2322                 for (i=0; i<(num_vp/2); i++) {
   2323                     if(recovered_ver <= BCM_WB_VERSION_1_3) {
   2324                         sal_memcpy(&mpls_info->vpws_vp_map[i].vp1, mpls_state,
   2325                                    sizeof(int));
   2326                         mpls_state += sizeof(int);
   2327                         sal_memcpy(&mpls_info->vpws_vp_map[i].vp2, mpls_state,
   2328                                    sizeof(int));
   2329                         mpls_state += sizeof(int);
   2330                         if(vp3_recovery_reqd) {
   2331                             sal_memcpy(&mpls_info->vpws_vp_map[i].vp3,
   2332                                        mpls_state, sizeof(int));
   2333                             mpls_state += sizeof(int);
   2334                         }
   2335                     } else { /* if recovered_ver > BCM_WB_VERSION_1_3 */
   2336                         sal_memcpy(&mpls_info->vpws_vp_map[i].vp1, mpls_state,
   2337                                    sizeof(int));
   2338                         mpls_state += sizeof(int);
   2339                         sal_memcpy(&mpls_info->vpws_vp_map[i].vp2, mpls_state,
   2340                                    sizeof(int));
   2341                         mpls_state += sizeof(int);
   2342                         sal_memcpy(&mpls_info->vpws_vp_map[i].vp3, mpls_state,
   2343                                    sizeof(int));
   2344                         mpls_state += sizeof(int);
   2345 
   2346                         if ((recovered_ver >= BCM_WB_VERSION_1_8) &&
   2347                             soc_feature(unit, soc_feature_hierarchical_protection)) {
   2348 
   2349                             sal_memcpy(&mpls_info->vpws_vp_map[i].vp_b_1, mpls_state,
   2350                                    sizeof(int));
   2351                             mpls_state += sizeof(int);
   2352                             sal_memcpy(&mpls_info->vpws_vp_map[i].vp_b_2, mpls_state,
   2353                                    sizeof(int));
   2354                             mpls_state += sizeof(int);
   2355                             sal_memcpy(&mpls_info->vpws_vp_map[i].vp_b_3, mpls_state,
   2356                                    sizeof(int));
   2357                             mpls_state += sizeof(int);
   2358                         } else if (recovered_ver == BCM_WB_VERSION_1_8) {
   2359                             /*  As part of version 8, we allocated space common
   2360                              *  for all devices without any soc checks because
   2361                              *  whole structure was synced. as part of 1.9
   2362                              *  version, the structure is broken to sync/alloc
   2363                              *  each field separately.
   2364                              */
   2365                             mpls_state += (3 * sizeof(int));
   2366                         }
   2367                     }
   2368                 }
   2369                 if (old_num_vp) {
   2370                     if(recovered_ver <= BCM_WB_VERSION_1_3) {
   2371                         mpls_state += ((sizeof(int) + sizeof(int)) *
   2372                                 (num_vp - (num_vp/2)));
   2373                         if(vp3_recovery_reqd) {
   2374                             mpls_state += (sizeof(int) *
   2375                                     (num_vp - (num_vp/2)));
   2376                         }
   2377                     } else {
   2378                         mpls_state += ((sizeof(int) * 3) *
   2379                                 (num_vp - (num_vp/2)));
   2380                         if (recovered_ver >= BCM_WB_VERSION_1_8) {
   2381                             mpls_state += ((sizeof(int) * 3) *
   2382                                     (num_vp - (num_vp/2)));
   2383                         }
   2384                     }
   2385                 }
   2386             } else { /* Reconstruct VPWS VP map from h/w */
   2387                 rv = _bcm_tr_mpls_vpws_vp_map_recover(unit);
   2388                 if (BCM_FAILURE(rv)) {
   2389                     goto cleanup;
   2390                 }
   2391                 if (old_num_vp) {
   2392                     vpws_vp_map_size = sizeof(_bcm_mpls_vpws_vp_map_info_t) *
   2393                         num_vp;
   2394                 } else {
   2395                     vpws_vp_map_size = sizeof(_bcm_mpls_vpws_vp_map_info_t) *
   2396                         (soc_mem_index_count(unit, SOURCE_VPm)/2);
   2397                 }
   2398                 rv = soc_scache_realloc(unit, scache_handle, vpws_vp_map_size);
   2399                 if (SOC_FAILURE(rv)) {
   2400                     goto cleanup;
   2401                 }
   2402             }
   2403 
   2404             /* Recover the MPLS map entry */
   2405             if (recovered_ver >= BCM_WB_VERSION_1_3) {
   2406                 sal_memcpy(mpls_info->egr_mpls_hw_idx, mpls_state,
   2407                            (num_mpls_map * sizeof(uint32)));
   2408                 mpls_state += (num_mpls_map * sizeof(uint32));
   2409 
   2410                 for (i = 0; i < num_mpls_map; i++) {
   2411                     if (_BCM_EGR_MPLS_MAP_USED_GET(unit, i)) {
   2412                         rv = _bcm_egr_mpls_combo_map_entry_reference(unit, 
   2413                                 ((mpls_info->egr_mpls_hw_idx[i]) * 64), 64);
   2414                         if (BCM_FAILURE(rv)) {
   2415                             goto cleanup;
   2416                         }
   2417                     }
   2418                 }
   2419             } else if (recovered_ver >= BCM_WB_VERSION_1_2) {
   2420                 /* Can not get correct data from VERSION_1_2 */
   2421                 additional_scache_sz = num_mpls_map * sizeof(uint32) -
   2422                     SHR_BITALLOCSIZE(num_mpls_map);
   2423             } else {
   2424                 additional_scache_sz = num_mpls_map * sizeof(uint32);
   2425             }
   2426 
   2427             if ( (recovered_ver >= BCM_WB_VERSION_1_1) && 
   2428                  (recovered_ver <= BCM_WB_VERSION_1_3) ){
   2429                 if (!vp3_recovery_reqd) {
   2430                     if (old_num_vp) {
   2431                         additional_scache_sz += sizeof(int) * num_vp;
   2432                     } else {
   2433                         additional_scache_sz += sizeof(int) * (num_vp/2);
   2434                     }
   2435                 }
   2436             }
   2437             if (!(soc_feature(unit, soc_feature_hierarchical_protection))) {
   2438 
   2439                 /* if 2 level protection is not enabled then we
   2440                  * will have to allocate space only for version 1.8 as we
   2441                  * sync the whole structure there. from 1.9 we changed
   2442                  * sync of whole strcuture to indivisual fields.
   2443                  * going from 1.8 to 1.9 we will have to remove the space also.
   2444                  */
   2445                 if (recovered_ver == BCM_WB_VERSION_1_8) {
   2446                    if (old_num_vp) {
   2447                         additional_scache_sz -= (3 *sizeof(int)) * num_vp;
   2448                     } else {
   2449                         additional_scache_sz -= (3 *sizeof(int)) * (num_vp/2);
   2450                     }
   2451                 }
   2452             } else {
   2453                 /* Adding state for 3 more backup VPs */
   2454                 if (recovered_ver < BCM_WB_VERSION_1_8) {
   2455                     if (old_num_vp) {
   2456                         additional_scache_sz += (3 *sizeof(int)) * num_vp;
   2457                     } else {
   2458                         additional_scache_sz += (3 *sizeof(int)) * (num_vp/2);
   2459                     }
   2460                 }
   2461             }
   2462 
   2463             /* Recover the MPLS svp profile set bitmap */
   2464             if (recovered_ver >= BCM_WB_VERSION_1_5) {
   2465                 SHR_BITCOPY_RANGE(mpls_info->svp_profile_set_bitmap, 0,
   2466                                   (SHR_BITDCL *)mpls_state, 0, num_vp);
   2467                 if (old_num_vp) {
   2468                     mpls_state += SHR_BITALLOCSIZE((num_vp * 2));
   2469                 } else {
   2470                     mpls_state += SHR_BITALLOCSIZE(num_vp);
   2471                 }
   2472 #ifdef BCM_TRIUMPH2_SUPPORT 
   2473                 rv = _bcm_tr_mpls_source_vp_recover(unit);
   2474                 if (BCM_FAILURE(rv)) {
   2475                     goto cleanup;
   2476                 }
   2477 #endif
   2478             } else {
   2479                 if (old_num_vp) {
   2480                     additional_scache_sz += SHR_BITALLOCSIZE((num_vp * 2));
   2481                 } else {
   2482                     additional_scache_sz += SHR_BITALLOCSIZE(num_vp);
   2483                 }
   2484             }
   2485 
   2486             /* Recover the network VP bitmap */
   2487             if (recovered_ver >= BCM_WB_VERSION_1_6) {
   2488                 SHR_BITCOPY_RANGE(mpls_info->network_vp_bitmap, 0,
   2489                         (SHR_BITDCL *)mpls_state, 0, num_vp);
   2490                 if (old_num_vp) {
   2491                     mpls_state += SHR_BITALLOCSIZE((num_vp * 2));
   2492                 } else {
   2493                     mpls_state += SHR_BITALLOCSIZE(num_vp);
   2494                 }
   2495              } else {
   2496                 if (old_num_vp) {
   2497                     additional_scache_sz += SHR_BITALLOCSIZE((num_vp * 2));
   2498                 } else {
   2499                     additional_scache_sz += SHR_BITALLOCSIZE(num_vp);
   2500                 }
   2501             }
   2502 #ifdef BCM_APACHE_SUPPORT
   2503             if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) {
   2504                 /* Recover MPLS EXP to PHB and CNG maps */ 
   2505                 if (recovered_ver >= BCM_WB_VERSION_1_7) {
   2506                     SHR_BITCOPY_RANGE(mpls_info->ing_exp_to_phb_cng_map_bitmap, 0,
   2507                             (SHR_BITDCL *)mpls_state, 0, 
   2508                             num_ing_exp_to_phb_cng_map);
   2509                     mpls_state += SHR_BITALLOCSIZE(num_ing_exp_to_phb_cng_map);
   2510                     SHR_BITCOPY_RANGE(mpls_info->egr_exp_to_phb_cng_map_bitmap, 0,
   2511                             (SHR_BITDCL *)mpls_state, 0, 
   2512                             num_egr_exp_to_phb_cng_map);
   2513                     mpls_state += SHR_BITALLOCSIZE(num_egr_exp_to_phb_cng_map);
   2514                 } else {
   2515                     additional_scache_sz +=
   2516                             (SHR_BITALLOCSIZE(num_ing_exp_to_phb_cng_map) +
   2517                                 SHR_BITALLOCSIZE(num_egr_exp_to_phb_cng_map));
   2518                 }
   2519             }
   2520 #endif
   2521 
   2522 #ifdef BCM_TRIUMPH2_SUPPORT
   2523             if (soc_feature(unit, soc_feature_mpls_failover)) {
   2524                 /* Recover failover vp */ 
   2525                 if (recovered_ver >= BCM_WB_VERSION_1_10) {
   2526                     sal_memcpy(mpls_info->failover_vp, (SHR_BITDCL *)mpls_state, 
   2527                                num_vp * sizeof(uint32));
   2528                     mpls_state += num_vp * sizeof(uint32);
   2529                 } else {
   2530                     additional_scache_sz += num_vp * sizeof(uint32);
   2531                 }
   2532             }
   2533 #endif
   2534 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   2535             if (soc_feature(unit, soc_feature_mpls_special_label)) {
   2536                 int num_entry = 0;
   2537                 bcmi_mpls_special_label_control_t *ptr;
   2538                 num_entry =
   2539                     soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm);
   2540 
   2541                 /* Recover MPLS MPLS special label identifier state */
   2542                 if (recovered_ver >= BCM_WB_VERSION_1_11) {
   2543 
   2544                     ptr = bcmi_special_label_precedence_state[unit];
   2545                     for (i = 0; i < num_entry; i++) {
   2546                         sal_memcpy((&(ptr[i].ref_count)), mpls_state,
   2547                                    sizeof(int));
   2548                         mpls_state += sizeof(int);
   2549                         sal_memcpy((&(ptr[i].cancun_added)), mpls_state,
   2550                                    sizeof(int));
   2551                         mpls_state += sizeof(int);
   2552                     }
   2553                 } else {
   2554                     /* Ask for space for new two variables */
   2555                     additional_scache_sz += (num_entry * 2 * sizeof(int));
   2556                 }
   2557             }
   2558 #endif
   2559 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
   2560              /*Recover VCSWAP Label Actions in TD3*/
   2561             if (recovered_ver >= BCM_WB_VERSION_1_12) {
   2562 #ifdef BCM_TRIDENT3_SUPPORT
   2563                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   2564                     sal_memcpy(mpls_info->egr_vc_swap_lbl_action, mpls_state,
   2565                             num_vc * sizeof(int));
   2566                     mpls_state += num_vc * sizeof(int);
   2567                 }
   2568 #endif
   2569             } else {
   2570                 additional_scache_sz += (num_vc * sizeof(int));
   2571             }
   2572 #endif
   2573 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   2574             if (soc_feature(unit, soc_feature_mpls_special_label)) {
   2575                 /* Recover MPLS special label egress state */
   2576                 if (recovered_ver >= BCM_WB_VERSION_1_13) {
   2577                     bcmi_mpls_special_label_egress_t *ptr;
   2578 
   2579                     ptr = (&(bcmi_special_label_egress_state[unit]));
   2580                     sal_memcpy((&(ptr->special_label_ref_count)), mpls_state,
   2581                                sizeof(int));
   2582 
   2583                     mpls_state += sizeof(int);
   2584                     sal_memcpy((&(ptr->entropy_label_ref_count)), mpls_state,
   2585                                sizeof(int));
   2586                     mpls_state += sizeof(int);
   2587                 } else {
   2588                     /* Ask for space for new two variables */
   2589                     additional_scache_sz += (2 * sizeof(int));
   2590                 }
   2591             }
   2592 #endif
   2593 
   2594             if (additional_scache_sz != 0) {
   2595                 rv = soc_scache_realloc(unit, scache_handle, additional_scache_sz);
   2596                 if (SOC_FAILURE(rv)) {
   2597                     goto cleanup;
   2598                 }
   2599             }
   2600         }
   2601         /* Egress Mpls Tunnel related flex stat reloaded after Mpls
   2602          * SW structures are populated since the flow require Mpls
   2603          * book-keeping information.
   2604          */
   2605 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2606         if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   2607             _bcm_esw_stat_flex_check_egress_mpls_tunnel_table(unit);
   2608         }
   2609 #endif
   2610     } else {
   2611     /* Cold Boot */
   2612         alloc_sz = 0;
   2613         BCM_IF_ERROR_RETURN(_bcm_tr_mpls_scache_size_get(unit, &alloc_sz));
   2614 
   2615         if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) {
   2616             if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_5) {
   2617                 alloc_sz +=
   2618                     SHR_BITALLOCSIZE(soc_mem_index_count(unit, SOURCE_VPm));
   2619             }
   2620 
   2621             /* For network_vp_bitmap */
   2622             if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_6) {
   2623                 alloc_sz +=
   2624                     SHR_BITALLOCSIZE(soc_mem_index_count(unit, SOURCE_VPm));
   2625             }
   2626 
   2627             /* Allocate MPLS scache for the VPWS VP map */
   2628             if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1) {
   2629                 alloc_sz += (MPLS_VPWS_VP_NUM * sizeof(int)) *
   2630                        (soc_mem_index_count(unit, SOURCE_VPm)/2);
   2631 
   2632                 if ((BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_8) &&
   2633                     (soc_feature(unit, soc_feature_hierarchical_protection))) {
   2634                     alloc_sz += (MPLS_VPWS_VP_NUM * sizeof(int)) *
   2635                          (soc_mem_index_count(unit, SOURCE_VPm)/2);
   2636                 }
   2637             }
   2638 
   2639 #ifdef BCM_TRIUMPH2_SUPPORT
   2640             if (soc_feature(unit, soc_feature_mpls_failover)) {
   2641                 num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   2642                 alloc_sz += num_vp * sizeof(uint32);
   2643             }
   2644 #endif
   2645         }
   2646 
   2647         /* Allocate scache for the MPLS map entry */
   2648         if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_2) {
   2649             alloc_sz += SHR_BITALLOCSIZE(num_mpls_map);  
   2650         }
   2651 
   2652         if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_3) {
   2653             alloc_sz += (num_mpls_map * sizeof(uint32) -
   2654                          SHR_BITALLOCSIZE(num_mpls_map));
   2655         }
   2656 
   2657 #ifdef BCM_APACHE_SUPPORT
   2658         /* For MPLS EXP to PHB and CNG maps */
   2659         if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) {
   2660             if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_7) {
   2661                 alloc_sz += SHR_BITALLOCSIZE(soc_mem_index_count(unit, 
   2662                             ING_MPLS_EXP_MAPPING_1m) / 16);
   2663                 alloc_sz += SHR_BITALLOCSIZE(soc_mem_index_count(unit, 
   2664                             EGR_MPLS_EXP_MAPPING_3m) / 8);
   2665             }
   2666         }
   2667 #endif
   2668         /* Maximum virtual port supported on saber2 5626x devices are 4K
   2669          * This fix is related to scaling down of vpn from 8K to 4K
   2670          */
   2671 #if defined(BCM_SABER2_SUPPORT)
   2672         if (soc_sb2_5626x_devtype(unit)) {
   2673             alloc_sz += sizeof(source_vp_sb2_5626x);
   2674         }
   2675 #endif /* BCM_SABER2_SUPPORT */
   2676 
   2677 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   2678         if (soc_feature(unit, soc_feature_mpls_special_label)) {
   2679             int num_entry = 0;
   2680 
   2681             if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_11) {
   2682                 num_entry =
   2683                     soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm);
   2684                 /* Ask for space for new two variables */
   2685                 alloc_sz += (num_entry * 2 * sizeof(int));
   2686             }
   2687         }
   2688 #endif
   2689        /*
   2690         * Alloc space for TD3 VCSWAP Label action
   2691         * in coldboot
   2692         */
   2693         if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_12) {
   2694             if(soc_feature(unit, soc_feature_td3_style_mpls)) {
   2695                 alloc_sz += soc_mem_index_count(unit,
   2696                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm) * sizeof(int);
   2697             }
   2698         }
   2699 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   2700         if (soc_feature(unit, soc_feature_mpls_special_label)) {
   2701 
   2702             if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_13) {
   2703                 /* Ask for space for new two variables */
   2704                 alloc_sz += (2 * sizeof(int));
   2705             }
   2706         }
   2707 #endif
   2708         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MPLS, 0);
   2709 
   2710         rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
   2711                                      alloc_sz, &mpls_state, 
   2712                                      BCM_WB_DEFAULT_VERSION, NULL);
   2713 
   2714         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   2715             return rv;
   2716         }
   2717     
   2718     }
   2719 
   2720 cleanup:
   2721     if (egr_nh_tbl_buf) {
   2722         soc_cm_sfree(unit, egr_nh_tbl_buf);
   2723     }
   2724 
   2725     return rv;
   2726 }
   2727 
   2728 /* 
   2729  * Function:
   2730  *      _bcm_tr_mpls_nexthop_ref_inc
   2731  * Purpose:
   2732  *      Recover the nexthop refcount for mpls entry from hw.
   2733  * Parameters:
   2734  *      unit    : (IN) Device Unit Number
   2735  * Returns:
   2736  *      BCM_E_XXX
   2737  */
   2738 STATIC int
   2739 _bcm_tr_mpls_nexthop_ref_inc(
   2740     int unit,
   2741     bcm_mpls_tunnel_switch_t *info,
   2742     void *user_data)
   2743 {
   2744     int rv = BCM_E_NONE;
   2745     int nexthop = 0, nh_idx = 0;
   2746     uint32 mpath_flag = 0;
   2747 
   2748     COMPILER_REFERENCE(user_data);
   2749     if (info == NULL) {
   2750         return BCM_E_PARAM;
   2751     }
   2752 
   2753     nexthop = info->egress_if;
   2754     if (nexthop) {
   2755         /* figure out hw index from egress object */
   2756         rv = bcm_xgs3_get_nh_from_egress_object(unit,
   2757                  nexthop, &mpath_flag, 1, &nh_idx);
   2758         if (BCM_FAILURE(rv)) {
   2759             return rv;
   2760         }
   2761     }
   2762 
   2763 #ifdef BCM_TRIDENT3_SUPPORT
   2764     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   2765         if ((info->action_if_bos == BCM_MPLS_SWITCH_ACTION_PHP) ||
   2766             (info->action_if_not_bos == BCM_MPLS_SWITCH_ACTION_PHP)) {
   2767             if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, info->egress_if)) {
   2768                 rv = bcm_xgs3_get_nh_from_egress_object(unit,
   2769                         info->egress_if, &mpath_flag, 1, &nh_idx);
   2770                 if (BCM_FAILURE(rv)) {
   2771                     return rv;
   2772                 }
   2773             }
   2774         }
   2775     }
   2776 #endif
   2777     return BCM_E_NONE;
   2778 }
   2779 
   2780 /*
   2781  * Function:
   2782  *      _bcm_tr_mpls_reinit
   2783  * Purpose:
   2784  *      Top level Warm Boot init for MPLS 
   2785  * Parameters:
   2786  *      unit    : (IN) Device Unit Number
   2787  * Returns:
   2788  *      BCM_E_XXX
   2789  */
   2790 STATIC int
   2791 _bcm_tr_mpls_reinit(int unit)
   2792 {
   2793     int rv = BCM_E_NONE;
   2794     int stable_size = 0;
   2795 
   2796     if (SOC_WARM_BOOT(unit)) {
   2797     (void)_bcm_esw_mpls_tunnel_switch_traverse_no_lock(unit,
   2798               _bcm_tr_mpls_nexthop_ref_inc, NULL);
   2799     }
   2800     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   2801 
   2802     if (stable_size == 0) {
   2803         rv = _bcm_tr_mpls_unsynchronized_reinit(unit);
   2804     } else if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   2805         rv = _bcm_tr_mpls_limited_reinit(unit);
   2806     } else {
   2807         rv = _bcm_tr_mpls_extended_reinit(unit);
   2808     }
   2809     return rv;
   2810 }
   2811 
   2812 /* 
   2813  * Function:
   2814  *      _bcm_tr_mpls_ingexpbitmap_sync
   2815  * Purpose:
   2816  *      This is called only in the Cold Boot sequence when 
   2817  *      limited scache is available. The 'ing_exp_map_bitmap' field of MPLS bk 
   2818  *      structure is needed by the QoS module during Warm Boot with limited and 
   2819  *      extended scache support. When extended scache support is available,
   2820  *      this field is retreived by the '_bcm_tr_mpls_extended_reinit' sequence.
   2821  * Parameters:
   2822  *      unit    : (IN) Device Unit Number
   2823  * Returns:
   2824  *      BCM_E_XXX
   2825  */
   2826 STATIC int
   2827 _bcm_tr_mpls_ingexpbitmap_sync(int unit)
   2828 {
   2829     int rv = BCM_E_NONE;
   2830     uint8  *mpls_state;
   2831     int    num_ing_exp_map;
   2832     soc_scache_handle_t scache_handle;
   2833     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   2834 
   2835     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MPLS, 0);
   2836 
   2837     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
   2838                                  sizeof(int32), &mpls_state, 
   2839                                  BCM_WB_DEFAULT_VERSION, NULL);
   2840 
   2841     if (BCM_FAILURE(rv) && (rv != BCM_E_INTERNAL)) {
   2842         return rv;
   2843     }
   2844 
   2845     num_ing_exp_map = _bcm_tr_get_ing_mpls_index_size(unit);
   2846 
   2847     BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit));
   2848     SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   2849                       mpls_info->ing_exp_map_bitmap, 0, num_ing_exp_map);
   2850     bcm_tr_mpls_unlock(unit);
   2851     return rv;
   2852 }
   2853 
   2854 /* 
   2855  * Function:
   2856  *      bcm_tr_mpls_sync
   2857  * Purpose:
   2858  *      Store the s/w maintained MPLS book keeping structure 
   2859  *      onto persistent memory.
   2860  * Parameters:
   2861  *      unit    : (IN) Device Unit Number
   2862  * Returns:
   2863  *      BCM_E_XXX
   2864  */
   2865 int
   2866 bcm_tr_mpls_sync(int unit)
   2867 {
   2868     int num_vp = 0, num_vc = 0;
   2869     int num_vrf, num_ip_tnl, num_mpls_map;
   2870     int num_ing_exp_map, num_egr_l2_exp_map, num_pw_term, num_pw_init;
   2871 #ifdef BCM_APACHE_SUPPORT
   2872     int num_ing_exp_to_phb_cng_map = 0;
   2873     int num_egr_exp_to_phb_cng_map = 0;
   2874 #endif
   2875     int num_nh, alloc_sz = 0;
   2876     int i, vp_count, rv = BCM_E_NONE;
   2877     uint8 *mpls_state, *mpls_state_marker;
   2878     soc_scache_handle_t scache_handle;
   2879     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   2880     _bcm_mpls_egr_nhopList_t  *nhop_ptr;
   2881     _bcm_mpls_vp_nh_list_t  *vp_ptr;
   2882     uint32 primary_nh_if, bitmask;
   2883 #if defined(BCM_SABER2_SUPPORT)
   2884     uint32     source_vp_sb2_5626x = 0xFED5ABC7;
   2885 #endif /* BCM_SABER2_SUPPORT */
   2886     soc_mem_t mem;
   2887 
   2888     if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   2889         return _bcm_tr_mpls_ingexpbitmap_sync(unit);
   2890     }
   2891 
   2892     num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
   2893 
   2894     BCM_IF_ERROR_RETURN(_bcm_tr_mpls_scache_size_get(unit, &alloc_sz));
   2895     if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) {
   2896         if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1) {
   2897             alloc_sz += (3 * sizeof(int)) *
   2898                         (soc_mem_index_count(unit, SOURCE_VPm)/2);
   2899 
   2900             if ((BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_8) &&
   2901                 (soc_feature(unit, soc_feature_hierarchical_protection))) {
   2902 
   2903                 alloc_sz += (3 * sizeof(int)) *
   2904                         (soc_mem_index_count(unit, SOURCE_VPm)/2);
   2905             }
   2906 
   2907         }
   2908 
   2909         if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_5) {
   2910             alloc_sz += SHR_BITALLOCSIZE(soc_mem_index_count(unit, SOURCE_VPm));
   2911         }
   2912 
   2913         /*
   2914          * For network_vp_bitmap
   2915          */
   2916         if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_6) {
   2917             alloc_sz += SHR_BITALLOCSIZE(soc_mem_index_count(unit, SOURCE_VPm));
   2918         }
   2919 
   2920         /*
   2921          * For failover_vp
   2922          */
   2923 #ifdef BCM_TRIUMPH2_SUPPORT
   2924         if (soc_feature(unit, soc_feature_mpls_failover)) {
   2925             if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_10) {
   2926                 alloc_sz +=
   2927                     sizeof(uint32) * soc_mem_index_count(unit, SOURCE_VPm);
   2928             }
   2929         }
   2930 #endif /* BCM_TRIUMPH2_SUPPORT */
   2931     }
   2932 
   2933     if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_2) {
   2934          alloc_sz += SHR_BITALLOCSIZE(num_mpls_map);
   2935     }
   2936 
   2937     if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_3) {
   2938         alloc_sz += (num_mpls_map * sizeof(uint32) -
   2939                      SHR_BITALLOCSIZE(num_mpls_map));
   2940     }
   2941 
   2942     /* Maximum virtual port supported on saber2 5626x devices are 4K
   2943      * This fix is related to scaling down of vpn from 8K to 4K
   2944      */
   2945 #if defined(BCM_SABER2_SUPPORT)
   2946         if (soc_sb2_5626x_devtype(unit)) {
   2947             alloc_sz += sizeof(source_vp_sb2_5626x);
   2948         }
   2949 #endif /* BCM_SABER2_SUPPORT */
   2950 
   2951 
   2952 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   2953     if (soc_feature(unit, soc_feature_mpls_special_label)) {
   2954         int num_entry = 0;
   2955         /* Recover MPLS EXP to PHB and CNG maps */
   2956         if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_11) {
   2957             num_entry =
   2958                 soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm);
   2959             alloc_sz += sizeof(bcmi_mpls_special_label_control_t) * num_entry;
   2960         }
   2961     }
   2962 #endif /* BCM_SPECIAL_LABEL_SUPPORT */
   2963 
   2964     /*
   2965      * Alloc sync space for TD3 VCSWAP Label action
   2966      */
   2967     if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_12) {
   2968         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   2969             alloc_sz += soc_mem_index_count(unit,
   2970                     EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm) * sizeof(int);
   2971         }
   2972     }
   2973 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   2974         if (soc_feature(unit, soc_feature_mpls_special_label)) {
   2975 
   2976             if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_13) {
   2977                 /* Ask for space for new two variables */
   2978                 alloc_sz += (2 * sizeof(int));
   2979             }
   2980         }
   2981 #endif
   2982 
   2983     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_MPLS, 0);
   2984     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
   2985                                  alloc_sz, &mpls_state, 
   2986                                  BCM_WB_DEFAULT_VERSION, NULL);
   2987     if (BCM_FAILURE(rv) && (rv != BCM_E_INTERNAL)) {
   2988         return rv;
   2989     }
   2990 
   2991     /* Maximum virtual port supported on saber2 5626x devices are 4K
   2992      * This fix is related to scaling down of vpn from 8K to 4K
   2993      */
   2994 #if defined(BCM_SABER2_SUPPORT)
   2995         if (soc_sb2_5626x_devtype(unit)) {
   2996             sal_memcpy(mpls_state, &source_vp_sb2_5626x, sizeof(source_vp_sb2_5626x));
   2997             mpls_state += sizeof(source_vp_sb2_5626x);
   2998         }
   2999 #endif /* BCM_SABER2_SUPPORT */
   3000     num_vrf = SOC_CONTROL(unit)->max_vrf_id + 1;
   3001     if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) {
   3002         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   3003     }
   3004     if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) {
   3005         num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
   3006     }
   3007 
   3008 #if defined(BCM_TRIDENT3_SUPPORT)
   3009     if(soc_feature(unit, soc_feature_td3_style_mpls)) {
   3010         num_ip_tnl = soc_mem_index_count(unit,
   3011                 EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm);
   3012     } else
   3013 #endif
   3014     {
   3015     num_ip_tnl = soc_mem_index_count(unit, EGR_IP_TUNNEL_MPLSm);
   3016     }
   3017 
   3018     /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */
   3019     num_ing_exp_map = _bcm_tr_get_ing_mpls_index_size(unit);
   3020     num_egr_l2_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit);
   3021 #ifdef BCM_APACHE_SUPPORT
   3022     if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) {
   3023         num_ing_exp_to_phb_cng_map = soc_mem_index_count(unit, 
   3024                 ING_MPLS_EXP_MAPPING_1m) / 16;
   3025         num_egr_exp_to_phb_cng_map = soc_mem_index_count(unit, 
   3026                 EGR_MPLS_EXP_MAPPING_3m) / 8;
   3027     }
   3028 #endif
   3029     num_pw_term = 0;
   3030     if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) {
   3031         num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm);
   3032     }
   3033     num_pw_init = 0;
   3034 #if defined(BCM_TRIDENT3_SUPPORT)
   3035     if(soc_feature(unit, soc_feature_td3_style_mpls)) {
   3036         mem = EGR_SEQUENCE_NUMBER_TABLEm; 
   3037     } else
   3038 #endif
   3039     {
   3040         mem = EGR_PW_INIT_COUNTERSm;
   3041     }
   3042     if (SOC_MEM_IS_VALID(unit, mem)) {
   3043         num_pw_init = soc_mem_index_count(unit, mem);
   3044     }
   3045     num_nh = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   3046 
   3047     BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit));
   3048 
   3049     rv = BCM_E_NONE;
   3050     SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   3051                       mpls_info->vrf_bitmap, 0, num_vrf);
   3052     mpls_state += SHR_BITALLOCSIZE(num_vrf);
   3053     SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   3054                       mpls_info->vpws_bitmap, 0, (num_vp/2));
   3055     mpls_state += SHR_BITALLOCSIZE(num_vp/2);
   3056     SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   3057                       mpls_info->vc_c_bitmap, 0, num_vc);
   3058     mpls_state += SHR_BITALLOCSIZE(num_vc);
   3059     SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   3060                       mpls_info->vc_nc_bitmap, 0, num_vc);
   3061     mpls_state += SHR_BITALLOCSIZE(num_vc);
   3062     if (num_pw_term) {
   3063         SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   3064                           mpls_info->pw_term_bitmap, 0, num_pw_term);
   3065         mpls_state += SHR_BITALLOCSIZE(num_pw_term);
   3066     }
   3067     if (num_pw_init) {
   3068         SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   3069                           mpls_info->pw_init_bitmap, 0, num_pw_init);
   3070         mpls_state += SHR_BITALLOCSIZE(num_pw_init);
   3071     }
   3072     
   3073     SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   3074                       mpls_info->egr_mpls_bitmap, 0, num_mpls_map);
   3075     mpls_state += SHR_BITALLOCSIZE(num_mpls_map);
   3076     SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   3077                       mpls_info->ing_exp_map_bitmap, 0, num_ing_exp_map);
   3078     mpls_state += SHR_BITALLOCSIZE(num_ing_exp_map);
   3079     SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   3080                       mpls_info->egr_l2_exp_map_bitmap, 0, num_egr_l2_exp_map);
   3081     mpls_state += SHR_BITALLOCSIZE(num_egr_l2_exp_map);
   3082     SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   3083                       mpls_info->tnl_bitmap, 0,
   3084                       (num_ip_tnl * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)));
   3085     mpls_state += SHR_BITALLOCSIZE(num_ip_tnl *
   3086             _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit));
   3087     SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   3088                       mpls_info->ip_tnl_bitmap, 0, num_ip_tnl);
   3089     mpls_state += SHR_BITALLOCSIZE(num_ip_tnl);
   3090     mpls_state_marker = mpls_state;
   3091 
   3092     bitmask = 1 << ((8 * sizeof(uint32)) - 1);
   3093     for (i = 0; i < _BCM_TR_MPLS_HASH_ELEMENTS; i++) {
   3094         if (_bcm_tr_mpls_nhop_headPtr[unit][i] != NULL) {
   3095             for (nhop_ptr = _bcm_tr_mpls_nhop_headPtr[unit][i];
   3096                  nhop_ptr != NULL;
   3097                  nhop_ptr = nhop_ptr->link) {
   3098                 primary_nh_if = nhop_ptr->egr_if;
   3099                 primary_nh_if |= bitmask;
   3100                 sal_memcpy(mpls_state, &primary_nh_if, sizeof(uint32));
   3101                 mpls_state += sizeof(uint32);
   3102                 for (vp_ptr = nhop_ptr->vp_head_ptr;
   3103                      vp_ptr != NULL;
   3104                      vp_ptr = vp_ptr->link) {
   3105                     sal_memcpy(mpls_state, &(vp_ptr->vp_nh_idx), sizeof(uint32));
   3106                     mpls_state += sizeof(uint32);
   3107                 } /* for each vp on nh */
   3108             } /* for each nh */
   3109         }
   3110     }
   3111     vp_count = 0xdeadbeef;
   3112     sal_memcpy(mpls_state, &vp_count, sizeof(uint32));
   3113     mpls_state = mpls_state_marker + (sizeof(uint32) * num_nh);
   3114 
   3115     /* Sync the MPLS scache for the VPWS VP map */
   3116     if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_1) {
   3117         mpls_state += sizeof(int);
   3118         /* Copy VPWS map table to scache */
   3119         for (i=0; i<(num_vp/2); i++) {
   3120             sal_memcpy(mpls_state, &mpls_info->vpws_vp_map[i].vp1,
   3121                        sizeof(int));
   3122             mpls_state += sizeof(int);
   3123             sal_memcpy(mpls_state, &mpls_info->vpws_vp_map[i].vp2,
   3124                        sizeof(int));
   3125             mpls_state += sizeof(int);
   3126             sal_memcpy(mpls_state, &mpls_info->vpws_vp_map[i].vp3,
   3127                        sizeof(int));
   3128             mpls_state += sizeof(int);
   3129 
   3130             if ((BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_8) &&
   3131                 (soc_feature(unit, soc_feature_hierarchical_protection))) {
   3132                 sal_memcpy(mpls_state, &mpls_info->vpws_vp_map[i].vp_b_1,
   3133                        sizeof(int));
   3134                 mpls_state += sizeof(int);
   3135                 sal_memcpy(mpls_state, &mpls_info->vpws_vp_map[i].vp_b_2,
   3136                        sizeof(int));
   3137                 mpls_state += sizeof(int);
   3138                 sal_memcpy(mpls_state, &mpls_info->vpws_vp_map[i].vp_b_3,
   3139                        sizeof(int));
   3140                 mpls_state += sizeof(int);
   3141             }
   3142         }
   3143     }
   3144 
   3145     /* Sync the scache for the MPLS map */
   3146     if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_2) {
   3147         sal_memcpy(mpls_state, mpls_info->egr_mpls_hw_idx,
   3148                    (num_mpls_map * sizeof(uint32)));
   3149         mpls_state += (num_mpls_map * sizeof(uint32));
   3150     }
   3151 
   3152     /* Sync the scache for the MPLS svp profile set */
   3153     if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_5) {
   3154         SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   3155                           mpls_info->svp_profile_set_bitmap, 0, num_vp);
   3156         mpls_state += SHR_BITALLOCSIZE(num_vp);
   3157     }
   3158 
   3159     /* Sync the scache for the MPLS network VP bitmap */
   3160     if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_6) {
   3161         SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   3162                           mpls_info->network_vp_bitmap, 0, num_vp);
   3163         mpls_state += SHR_BITALLOCSIZE(num_vp);
   3164     }
   3165 #ifdef BCM_APACHE_SUPPORT
   3166     if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) {
   3167         /* Sync the scache for the MPLS EXP to PHB and CNG maps */
   3168         
   3169         SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   3170                 mpls_info->ing_exp_to_phb_cng_map_bitmap, 0, 
   3171                 num_ing_exp_to_phb_cng_map);
   3172         mpls_state += SHR_BITALLOCSIZE(num_ing_exp_to_phb_cng_map);
   3173         SHR_BITCOPY_RANGE((SHR_BITDCL *)mpls_state, 0,
   3174                 mpls_info->egr_exp_to_phb_cng_map_bitmap, 0, 
   3175                 num_egr_exp_to_phb_cng_map);
   3176         mpls_state += SHR_BITALLOCSIZE(num_egr_exp_to_phb_cng_map);
   3177     }
   3178 #endif
   3179 
   3180 #ifdef BCM_TRIUMPH2_SUPPORT
   3181     if (soc_feature(unit, soc_feature_mpls_failover)) {
   3182         if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_10) {
   3183             sal_memcpy(mpls_state, mpls_info->failover_vp, 
   3184                        (num_vp * sizeof(uint32)));
   3185             mpls_state += sizeof(uint32) * soc_mem_index_count(unit, SOURCE_VPm);
   3186         }
   3187     }
   3188 #endif /* BCM_TRIUMPH2_SUPPORT */
   3189 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   3190     if (soc_feature(unit, soc_feature_mpls_special_label)) {
   3191         int num_entry = 0;
   3192         bcmi_mpls_special_label_control_t *ptr;
   3193         /* Recover MPLS EXP to PHB and CNG maps */
   3194         if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_11) {
   3195 
   3196             ptr = bcmi_special_label_precedence_state[unit];
   3197             num_entry =
   3198                 soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm);
   3199             for (i = 0; i < num_entry; i++) {
   3200                 sal_memcpy(mpls_state, (&(ptr[i].ref_count)),
   3201                            sizeof(int));
   3202                 mpls_state += sizeof(int);
   3203                 sal_memcpy(mpls_state, (&(ptr[i].cancun_added)),
   3204                            sizeof(int));
   3205                 mpls_state += sizeof(int);
   3206             }
   3207         }
   3208     }
   3209 #endif
   3210 
   3211 #if defined(BCM_TRIDENT3_SUPPORT)
   3212     /* Sync VCSWAP Label action into scache*/
   3213     if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_12) {
   3214         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   3215             sal_memcpy(mpls_state, mpls_info->egr_vc_swap_lbl_action,
   3216                     num_vc * sizeof(int));
   3217             mpls_state += num_vc * sizeof(int);
   3218         }
   3219     }
   3220 #endif
   3221 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   3222     if (soc_feature(unit, soc_feature_mpls_special_label)) {
   3223         if (BCM_WB_DEFAULT_VERSION >= BCM_WB_VERSION_1_13) {
   3224             bcmi_mpls_special_label_egress_t *ptr;
   3225 
   3226             ptr = (&(bcmi_special_label_egress_state[unit]));
   3227             sal_memcpy(mpls_state, (&(ptr->special_label_ref_count)),
   3228                            sizeof(int));
   3229             mpls_state += sizeof(int);
   3230             sal_memcpy(mpls_state, (&(ptr->entropy_label_ref_count)),
   3231                            sizeof(int));
   3232             mpls_state += sizeof(int);
   3233 
   3234         }
   3235     }
   3236 #endif
   3237 
   3238     bcm_tr_mpls_unlock(unit);
   3239 
   3240     return rv;
   3241 }
   3242 
   3243 #endif
   3244 
   3245 int
   3246 _egr_qos_id2hw_idx (int unit,int qos_id,int *hw_inx)
   3247 {
   3248     int rv = BCM_E_NOT_FOUND;
   3249     int table_num;
   3250 
   3251     if (SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit)) {
   3252         rv = _bcm_tr_qos_id2idx(unit, qos_id, hw_inx);
   3253     } else {
   3254 #ifdef BCM_TRIUMPH2_SUPPORT
   3255         rv = _bcm_tr2_qos_id2idx(unit, qos_id, hw_inx);
   3256 #endif /* BCM_TRIUMPH2_SUPPORT */
   3257     }
   3258 
   3259     if (rv == BCM_E_NOT_FOUND) {
   3260         /* created from API bcm_mpls_exp_map_create() */
   3261         if ((qos_id & (~_BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK)) ==
   3262             _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS) {
   3263             table_num = qos_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK;
   3264             if (!_BCM_EGR_MPLS_MAP_USED_GET(unit, table_num)) {
   3265                 return BCM_E_PARAM;
   3266             }
   3267             *hw_inx = MPLS_INFO(unit)->egr_mpls_hw_idx[table_num];
   3268             rv = BCM_E_NONE;
   3269            } else if ((qos_id & (~_BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK)) ==
   3270             _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS_L2) {
   3271             table_num = qos_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK;
   3272             if (!_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, table_num)) {
   3273                 return BCM_E_PARAM;
   3274             } 
   3275             *hw_inx = table_num;
   3276             rv = BCM_E_NONE;
   3277           } else {
   3278             rv = BCM_E_NOT_FOUND;
   3279           } 
   3280     }
   3281     if (rv == BCM_E_NOT_FOUND) {
   3282         rv = BCM_E_PARAM;
   3283     }
   3284     return rv;
   3285 }
   3286 
   3287 #if !defined(_BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS) 
   3288 #define _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS      2
   3289 #endif
   3290 
   3291 int
   3292 _egr_qos_hw_idx2id (int unit, int hw_idx, int *map_id)
   3293 {
   3294     int rv = BCM_E_NOT_FOUND;
   3295     int num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
   3296     int id;
   3297 
   3298     if (SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit)) {
   3299         rv = _bcm_tr_qos_idx2id(unit, hw_idx, _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS, map_id);
   3300     } else {
   3301 #ifdef BCM_TRIUMPH2_SUPPORT
   3302         rv = _bcm_tr2_qos_idx2id(unit, hw_idx, _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS, map_id);
   3303 #endif /* BCM_TRIUMPH2_SUPPORT */
   3304     }
   3305 
   3306 
   3307     if (rv == BCM_E_NOT_FOUND) {
   3308         /* created from API bcm_mpls_exp_map_create() */
   3309 
   3310         for (id = 0; id < num_exp_map; id++) {
   3311             if (_BCM_EGR_MPLS_MAP_USED_GET(unit, id)) {
   3312                 if (MPLS_INFO(unit)->egr_mpls_hw_idx[id] == (uint32)hw_idx) {
   3313                     *map_id = id | _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS;
   3314                     rv = BCM_E_NONE;
   3315                     break;
   3316                 }
   3317             }
   3318         }
   3319     }
   3320 
   3321     if (rv == BCM_E_NOT_FOUND) {
   3322         for (id = 0; id < num_exp_map; id++) { 
   3323             if (_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, id)) { 
   3324                 if (id == hw_idx) { 
   3325                     *map_id = id | _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS_L2; 
   3326                     rv = BCM_E_NONE; 
   3327                     break; 
   3328                 } 
   3329             } 
   3330         } 
   3331     }  
   3332     if (rv == BCM_E_NOT_FOUND) {
   3333         if (hw_idx == 0) {
   3334             *map_id = 0;
   3335             return BCM_E_NONE;
   3336         }
   3337         rv = BCM_E_PARAM;
   3338     }
   3339     return rv;
   3340 }
   3341 #ifdef BCM_APACHE_SUPPORT
   3342 STATIC int bcm_apache_mpls_effective_phb_select_init(int unit)
   3343 {
   3344     int num_ing_phb_select_entries, num_egr_phb_select_entries, index;
   3345     effective_phb_select_entry_t ing_phb_select_entry;
   3346     egr_effective_phb_select_entry_t egr_phb_select_entry;
   3347    
   3348     num_ing_phb_select_entries = soc_mem_index_count(unit, 
   3349                                                      EFFECTIVE_PHB_SELECTm);
   3350     num_egr_phb_select_entries = soc_mem_index_count(unit, 
   3351                                                      EGR_EFFECTIVE_PHB_SELECTm);
   3352 
   3353     /*Use PHB for INNER label  in Ingress pipeline(Decapsulation) */
   3354     for (index = 0; index < num_ing_phb_select_entries; index++) {
   3355         BCM_IF_ERROR_RETURN(READ_EFFECTIVE_PHB_SELECTm(unit, MEM_BLOCK_ANY,
   3356                                                        index, 
   3357                                                        &ing_phb_select_entry));
   3358         if((index & 1) == 0) {
   3359             soc_EFFECTIVE_PHB_SELECTm_field32_set(unit, &ing_phb_select_entry,
   3360                     EFFECTIVE_PHB3_SELECTf, 
   3361                     _BCM_MPLS_FWD_LABEL3_PHB_FROM_TOS);
   3362         } else {
   3363             soc_EFFECTIVE_PHB_SELECTm_field32_set(unit, &ing_phb_select_entry,
   3364                     EFFECTIVE_PHB3_SELECTf, 
   3365                     _BCM_MPLS_FWD_LABEL2_PHB_FROM_TOS);
   3366         }
   3367         if((index & 2) == 0) {
   3368             soc_EFFECTIVE_PHB_SELECTm_field32_set(unit, &ing_phb_select_entry,
   3369                     EFFECTIVE_PHB2_SELECTf, 
   3370                     _BCM_MPLS_FWD_LABEL2_PHB_FROM_TOS);
   3371         } else {
   3372             soc_EFFECTIVE_PHB_SELECTm_field32_set(unit, &ing_phb_select_entry,
   3373                     EFFECTIVE_PHB2_SELECTf, 
   3374                     _BCM_MPLS_FWD_LABEL1_PHB_FROM_TOS);
   3375         }
   3376         /*Use PHB of label 1 both for pipe and uniform tunnels*/
   3377         soc_EFFECTIVE_PHB_SELECTm_field32_set(unit, &ing_phb_select_entry,
   3378                 EFFECTIVE_PHB1_SELECTf, 
   3379                 _BCM_MPLS_FWD_LABEL1_PHB_FROM_TOS);
   3380         
   3381         BCM_IF_ERROR_RETURN(WRITE_EFFECTIVE_PHB_SELECTm(unit, MEM_BLOCK_ALL,
   3382                                                         index, 
   3383                                                         &ing_phb_select_entry));
   3384     }
   3385 
   3386     /*Use PHB from INNER label in the Egress pipeline (Encapsulation)*/
   3387     for (index = 0; index < num_egr_phb_select_entries; index++) {
   3388         BCM_IF_ERROR_RETURN(READ_EGR_EFFECTIVE_PHB_SELECTm(unit, MEM_BLOCK_ANY,
   3389                                                        index, 
   3390                                                        &egr_phb_select_entry));
   3391         /*Use PHB of label 3 both for pipe and uniform tunnels*/
   3392         soc_EGR_EFFECTIVE_PHB_SELECTm_field32_set(unit, &egr_phb_select_entry,
   3393                 EFFECTIVE_PHB3_SELECTf, 
   3394                 _BCM_MPLS_FWD_LABEL3_PHB_FROM_TOS);
   3395         
   3396         if(((index & 0xc) >> 2) == 2) {
   3397             soc_EGR_EFFECTIVE_PHB_SELECTm_field32_set(unit, &egr_phb_select_entry,
   3398                     EFFECTIVE_PHB2_SELECTf, 
   3399                     _BCM_MPLS_FWD_LABEL2_PHB_FROM_TOS);
   3400         } else {
   3401             soc_EGR_EFFECTIVE_PHB_SELECTm_field32_set(unit, &egr_phb_select_entry,
   3402                     EFFECTIVE_PHB2_SELECTf, 
   3403                     _BCM_MPLS_FWD_LABEL3_PHB_FROM_TOS);
   3404         }
   3405         if(((index & 0x30) >> 4) == 2) {
   3406             soc_EGR_EFFECTIVE_PHB_SELECTm_field32_set(unit, &egr_phb_select_entry,
   3407                     EFFECTIVE_PHB1_SELECTf, 
   3408                     _BCM_MPLS_FWD_LABEL1_PHB_FROM_TOS);
   3409         } else {
   3410             soc_EGR_EFFECTIVE_PHB_SELECTm_field32_set(unit, &egr_phb_select_entry,
   3411                     EFFECTIVE_PHB1_SELECTf, 
   3412                     _BCM_MPLS_FWD_LABEL2_PHB_FROM_TOS);
   3413         }
   3414         BCM_IF_ERROR_RETURN(WRITE_EGR_EFFECTIVE_PHB_SELECTm(unit, MEM_BLOCK_ALL,
   3415                                                         index, 
   3416                                                         &egr_phb_select_entry));
   3417     }
   3418     return BCM_E_NONE;  
   3419 }
   3420 #endif
   3421 
   3422 #if defined(BCM_TRIDENT2_SUPPORT)
   3423 /*
   3424  * Function:
   3425  *      _bcm_tr_l3_ingress_interface_dma_init
   3426  * Purpose:
   3427  *      Perform L3_IIF Table Initialization using DMA Operation
   3428  * Parameters:
   3429  *      unit      : (IN) Device Unit Number
   3430  *      start_idx : (IN) Start index for Read/Write
   3431  *      end_idx : (IN) End index for Read/Write
   3432  * Returns:
   3433  *      BCM_E_XXX
   3434  *
   3435  * Note:
   3436  * Function to perform DMA Read / Write of L3_IIF during initialization
   3437  * and perform all init related operations without read / writes to H/W
   3438  */
   3439 int _bcm_tr_l3_ingress_interface_dma_init(int unit,
   3440                                           int start_idx,
   3441                                           int end_idx)
   3442 {
   3443     uint32 *l3iif_buf = NULL;
   3444     iif_entry_t *hw_entry = NULL;
   3445     iif_entry_t write_entry;
   3446     _bcm_l3_ingress_intf_t iif;
   3447     int idx, size, count;
   3448     int rv = BCM_E_INTERNAL;
   3449 
   3450     /* Determine size of buffer to be allocated.
   3451      * Ideally buffer allocation should be done in chunks in case chunk size
   3452      * is defined.
   3453      */
   3454     count = (end_idx - start_idx +1);
   3455     size = count * soc_mem_entry_words(unit, L3_IIFm) * 4;
   3456 
   3457     l3iif_buf = soc_cm_salloc(unit, size, "l3_iif_buffer");
   3458     if (l3iif_buf == NULL) {
   3459         return BCM_E_MEMORY;
   3460     }
   3461 
   3462     sal_memset((void *)l3iif_buf, 0, size);
   3463     /* Read L3_IIF Table */
   3464     rv = soc_mem_read_range(unit, L3_IIFm, MEM_BLOCK_ANY,
   3465                            start_idx, end_idx, l3iif_buf);
   3466     if (SOC_FAILURE(rv)) {
   3467         LOG_ERROR(BSL_LS_BCM_MPLS,
   3468                   (BSL_META_U(unit,
   3469                               "Mpls Init: DMA Read Failed for L3_IIF\n")));
   3470         soc_cm_sfree(unit, l3iif_buf);
   3471         return rv;
   3472     }
   3473 
   3474     /* Iterate over each entry to get and set the S/W structure */
   3475     for (idx = 0; idx < count; idx++) {
   3476         sal_memset(&iif, 0, sizeof(_bcm_l3_ingress_intf_t));
   3477         iif.intf_id = idx + start_idx;
   3478         iif.vrf = 0;
   3479         sal_memcpy(&write_entry,  soc_mem_entry_null(unit, L3_IIFm),
   3480                    sizeof(iif_entry_t));
   3481 
   3482         /* Read entry from buffer and pass it to interface function in order
   3483          * to avoid a PIO read */
   3484         hw_entry = soc_mem_table_idx_to_pointer(unit, L3_IIFm, iif_entry_t *,
   3485                                                l3iif_buf, idx);
   3486 
   3487         /* Populate iif structure to using a _get API , No PIO Reads performed*/
   3488         rv = _bcm_tr_l3_ingress_interface_get(unit, hw_entry, &iif);
   3489         if (BCM_FAILURE(rv)) {
   3490             LOG_ERROR(BSL_LS_BCM_MPLS,
   3491                 (BSL_META_U(unit,
   3492                     "Mpls Init: Ingress interface get failed for index=(%d)\n"),
   3493                     idx));
   3494             soc_cm_sfree(unit, l3iif_buf);
   3495             return rv;
   3496         }
   3497 
   3498         /* Get the new entry to be written to hw , pass the hw_entry as an argument
   3499          * to the function to avoid PIO read & write.
   3500          * Profile function is also updated to not read from H/W but use the hw_entry
   3501          * provided
   3502          */
   3503         rv = _bcm_tr_l3_ingress_interface_set(unit, &iif, hw_entry,
   3504                                                      &write_entry);
   3505         if (BCM_FAILURE(rv)) {
   3506             LOG_ERROR(BSL_LS_BCM_MPLS,
   3507                 (BSL_META_U(unit,
   3508                     "Mpls Init: Ingress interface set failed for index=(%d)\n"),
   3509                     idx));
   3510             soc_cm_sfree(unit, l3iif_buf);
   3511             return rv;
   3512         }
   3513 
   3514         /* Update the entry copy in the DMAed buffer with the new contents
   3515          * of write_entry modified by interface_set.
   3516          */
   3517         sal_memcpy(hw_entry, &write_entry, soc_mem_entry_words(unit, L3_IIFm) * 4);
   3518     }
   3519 
   3520     /* Write to H/W */
   3521     rv = soc_mem_write_range(unit, L3_IIFm, MEM_BLOCK_ALL,
   3522                              start_idx, end_idx, l3iif_buf);
   3523     soc_cm_sfree(unit, l3iif_buf);
   3524     return rv;
   3525 }
   3526 #endif
   3527 
   3528 /*
   3529  * Function:
   3530  *      bcm_mpls_init
   3531  * Purpose:
   3532  *      Initialize the MPLS software module
   3533  * Parameters:
   3534  *      unit     - Device Number
   3535  * Returns:
   3536  *      BCM_E_XXX
   3537  */
   3538 int
   3539 bcm_tr_mpls_init(int unit)
   3540 {
   3541     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   3542     bcm_tr_mpls_vc_swap_table_hash_t *vc_swap_hash;
   3543     int rv=0, i, num_vp = 0, num_vpws = 0, num_vc = 0, num_vrf, num_iif, num_trunk = 0;
   3544     int num_pw_term, num_pw_init, num_ip_tnl, num_mpls_map, num_ing_exp_map, num_egr_l2_exp_map, pkt_cfi, pkt_pri;
   3545 #ifdef BCM_APACHE_SUPPORT
   3546     int num_egr_mpls_exp_to_phb_cng_map = 0;
   3547     int num_ing_mpls_exp_to_phb_cng_map = 0;
   3548 #endif
   3549     soc_mem_t mem;
   3550     soc_field_t pri_field;
   3551     uint32 pri_map[SOC_MAX_MEM_FIELD_WORDS];
   3552     vfi_entry_t vfi_entry;
   3553     int num_vfi = 0;
   3554 
   3555     _bcm_l3_ingress_intf_t iif;
   3556     uint32 label;
   3557 #ifdef BCM_KATANA_SUPPORT
   3558     int num_ing_qmap = 0;
   3559 #endif /* BCM_KATANA_SUPPORT */
   3560 
   3561     if (!L3_INFO(unit)->l3_initialized) {
   3562         LOG_ERROR(BSL_LS_BCM_MPLS,
   3563                   (BSL_META_U(unit,
   3564                               "L3 module must be initialized prior to MPLS_init\n")));
   3565         return BCM_E_CONFIG;
   3566     }
   3567 
   3568     /* cache the EGR_MPLS_VC_AND_SWAP_LABEL_TABLE field info for fast performance in the
   3569      * table serarch function.
   3570      */
   3571     if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
   3572         SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit],
   3573                                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_LABELf);
   3574         SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit],
   3575                                  EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_LABEL_ACTIONf);
   3576         SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit],
   3577                                  EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_TTLf);
   3578         SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit],
   3579                                  EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, CW_INSERT_FLAGf);
   3580         SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit],
   3581                                  EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_EXPf);
   3582         SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit],
   3583                                  EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, NEW_PRIf);
   3584         SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit],
   3585                                  EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, NEW_CFIf);
   3586         SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit],
   3587                                  EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, SD_TAG_VIDf);
   3588         SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit],
   3589                     EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, SD_TAG_ACTION_IF_PRESENTf);
   3590         SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit],
   3591                     EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, SD_TAG_ACTION_IF_NOT_PRESENTf);
   3592         SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit],
   3593                     EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_EXP_SELECTf);
   3594         SOC_VC_SWAP_LABLE_FIELD_ASSIGN(unit, &soc_emvasltm_field_cache[unit],
   3595                     EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, MPLS_EXP_MAPPING_PTRf);
   3596     }
   3597     
   3598     /* 
   3599      * Include flex stat hooks when implemented
   3600      */
   3601     if (SOC_MEM_IS_VALID(unit, VFIm)) {
   3602         num_vfi = soc_mem_index_count(unit, VFIm);
   3603     }
   3604 
   3605     num_vrf = SOC_CONTROL(unit)->max_vrf_id + 1;
   3606     num_iif = soc_mem_index_count(unit, L3_IIFm);
   3607     if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) {
   3608         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   3609         num_vpws = num_vp / 2;
   3610     }
   3611     if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) {
   3612         num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
   3613     }
   3614 #if defined(BCM_TRIDENT3_SUPPORT)
   3615     if(soc_feature(unit, soc_feature_td3_style_mpls)) {
   3616         num_ip_tnl = soc_mem_index_count(unit,
   3617                 EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm);
   3618     } else
   3619 #endif
   3620     {
   3621     num_ip_tnl = soc_mem_index_count(unit, EGR_IP_TUNNEL_MPLSm);
   3622     }
   3623     if (SOC_MEM_IS_VALID(unit, TRUNK_GROUPm)) {
   3624         num_trunk = soc_mem_index_count(unit, TRUNK_GROUPm);
   3625     }
   3626 #ifdef BCM_KATANA_SUPPORT
   3627     if (soc_feature(unit, soc_feature_extended_queueing)) {
   3628         num_ing_qmap = soc_mem_index_count(unit, ING_QUEUE_MAPm);
   3629     }
   3630 #endif /* BCM_KATANA_SUPPORT */
   3631     /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */
   3632     num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
   3633     num_ing_exp_map = _bcm_tr_get_ing_mpls_index_size(unit);
   3634 #ifdef BCM_APACHE_SUPPORT
   3635     if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) {
   3636         num_egr_mpls_exp_to_phb_cng_map = soc_mem_index_count(unit, 
   3637                 EGR_MPLS_EXP_MAPPING_3m) / 8;
   3638         num_ing_mpls_exp_to_phb_cng_map = soc_mem_index_count(unit, 
   3639                 ING_MPLS_EXP_MAPPING_1m) / 16;
   3640     }
   3641 #endif
   3642 
   3643     num_egr_l2_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit);
   3644     num_pw_term = 0;
   3645     if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) {
   3646         num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm);
   3647     } else if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_SEQ_NUMm)) {
   3648         num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_SEQ_NUMm);
   3649     }
   3650     num_pw_init = 0;
   3651 #if defined(BCM_TRIDENT3_SUPPORT)
   3652     if(soc_feature(unit, soc_feature_td3_style_mpls)) {
   3653         mem = EGR_SEQUENCE_NUMBER_TABLEm; 
   3654     } else
   3655 #endif
   3656     {
   3657         mem = EGR_PW_INIT_COUNTERSm;
   3658     }
   3659     if (SOC_MEM_IS_VALID(unit, mem)) {
   3660         num_pw_init = soc_mem_index_count(unit, mem);
   3661     }
   3662 
   3663     /*
   3664      * allocate resources
   3665      */
   3666     if (mpls_info->initialized) {
   3667         /* coverity[stack_use_overflow : FALSE] */
   3668         rv = bcm_tr_mpls_cleanup(unit);
   3669         BCM_IF_ERROR_RETURN(rv);
   3670     }
   3671 
   3672     mpls_info->vrf_bitmap =
   3673         sal_alloc(SHR_BITALLOCSIZE(num_vrf), "vrf_bitmap");
   3674     if (mpls_info->vrf_bitmap == NULL) {
   3675         _bcm_tr_mpls_free_resource(unit, mpls_info);
   3676         return BCM_E_MEMORY;
   3677     }
   3678 
   3679     if (num_vpws) {
   3680         mpls_info->vpws_bitmap =
   3681             sal_alloc(SHR_BITALLOCSIZE(num_vpws), "vpws_bitmap");
   3682         if (mpls_info->vpws_bitmap == NULL) {
   3683             _bcm_tr_mpls_free_resource(unit, mpls_info);
   3684             return BCM_E_MEMORY;
   3685         }
   3686 
   3687         mpls_info->vpws_vp_map =
   3688             sal_alloc(sizeof(_bcm_mpls_vpws_vp_map_info_t) * (num_vpws), "vpws_vp_map");
   3689         if (mpls_info->vpws_vp_map == NULL) {
   3690             _bcm_tr_mpls_free_resource(unit, mpls_info);
   3691             return BCM_E_MEMORY;
   3692         }
   3693     } else {
   3694         mpls_info->vpws_bitmap = NULL;
   3695         mpls_info->vpws_vp_map = NULL;
   3696     }
   3697 
   3698     if (num_trunk) {
   3699         mpls_info->trunk_vp_map =
   3700             sal_alloc(sizeof(int) * (num_trunk), "trunk_vp_map");
   3701         if (mpls_info->trunk_vp_map == NULL) {
   3702             _bcm_tr_mpls_free_resource(unit, mpls_info);
   3703             return BCM_E_MEMORY;
   3704         }
   3705     } else {
   3706         mpls_info->trunk_vp_map = NULL;
   3707     }
   3708 
   3709     if (num_vp) {
   3710         mpls_info->match_key =
   3711             sal_alloc(sizeof(_bcm_tr_mpls_match_port_info_t) * num_vp, "match_key");
   3712         if (mpls_info->match_key == NULL) {
   3713             _bcm_tr_mpls_free_resource(unit, mpls_info);
   3714             return BCM_E_MEMORY;
   3715         }
   3716     } else {
   3717         mpls_info->match_key = NULL;
   3718     }
   3719 
   3720 
   3721     if (num_vc) {
   3722         mpls_info->vc_c_bitmap =
   3723             sal_alloc(SHR_BITALLOCSIZE(num_vc), "vc_c_bitmap"); 
   3724         if (mpls_info->vc_c_bitmap == NULL) {
   3725             _bcm_tr_mpls_free_resource(unit, mpls_info);
   3726             return BCM_E_MEMORY;
   3727         }
   3728 
   3729         mpls_info->vc_nc_bitmap =
   3730             sal_alloc(SHR_BITALLOCSIZE(num_vc), "vc_nc_bitmap"); 
   3731         if (mpls_info->vc_nc_bitmap == NULL) {
   3732             _bcm_tr_mpls_free_resource(unit, mpls_info);
   3733             return BCM_E_MEMORY;
   3734         }
   3735     } else {
   3736         mpls_info->vc_c_bitmap = NULL;
   3737         mpls_info->vc_nc_bitmap = NULL;
   3738     }
   3739 
   3740     if (num_pw_term) {
   3741        mpls_info->pw_term_bitmap =
   3742           sal_alloc(SHR_BITALLOCSIZE(num_pw_term), "pw_term_bitmap");
   3743        if (mpls_info->pw_term_bitmap == NULL) {
   3744            _bcm_tr_mpls_free_resource(unit, mpls_info);
   3745            return BCM_E_MEMORY;
   3746        }
   3747     }
   3748 
   3749     if(num_pw_init) {
   3750         mpls_info->pw_init_bitmap =
   3751             sal_alloc(SHR_BITALLOCSIZE(num_pw_init), "pw_init_bitmap");
   3752         if (mpls_info->pw_init_bitmap == NULL) {
   3753             _bcm_tr_mpls_free_resource(unit, mpls_info);
   3754             return BCM_E_MEMORY;
   3755         }
   3756     }
   3757 
   3758     mpls_info->egr_mpls_bitmap =
   3759         sal_alloc(SHR_BITALLOCSIZE(num_mpls_map), "egr_mpls_bitmap");
   3760     if (mpls_info->egr_mpls_bitmap == NULL) {
   3761         _bcm_tr_mpls_free_resource(unit, mpls_info);
   3762         return BCM_E_MEMORY;
   3763     }
   3764     mpls_info->egr_mpls_hw_idx = 
   3765         sal_alloc(sizeof(uint32) * num_mpls_map, "egr_mpls_hw_idx");
   3766     if (mpls_info->egr_mpls_hw_idx == NULL) {
   3767         _bcm_tr_mpls_free_resource(unit, mpls_info);
   3768         return BCM_E_MEMORY;
   3769     }    
   3770 
   3771     mpls_info->ing_exp_map_bitmap =
   3772         sal_alloc(SHR_BITALLOCSIZE(num_ing_exp_map), "ing_exp_map_bitmap");
   3773     if (mpls_info->ing_exp_map_bitmap == NULL) {
   3774         _bcm_tr_mpls_free_resource(unit, mpls_info);
   3775         return BCM_E_MEMORY;
   3776     }
   3777 
   3778     mpls_info->egr_l2_exp_map_bitmap =
   3779         sal_alloc(SHR_BITALLOCSIZE(num_egr_l2_exp_map), "egr_l2_exp_map_bitmap");
   3780     if (mpls_info->egr_l2_exp_map_bitmap == NULL) {
   3781         _bcm_tr_mpls_free_resource(unit, mpls_info);
   3782         return BCM_E_MEMORY;
   3783     }
   3784 #ifdef BCM_APACHE_SUPPORT
   3785     if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) {
   3786         mpls_info->ing_exp_to_phb_cng_map_bitmap =
   3787             sal_alloc(SHR_BITALLOCSIZE(num_ing_mpls_exp_to_phb_cng_map), 
   3788                     "ing_exp_to_phb_cng_map_bitmap");
   3789         if (mpls_info->ing_exp_to_phb_cng_map_bitmap == NULL) {
   3790             _bcm_tr_mpls_free_resource(unit, mpls_info);
   3791             return BCM_E_MEMORY;
   3792         }
   3793 
   3794         mpls_info->egr_exp_to_phb_cng_map_bitmap =
   3795             sal_alloc(SHR_BITALLOCSIZE(num_egr_mpls_exp_to_phb_cng_map), 
   3796                     "egr_exp_to_phb_cng_map_bitmap");
   3797         if (mpls_info->egr_exp_to_phb_cng_map_bitmap == NULL) {
   3798             _bcm_tr_mpls_free_resource(unit, mpls_info);
   3799             return BCM_E_MEMORY;
   3800         }
   3801     } 
   3802 #endif
   3803     /* 4 MPLS entries for each EGR_IP_TUNNEL_MPLS entry */
   3804     mpls_info->tnl_bitmap =
   3805         sal_alloc(SHR_BITALLOCSIZE(num_ip_tnl * 
   3806                     _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)),
   3807                 "tnl_bitmap");
   3808     if (mpls_info->tnl_bitmap == NULL) {
   3809         _bcm_tr_mpls_free_resource(unit, mpls_info);
   3810         return BCM_E_MEMORY;
   3811     }
   3812 
   3813     mpls_info->ip_tnl_bitmap =
   3814         sal_alloc(SHR_BITALLOCSIZE(num_ip_tnl), "ip_tnl_bitmap");
   3815     if (mpls_info->ip_tnl_bitmap == NULL) {
   3816         _bcm_tr_mpls_free_resource(unit, mpls_info);
   3817         return BCM_E_MEMORY;
   3818     }
   3819 
   3820     if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)
   3821        && (NULL == mpls_info->vc_swap_ref_count)) {
   3822          mpls_info->vc_swap_ref_count = sal_alloc(sizeof(uint16) *
   3823                                      num_vc, "vc_swap_refcount");
   3824          if (mpls_info->vc_swap_ref_count == NULL) {
   3825               _bcm_tr_mpls_free_resource(unit, mpls_info);
   3826               return BCM_E_MEMORY;
   3827          }
   3828         sal_memset(mpls_info->vc_swap_ref_count, 0, 
   3829                 sizeof(uint16) * num_vc);
   3830     }
   3831 
   3832     if (NULL == mpls_info->egr_tunnel_ref_count) {
   3833          mpls_info->egr_tunnel_ref_count = sal_alloc(sizeof(uint16) *
   3834                  (num_ip_tnl * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)), 
   3835                  "egr_tunnel_ref_count");
   3836          if (mpls_info->egr_tunnel_ref_count == NULL) {
   3837               _bcm_tr_mpls_free_resource(unit, mpls_info);
   3838               return BCM_E_MEMORY;
   3839          }
   3840          sal_memset(mpls_info->egr_tunnel_ref_count, 0, 
   3841                  sizeof(uint16) * (num_ip_tnl *
   3842                      _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)));
   3843     }
   3844 
   3845     if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) {
   3846         if (NULL == bcmi_vc_swap_label_hash[unit]) {
   3847             bcmi_vc_swap_label_hash[unit] = sal_alloc(
   3848                 BCM_TR_MPLS_VC_SWAP_HASH_BUCKETS *
   3849                 sizeof (bcm_tr_mpls_vc_swap_table_hash_t), "vc_swap_hash");
   3850 
   3851             if (bcmi_vc_swap_label_hash[unit] == NULL) {
   3852                 _bcm_tr_mpls_free_resource(unit, mpls_info);
   3853                 return SOC_E_MEMORY;
   3854             }
   3855 
   3856             for (i = 0; i < BCM_TR_MPLS_VC_SWAP_HASH_BUCKETS; i++) {
   3857                 vc_swap_hash = &(bcmi_vc_swap_label_hash[unit][i]);
   3858                 vc_swap_hash->head_link = NULL;
   3859             }
   3860         }
   3861 
   3862         mpls_info->svp_profile_set_bitmap =
   3863             sal_alloc(SHR_BITALLOCSIZE(num_vp), "svp_profile_set_bitmap");
   3864         if (mpls_info->svp_profile_set_bitmap == NULL) {
   3865             _bcm_tr_mpls_free_resource(unit, mpls_info);
   3866             return BCM_E_MEMORY;
   3867         }
   3868 
   3869         mpls_info->network_vp_bitmap =
   3870             sal_alloc(SHR_BITALLOCSIZE(num_vp), "network_vp_bitmap");
   3871         if (mpls_info->network_vp_bitmap == NULL) {
   3872             _bcm_tr_mpls_free_resource(unit, mpls_info);
   3873             return BCM_E_MEMORY;
   3874         }
   3875     }
   3876 
   3877 #ifdef BCM_KATANA_SUPPORT
   3878     if (soc_feature(unit, soc_feature_extended_queueing)) {
   3879         if (NULL == mpls_info->ing_qmap_ref_count) {
   3880              mpls_info->ing_qmap_ref_count = sal_alloc(sizeof(uint16) *
   3881                                          num_ing_qmap, "ing_qmap_ref_count");
   3882              if (mpls_info->ing_qmap_ref_count == NULL) {
   3883                   _bcm_tr_mpls_free_resource(unit, mpls_info);
   3884                   return BCM_E_MEMORY;
   3885              }
   3886             sal_memset(mpls_info->ing_qmap_ref_count, 0,
   3887                        sizeof(uint16) * num_ing_qmap);
   3888         }
   3889     }
   3890 #endif /* BCM_KATANA_SUPPORT */
   3891 #ifdef BCM_TRIUMPH2_SUPPORT
   3892     if (soc_feature(unit, soc_feature_mpls_failover)) {
   3893         mpls_info->failover_vp =
   3894             sal_alloc(num_vp * sizeof(uint32), "failover vp");
   3895         if (mpls_info->failover_vp == NULL) {
   3896             _bcm_tr_mpls_free_resource(unit, mpls_info);
   3897             return BCM_E_MEMORY;
   3898         }
   3899     }
   3900 #endif /* BCM_TRIUMPH2_SUPPORT */
   3901 
   3902 
   3903 #if defined(BCM_TRIDENT3_SUPPORT)
   3904     /*To store label actions of vc swap index*/
   3905     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   3906         mpls_info->egr_vc_swap_lbl_action =
   3907             sal_alloc((num_vc * sizeof(int)), "egr_vc_swap_lbl_action");
   3908         if (mpls_info->egr_vc_swap_lbl_action == NULL) {
   3909             _bcm_tr_mpls_free_resource(unit, mpls_info);
   3910             return BCM_E_MEMORY;
   3911         }
   3912     }
   3913 #endif
   3914 
   3915     sal_memset(mpls_info->vrf_bitmap, 0, SHR_BITALLOCSIZE(num_vrf));
   3916     sal_memset(mpls_info->vpws_bitmap, 0, SHR_BITALLOCSIZE(num_vpws));
   3917     sal_memset(mpls_info->vc_c_bitmap, 0, SHR_BITALLOCSIZE(num_vc));
   3918     sal_memset(mpls_info->vc_nc_bitmap, 0, SHR_BITALLOCSIZE(num_vc));
   3919     if (num_pw_term) {
   3920         sal_memset(mpls_info->pw_term_bitmap, 0, SHR_BITALLOCSIZE(num_pw_term));
   3921     }
   3922     sal_memset(mpls_info->pw_init_bitmap, 0, SHR_BITALLOCSIZE(num_pw_init));	
   3923     sal_memset(mpls_info->egr_mpls_bitmap, 0, SHR_BITALLOCSIZE(num_mpls_map));
   3924     sal_memset(mpls_info->egr_mpls_hw_idx, 0, (sizeof(uint32) * num_mpls_map));
   3925     sal_memset(mpls_info->ing_exp_map_bitmap, 0, SHR_BITALLOCSIZE(num_ing_exp_map));
   3926     sal_memset(mpls_info->egr_l2_exp_map_bitmap, 0, SHR_BITALLOCSIZE(num_egr_l2_exp_map));
   3927 #ifdef BCM_APACHE_SUPPORT
   3928     if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) {
   3929         sal_memset(mpls_info->ing_exp_to_phb_cng_map_bitmap, 0, 
   3930                 SHR_BITALLOCSIZE(num_ing_mpls_exp_to_phb_cng_map));
   3931         sal_memset(mpls_info->egr_exp_to_phb_cng_map_bitmap, 0, 
   3932                 SHR_BITALLOCSIZE(num_egr_mpls_exp_to_phb_cng_map));
   3933     }
   3934 #endif
   3935     sal_memset(mpls_info->match_key, 0, sizeof(_bcm_tr_mpls_match_port_info_t) * num_vp);
   3936     sal_memset(mpls_info->tnl_bitmap, 0,
   3937             SHR_BITALLOCSIZE(num_ip_tnl *
   3938                 _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)));
   3939     sal_memset(mpls_info->ip_tnl_bitmap, 0, SHR_BITALLOCSIZE(num_ip_tnl));
   3940     sal_memset(mpls_info->svp_profile_set_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
   3941 #if defined(BCM_TRIDENT3_SUPPORT)
   3942     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   3943         sal_memset(mpls_info->egr_vc_swap_lbl_action, 0,
   3944                 (num_vc * sizeof(int)));
   3945     }
   3946 #endif
   3947 #ifdef BCM_TRIUMPH2_SUPPORT
   3948     if (soc_feature(unit, soc_feature_mpls_failover)) {
   3949        sal_memset(mpls_info->failover_vp, 0, num_vp * sizeof(uint32));    
   3950     }
   3951 #endif /* BCM_TRIUMPH2_SUPPORT */
   3952 
   3953     if (!SOC_WARM_BOOT(unit)) {
   3954     /*
   3955      * Initialize the VFI table by setting L3MC_INDEX to 0 and
   3956      * PFM to 3. The PFM==3 (invalid) indicates that the VFI entry is not used.
   3957      * This can be used to recover SW state during warm reboot.
   3958      */
   3959 
   3960 #ifdef BCM_TRIUMPH2_SUPPORT
   3961     if (soc_feature(unit, soc_feature_mpls_enhanced)
   3962         && SOC_MEM_IS_VALID(unit, VFIm)) {
   3963         /* Initialize VFIm entries need to have:
   3964          * { BC_INDEX == 0,  UUC_INDEX == 0, UMC_INDEX == 0 } 
   3965          * Just same to clear it.
   3966          */
   3967         rv = soc_mem_clear(unit, VFIm, MEM_BLOCK_ANY, TRUE);
   3968         if (rv < 0) {
   3969             _bcm_tr_mpls_free_resource(unit, mpls_info);
   3970             return rv;
   3971         }
   3972     } else
   3973 #endif /* BCM_TRIUMPH2_SUPPORT */
   3974     {
   3975         if (soc_mem_field_valid(unit, VFIm, PFMf)) { 
   3976            sal_memset(&vfi_entry, 0, sizeof(vfi_entry_t));
   3977         
   3978            soc_VFIm_field32_set(unit, &vfi_entry, L3MC_INDEXf, 0);
   3979            soc_VFIm_field32_set(unit, &vfi_entry, PFMf, 3);
   3980            for (i = 0; i < num_vfi; i++) {
   3981                   rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, i, &vfi_entry);
   3982                   if (rv < 0) {
   3983                         _bcm_tr_mpls_free_resource(unit, mpls_info);
   3984                         return rv;
   3985                   }
   3986            }
   3987         }
   3988     }
   3989 
   3990     /* 
   3991      * Initialize L3_IIF entries starting from 
   3992      * _BCM_TR_MPLS_L3_IIF_BASE for each valid IIF value.
   3993      */
   3994 #if defined(BCM_TRIDENT2_SUPPORT)
   3995     if (soc_feature(unit, soc_feature_l3_iif_profile) &&
   3996         !soc_feature(unit, soc_feature_l3_iif_under_4k)) {
   3997         rv = _bcm_tr_l3_ingress_interface_dma_init(unit,
   3998                 _BCM_TR_MPLS_L3_IIF_BASE+1,
   3999                 soc_mem_index_max(unit, L3_IIFm));
   4000 
   4001         if (BCM_FAILURE(rv)) {
   4002             _bcm_tr_mpls_free_resource(unit, mpls_info);
   4003             return rv;
   4004         }
   4005     } else
   4006 #endif /* BCM_TRIDENT2_SUPPORT */
   4007     {
   4008         sal_memset(&iif, 0, sizeof(_bcm_l3_ingress_intf_t));
   4009         for (i = _BCM_TR_MPLS_L3_IIF_BASE+1; i < num_iif; i++) {
   4010             iif.intf_id = i;
   4011             iif.vrf = 0;
   4012 
   4013             rv = _bcm_tr_l3_ingress_interface_set(unit, &iif,
   4014                     NULL, NULL);
   4015             if (BCM_FAILURE(rv)) {
   4016                 _bcm_tr_mpls_free_resource(unit, mpls_info);
   4017                 return rv;
   4018             }
   4019         }
   4020     }
   4021 
   4022     /* 
   4023      * Reserve one mapping instance in ING_PRI_CNG_MAP for
   4024      * identity mapping of packet pri/cfi to internal pri/color.
   4025      */
   4026     sal_memset(pri_map, 0, (SOC_MAX_MEM_FIELD_WORDS) * 4);
   4027     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   4028         mem = PHB_MAPPING_TBL_1m;
   4029         pri_field = INT_PRIf;
   4030     } else {
   4031         mem = ING_PRI_CNG_MAPm;
   4032         pri_field = PRIf;
   4033     }
   4034 
   4035     for (pkt_cfi = 0; pkt_cfi <= 1; pkt_cfi++) {
   4036         for (pkt_pri = 0; pkt_pri <= 7; pkt_pri++) {
   4037             /* ING_PRI_CNG_MAP table is indexed with
   4038              * port[0:4] incoming priority[2:0] incoming CFI[0]
   4039              */
   4040             i = (_BCM_TR_MPLS_PRI_CNG_MAP_IDENTITY << 4) | (pkt_pri << 1) | pkt_cfi;
   4041             soc_mem_field32_set(unit, mem, pri_map, pri_field, 
   4042                                 pkt_pri);
   4043             soc_mem_field32_set(unit, mem, pri_map, CNGf,
   4044                                 pkt_cfi);
   4045             rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, i, pri_map);
   4046             if (rv < 0) {
   4047                 _bcm_tr_mpls_free_resource(unit, mpls_info);
   4048                 return rv;
   4049             }
   4050         }
   4051     }
   4052 
   4053     /* Clear L2 PW Counters */
   4054         rv = _bcm_tr_mpls_stat_clear(unit);
   4055         if (rv < 0) {
   4056             return rv;
   4057         }
   4058 
   4059     /* Initialize the entire label space "Port Independent"
   4060       * Use Switch Controls to re-configure the Label Space 
   4061       * for Port-Dependant and Port-Independant 
   4062       */
   4063  
   4064     label = 0;
   4065     rv = soc_reg_field32_modify(unit, GLOBAL_MPLS_RANGE_1_LOWERr,
   4066                                 REG_PORT_ANY, LABELf, label);
   4067     if (rv < 0) {
   4068         _bcm_tr_mpls_free_resource(unit, mpls_info);
   4069         return rv;
   4070     }
   4071     rv = soc_reg_field32_modify(unit, GLOBAL_MPLS_RANGE_2_LOWERr,
   4072                                 REG_PORT_ANY, LABELf, label);
   4073     if (rv < 0) {
   4074         _bcm_tr_mpls_free_resource(unit, mpls_info);
   4075         return rv;
   4076     }
   4077 
   4078     label = (1 << 20) - 1;
   4079     rv = soc_reg_field32_modify(unit, GLOBAL_MPLS_RANGE_1_UPPERr,
   4080                                 REG_PORT_ANY, LABELf, label);
   4081     if (rv < 0) {
   4082         _bcm_tr_mpls_free_resource(unit, mpls_info);
   4083         return rv;
   4084     }
   4085     rv = soc_reg_field32_modify(unit, GLOBAL_MPLS_RANGE_2_UPPERr,
   4086                                 REG_PORT_ANY, LABELf, label);
   4087     if (rv < 0) {
   4088         _bcm_tr_mpls_free_resource(unit, mpls_info);
   4089         return rv;
   4090     }
   4091 
   4092     /* Enable MPLS */
   4093     rv = bcm_tr_mpls_enable(unit, TRUE);
   4094     if (rv < 0) {
   4095         _bcm_tr_mpls_free_resource(unit, mpls_info);
   4096         return rv;
   4097     }
   4098 #ifdef BCM_APACHE_SUPPORT
   4099     if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) {
   4100         rv = bcm_apache_mpls_effective_phb_select_init(unit);
   4101         if (rv < 0) {
   4102             _bcm_tr_mpls_free_resource(unit, mpls_info);
   4103             return rv;
   4104         }
   4105     }
   4106 #endif
   4107     } /* !WARM_BOOT */
   4108 
   4109     /* Init Software State */
   4110     for (i=0; i < num_vp; i++) {
   4111          mpls_info->match_key[i].modid = -1;
   4112          mpls_info->match_key[i].trunk_id = -1;
   4113          mpls_info->match_key[i].fo_modid = -1;
   4114          mpls_info->match_key[i].fo_trunk_id = -1;
   4115          mpls_info->match_key[i].match_count = 0;
   4116          mpls_info->match_key[i].index = 0;
   4117     }
   4118 
   4119     for (i=0; i < num_vpws; i++) {
   4120          mpls_info->vpws_vp_map[i].vp1 = -1;
   4121          mpls_info->vpws_vp_map[i].vp2 = -1;
   4122          mpls_info->vpws_vp_map[i].vp3 = -1;
   4123 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT
   4124         if ((soc_feature(unit, soc_feature_hierarchical_protection))) {
   4125              mpls_info->vpws_vp_map[i].vp_b_1 = -1;
   4126              mpls_info->vpws_vp_map[i].vp_b_2 = -1;
   4127              mpls_info->vpws_vp_map[i].vp_b_3 = -1;
   4128         }
   4129 #endif
   4130     }
   4131     for (i = 0; i < num_trunk; i++) {
   4132          mpls_info->trunk_vp_map[i] = -1;
   4133     }
   4134     if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) {
   4135         /* Reserve  Default-VC_AND_SWAP_LABEL_TABLE entry */
   4136         rv = _bcm_tr_mpls_default_entry_setup(unit);
   4137         if (rv < 0) {
   4138             _bcm_tr_mpls_free_resource(unit, mpls_info);
   4139             return rv;
   4140         }
   4141     }
   4142 
   4143     /* Create MPLS protection mutex. */
   4144     MPLS_INFO((unit))->mpls_mutex = sal_mutex_create("mpls_mutex");
   4145     if (!MPLS_INFO((unit))->mpls_mutex) {
   4146         _bcm_tr_mpls_free_resource(unit, mpls_info);
   4147         return rv;
   4148     }
   4149 
   4150     for(i=0; i < _BCM_TR_MPLS_HASH_ELEMENTS; ++i) {
   4151         _bcm_tr_mpls_nhop_headPtr[unit][i] = NULL;
   4152     }
   4153 
   4154 #if defined(BCM_APACHE_SUPPORT) || defined(BCM_TOMAHAWK2_SUPPORT) \
   4155     || defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
   4156     if (soc_feature(unit, soc_feature_egr_ip_tnl_mpls_double_wide) ||
   4157         (soc_feature(unit, soc_feature_th3_style_simple_mpls))) {
   4158         rv = bcmi_egr_ip_tunnel_mpls_sw_init(unit);
   4159         if (rv != BCM_E_NONE) {
   4160             _bcm_tr_mpls_free_resource(unit, mpls_info);
   4161         }
   4162     }
   4163 #endif
   4164 
   4165 #if defined(BCM_SPECIAL_LABEL_SUPPORT)
   4166     if (soc_feature(unit, soc_feature_mpls_special_label)) {
   4167         rv = bcmi_mpls_special_label_init(unit);
   4168         if (rv != BCM_E_NONE) {
   4169             _bcm_tr_mpls_free_resource(unit, mpls_info);
   4170         }
   4171     }
   4172 #endif
   4173 
   4174 
   4175 #if defined(BCM_TRIDENT3_SUPPORT)
   4176     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   4177         if (!SOC_WARM_BOOT(unit)) {
   4178             rv = soc_reg_field32_modify(unit, RTAG7_HASH_CONTROLr,
   4179                     REG_PORT_ANY, USE_MPLS_STACK_FOR_HASHINGf, 0);
   4180 
   4181             if (rv != BCM_E_NONE) {
   4182                 _bcm_tr_mpls_free_resource(unit, mpls_info);
   4183             }
   4184         }
   4185     }
   4186 #endif
   4187 
   4188 #ifdef BCM_WARM_BOOT_SUPPORT
   4189     rv = _bcm_tr_mpls_reinit(unit);
   4190     if (rv != BCM_E_NONE) {
   4191         _bcm_tr_mpls_free_resource(unit, mpls_info);
   4192     }
   4193 #endif /* BCM_WARM_BOOT_SUPPORT */
   4194 
   4195     /* Mark the state as initialized */
   4196     mpls_info->initialized = TRUE;
   4197 
   4198     return rv;
   4199 }
   4200 
   4201 #ifdef BCM_APACHE_SUPPORT
   4202 /*
   4203  * Function:
   4204  *      bcm_tr_mpls_exp_to_phb_cng_map_destroy_all
   4205  * Purpose:
   4206  *      Destroy all existing MPLS EXP to PBH and CNG map instances.
   4207  * Parameters:
   4208  *      unit       - (IN) SOC unit #
   4209  * Returns:
   4210  *      BCM_E_XXX
   4211  */
   4212 STATIC int
   4213 bcm_tr_mpls_exp_to_phb_cng_map_destroy_all(int unit)
   4214 {
   4215     int i, num_exp_map;
   4216 
   4217     /* ING_MPLS_EXP_MAPPING_1 profiles indexed by EXP */
   4218     num_exp_map = soc_mem_index_count(unit, ING_MPLS_EXP_MAPPING_1m) / 16;
   4219     for (i = 0; i < num_exp_map; i++) {
   4220         if (_BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_GET(unit, i)) {
   4221             _BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_CLR(unit, i);
   4222         }
   4223     }
   4224 
   4225     /* EGR_MPLS_EXP_MAPPING_3m profiles indexed by EXP */
   4226     num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_3m) / 8;
   4227     for (i = 0; i < num_exp_map; i++) {
   4228         if (_BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_GET(unit, i)) {
   4229             _BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_CLR(unit, i);
   4230         }
   4231     }
   4232 
   4233     return BCM_E_NONE;
   4234 }
   4235 #endif
   4236 /*
   4237  * Function:
   4238  *      _bcm_tr_mpls_hw_clear
   4239  * Purpose:
   4240  *     Perform hw tables clean up for mpls module. 
   4241  * Parameters:
   4242  *      unit     - Device Number
   4243  * Returns:
   4244  *      BCM_E_XXX
   4245  */
   4246 STATIC int
   4247 _bcm_tr_mpls_hw_clear(int unit)
   4248 {
   4249     int rv=BCM_E_NONE, rv_error = BCM_E_NONE;
   4250 
   4251     rv = bcm_tr_mpls_enable(unit, FALSE);
   4252     if (BCM_FAILURE(rv)) {
   4253         rv_error = rv;
   4254     }
   4255 
   4256     /* Clear L2 PW Counters */
   4257     rv = _bcm_tr_mpls_stat_clear(unit);
   4258     if (rv<0) {
   4259        rv_error = rv;
   4260     }
   4261 
   4262     if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
   4263         /* Destroy all VPNs */
   4264         rv = bcm_tr_mpls_vpn_id_destroy_all(unit);
   4265         if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) {
   4266             rv_error = rv;
   4267         }
   4268     }
   4269 
   4270     /* Delete all L2 tunnel entries */
   4271     rv = bcm_esw_l2_tunnel_delete_all(unit);
   4272     if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) {
   4273         rv_error = rv;
   4274     }
   4275 
   4276     /* Clear all MPLS tunnel initiators */
   4277     rv = bcm_esw_mpls_tunnel_initiator_clear_all(unit);
   4278     if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) {
   4279         rv_error = rv;
   4280     }
   4281 
   4282     /* Delete all MPLS switch entries */
   4283     rv = _bcm_esw_mpls_tunnel_switch_delete_all(unit);
   4284     if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) {
   4285         rv_error = rv;
   4286     }
   4287 
   4288     /* Destroy all EXP maps */
   4289     rv = bcm_tr_mpls_exp_map_destroy_all(unit);
   4290     if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) {
   4291         rv_error = rv;
   4292     }
   4293 
   4294 #ifdef BCM_APACHE_SUPPORT
   4295     if (soc_feature(unit, soc_feature_mpls_exp_to_phb_cng_map)) {
   4296         rv = bcm_tr_mpls_exp_to_phb_cng_map_destroy_all(unit);
   4297         if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) {
   4298             rv_error = rv;
   4299         }
   4300     }
   4301 #endif
   4302     return rv_error;
   4303 }
   4304 
   4305 /*
   4306  * Function:
   4307  *      bcm_mpls_cleanup
   4308  * Purpose:
   4309  *      Detach the MPLS software module
   4310  * Parameters:
   4311  *      unit     - Device Number
   4312  * Returns:
   4313  *      BCM_E_XXX
   4314  */
   4315 int
   4316 bcm_tr_mpls_cleanup(int unit)
   4317 {
   4318     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   4319     int rv=BCM_E_NONE;
   4320 
   4321     if (FALSE == mpls_info->initialized) {
   4322         return (BCM_E_NONE);
   4323     } 
   4324 
   4325     rv = bcm_tr_mpls_lock (unit);
   4326     if (BCM_FAILURE(rv)) {
   4327         return rv;
   4328     }
   4329 
   4330     if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 
   4331         rv = _bcm_tr_mpls_hw_clear(unit);
   4332     }
   4333 
   4334     /* Free software resources */
   4335     (void) _bcm_tr_mpls_free_resource(unit, mpls_info);
   4336 
   4337     bcm_tr_mpls_unlock (unit);
   4338 
   4339     /* Destroy MPLS protection mutex. */
   4340     sal_mutex_destroy(MPLS_INFO((unit))->mpls_mutex );
   4341 
   4342     /* Mark the state as uninitialized */
   4343     mpls_info->initialized = FALSE;
   4344 
   4345     return rv;
   4346 }
   4347 
   4348 /*
   4349  * Function:
   4350  *      _bcm_tr_vpws_vpn_alloc
   4351  * Purpose:
   4352  *      Internal function for allocating a VPWS Vpn_id
   4353  * Parameters:
   4354  *      unit    -  (IN) Device number.
   4355  *      vpn_id     -  (OUT) VPWS Vpn_id
   4356  * Returns:
   4357  *      BCM_X_XXX
   4358  */
   4359 
   4360 int
   4361 _bcm_tr_vpws_vpn_alloc(int unit, bcm_vpn_t  *vpn_id)
   4362 {
   4363     int i, num_vpws;
   4364 
   4365     num_vpws = soc_mem_index_count(unit, SOURCE_VPm) / 2;
   4366 
   4367     for (i = 0; i < num_vpws; i++) {
   4368         if (!_BCM_MPLS_VPWS_USED_GET(unit, i)) {
   4369             break;
   4370         }
   4371     }
   4372     if (i == num_vpws) {
   4373         return BCM_E_RESOURCE;
   4374     }
   4375 
   4376     *vpn_id = i;
   4377     _BCM_MPLS_VPWS_USED_SET(unit, *vpn_id);
   4378 
   4379     return BCM_E_NONE;
   4380 }
   4381 
   4382 
   4383 /*
   4384  * Function:
   4385  *      bcm_mpls_vpn_id_create
   4386  * Purpose:
   4387  *      Create a VPN instance
   4388  * Parameters:
   4389  *      unit  - (IN)  Device Number
   4390  *      info  - (IN/OUT) VPN configuration info
   4391  * Returns:
   4392  *      BCM_E_XXX
   4393  * Note:
   4394  *      No hardware action
   4395  */
   4396 int
   4397 bcm_tr_mpls_vpn_id_create(int unit, bcm_mpls_vpn_config_t *info)
   4398 {
   4399     int rv = BCM_E_PARAM;
   4400     bcm_vpn_t  vpn_id;
   4401     int proto_pkt_inx;
   4402     int num_vpws;
   4403 #if defined(BCM_TRIDENT3_SUPPORT)
   4404     uint32 vfi_profile_idx=0;
   4405 #endif
   4406 
   4407     if (info->flags & BCM_MPLS_VPN_REPLACE) {
   4408         if (!(info->flags & BCM_MPLS_VPN_WITH_ID)) {
   4409             return BCM_E_PARAM;
   4410         }
   4411     }
   4412 
   4413     if (info->flags & BCM_MPLS_VPN_VPWS) {
   4414         if (info->flags & BCM_MPLS_VPN_WITH_ID) {
   4415             if (!_BCM_MPLS_VPN_IS_VPWS(info->vpn)) {
   4416                 return BCM_E_PARAM;
   4417             }          
   4418             _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, info->vpn);
   4419             num_vpws = soc_mem_index_count(unit, SOURCE_VPm) / 2;
   4420             if (vpn_id >= num_vpws) {
   4421                 return BCM_E_PARAM;
   4422             } else if (_BCM_MPLS_VPWS_USED_GET(unit, vpn_id)) {
   4423                 /* Already used */
   4424                 return BCM_E_EXISTS;
   4425             }
   4426             _BCM_MPLS_VPWS_USED_SET(unit, vpn_id);
   4427             rv = BCM_E_NONE;
   4428         } else {
   4429            /* Get vpn_id */
   4430            rv = _bcm_tr_vpws_vpn_alloc(unit, &vpn_id);
   4431            if (BCM_SUCCESS(rv)) {
   4432                  _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_VPWS, vpn_id);
   4433            }
   4434         }
   4435     } else if (info->flags & BCM_MPLS_VPN_VPLS) {
   4436         vfi_entry_t vfi_entry;
   4437         int vfi_index, mc_group=0, mc_group_type, num_vfi;
   4438         bcm_vpn_t vpls_vpn_min=0;
   4439 
   4440         bcm_vlan_mcast_flood_t mode;
   4441 #if defined(BCM_TRIUMPH2_SUPPORT)
   4442         int bc_group=0, umc_group=0, uuc_group=0;
   4443         int bc_group_type, umc_group_type, uuc_group_type;
   4444 #endif /* BCM_TRIUMPH2_SUPPORT  */
   4445 
   4446         num_vfi = soc_mem_index_count(unit, VFIm);
   4447 #ifdef BCM_TRIUMPH2_SUPPORT
   4448         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   4449             /* Check that the groups are valid. */
   4450             bc_group_type = _BCM_MULTICAST_TYPE_GET(info->broadcast_group);
   4451             bc_group = _BCM_MULTICAST_ID_GET(info->broadcast_group);
   4452             umc_group_type = _BCM_MULTICAST_TYPE_GET(info->unknown_multicast_group);
   4453             umc_group = _BCM_MULTICAST_ID_GET(info->unknown_multicast_group);
   4454             uuc_group_type = _BCM_MULTICAST_TYPE_GET(info->unknown_unicast_group);
   4455             uuc_group = _BCM_MULTICAST_ID_GET(info->unknown_unicast_group);
   4456 
   4457             if ((bc_group_type != _BCM_MULTICAST_TYPE_VPLS) ||
   4458                 (umc_group_type != _BCM_MULTICAST_TYPE_VPLS) ||
   4459                 (uuc_group_type != _BCM_MULTICAST_TYPE_VPLS) ||
   4460                 (bc_group >= soc_mem_index_count(unit, L3_IPMCm)) ||
   4461                 (umc_group >= soc_mem_index_count(unit, L3_IPMCm)) ||
   4462                 (uuc_group >= soc_mem_index_count(unit, L3_IPMCm))) {
   4463                 return BCM_E_PARAM;
   4464             }
   4465         } else
   4466 #endif
   4467         {
   4468             /* Check that the broadcast group is valid. Also check that
   4469              * broadcast, unknown_unicast, and unknown_multicast groups
   4470              * are the same (this device only supports on multicast group
   4471              * for all 3 types of multicast traffic.
   4472              */
   4473 
   4474             mc_group_type = _BCM_MULTICAST_TYPE_GET(info->broadcast_group);
   4475             mc_group = _BCM_MULTICAST_ID_GET(info->broadcast_group);
   4476 
   4477             if ((mc_group_type != _BCM_MULTICAST_TYPE_VPLS) ||
   4478                 (mc_group >= soc_mem_index_count(unit, L3_IPMCm)) ||
   4479                 (info->broadcast_group != info->unknown_unicast_group) ||
   4480                 (info->broadcast_group != info->unknown_multicast_group)) {
   4481                 return BCM_E_PARAM;
   4482             }
   4483         }
   4484 
   4485         /* validate parameter protocol_pkt */
   4486         if (SOC_MEM_FIELD_VALID(unit, VFIm, PROTOCOL_PKT_INDEXf)) {
   4487             rv = _bcm_xgs3_protocol_packet_actions_validate(unit,
   4488                                    &info->protocol_pkt);
   4489             if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) {
   4490                 return rv;
   4491             }
   4492         }
   4493 
   4494         /* Allocate a VFI */
   4495         /* Lock the VFI table while allocating and writing to allow
   4496          * proper operation with the service counters */
   4497         soc_mem_lock(unit, VFIm);
   4498         if (info->flags & BCM_MPLS_VPN_WITH_ID) {
   4499             _BCM_MPLS_VPN_SET(vpls_vpn_min, _BCM_MPLS_VPN_TYPE_VPLS, 0);
   4500             if ( info->vpn < vpls_vpn_min || info->vpn > (vpls_vpn_min+num_vfi-1) ) {
   4501                 soc_mem_unlock(unit, VFIm);
   4502                 return BCM_E_PARAM;
   4503             }
   4504 
   4505             _BCM_MPLS_VPN_GET(vfi_index, _BCM_MPLS_VPN_TYPE_VPLS, info->vpn);
   4506 
   4507             if (_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeMpls)) {
   4508                 if (!(info->flags & BCM_MPLS_VPN_REPLACE)) {
   4509                     soc_mem_unlock(unit, VFIm);
   4510                     return BCM_E_EXISTS;
   4511                 }
   4512             } else {
   4513                 rv = _bcm_vfi_alloc_with_id(unit, VFIm, _bcmVfiTypeMpls, vfi_index);
   4514                 if (rv < 0) {
   4515                     soc_mem_unlock(unit, VFIm);
   4516                     return rv;
   4517                 }
   4518             }
   4519         } else {
   4520             rv = _bcm_vfi_alloc(unit, VFIm, _bcmVfiTypeMpls, &vfi_index);
   4521             if (rv < 0) {
   4522                 soc_mem_unlock(unit, VFIm);
   4523                 return rv;
   4524             }
   4525 
   4526         }
   4527 
   4528         /* Get the default flood mode */
   4529         BCM_IF_ERROR_RETURN(_bcm_esw_vlan_flood_default_get(unit, &mode));
   4530         switch (mode) {
   4531         case BCM_VLAN_MCAST_FLOOD_ALL:
   4532             mode = 0;
   4533             break;
   4534         case BCM_VLAN_MCAST_FLOOD_NONE:
   4535             mode = 2;
   4536             break;
   4537         default:
   4538             mode = 1;
   4539             break;
   4540         }
   4541 
   4542         /* Commit the entry to HW */
   4543         BCM_IF_ERROR_RETURN(READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
   4544         if (info->flags & BCM_MPLS_VPN_REPLACE) {
   4545             rv = READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry);
   4546             if (BCM_FAILURE(rv)) {
   4547                 soc_mem_unlock(unit, VFIm);
   4548                 return rv;
   4549             }
   4550         }
   4551 #ifdef BCM_TRIUMPH2_SUPPORT
   4552         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   4553             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   4554                 soc_mem_field32_dest_set(unit, VFIm, &vfi_entry,
   4555                         UMC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, umc_group);
   4556                 soc_mem_field32_dest_set(unit, VFIm, &vfi_entry,
   4557                         UUC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, uuc_group);
   4558                 soc_mem_field32_dest_set(unit, VFIm, &vfi_entry,
   4559                         BC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, bc_group);
   4560 
   4561 #if defined(BCM_TRIDENT3_SUPPORT)
   4562                 /*VFI_PROFILE setting as per CMH rules*/
   4563                 bcmi_cmh_vfi_profile_set(unit, &vfi_profile_idx);
   4564                 if(vfi_profile_idx != 0) {
   4565                     soc_VFIm_field32_set(unit, &vfi_entry,
   4566                             VFI_PROFILE_PTRf, vfi_profile_idx);
   4567                 }
   4568 #endif
   4569             } else {
   4570             soc_VFIm_field32_set(unit, &vfi_entry, UMC_INDEXf, umc_group);
   4571             soc_VFIm_field32_set(unit, &vfi_entry, UUC_INDEXf, uuc_group);
   4572             soc_VFIm_field32_set(unit, &vfi_entry, BC_INDEXf, bc_group);
   4573             }
   4574         } else
   4575 #endif
   4576         {
   4577             soc_VFIm_field32_set(unit, &vfi_entry, L3MC_INDEXf, mc_group);
   4578             soc_VFIm_field32_set(unit, &vfi_entry, PFMf, mode);
   4579         }
   4580 
   4581 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
   4582                                                 defined(BCM_APACHE_SUPPORT)
   4583         if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit)) {
   4584             rv = _bcm_esw_add_policer_to_table(unit, info->policer_id, VFIm,
   4585                                                     0, &vfi_entry);
   4586             if (rv < 0) {
   4587                 soc_mem_unlock(unit, VFIm);
   4588                 return rv;
   4589             }
   4590         }
   4591 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_APACHE_SUPPORT */
   4592 
   4593         if (SOC_MEM_FIELD_VALID (unit,VFIm, PROTOCOL_PKT_INDEXf)) {
   4594             if (info->flags & BCM_MPLS_VPN_REPLACE) {
   4595                 proto_pkt_inx = soc_VFIm_field32_get(unit, &vfi_entry, 
   4596                                     PROTOCOL_PKT_INDEXf);
   4597             } else {
   4598                 proto_pkt_inx = -1;
   4599             }
   4600             rv = _bcm_xgs3_protocol_pkt_ctrl_set(unit,proto_pkt_inx,
   4601                                     &info->protocol_pkt,
   4602                                     &proto_pkt_inx);
   4603             if (BCM_SUCCESS(rv)) { 
   4604                 soc_VFIm_field32_set(unit, &vfi_entry, PROTOCOL_PKT_INDEXf, 
   4605                                  proto_pkt_inx);
   4606             } else if (rv != BCM_E_UNAVAIL) {
   4607                 soc_mem_unlock(unit, VFIm);
   4608                 return rv;
   4609             }
   4610         }
   4611         rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry);
   4612         if (rv < 0) {
   4613             (void) _bcm_vfi_free(unit, _bcmVfiTypeMpls, vfi_index);
   4614             soc_mem_unlock(unit, VFIm);
   4615             return rv;
   4616         }
   4617         soc_mem_unlock(unit, VFIm);
   4618 
   4619         /* Set the returned VPN id */
   4620         _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_VPLS, vfi_index);
   4621 
   4622     } else if (info->flags & BCM_MPLS_VPN_L3) {
   4623         int vrf;
   4624         uint16 vrf_vpn_min;
   4625 
   4626         /* 
   4627          * The caller manages VRF space. An MPLS L3 VPN identifier
   4628          * is simply the VRF value passed in by the caller (info->lookup_id)
   4629          * added to a base offset. The VPN ID returned here can 
   4630          * be used in the bcm_mpls_tunnel_switch_* APIs. 
   4631          */
   4632         if (info->flags & BCM_MPLS_VPN_WITH_ID) {
   4633             _BCM_MPLS_VPN_SET(vrf_vpn_min, _BCM_MPLS_VPN_TYPE_L3, 0);
   4634 
   4635             if ( info->vpn < vrf_vpn_min || info->vpn > (vrf_vpn_min +SOC_VRF_MAX(unit)) ) {
   4636                 return BCM_E_PARAM;
   4637             }
   4638 
   4639             _BCM_MPLS_VPN_GET(vrf, _BCM_MPLS_VPN_TYPE_L3, info->vpn);
   4640         } else {
   4641             vrf = info->lookup_id;
   4642         }
   4643 
   4644         if ((vrf < 0) || (vrf > SOC_VRF_MAX(unit))) {
   4645             return BCM_E_PARAM;
   4646         }
   4647         if (_BCM_MPLS_VRF_USED_GET(unit, vrf)) {
   4648             if (info->flags & BCM_MPLS_VPN_REPLACE) {
   4649                 return BCM_E_CONFIG;
   4650             }
   4651             return BCM_E_EXISTS;
   4652         }
   4653         _BCM_MPLS_VRF_USED_SET(unit, vrf);
   4654         _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_L3, vrf);
   4655         rv = BCM_E_NONE;
   4656     }
   4657 
   4658 #ifdef BCM_WARM_BOOT_SUPPORT
   4659     SOC_CONTROL_LOCK(unit);
   4660     SOC_CONTROL(unit)->scache_dirty = 1;
   4661     SOC_CONTROL_UNLOCK(unit);
   4662 #endif
   4663 
   4664     return rv;
   4665 }
   4666 
   4667 /*
   4668  * Function:
   4669  *      bcm_tr_mpls_vpn_id_get
   4670  * Purpose:
   4671  *      Get VPN instance
   4672  * Parameters:
   4673  *      unit  - (IN)  Device Number
   4674  *      vpn -  (IN)  VPN instance ID
   4675  *      info  - (OUT) VPN configuration info
   4676  * Returns:
   4677  *      BCM_E_XXX
   4678  * Note:
   4679  *      No hardware action
   4680  */
   4681 
   4682 int
   4683 bcm_tr_mpls_vpn_id_get(int unit,
   4684                        bcm_vpn_t vpn,
   4685                        bcm_mpls_vpn_config_t *info)
   4686 {
   4687     int proto_pkt_inx;
   4688     int rv;
   4689 
   4690     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
   4691         if ((_BCM_MPLS_VPN_IS_VPWS(vpn)) || (_BCM_MPLS_VPN_IS_VPLS(vpn))) {
   4692             return BCM_E_PARAM;
   4693         }
   4694     }
   4695 
   4696     if (_BCM_MPLS_VPN_IS_VPWS(vpn)) {
   4697         bcm_vpn_t vpws_vpn_id;
   4698         int num_vpws;
   4699 
   4700         num_vpws = soc_mem_index_count(unit, SOURCE_VPm) / 2;
   4701 
   4702         /*
   4703          * validate the vpn id, must be in the range 0 to
   4704          * (number of SOURCE_VP entries / 2)
   4705          */
   4706         _BCM_MPLS_VPN_GET(vpws_vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn);
   4707 
   4708         if (vpws_vpn_id >= num_vpws) {
   4709             return BCM_E_PARAM;
   4710         }
   4711 
   4712         if (!_BCM_MPLS_VPWS_USED_GET(unit, vpws_vpn_id)) {
   4713             return BCM_E_NOT_FOUND;
   4714         }
   4715 
   4716         /* Set the VPN id value returned to caller */
   4717         _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_VPWS, vpws_vpn_id);
   4718         info->flags |=  BCM_MPLS_VPN_VPWS;
   4719 
   4720     } else if (_BCM_MPLS_VPN_IS_VPLS(vpn)) {
   4721         int vfi_index, num_vfi;
   4722         bcm_vpn_t vpls_vpn_min=0;
   4723         vfi_entry_t vfi_entry;
   4724 
   4725         num_vfi = soc_mem_index_count(unit, VFIm);
   4726 
   4727         _BCM_MPLS_VPN_SET(vpls_vpn_min, _BCM_MPLS_VPN_TYPE_VPLS, 0);
   4728         if ( vpn < vpls_vpn_min || vpn > (vpls_vpn_min+num_vfi-1) ) {
   4729             return BCM_E_PARAM;
   4730         }
   4731 
   4732         _BCM_MPLS_VPN_GET(vfi_index, _BCM_MPLS_VPN_TYPE_VPLS, vpn);
   4733 
   4734         if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeMpls)) {
   4735             return BCM_E_NOT_FOUND;
   4736         }
   4737 
   4738         BCM_IF_ERROR_RETURN
   4739             (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
   4740 #ifdef BCM_TRIUMPH2_SUPPORT
   4741         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   4742             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   4743                 uint32 dt, dv;
   4744 
   4745                 dv = soc_mem_field32_dest_get(unit, VFIm,
   4746                         &vfi_entry, BC_DESTINATIONf, &dt);
   4747                 if (dt == SOC_MEM_FIF_DEST_IPMC) {
   4748                     _BCM_MULTICAST_GROUP_SET(info->broadcast_group,
   4749                             _BCM_MULTICAST_TYPE_VPLS, dv);
   4750                 } else {
   4751                     return BCM_E_INTERNAL;
   4752                 }
   4753 
   4754                 dv = soc_mem_field32_dest_get(unit, VFIm,
   4755                         &vfi_entry, UUC_DESTINATIONf, &dt);
   4756                 if (dt == SOC_MEM_FIF_DEST_IPMC) {
   4757                     _BCM_MULTICAST_GROUP_SET(info->unknown_unicast_group,
   4758                             _BCM_MULTICAST_TYPE_VPLS, dv);
   4759                 } else {
   4760                     return BCM_E_INTERNAL;
   4761                 }
   4762 
   4763                 dv = soc_mem_field32_dest_get(unit, VFIm,
   4764                         &vfi_entry, UMC_DESTINATIONf, &dt);
   4765                 if (dt == SOC_MEM_FIF_DEST_IPMC) {
   4766                     _BCM_MULTICAST_GROUP_SET(info->unknown_multicast_group,
   4767                             _BCM_MULTICAST_TYPE_VPLS, dv);
   4768                 } else {
   4769                     return BCM_E_INTERNAL;
   4770                 }
   4771 
   4772             } else {
   4773             _BCM_MULTICAST_GROUP_SET(info->broadcast_group,
   4774                                      _BCM_MULTICAST_TYPE_VPLS,	
   4775                       soc_VFIm_field32_get(unit, &vfi_entry, BC_INDEXf));
   4776             _BCM_MULTICAST_GROUP_SET(info->unknown_unicast_group, 
   4777                                      _BCM_MULTICAST_TYPE_VPLS,  
   4778                       soc_VFIm_field32_get(unit, &vfi_entry, UUC_INDEXf));
   4779             _BCM_MULTICAST_GROUP_SET(info->unknown_multicast_group, 
   4780                                      _BCM_MULTICAST_TYPE_VPLS,  
   4781                       soc_VFIm_field32_get(unit, &vfi_entry, UMC_INDEXf));
   4782             }
   4783         } else
   4784 #endif
   4785         {
   4786             _BCM_MULTICAST_GROUP_SET(info->broadcast_group,
   4787                                      _BCM_MULTICAST_TYPE_VPLS, 
   4788                       soc_VFIm_field32_get(unit, &vfi_entry, L3MC_INDEXf));
   4789             info->unknown_multicast_group = info->broadcast_group;
   4790             info->unknown_unicast_group = info->broadcast_group;
   4791         }
   4792 
   4793         if (SOC_MEM_FIELD_VALID (unit,VFIm, PROTOCOL_PKT_INDEXf)) {
   4794             proto_pkt_inx = soc_VFIm_field32_get(unit, &vfi_entry,
   4795                                     PROTOCOL_PKT_INDEXf);
   4796             rv = _bcm_xgs3_protocol_pkt_ctrl_get(unit,proto_pkt_inx,
   4797                                     &info->protocol_pkt);
   4798             if (BCM_FAILURE(rv) && (rv != BCM_E_UNAVAIL)) {
   4799                 return (rv);
   4800             }
   4801         }
   4802 
   4803         /* Set the returned VPN id */
   4804         _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_VPLS, vfi_index);
   4805         info->flags |=  BCM_MPLS_VPN_VPLS;
   4806 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   4807         if (soc_feature(unit, soc_feature_global_meter)) {
   4808             _bcm_esw_get_policer_from_table(unit, VFIm, vfi_index, &vfi_entry, 
   4809                                                       &info->policer_id, 1); 
   4810         }
   4811 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT */
   4812     } else if (_BCM_MPLS_VPN_IS_L3(vpn)) {
   4813         int vrf_id;
   4814 
   4815        _BCM_MPLS_VPN_GET(vrf_id, _BCM_MPLS_VPN_TYPE_L3, vpn);
   4816         if ((vrf_id < 0) || (vrf_id > SOC_VRF_MAX(unit))) {
   4817             return BCM_E_PARAM;
   4818         }
   4819         if (!_BCM_MPLS_VRF_USED_GET(unit, vrf_id)) {
   4820             return BCM_E_NOT_FOUND;
   4821         }
   4822         _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_L3, vrf_id);
   4823         info->flags |=  BCM_MPLS_VPN_L3;
   4824 
   4825     } else {
   4826         return BCM_E_PARAM;
   4827     }
   4828 
   4829     return BCM_E_NONE;
   4830 }
   4831 
   4832 /*
   4833  * Function:
   4834  *      bcm_mpls_vpn_id_destroy
   4835  * Purpose:
   4836  *      Delete a VPN instance
   4837  * Parameters:
   4838  *      unit - Device Number
   4839  *      vpn - VPN instance ID
   4840  * Returns:
   4841  *      BCM_E_XXX
   4842  */
   4843 int
   4844 bcm_tr_mpls_vpn_id_destroy (int unit, bcm_vpn_t vpn)
   4845 {
   4846     int rv;
   4847 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   4848     int policer = 0;
   4849 #endif 
   4850 
   4851     if (_BCM_MPLS_VPN_IS_VPWS(vpn)) {
   4852         bcm_vpn_t   vpn_id;
   4853 
   4854         _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn);
   4855 
   4856         if (!_BCM_MPLS_VPWS_USED_GET(unit, vpn_id)) {
   4857             return BCM_E_NOT_FOUND;
   4858         }
   4859 
   4860         /* Delete all the mpls ports on this VPN */
   4861         rv = bcm_tr_mpls_port_delete_all(unit, vpn);
   4862         BCM_IF_ERROR_RETURN(rv);
   4863 
   4864         (void)    _bcm_tr_mpls_vpws_vp_map_clear (unit, vpn_id);
   4865 
   4866         /* Clear the  VPWS pair in-use status */
   4867         _BCM_MPLS_VPWS_USED_CLR(unit, vpn_id);
   4868     } else if (_BCM_MPLS_VPN_IS_VPLS(vpn)) {
   4869         int vfi, num_vfi;
   4870         vfi_entry_t vfi_entry;
   4871         bcm_vpn_t vpls_vpn_min=0;
   4872 
   4873         num_vfi = soc_mem_index_count(unit, VFIm);
   4874 
   4875         _BCM_MPLS_VPN_SET(vpls_vpn_min, _BCM_MPLS_VPN_TYPE_VPLS, 0);
   4876         if ( vpn < vpls_vpn_min || vpn > (vpls_vpn_min+num_vfi-1) ) {
   4877             return BCM_E_PARAM;
   4878         }
   4879 
   4880        _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vpn);
   4881 
   4882         if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
   4883             return BCM_E_NOT_FOUND;
   4884         }
   4885 
   4886         /* Delete all the mpls ports on this VPN */
   4887         rv = bcm_tr_mpls_port_delete_all(unit, vpn);
   4888         BCM_IF_ERROR_RETURN(rv);
   4889 
   4890         /*
   4891          * Clear the VFI table entry by setting L3MC_INDEX to 0 and
   4892          * PFM to 3. The PFM==3 (invalid) indicates that the VFI entry is not used.
   4893          * This can be used to recover SW state during warm reboot.
   4894          */
   4895 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   4896         if (soc_feature(unit, soc_feature_global_meter)) {
   4897             rv = _bcm_esw_get_policer_from_table(unit,VFIm, vfi, &vfi_entry, 
   4898                                                       &policer, 0); 
   4899             if(BCM_SUCCESS(rv)) {
   4900                  _bcm_esw_policer_decrement_ref_count(unit, policer);
   4901             } else {
   4902                 return rv;
   4903             }
   4904         }
   4905 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT */
   4906         if (SOC_MEM_FIELD_VALID(unit, VFIm, PROTOCOL_PKT_INDEXf)) {
   4907             int ref_count;
   4908             int proto_pkt_inx;
   4909 
   4910             sal_memset(&vfi_entry, 0, sizeof(vfi_entry_t));
   4911             rv = READ_VFIm(unit, MEM_BLOCK_ALL, vfi, &vfi_entry);
   4912             BCM_IF_ERROR_RETURN(rv);
   4913             proto_pkt_inx = soc_VFIm_field32_get(unit, &vfi_entry,
   4914                                     PROTOCOL_PKT_INDEXf);
   4915             BCM_IF_ERROR_RETURN(_bcm_prot_pkt_ctrl_ref_count_get (unit,
   4916                                proto_pkt_inx, &ref_count));
   4917             if (ref_count > 0) { 
   4918                 BCM_IF_ERROR_RETURN(_bcm_prot_pkt_ctrl_delete(unit,proto_pkt_inx));
   4919             }
   4920         }
   4921 
   4922 #ifdef BCM_TRIUMPH2_SUPPORT
   4923         if (soc_feature(unit, soc_feature_gport_service_counters)) {
   4924             /* Release Service counter, if any */
   4925             _bcm_esw_flex_stat_handle_free(unit, _bcmFlexStatTypeService, vpn);
   4926         }
   4927 #endif /* BCM_TRIUMPH2_SUPPORT */
   4928 
   4929         (void) _bcm_vfi_free(unit, _bcmVfiTypeMpls, vfi);
   4930 
   4931         if (!soc_feature(unit, soc_feature_mpls_enhanced)) {
   4932             if (SOC_MEM_FIELD_VALID(unit, VFIm, PFMf)) {
   4933                 BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, VFIm,
   4934                                     vfi, PFMf, 3));
   4935             }
   4936         }
   4937     } else if (_BCM_MPLS_VPN_IS_L3(vpn)) {
   4938         int vrf;
   4939 
   4940        _BCM_MPLS_VPN_GET(vrf, _BCM_MPLS_VPN_TYPE_L3, vpn);
   4941         if ((vrf < 0) || (vrf > SOC_VRF_MAX(unit))) {
   4942             return BCM_E_PARAM;
   4943         }
   4944 
   4945         if (!_BCM_MPLS_VRF_USED_GET(unit, vrf)) {
   4946             return BCM_E_NOT_FOUND;
   4947         }
   4948         _BCM_MPLS_VRF_USED_CLR(unit, vrf);
   4949     } else {
   4950         return BCM_E_PARAM;
   4951     }
   4952 
   4953 #ifdef BCM_WARM_BOOT_SUPPORT
   4954     SOC_CONTROL_LOCK(unit);
   4955     SOC_CONTROL(unit)->scache_dirty = 1;
   4956     SOC_CONTROL_UNLOCK(unit);
   4957 #endif
   4958 
   4959     return BCM_E_NONE;
   4960 }
   4961 
   4962 /*
   4963  * Function:
   4964  *      bcm_mpls_vpn_id_destroy_all
   4965  * Purpose:
   4966  *      Delete all  VPN instances
   4967  * Parameters:
   4968  *      unit - Device Number
   4969  * Returns:
   4970  *      BCM_E_XXX
   4971  */
   4972 
   4973 int
   4974 bcm_tr_mpls_vpn_id_destroy_all (int unit)
   4975 {
   4976     int num_vpws = 0, num_vfi = 0, num_vrf, idx, rv, rv_error = BCM_E_NONE;
   4977     bcm_vpn_t vpn;
   4978 
   4979 
   4980     /* Destroy all VPWS VPNs */
   4981     if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) {
   4982         num_vpws = soc_mem_index_count(unit, SOURCE_VPm) / 2;
   4983     }
   4984     for (idx = 0; idx < num_vpws; idx++) {
   4985         if (_BCM_MPLS_VPWS_USED_GET(unit, idx)) {
   4986             _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, (idx));
   4987             rv = bcm_tr_mpls_vpn_id_destroy(unit, vpn);
   4988             if (rv < 0) {
   4989                 rv_error = rv;
   4990             }
   4991         }
   4992     }
   4993 
   4994     /* Destroy all VPLS VPNs */
   4995     if (SOC_MEM_IS_VALID(unit, VFIm)) {
   4996         num_vfi = soc_mem_index_count(unit, VFIm);
   4997     }
   4998     for (idx = 0; idx < num_vfi; idx++) {
   4999         if (_bcm_vfi_used_get(unit, idx, _bcmVfiTypeMpls)) {
   5000             _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPLS, idx);
   5001             rv = bcm_tr_mpls_vpn_id_destroy(unit, vpn);
   5002             if (rv < 0) {
   5003                 rv_error = rv;
   5004             }
   5005         }
   5006     }
   5007 
   5008     /* Destroy all L3 VPNs */
   5009     num_vrf = SOC_VRF_MAX(unit) + 1;
   5010     for (idx = 0; idx < num_vrf; idx++) {
   5011         if (_BCM_MPLS_VRF_USED_GET(unit, idx)) {
   5012             _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_L3, idx);
   5013             rv = bcm_tr_mpls_vpn_id_destroy(unit, vpn);
   5014             if (rv < 0) {
   5015                 rv_error = rv;
   5016             }
   5017         }
   5018     }
   5019 
   5020     /* Destroy default  VP */
   5021     if (_bcm_vp_used_get(unit, 0, _bcmVpTypeMpls)) {
   5022         _bcm_vp_free(unit, _bcmVpTypeMpls, 1, 0);
   5023     }
   5024 
   5025     return rv_error;
   5026 }
   5027 
   5028 /*
   5029  * Function:
   5030  *      bcm_mpls_vpn_traverse
   5031  * Purpose:
   5032  *      Get information about a VPN instance
   5033  * Parameters:
   5034  *      unit  - (IN)  Device Number
   5035  *      cb    - (IN)  User-provided callback
   5036  *      info  - (IN/OUT) Cookie
   5037  * Returns:
   5038  *      BCM_E_XXX
   5039  */
   5040 
   5041 int bcm_tr_mpls_vpn_traverse(int unit, bcm_mpls_vpn_traverse_cb cb, 
   5042                              void *user_data)
   5043 {
   5044     int idx, num_vpws = 0, num_vfi = 0, num_vrf = 0, rv = BCM_E_NONE;
   5045     int vpn;
   5046     bcm_mpls_vpn_config_t info;
   5047 
   5048     /* VPWS VPNs */
   5049     if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) {
   5050         num_vpws = soc_mem_index_count(unit, SOURCE_VPm) / 2;
   5051     }
   5052     for (idx = 0; idx < num_vpws; idx++) {
   5053          if (_BCM_MPLS_VPWS_USED_GET(unit, idx)) {
   5054               _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, (idx));
   5055               bcm_mpls_vpn_config_t_init(&info);
   5056               rv = bcm_tr_mpls_vpn_id_get(unit, vpn, &info);
   5057               if (BCM_FAILURE(rv)) {
   5058                    return rv;
   5059               }
   5060               rv = cb(unit, &info, user_data);
   5061               if (BCM_FAILURE(rv)) {
   5062                    return rv;
   5063               }
   5064         }
   5065     }
   5066 
   5067     /* VPLS VPNs */
   5068     if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) {
   5069         num_vfi = soc_mem_index_count(unit, VFIm);
   5070     }
   5071     for (idx = 0; idx < num_vfi; idx++) {
   5072          if (_bcm_vfi_used_get(unit, idx, _bcmVfiTypeMpls)) {
   5073               _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPLS, idx);
   5074               bcm_mpls_vpn_config_t_init(&info);
   5075               rv = bcm_tr_mpls_vpn_id_get(unit, vpn, &info);
   5076               if (BCM_FAILURE(rv)) {
   5077                    return rv;
   5078               }
   5079               rv = cb(unit, &info, user_data);
   5080               if (BCM_FAILURE(rv)) {
   5081                    return rv;
   5082               }
   5083          }
   5084     }
   5085 
   5086     /* L3 VPNs */
   5087     num_vrf = SOC_VRF_MAX(unit) + 1;
   5088     for (idx = 0; idx < num_vrf; idx++) {
   5089          if (_BCM_MPLS_VRF_USED_GET(unit, idx)) {
   5090               _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_L3, idx);
   5091               bcm_mpls_vpn_config_t_init(&info);
   5092               rv = bcm_tr_mpls_vpn_id_get(unit, vpn, &info);
   5093               if (BCM_FAILURE(rv)) {
   5094                    return rv;
   5095               }
   5096               rv = cb(unit, &info, user_data);
   5097               if (BCM_FAILURE(rv)) {
   5098                    return rv;
   5099               }
   5100         }
   5101     }
   5102     return rv;
   5103 }
   5104 
   5105 typedef struct _bcm_tr_ing_nh_info_s {
   5106     bcm_port_t      port;
   5107     int      module;
   5108     bcm_trunk_t      trunk;
   5109     uint32   mtu;
   5110     int qtag;
   5111     int tag_type;
   5112 } _bcm_tr_ing_nh_info_t;
   5113 
   5114 typedef struct _bcm_tr_egr_nh_info_s {
   5115     int    entry_type;
   5116     int    dvp_is_network;
   5117     int    dvp_network_group_id;
   5118     int    sd_tag_action_present;
   5119     int    sd_tag_action_not_present;
   5120     int      dvp;
   5121     int      intf_num;
   5122     int      sd_tag_vlan;
   5123     int      sd_tag_pri;
   5124     int      sd_tag_cfi;
   5125     int      lltag_vlan;
   5126     int      lltag_pri;
   5127     int      lltag_cfi;
   5128     int      macda_index;
   5129     int      vc_swap_index;
   5130     int      tpid_index;
   5131     int      pw_init_cnt;
   5132     int      vintf_ctr_index;
   5133     int      flex_ctr_base_cnt_idx;
   5134     int      flex_ctr_pool_num;
   5135     int      flex_ctr_offset_mode;
   5136     int      class_id;
   5137     uint16   oam_global_context_id;
   5138 } _bcm_tr_egr_nh_info_t;
   5139 
   5140 
   5141 STATIC int
   5142 _bcm_tr_mpls_INITIAL_ING_L3_NEXT_HOP_add(int unit,  _bcm_tr_ing_nh_info_t  *ing_nh_info,
   5143                                          int nh_index, bcm_port_t *local_port, int *is_local)
   5144 {
   5145     initial_ing_l3_next_hop_entry_t   initial_ing_nh;
   5146     int rv;
   5147     int modid_local=0;
   5148 #if defined(BCM_KATANA2_SUPPORT)
   5149     bcm_port_t pp_port;
   5150 #endif
   5151 
   5152     sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t));
   5153     if (ing_nh_info->trunk == -1) {
   5154         if (soc_feature(unit, soc_feature_generic_dest)) {
   5155             soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh,
   5156                     DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
   5157                     ing_nh_info->module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_info->port);
   5158         } else {
   5159         soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   5160                             &initial_ing_nh, PORT_NUMf, ing_nh_info->port);
   5161         soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   5162                             &initial_ing_nh, MODULE_IDf, ing_nh_info->module);
   5163         }
   5164         BCM_IF_ERROR_RETURN( _bcm_esw_modid_is_local(unit, ing_nh_info->module, &modid_local));
   5165 
   5166 #if defined(BCM_HGPROXY_COE_SUPPORT)
   5167         if(soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   5168            _bcm_xgs5_subport_coe_mod_local(unit, ing_nh_info->module)) {
   5169 
   5170             *is_local = 1;
   5171             BCM_IF_ERROR_RETURN(_bcmi_coe_subport_mod_port_physical_port_get(unit,
   5172                                                                     ing_nh_info->module,
   5173                                                                     ing_nh_info->port,
   5174                                                                     local_port));
   5175         } else
   5176 #endif
   5177 
   5178 #if defined(BCM_KATANA2_SUPPORT)
   5179         if (soc_feature(unit, soc_feature_linkphy_coe) ||
   5180             soc_feature(unit, soc_feature_subtag_coe)) {
   5181             if (modid_local == 0) {
   5182                 /* Check if this is local LinkPHYSubtag modid */
   5183                 if (_bcm_kt2_mod_is_coe_mod_check(unit, ing_nh_info->module) == BCM_E_NONE) {
   5184                     BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(
   5185                          unit, ing_nh_info->module,
   5186                          ing_nh_info->port, &pp_port));
   5187                     if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, pp_port)){
   5188                         *is_local = 1;
   5189                         *local_port = pp_port;
   5190                     }
   5191                 }
   5192             }
   5193         }
   5194 #endif
   5195         if (modid_local) {
   5196             /* Indicated to calling function that this is a local port */
   5197             *is_local = 1;
   5198             *local_port = ing_nh_info->port;
   5199         }
   5200     } else {
   5201 
   5202         if (soc_feature(unit, soc_feature_generic_dest)) {
   5203             soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh,
   5204                     DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_info->trunk);
   5205         } else {
   5206         soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   5207                             &initial_ing_nh, Tf, 1);
   5208         soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   5209                             &initial_ing_nh, TGIDf, ing_nh_info->trunk);
   5210         }
   5211         *is_local = 1;
   5212         BCM_GPORT_TRUNK_SET(*local_port, ing_nh_info->trunk);
   5213     }
   5214 
   5215     rv = soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm,
   5216                        MEM_BLOCK_ALL, nh_index, &initial_ing_nh);
   5217 
   5218     return rv;
   5219 }
   5220 
   5221 
   5222 STATIC int
   5223 _bcm_tr_mpls_ING_L3_NEXT_HOP_add(int unit,  _bcm_tr_ing_nh_info_t  *ing_nh_info, 
   5224                                  int nh_index, int  drop)
   5225 {
   5226     ing_l3_next_hop_entry_t ing_nh;
   5227     int rv;
   5228 #ifdef BCM_TRIUMPH3_SUPPORT
   5229     uint32 mtu_profile_index = 0;
   5230 #endif /* BCM_TRIUMPH3_SUPPORT */
   5231 
   5232     sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t));
   5233 
   5234     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, drop);
   5235     if (ing_nh_info->trunk == -1) {
   5236         if (soc_feature(unit, soc_feature_generic_dest)) {
   5237             if (ing_nh_info->port!=0) {
   5238                 soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   5239                         DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
   5240                         ing_nh_info->module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_info->port);
   5241             }
   5242         } else {
   5243         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   5244                             &ing_nh, PORT_NUMf, ing_nh_info->port);
   5245         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   5246                             &ing_nh, MODULE_IDf, ing_nh_info->module);
   5247         }
   5248     } else {
   5249         if (soc_feature(unit, soc_feature_generic_dest)) {
   5250             soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   5251                     DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_info->trunk);
   5252     } else {	 
   5253         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   5254                             &ing_nh, Tf, 1);
   5255         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   5256                             &ing_nh, TGIDf, ing_nh_info->trunk);
   5257     }
   5258     }
   5259     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   5260                         &ing_nh, ENTRY_TYPEf, 0x2); /* L2 DVP */
   5261     if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) {
   5262         if (ing_nh_info->mtu >=
   5263             (1 << soc_mem_field_length(unit, ING_L3_NEXT_HOPm, MTU_SIZEf))) {
   5264             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   5265                                 &ing_nh, MTU_SIZEf, 0x3fff);
   5266         } else {
   5267             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   5268                                 &ing_nh, MTU_SIZEf, ing_nh_info->mtu);
   5269         }
   5270     }
   5271 #ifdef BCM_TRIUMPH3_SUPPORT
   5272     else if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, 
   5273                  DVP_ATTRIBUTE_1_INDEXf)) {
   5274         BCM_IF_ERROR_RETURN(
   5275           _bcm_tr3_mtu_profile_index_get(unit, 0x3fff, &mtu_profile_index));
   5276         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, 
   5277                       DVP_ATTRIBUTE_1_INDEXf, mtu_profile_index);
   5278     }
   5279 #endif /*BCM_TRIUMPH3_SUPPORT */
   5280 
   5281     if ((ing_nh_info->qtag != -1) && 
   5282         SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm,EH_QUEUE_TAGf)) {
   5283         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   5284                       EH_QUEUE_TAGf, ing_nh_info->qtag);
   5285     }
   5286     if ((ing_nh_info->tag_type != -1) &&
   5287         SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm,EH_TAG_TYPEf)) {
   5288         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   5289                       EH_TAG_TYPEf, ing_nh_info->tag_type);
   5290     }
   5291 
   5292     rv = soc_mem_write (unit, ING_L3_NEXT_HOPm,
   5293                         MEM_BLOCK_ALL, nh_index, &ing_nh);
   5294     return rv;
   5295 }
   5296 
   5297 
   5298 STATIC int
   5299 _bcm_tr_mpls_EGR_L3_NEXT_HOP_add(int unit,  _bcm_tr_egr_nh_info_t  *egr_nh_info, 
   5300                                  uint32 flags, int nh_index, int *is_local, int is_vpws, int drop)
   5301 {
   5302     egr_l3_next_hop_entry_t egr_nh;
   5303     int rv;
   5304 
   5305     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   5306 
   5307     if (egr_nh_info->entry_type == 0x1) {
   5308 
   5309         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   5310             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5311                     &egr_nh, L3__INTF_NUMf, egr_nh_info->intf_num);
   5312         } else {
   5313         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5314                            &egr_nh, INTF_NUMf, egr_nh_info->intf_num);
   5315         }
   5316         if (egr_nh_info->macda_index != -1) {
   5317               if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5318                    soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5319                             &egr_nh, MPLS__MAC_DA_PROFILE_INDEXf,
   5320                             egr_nh_info->macda_index);
   5321               } else {
   5322                    soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5323                              &egr_nh, MAC_DA_PROFILE_INDEXf,
   5324                              egr_nh_info->macda_index);
   5325               }
   5326         }
   5327         if (egr_nh_info->vc_swap_index != -1) {
   5328              if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5329                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5330                                   &egr_nh, MPLS__VC_AND_SWAP_INDEXf,
   5331                                   egr_nh_info->vc_swap_index);
   5332              } else {
   5333                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5334                                   &egr_nh, VC_AND_SWAP_INDEXf,
   5335                                   egr_nh_info->vc_swap_index);
   5336              }
   5337         }
   5338 
   5339         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5340 
   5341             if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, MPLS__CLASS_IDf)) {
   5342                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5343                                     MPLS__CLASS_IDf, egr_nh_info->class_id);
   5344             }
   5345 
   5346 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   5347             if ((egr_nh_info->flex_ctr_base_cnt_idx != -1) &&
   5348                 soc_feature(unit,soc_feature_advanced_flex_counter)) {
   5349                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5350                                  MPLS__FLEX_CTR_BASE_COUNTER_IDXf, 
   5351                                  egr_nh_info->flex_ctr_base_cnt_idx);
   5352                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5353                                  MPLS__FLEX_CTR_POOL_NUMBERf, 
   5354                                  egr_nh_info->flex_ctr_pool_num);
   5355                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5356                                  MPLS__FLEX_CTR_OFFSET_MODEf, 
   5357                                  egr_nh_info->flex_ctr_offset_mode);
   5358             } else
   5359 #endif
   5360             if ((egr_nh_info->vintf_ctr_index != -1) && 
   5361                 soc_feature(unit, soc_feature_gport_service_counters)) {
   5362                 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
   5363                                   MPLS__USE_VINTF_CTR_IDXf)) {
   5364                      soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5365                                   MPLS__USE_VINTF_CTR_IDXf,
   5366                                   egr_nh_info->vintf_ctr_index ? 1 : 0);
   5367                 }
   5368                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5369                                  MPLS__VINTF_CTR_IDXf, 
   5370                                  egr_nh_info->vintf_ctr_index);
   5371             }
   5372         }
   5373 
   5374         if (egr_nh_info->pw_init_cnt != -1) {
   5375              if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5376                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5377                                   MPLS__PW_INIT_NUMf, egr_nh_info->pw_init_cnt);
   5378              } else {
   5379                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5380                                   PW_INIT_NUMf, egr_nh_info->pw_init_cnt);
   5381              }
   5382         }
   5383 
   5384         if (soc_feature(unit, soc_feature_vlan_xlate)) {
   5385              soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5386                                   MPLS__USE_DVP_IN_EVXLT_KEYf, 0x1);
   5387         }
   5388 
   5389         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5390               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5391                         MPLS__BC_DROPf, drop ? 1 : 0);
   5392               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5393                         MPLS__UUC_DROPf, drop ? 1 : 0);
   5394               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5395                         MPLS__UMC_DROPf, drop ? 1 : 0);
   5396               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5397                         MPLS__DVPf, egr_nh_info->dvp);
   5398               if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   5399                   if (!(soc_feature(unit, soc_feature_td3_style_mpls))) {
   5400                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5401                         &egr_nh, MPLS__DVP_NETWORK_GROUPf,
   5402                         egr_nh_info->dvp_network_group_id);
   5403                   }
   5404               } else {
   5405                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5406                         &egr_nh, MPLS__DVP_IS_NETWORK_PORTf,
   5407                         egr_nh_info->dvp_is_network);
   5408               }
   5409               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5410                         MPLS__HG_LEARN_OVERRIDEf, is_vpws ? 1 : 0);
   5411               /*
   5412                * Generally for L2 MPLS,
   5413                * - VPWS application, MPLS tunnel header can be encapsulated
   5414                * at ingress chip or egress chip, the suggestion is add MPLS
   5415                * header at egress chip to save HG bandwidth.
   5416                *
   5417                * - VPLS application, L2 learning is needed on egress chip,
   5418                * that means the MPLS tunnel header need to be encapsulated at
   5419                * the egress chip. SVP and DVP field in PPD type 2 will provide
   5420                * infomation for these requirements.
   5421                */
   5422               if (flags & BCM_MPLS_PORT2_PROXY_MODE) {
   5423                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5424                                       MPLS__HG_MODIFY_ENABLEf, 0x1);
   5425                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5426                                       MPLS__HG_HDR_SELf, 0);
   5427               } else {
   5428                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5429                                       MPLS__HG_MODIFY_ENABLEf, 0x0);
   5430                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5431                                       MPLS__HG_HDR_SELf, 1);
   5432               }
   5433         } else {
   5434               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5435                         DVPf, egr_nh_info->dvp);
   5436               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5437                         &egr_nh, DVP_IS_NETWORK_PORTf,
   5438                         egr_nh_info->dvp_is_network);
   5439               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5440                         HG_LEARN_OVERRIDEf, is_vpws ? 1 : 0);
   5441               /* For L2 MPLS, HG_MODIFY_ENABLE must be 0x0 for Ingress and Egress Chip */
   5442               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5443                         HG_MODIFY_ENABLEf, 0x0);
   5444               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5445                         HG_HDR_SELf, 1);
   5446         }
   5447 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   5448         if (soc_feature(unit, soc_feature_mpls_nh_ttl_control)) {
   5449            if (flags & BCM_MPLS_PORT2_KEEP_TTL) {
   5450                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5451                                    MPLS__DISABLE_TTL_DECREMENTf, 1);
   5452            }
   5453         }
   5454 #endif
   5455     } else if (egr_nh_info->entry_type == 0x2) {
   5456 
   5457         if (egr_nh_info->lltag_vlan != -1) {
   5458             if (soc_feature(unit, soc_feature_lltag)) {
   5459                 if (egr_nh_info->lltag_pri != -1) {
   5460                     /*  PCP, DE fields are copied from this table. */
   5461                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5462                                 &egr_nh, SD_TAG__LLTAG_PCP_DE_SOURCEf, 0x02);
   5463                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5464                                 &egr_nh, SD_TAG__LLTAG_PCPf, egr_nh_info->lltag_pri);
   5465                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5466                                 &egr_nh, SD_TAG__LLTAG_DEf, egr_nh_info->lltag_cfi); 
   5467                 } else {
   5468                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5469                                 &egr_nh, SD_TAG__LLTAG_PCP_DE_SOURCEf, 0x03);  
   5470                 }  
   5471                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5472                                 &egr_nh, SD_TAG__LLTAG_ACTIONSf, 0x04);
   5473                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5474                                 &egr_nh, SD_TAG__LLTAG_VIDf, egr_nh_info->lltag_vlan);
   5475                 
   5476             }
   5477         }
   5478 
   5479         if (egr_nh_info->sd_tag_vlan != -1) {
   5480              if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5481 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   5482                 if (soc_feature(unit, soc_feature_vp_sharing)) {
   5483                     if (egr_nh_info->sd_tag_vlan == BCM_VLAN_INVALID) {
   5484                         if(SOC_MEM_FIELD_VALID(unit,
   5485                                     EGR_L3_NEXT_HOPm,
   5486                                     SD_TAG__SD_TAG_NOT_VALIDf)) {
   5487                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5488                                        &egr_nh, SD_TAG__SD_TAG_NOT_VALIDf, 1);
   5489                         }
   5490                     } else {
   5491                         if(SOC_MEM_FIELD_VALID(unit,
   5492                                     EGR_L3_NEXT_HOPm,
   5493                                     SD_TAG__SD_TAG_NOT_VALIDf)) {
   5494                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5495                                        &egr_nh, SD_TAG__SD_TAG_NOT_VALIDf, 0);
   5496                         }
   5497                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5498                                     &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan);
   5499                     }
   5500                  } else
   5501 #endif
   5502                 {
   5503                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5504                                   &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan);
   5505                 }
   5506              } else {
   5507                  soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5508                                 &egr_nh, SD_TAG_VIDf, egr_nh_info->sd_tag_vlan);
   5509              }
   5510         }
   5511 
   5512         if (egr_nh_info->sd_tag_action_present != -1) {
   5513              if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5514                    soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5515                              SD_TAG__SD_TAG_ACTION_IF_PRESENTf,
   5516                              egr_nh_info->sd_tag_action_present);
   5517              } else {
   5518                    soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5519                              SD_TAG_ACTION_IF_PRESENTf,
   5520                              egr_nh_info->sd_tag_action_present);
   5521              }
   5522         }
   5523 
   5524         if (egr_nh_info->sd_tag_action_not_present != -1) {
   5525              if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5526                    soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5527                              SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf,
   5528                              egr_nh_info->sd_tag_action_not_present);
   5529              } else {
   5530                    soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5531                              SD_TAG_ACTION_IF_NOT_PRESENTf,
   5532                              egr_nh_info->sd_tag_action_not_present);
   5533              }
   5534         }
   5535 
   5536         if (egr_nh_info->sd_tag_pri != -1) {
   5537              if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5538                  if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__NEW_PRIf)) {
   5539                        soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5540                              SD_TAG__NEW_PRIf,
   5541                              egr_nh_info->sd_tag_pri);
   5542                  }
   5543              }
   5544         }
   5545 
   5546         if (egr_nh_info->sd_tag_cfi != -1) {
   5547              if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5548                    if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__NEW_CFIf)) {
   5549                        soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5550                              SD_TAG__NEW_CFIf,
   5551                              egr_nh_info->sd_tag_cfi);
   5552                    }
   5553                    if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__SD_TAG_REMARK_CFIf)) {
   5554                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5555                              SD_TAG__SD_TAG_REMARK_CFIf, 1);
   5556                    }
   5557              }
   5558         }
   5559 
   5560         if (egr_nh_info->tpid_index != -1) {
   5561              if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5562                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5563                                 &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf,
   5564                                 egr_nh_info->tpid_index);
   5565              } else {
   5566                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5567                                 &egr_nh, SD_TAG_TPID_INDEXf,
   5568                                 egr_nh_info->tpid_index);
   5569              }
   5570         }
   5571 
   5572         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5573 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   5574             if ((egr_nh_info->flex_ctr_base_cnt_idx != -1) &&
   5575                 soc_feature(unit,soc_feature_advanced_flex_counter)) {
   5576                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5577                                  SD_TAG__FLEX_CTR_BASE_COUNTER_IDXf,
   5578                                  egr_nh_info->flex_ctr_base_cnt_idx);
   5579                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5580                                  SD_TAG__FLEX_CTR_POOL_NUMBERf,
   5581                                  egr_nh_info->flex_ctr_pool_num);
   5582                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5583                                  SD_TAG__FLEX_CTR_OFFSET_MODEf,
   5584                                  egr_nh_info->flex_ctr_offset_mode);
   5585             } else
   5586 #endif
   5587             if ((egr_nh_info->vintf_ctr_index != -1) &&
   5588                 soc_feature(unit, soc_feature_gport_service_counters)) {
   5589                 if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
   5590                                   SD_TAG__USE_VINTF_CTR_IDXf)) {
   5591                      soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5592                                   SD_TAG__USE_VINTF_CTR_IDXf,
   5593                                   egr_nh_info->vintf_ctr_index ? 1 : 0);
   5594                 }
   5595                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5596                                  SD_TAG__VINTF_CTR_IDXf,
   5597                                  egr_nh_info->vintf_ctr_index);
   5598             }
   5599         }
   5600 
   5601         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5602               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5603                         SD_TAG__BC_DROPf, drop ? 1 : 0);
   5604               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5605                         SD_TAG__UUC_DROPf, drop ? 1 : 0);
   5606               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5607                         SD_TAG__UMC_DROPf, drop ? 1 : 0);
   5608         }
   5609 
   5610         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5611               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5612                         SD_TAG__BC_DROPf, drop ? 1 : 0);
   5613               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5614                         SD_TAG__UUC_DROPf, drop ? 1 : 0);
   5615               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5616                         SD_TAG__UMC_DROPf, drop ? 1 : 0);
   5617               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5618                         SD_TAG__DVPf, egr_nh_info->dvp);
   5619               if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   5620                   if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   5621                       rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm,
   5622                               egr_nh_info->dvp, COMMON__DVP_NETWORK_GROUPf,
   5623                               egr_nh_info->dvp_network_group_id);
   5624                       if (rv < 0) {
   5625                           return rv;
   5626                       }
   5627                   } else {
   5628                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5629                         &egr_nh, SD_TAG__DVP_NETWORK_GROUPf,
   5630                         egr_nh_info->dvp_network_group_id);
   5631                   }
   5632               } else {
   5633                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5634                         &egr_nh, SD_TAG__DVP_IS_NETWORK_PORTf,
   5635                         egr_nh_info->dvp_is_network);
   5636               }
   5637               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5638                         SD_TAG__HG_LEARN_OVERRIDEf, is_vpws ? 1 : 0);
   5639               /*
   5640                * Generally for L2 MPLS,
   5641                * - VPWS application, MPLS tunnel header can be encapsulated
   5642                * at ingress chip or egress chip, the suggestion is add MPLS
   5643                * header at egress chip to save HG bandwidth.
   5644                *
   5645                * - VPLS application, L2 learning is needed on egress chip,
   5646                * that means the MPLS tunnel header need to be encapsulated at
   5647                * the egress chip. SVP and DVP field in PPD type 2 will provide
   5648                * infomation for these requirements.
   5649                */
   5650               if (flags & BCM_MPLS_PORT2_PROXY_MODE) {
   5651                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5652                                       SD_TAG__HG_MODIFY_ENABLEf, 0x1);
   5653                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5654                                       SD_TAG__HG_HDR_SELf, 0);
   5655               } else {
   5656                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5657                                       SD_TAG__HG_MODIFY_ENABLEf, 0x0);
   5658                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5659                                       SD_TAG__HG_HDR_SELf, 1);
   5660               }
   5661 
   5662               if (egr_nh_info->class_id != BCM_CLASS_ID_INVALID) {
   5663                   if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__CLASS_IDf)) {
   5664                       soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5665                               SD_TAG__CLASS_IDf, egr_nh_info->class_id);
   5666                   }
   5667               }
   5668         } else {
   5669               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5670                         DVPf, egr_nh_info->dvp);
   5671               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   5672                         &egr_nh, DVP_IS_NETWORK_PORTf,
   5673                         egr_nh_info->dvp_is_network);
   5674               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5675                         HG_LEARN_OVERRIDEf, is_vpws ? 1 : 0);
   5676               /* For L2 MPLS, HG_MODIFY_ENABLE must be 0x0 for Ingress and Egress Chip */
   5677               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5678                         HG_MODIFY_ENABLEf, 0x0);
   5679               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   5680                         HG_HDR_SELf, 1);
   5681         }
   5682     } else {
   5683          return BCM_E_PARAM;
   5684     }
   5685 
   5686     if ((_BCM_MPLS_MEPID_IN_VALID_RANGE(egr_nh_info->oam_global_context_id)) &&
   5687         (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, MPLS__MEPIDf))) {
   5688         /* Writing MPLS LM/DM value. it doesnt matter since
   5689            data packets are similar for BHH and MPLS LM/DM */
   5690         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5691                 MPLS__MPLS_OAM_DOWNMEP_ENABLEf, 2);
   5692         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5693                 MPLS__MEPIDf, egr_nh_info->oam_global_context_id);
   5694     }
   5695 
   5696     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5697                         nh_entry_type_field[unit], egr_nh_info->entry_type);
   5698 
   5699     rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   5700                        MEM_BLOCK_ALL, nh_index, &egr_nh);
   5701 
   5702     return rv;
   5703 }
   5704 
   5705 /*
   5706  * Function:
   5707  *       _bcm_tr_mpls_compute_nhop_hash
   5708  * Purpose:
   5709  *       Compute the hash Index from Egress Tunnel If
   5710  * Parameters:
   5711  *       unit - (IN) bcm device.
   5712  *       egress_if  - (IN) Egress Tunnel If
   5713  * Returns:
   5714  *       BCM_E_XXX
   5715  */
   5716 
   5717 STATIC void
   5718 _bcm_tr_mpls_compute_nhop_hash (bcm_if_t egress_if, int *hash_idx)
   5719 {
   5720     *hash_idx = egress_if % 1024;
   5721 }
   5722 
   5723 /*
   5724  * Function:
   5725  *		_bcm_tr_mpls_add_vp_nh
   5726  * Purpose:
   5727  *		Add MPLS VP NextHop index into a list
   5728  * Parameters:
   5729  *		unit	- (IN) bcm device.
   5730  *		mpls_port	- (IN) MPLS Port
   5731  *		nh_index	 - (IN) VP NextHop Index
   5732  * Returns:
   5733  *		BCM_E_XXX
   5734  */
   5735 
   5736 STATIC int
   5737 _bcm_tr_mpls_add_vp_nh ( int unit, bcm_if_t  egr_if, int nh_index )
   5738 {
   5739     _bcm_mpls_egr_nhopList_t  *nhop_cursorPtr;
   5740     _bcm_mpls_vp_nh_list_t  *vp_cursorPtr;
   5741     _bcm_mpls_vp_nh_list_t *newVpNode;
   5742     int   hash_idx;
   5743 
   5744     (void) _bcm_tr_mpls_compute_nhop_hash (egr_if, &hash_idx);
   5745 
   5746 
   5747     /* If Node is present, then insert the VP_index */
   5748     for (nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][hash_idx]; 
   5749            nhop_cursorPtr != NULL; nhop_cursorPtr = nhop_cursorPtr->link) {
   5750         if (nhop_cursorPtr->egr_if == egr_if ) {
   5751             for (vp_cursorPtr = nhop_cursorPtr->vp_head_ptr; vp_cursorPtr != NULL; vp_cursorPtr = vp_cursorPtr->link) {
   5752                 if (vp_cursorPtr->vp_nh_idx == nh_index) {
   5753                     return BCM_E_NONE;
   5754                 }
   5755             }
   5756             newVpNode = (_bcm_mpls_vp_nh_list_t *) sal_alloc (sizeof (_bcm_mpls_vp_nh_list_t), "VP NH Index");
   5757             if (NULL == newVpNode) {
   5758                 return (BCM_E_MEMORY); 
   5759             }	 
   5760             newVpNode->vp_nh_idx = nh_index;
   5761             newVpNode->link = nhop_cursorPtr->vp_head_ptr;
   5762             nhop_cursorPtr->vp_head_ptr = newVpNode;
   5763             return BCM_E_NONE;
   5764         }
   5765     }
   5766     return BCM_E_NOT_FOUND;
   5767 }
   5768 
   5769 
   5770 /*
   5771  * Function:
   5772  *       bcm_tr_mpls_update_vp_nh
   5773  * Purpose:
   5774  *       Update NextHop Table indexed by VP NextHop index
   5775  * Parameters:
   5776  *unit	- (IN) bcm device.
   5777  *       egr_index - (IN) NextHop Index of Parent Egr Object
   5778  * Returns:
   5779  *       BCM_E_XXX
   5780  */
   5781 
   5782 int
   5783 bcm_tr_mpls_update_vp_nh ( int unit, bcm_if_t  egr_if )
   5784 {
   5785     _bcm_mpls_egr_nhopList_t  *nhop_cursorPtr;
   5786     _bcm_mpls_vp_nh_list_t  *vp_cursorPtr;
   5787     ing_l3_next_hop_entry_t ing_nh;
   5788     egr_l3_next_hop_entry_t egr_nh;
   5789     initial_ing_l3_next_hop_entry_t   initial_ing_nh;
   5790     _bcm_tr_ing_nh_info_t ing_nh_info;
   5791     _bcm_tr_egr_nh_info_t egr_nh_info;
   5792     bcm_l3_egress_t nh_info;
   5793     void *entries[1];
   5794     int  vp_index=-1;
   5795     int  egr_index=-1;
   5796     int  hash_idx=-1;
   5797     int  old_macda_idx=-1;
   5798     uint32 flags=0;
   5799     egr_mac_da_profile_entry_t macda;
   5800 
   5801     (void) _bcm_tr_mpls_compute_nhop_hash (egr_if, &hash_idx);
   5802 
   5803 
   5804     for (nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][hash_idx]; 
   5805               nhop_cursorPtr != NULL; nhop_cursorPtr = nhop_cursorPtr->link) {
   5806         if (nhop_cursorPtr->egr_if == egr_if) {
   5807             for (vp_cursorPtr = nhop_cursorPtr->vp_head_ptr;  vp_cursorPtr != NULL; vp_cursorPtr = vp_cursorPtr->link) {
   5808                 vp_index = vp_cursorPtr->vp_nh_idx;
   5809 
   5810                 /* Get the Egress Hext Hop Index from the Egress Object Id without incrementing ref_count*/
   5811                 BCM_IF_ERROR_RETURN(bcm_xgs3_get_nh_from_egress_object(unit, egr_if, &flags, 0, &egr_index));
   5812  
   5813                 /* Read the egress next_hop entry pointed by EGRess-Object */	  
   5814                 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_get(unit, egr_index, &nh_info));  
   5815 
   5816                 /* Obtain  the MPLS tunnel destination port information. */
   5817                 if (nh_info.flags & BCM_L3_TGID) {
   5818                     ing_nh_info.port = -1;
   5819                     ing_nh_info.module = -1;
   5820                     ing_nh_info.trunk = nh_info.trunk; 
   5821                 } else {
   5822                     BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit, 
   5823                                                                 BCM_STK_MODMAP_SET,
   5824                                                                 nh_info.module, nh_info.port,
   5825                                                                 &nh_info.module, &nh_info.port));
   5826                     ing_nh_info.port = nh_info.port;
   5827                     ing_nh_info.module = nh_info.module;
   5828                     ing_nh_info.trunk = -1; 
   5829                 }
   5830                 egr_nh_info.intf_num = nh_info.intf;
   5831                 egr_nh_info.entry_type = 0x1; /* MPLS_MACDA_PROFILE */
   5832 
   5833                 /* Read the existing egress next_hop entry pointed by VP NextHop Index */
   5834                 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, 
   5835                                                   vp_index, &egr_nh));
   5836 
   5837                 /* Delete existing MACDA_PROFILE */
   5838                 if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5839                     old_macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   5840                                                          MPLS__MAC_DA_PROFILE_INDEXf);
   5841                 } else {
   5842                     old_macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   5843                                                          MAC_DA_PROFILE_INDEXf);
   5844                 }
   5845 
   5846                 if (old_macda_idx != -1) {
   5847                    BCM_IF_ERROR_RETURN
   5848                         (_bcm_mac_da_profile_entry_delete(unit, old_macda_idx));
   5849                 }
   5850 
   5851                 /* Obtain new MACDA_PROFILE */
   5852 
   5853                 sal_memset(&macda, 0, sizeof(egr_mac_da_profile_entry_t));
   5854                 soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, 
   5855                                      &macda, MAC_ADDRESSf, nh_info.mac_addr);
   5856                 entries[0] = &macda;
   5857                 BCM_IF_ERROR_RETURN(_bcm_mac_da_profile_entry_add(unit, entries, 1,
   5858                                                                   (uint32 *) &egr_nh_info.macda_index));
   5859 
   5860                 /* Modify  the Egress NextHop entry pointed by VP NextHop Index */
   5861                 if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   5862                      soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5863                                     MPLS__MAC_DA_PROFILE_INDEXf, egr_nh_info.macda_index);
   5864                      soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5865                                     MPLS__INTF_NUMf, egr_nh_info.intf_num);
   5866                 } else {
   5867                      soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5868                                     MAC_DA_PROFILE_INDEXf, egr_nh_info.macda_index);
   5869                      soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5870                                     INTF_NUMf, egr_nh_info.intf_num);
   5871                 }
   5872                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5873                                     nh_entry_type_field[unit], egr_nh_info.entry_type);
   5874 
   5875                 if ((_BCM_MPLS_MEPID_IN_VALID_RANGE(nh_info.oam_global_context_id)) &&
   5876                         (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, MPLS__MEPIDf))) {
   5877                     /* Writing MPLS LM/DM value. it doesnt matter since
   5878                        data packets are similar for BHH and MPLS LM/DM */
   5879                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5880                             MPLS__MPLS_OAM_DOWNMEP_ENABLEf, 2);
   5881                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   5882                             MPLS__MEPIDf, nh_info.oam_global_context_id);
   5883                 }
   5884 
   5885 
   5886                 /* Update HW Table Memory */
   5887                 BCM_IF_ERROR_RETURN (soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   5888                                                    MEM_BLOCK_ALL, vp_index, &egr_nh));
   5889 
   5890 
   5891                 /* Read the existing Ingress next_hop entry pointed by VP NextHop Index */
   5892                 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ALL, 
   5893                                                   vp_index, &ing_nh));
   5894 
   5895                 /* Modify  the Ingress NextHop entry pointed by VP NextHop Index */
   5896                 if (ing_nh_info.trunk == -1) {
   5897                     if (soc_feature(unit, soc_feature_generic_dest)) {
   5898                         soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   5899                                 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, 0);
   5900                         soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   5901                                 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
   5902                                 ing_nh_info.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_info.port);
   5903                     } else {
   5904                     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   5905                                         &ing_nh, Tf, 0);
   5906                     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   5907                                         &ing_nh, TGIDf, 0);
   5908                     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   5909                                         &ing_nh, PORT_NUMf, ing_nh_info.port);
   5910                     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   5911                                         &ing_nh, MODULE_IDf, ing_nh_info.module);
   5912                     }
   5913 
   5914                 } else {
   5915 
   5916                     if (soc_feature(unit, soc_feature_generic_dest)) {
   5917                         soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   5918                                 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 0);
   5919                         soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   5920                                 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_info.trunk);
   5921                     } else {
   5922                     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   5923                                         &ing_nh, PORT_NUMf, 0);
   5924                     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   5925                                         &ing_nh, MODULE_IDf, 0);
   5926                     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   5927                                         &ing_nh, Tf, 1);
   5928                     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   5929                                         &ing_nh, TGIDf, ing_nh_info.trunk);
   5930                 }
   5931                 }
   5932 
   5933                 /* Update HW Table Memory */
   5934                 BCM_IF_ERROR_RETURN (soc_mem_write (unit, ING_L3_NEXT_HOPm,
   5935                                                     MEM_BLOCK_ALL, vp_index, &ing_nh));
   5936 
   5937                 /* Read the existing Initial-Ingress next_hop entry pointed by VP NextHop Index */
   5938                 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_ING_L3_NEXT_HOPm, MEM_BLOCK_ALL,
   5939                                                   vp_index, &initial_ing_nh));
   5940 
   5941                 /* Modify the Initial-Ingress NextHop entry pointed by VP NextHop Index */
   5942                 if (ing_nh_info.trunk == -1) {
   5943 
   5944                     if (soc_feature(unit, soc_feature_generic_dest)) {
   5945                         soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh,
   5946                                 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, 0);
   5947                         soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh,
   5948                                 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
   5949                                 ing_nh_info.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_info.port);
   5950                     } else {
   5951                         soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   5952                                         &initial_ing_nh, PORT_NUMf, ing_nh_info.port);
   5953                         soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   5954                                         &initial_ing_nh, MODULE_IDf, ing_nh_info.module);
   5955                         soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   5956                                         &initial_ing_nh, Tf, 0);
   5957                     }
   5958                 } else {
   5959 
   5960                     if (soc_feature(unit, soc_feature_generic_dest)) {
   5961                         soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh,
   5962                                 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, 0);
   5963                         soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh,
   5964                                 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_info.trunk);
   5965                     } else {
   5966                         soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   5967                                         &initial_ing_nh, Tf, 1);
   5968                         soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   5969                                         &initial_ing_nh, TGIDf, ing_nh_info.trunk);
   5970                     }
   5971                 }
   5972 
   5973                 /* Update HW Table Memory */
   5974                 BCM_IF_ERROR_RETURN (soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm,
   5975                                                    MEM_BLOCK_ALL, vp_index, &initial_ing_nh));
   5976 
   5977             }
   5978         }
   5979     }
   5980     return BCM_E_NONE;
   5981 }
   5982 
   5983 /*
   5984  * Function:
   5985  *       bcm_dump_mpls_port
   5986  * Purpose:
   5987  *       Displays MPLS Port Structure Information
   5988  * Parameters:
   5989  *       mpls_port - (IN) MPLS Port Structure
   5990  * Returns:
   5991  *       None
   5992  */
   5993 
   5994 	
   5995 void
   5996 bcm_dump_mpls_port (bcm_mpls_port_t *mpls_port) 
   5997 {
   5998     LOG_CLI((BSL_META("\n MPLS Port ID: %d"), (bcm_gport_t) mpls_port->mpls_port_id));
   5999     LOG_CLI((BSL_META("\n Egress Tunnel If: %d"),
   6000              (bcm_if_t) mpls_port->egress_tunnel_if));
   6001     LOG_CLI((BSL_META("\n flags: %X"), mpls_port->flags));
   6002     LOG_CLI((BSL_META("\n service_tpid: %d"), mpls_port->service_tpid));
   6003     LOG_CLI((BSL_META("\n match_vlan: %d"), mpls_port->match_vlan));
   6004     LOG_CLI((BSL_META("\n mpls_label: %d"), (bcm_mpls_label_t) mpls_port->match_label));
   6005     LOG_CLI((BSL_META("\n encap_id: %d"), (bcm_if_t) mpls_port->encap_id));
   6006 }
   6007 
   6008 /* 
   6009  * Function:   * Function: 
   6010  *              _bcm_tr_mpls_dump_egrNhop 
   6011  * Purpose: 
   6012  *              Dump Egr NextHop List
   6013  * Parameters: 
   6014  *              unit    - (IN) bcm device. 
   6015  *              vp_idx   - (IN) VP NextHop Index
   6016  * Returns: 
   6017  *              BCM_E_XXX 
   6018  */ 
   6019      
   6020 void
   6021 _bcm_tr_mpls_dump_egrNhop (int unit)
   6022 { 
   6023     _bcm_mpls_egr_nhopList_t  *nhop_cursorPtr; 
   6024     _bcm_mpls_vp_nh_list_t *vp_cursorPtr; 
   6025     int   index; 
   6026 
   6027     for(index=0; index < _BCM_TR_MPLS_HASH_ELEMENTS; ++index) {
   6028         if (_bcm_tr_mpls_nhop_headPtr[unit][index] != NULL) {
   6029             for (nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][index]; 
   6030                  nhop_cursorPtr != NULL; nhop_cursorPtr = nhop_cursorPtr->link) {
   6031                 LOG_CLI((BSL_META_U(unit,
   6032                                     "\n Egress Tunnel If: %d"),
   6033                          (bcm_if_t) nhop_cursorPtr->egr_if));
   6034                 for (vp_cursorPtr = nhop_cursorPtr->vp_head_ptr; 
   6035                      vp_cursorPtr != NULL; vp_cursorPtr = vp_cursorPtr->link) { 
   6036                     LOG_CLI((BSL_META_U(unit,
   6037                                         "\n VP Nhop Idx= %d"),
   6038                              vp_cursorPtr->vp_nh_idx));
   6039                 } 
   6040             }
   6041         }
   6042     }
   6043 }
   6044 
   6045 
   6046 /*
   6047  * Function:
   6048  *           _bcm_tr_mpls_add_egrNhop
   6049  * Purpose:
   6050  *            Add Nhop information into a Hash-Table
   6051  * Parameters:
   6052  *            unit - (IN) bcm device.
   6053  *            egress_if - (IN) Egress Tunnel If
   6054  * Returns:
   6055  *            BCM_E_XXX
   6056  */
   6057 
   6058 STATIC int
   6059 _bcm_tr_mpls_add_egrNhop ( int unit, bcm_if_t egress_if)
   6060 {
   6061     _bcm_mpls_egr_nhopList_t  *newNhopNode;
   6062     _bcm_mpls_egr_nhopList_t  *nhop_cursorPtr;
   6063     int   hash_idx;
   6064 
   6065     (void) _bcm_tr_mpls_compute_nhop_hash (egress_if, &hash_idx);
   6066     /* Does the Node exist? */
   6067     for (nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][hash_idx]; 
   6068          nhop_cursorPtr != NULL; nhop_cursorPtr = nhop_cursorPtr->link) {
   6069         if (nhop_cursorPtr->egr_if == egress_if) {
   6070             return (BCM_E_NONE);
   6071         } 
   6072     }
   6073 
   6074     newNhopNode = (_bcm_mpls_egr_nhopList_t *) 
   6075         sal_alloc (sizeof (_bcm_mpls_egr_nhopList_t), "MPLS Egr Nhop");
   6076     if (NULL == newNhopNode) {
   6077         return (BCM_E_MEMORY); 
   6078     }
   6079     newNhopNode->egr_if = (bcm_if_t) egress_if;
   6080     newNhopNode->vp_head_ptr = ( _bcm_mpls_vp_nh_list_t *) NULL;
   6081     newNhopNode->link = _bcm_tr_mpls_nhop_headPtr[unit][hash_idx];
   6082     _bcm_tr_mpls_nhop_headPtr[unit][hash_idx] = newNhopNode;
   6083     return BCM_E_NONE;
   6084 }
   6085 
   6086 
   6087 /*
   6088  * Function:
   6089  *            _bcm_tr_mpls_delete_egrNhop
   6090  * Purpose:
   6091  *            Delete MPLS Egress NHOP from Hash-table
   6092  * Parameters:
   6093  *           unit	- (IN) bcm device.
   6094  *           egress_if - (IN) Egress Tunnel If
   6095  * Returns:
   6096  *            BCM_E_XXX
   6097  */
   6098 
   6099 STATIC int
   6100 _bcm_tr_mpls_delete_egrNhop (int unit,  bcm_if_t egress_if )
   6101 {
   6102     _bcm_mpls_egr_nhopList_t  *nhop_cursorPtr;
   6103     _bcm_mpls_egr_nhopList_t  *removeNode;
   6104     int   hash_idx;
   6105 
   6106     (void) _bcm_tr_mpls_compute_nhop_hash (egress_if, &hash_idx);
   6107 
   6108     removeNode = _bcm_tr_mpls_nhop_headPtr[unit][hash_idx];
   6109     if (removeNode != NULL)  {
   6110         if (removeNode->egr_if ==  egress_if) {
   6111             if (removeNode->vp_head_ptr == NULL) {
   6112                 _bcm_tr_mpls_nhop_headPtr[unit][hash_idx] = removeNode->link;
   6113                 sal_free (removeNode);
   6114                 return BCM_E_NONE;
   6115             } else {
   6116                 return BCM_E_BUSY;
   6117             }
   6118         } else {
   6119             for (nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][hash_idx]; 
   6120                  nhop_cursorPtr->link != NULL; nhop_cursorPtr = nhop_cursorPtr->link) {
   6121                 if (nhop_cursorPtr->link->egr_if ==  egress_if) {
   6122                     if (nhop_cursorPtr->link->vp_head_ptr == NULL) {
   6123                         removeNode = nhop_cursorPtr->link;
   6124                         nhop_cursorPtr->link = removeNode->link;
   6125                         sal_free (removeNode);
   6126                         return BCM_E_NONE;
   6127                     } else {
   6128                         return BCM_E_BUSY;
   6129                     }
   6130                 }
   6131             }
   6132         }
   6133     }
   6134     return BCM_E_NOT_FOUND;
   6135 } 
   6136 
   6137 /*
   6138  * Function:
   6139  *            _bcm_tr_mpls_delete_vp_nh
   6140  * Purpose:
   6141  *            Delete VP NextHop information from List
   6142  * Parameters:
   6143  *           unit - (IN) bcm device.
   6144  *           vp_idx - (IN) VP NextHop Index
   6145  *           egress_if - (IN) Egress Tunnel If
   6146  * Returns:
   6147  *            BCM_E_XXX
   6148  */
   6149 
   6150 STATIC int
   6151 _bcm_tr_mpls_delete_vp_nh ( int unit,  int vp_idx, bcm_if_t egress_if)
   6152 {
   6153     _bcm_mpls_egr_nhopList_t  *nhop_cursorPtr;
   6154     _bcm_mpls_vp_nh_list_t  *vp_cursorPtr;
   6155     _bcm_mpls_vp_nh_list_t  *vpRemoveNode;	
   6156     int   hash_idx;
   6157 
   6158     (void) _bcm_tr_mpls_compute_nhop_hash (egress_if, &hash_idx);
   6159 
   6160     for (nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][hash_idx]; 
   6161          nhop_cursorPtr != NULL; nhop_cursorPtr = nhop_cursorPtr->link) {
   6162         vp_cursorPtr = nhop_cursorPtr->vp_head_ptr;
   6163         if (vp_cursorPtr  != NULL) {
   6164             if (vp_cursorPtr->vp_nh_idx == vp_idx)  {
   6165                 nhop_cursorPtr->vp_head_ptr = vp_cursorPtr->link;
   6166                 sal_free (vp_cursorPtr);
   6167                 if (nhop_cursorPtr->vp_head_ptr == NULL) {
   6168                     BCM_IF_ERROR_RETURN(
   6169                         _bcm_tr_mpls_delete_egrNhop (unit, nhop_cursorPtr->egr_if));
   6170                 }
   6171                 return BCM_E_NONE;
   6172             } else {
   6173                 for ( ; vp_cursorPtr->link != NULL; vp_cursorPtr = vp_cursorPtr->link){
   6174                     if (vp_cursorPtr->link->vp_nh_idx == vp_idx) {
   6175                         vpRemoveNode = vp_cursorPtr->link;
   6176                         vp_cursorPtr->link = vpRemoveNode->link;
   6177                         sal_free (vpRemoveNode);
   6178                         return BCM_E_NONE;
   6179                     }
   6180                 }
   6181             } 
   6182         }
   6183     }
   6184     return BCM_E_NOT_FOUND;
   6185 }
   6186 
   6187 /*
   6188  * Function:
   6189  *       _bcm_tr_mpls_cleanup_egrNhop
   6190  * Purpose:
   6191  *      Cleanup MPLS Egress NHOP from Hash-table
   6192  * Parameters:
   6193  *      unit - (IN) bcm device.
   6194  * Returns:
   6195  *      BCM_E_XXX
   6196  */
   6197 
   6198 STATIC void
   6199 _bcm_tr_mpls_cleanup_egrNhop (int unit)
   6200 {
   6201     _bcm_mpls_egr_nhopList_t  *nhop_cursorPtr;
   6202     _bcm_mpls_vp_nh_list_t	*vp_cursorPtr;
   6203     int   index;
   6204 
   6205     for(index=0; index < _BCM_TR_MPLS_HASH_ELEMENTS; ++index) {
   6206         if (_bcm_tr_mpls_nhop_headPtr[unit][index] != NULL) {
   6207             nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][index];
   6208             while ( nhop_cursorPtr != NULL ) {
   6209                 vp_cursorPtr = nhop_cursorPtr->vp_head_ptr;
   6210                 while (vp_cursorPtr != NULL) {
   6211                     (void)_bcm_tr_mpls_delete_vp_nh (unit, vp_cursorPtr->vp_nh_idx,
   6212                                                      nhop_cursorPtr->egr_if);
   6213                     nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][index];
   6214                     if (nhop_cursorPtr != NULL) {
   6215                         vp_cursorPtr = nhop_cursorPtr->vp_head_ptr;
   6216                     } else {
   6217                         vp_cursorPtr = NULL;
   6218                     }
   6219                 }
   6220             }
   6221         }
   6222     }
   6223 } 
   6224 
   6225 /* 
   6226  * Function:   * Function: 
   6227  *              bcm_tr_mpls_get_vp_nh 
   6228  * Purpose: 
   6229  *              Find whether  VP NextHop is present within list 
   6230  * Parameters: 
   6231  *              unit    - (IN) bcm device. 
   6232  *              vp_idx   - (IN) VP NextHop Index
   6233  *              egress_if - (OUT) Egr_If
   6234  * Returns: 
   6235  *              BCM_E_XXX 
   6236  */ 
   6237      
   6238 int 
   6239 bcm_tr_mpls_get_vp_nh (int unit, int vp_index, bcm_if_t *egress_if) 
   6240 { 
   6241     _bcm_mpls_egr_nhopList_t  *nhop_cursorPtr; 
   6242     _bcm_mpls_vp_nh_list_t *vp_cursorPtr; 
   6243     int   index; 
   6244 
   6245     for(index=0; index < _BCM_TR_MPLS_HASH_ELEMENTS; ++index) {
   6246         if (_bcm_tr_mpls_nhop_headPtr[unit][index] != NULL) {
   6247             for (nhop_cursorPtr = _bcm_tr_mpls_nhop_headPtr[unit][index]; 
   6248                  nhop_cursorPtr != NULL; nhop_cursorPtr = nhop_cursorPtr->link) { 
   6249                 for (vp_cursorPtr = nhop_cursorPtr->vp_head_ptr; 
   6250                      vp_cursorPtr != NULL; vp_cursorPtr = vp_cursorPtr->link) { 
   6251                     if (vp_index == vp_cursorPtr->vp_nh_idx) {
   6252                         *egress_if = nhop_cursorPtr->egr_if;
   6253                         return BCM_E_NONE; 
   6254                     }
   6255                 } 
   6256             }
   6257         }
   6258     }
   6259     return BCM_E_NOT_FOUND; 
   6260 }
   6261 
   6262 /* 
   6263  * Function:   * Function: 
   6264  *              _bcm_tr_mpls_create_vp_nh 
   6265  * Purpose: 
   6266  *              Allocate MPLS VP NextHop index entry
   6267  * Parameters: 
   6268  *              unit    - (IN) bcm device. 
   6269  *              egress_if - (IN) Egr_If
   6270  *              vp_nh_index   - (OUT) NextHop Index
   6271  * Returns: 
   6272  *              BCM_E_XXX 
   6273  */ 
   6274      
   6275 STATIC int 
   6276 _bcm_tr_mpls_create_vp_nh ( int unit, bcm_if_t  egress_tunnel_if,
   6277                              int  *vp_nh_index, bcm_mpls_port_t *mpls_port)
   6278 {
   6279     int rv;
   6280     bcm_l3_egress_t nh_info;
   6281     uint32 nh_flags;
   6282     int flags = mpls_port->flags;
   6283     int failover_nh_index = -1;
   6284     int failover_vp;
   6285     int i = 0;
   6286     int num_elements = 1;
   6287     ing_dvp_table_entry_t failover_dvp;
   6288     /*
   6289      * Allocate MPLS VP next-hop entry. By calling bcm_xgs3_nh_add()
   6290      * with _BCM_L3_SHR_WRITE_DISABLE flag, a next-hop index is
   6291      * allocated but nothing is written to hardware. The "nh_info"
   6292      * in this case is not used, so just set to all zeros.
   6293      */
   6294 
   6295     bcm_l3_egress_t_init(&nh_info);
   6296 
   6297     nh_info.failover_id       = mpls_port->failover_id;
   6298     nh_info.failover_mc_group = mpls_port->failover_mc_group;
   6299 
   6300     failover_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id);
   6301     if (failover_vp !=-1) {
   6302         BCM_IF_ERROR_RETURN(READ_ING_DVP_TABLEm(
   6303             unit, MEM_BLOCK_ANY, failover_vp, &failover_dvp));
   6304 
   6305         failover_nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &failover_dvp,
   6306                                              NEXT_HOP_INDEXf);
   6307         failover_nh_index += BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   6308     }
   6309 
   6310     nh_info.failover_if_id    = failover_nh_index;
   6311 
   6312     nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE;
   6313     if (flags & BCM_MPLS_PORT_ENCAP_WITH_ID) {
   6314         nh_flags |= _BCM_L3_SHR_WITH_ID | _BCM_L3_SHR_UPDATE;
   6315     }
   6316     BCM_IF_ERROR_RETURN(bcm_xgs3_nh_add(unit, nh_flags, &nh_info, vp_nh_index));
   6317 
   6318     rv = _bcm_tr_mpls_add_egrNhop (unit, egress_tunnel_if);
   6319     if (rv < 0) {
   6320        num_elements = bcmi_l3_nh_multi_count_get(unit, *vp_nh_index);
   6321        for (; i<num_elements; i++) {
   6322            (void) bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, *vp_nh_index+i);
   6323         }
   6324         return rv;
   6325     }
   6326 
   6327     rv = _bcm_tr_mpls_add_vp_nh (unit, egress_tunnel_if, *vp_nh_index);
   6328     if (rv < 0) {
   6329        num_elements = bcmi_l3_nh_multi_count_get(unit, *vp_nh_index);
   6330        for (; i<num_elements; i++) {
   6331            (void) bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, *vp_nh_index+i);
   6332         }
   6333        (void) _bcm_tr_mpls_delete_egrNhop (unit, egress_tunnel_if);
   6334     }
   6335 
   6336    return rv;
   6337 }
   6338 
   6339 #ifdef BCM_KATANA_SUPPORT
   6340 /*
   6341  * Function:
   6342  *      _bcm_tr_mpls_ing_queue_map_ref_count_adjust
   6343  * Purpose:
   6344  *      Increment / Decrement Reference Count for Ingress Queue Map
   6345  * Parameters:
   6346  *      unit              Unit number
   6347  *      index            (IN) Entry Index
   6348  *      step              (IN) usage reference
   6349  */
   6350 
   6351 STATIC void
   6352 _bcm_tr_mpls_ing_queue_map_ref_count_adjust (int unit, int index, int step)
   6353 {
   6354     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   6355 
   6356     if (( mpls_info->ing_qmap_ref_count[index] == 0 ) && (step < 0)) {
   6357          mpls_info->ing_qmap_ref_count[index] = 0;
   6358     } else {
   6359          mpls_info->ing_qmap_ref_count[index] += step;
   6360     }
   6361 }
   6362 
   6363 /*
   6364  * Function:
   6365  *       _bcm_tr_mpls_ing_queue_map_index_reset
   6366  * Purpose:
   6367  *       Reset  ING_QUEUE_MAP_TABLE entry
   6368  * Parameters:
   6369  *           IN :  Unit
   6370  *           IN : ing_queue_map_index
   6371  * Returns:
   6372  *            BCM_E_XXX
   6373  */
   6374 STATIC int
   6375 _bcm_tr_mpls_ing_queue_map_index_reset (int unit, int ing_queue_map_index)
   6376 {
   6377     ing_queue_map_entry_t  ing_queue_entry;
   6378     int rv = BCM_E_NONE;
   6379     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   6380 
   6381     if ( mpls_info->ing_qmap_ref_count[ing_queue_map_index] != 0 ) {
   6382          return BCM_E_NONE;
   6383     }
   6384 
   6385     sal_memset(&ing_queue_entry, 0,
   6386               sizeof(ing_queue_map_entry_t));
   6387 
   6388     rv = BCM_XGS3_MEM_WRITE(unit, ING_QUEUE_MAPm,
   6389                             ing_queue_map_index, &ing_queue_entry);
   6390 
   6391     return rv;
   6392 }
   6393 #endif /* BCM_KATANA_SUPPORT */
   6394 
   6395 #if defined(BCM_TRIUMPH3_SUPPORT)
   6396 /*
   6397  * Function:
   6398  *       _bcm_tr_mpls_vc_swap_table_hash_nhop_alloc
   6399  * Purpose:
   6400  *       Allocate an nhop entry for vc and swap hash
   6401  * Parameters:
   6402  *       unit           - (IN) Device Number
   6403  *       nh_index    -(IN) Next hop index
   6404  * Returns:
   6405  *       The pointer of nhop entry
   6406  */
   6407 
   6408 bcm_tr_mpls_vc_swap_table_nhop_list_t *
   6409 _bcm_tr_mpls_vc_swap_table_hash_nhop_alloc(int unit, int nh_index)
   6410 {
   6411     bcm_tr_mpls_vc_swap_table_nhop_list_t *ptr;
   6412     ptr =  sal_alloc(sizeof(bcm_tr_mpls_vc_swap_table_nhop_list_t),
   6413                      "vc and swap table hash nhop list");
   6414     sal_memset(ptr, 0, sizeof(bcm_tr_mpls_vc_swap_table_nhop_list_t));
   6415 
   6416     ptr->nh_index = nh_index;
   6417     ptr->next = NULL;
   6418 
   6419     return ptr;
   6420 }
   6421 /*
   6422  * Function:
   6423  *       _bcm_tr_mpls_vc_and_swap_hash_nhop_delete
   6424  * Purpose:
   6425  *       Delete an nhop entry from vc and swap hash
   6426  * Parameters:
   6427  *       unit                  - (IN) Device Number
   6428  *       vc_swap_index   -(IN) Vc and swap table index
   6429  *       nh_index           -(IN) Next hop index
   6430  * Returns:
   6431  *       BCM_E_XXX
   6432  */
   6433 STATIC int
   6434 _bcm_tr_mpls_vc_and_swap_hash_nhop_delete (int unit, int vc_swap_index,
   6435                                                            int nh_index)
   6436 {
   6437     int hash_idx;
   6438     bcm_tr_mpls_vc_swap_table_hash_t *hash_input;
   6439     bcm_tr_mpls_vc_swap_table_hash_entry_t *temp_hash;
   6440     bcm_tr_mpls_vc_swap_table_nhop_list_t *temp_nhop, *prev_nhop;
   6441     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
   6442     int action = 0;
   6443 
   6444     /* Entry 0 is reserved with _bcm_tr_mpls_default_entry_setup during init */
   6445     if (vc_swap_index == VC_AND_SWAP_TABLE_RESV_INDEX) {
   6446         LOG_INFO(BSL_LS_BCM_L3,
   6447                 (BSL_META_U(unit,"Not resetting reserved index: %d in "
   6448                             "VC AND SWAP TABLE\n"), VC_AND_SWAP_TABLE_RESV_INDEX));
   6449         return BCM_E_NONE;
   6450     }
   6451 
   6452     BCM_IF_ERROR_RETURN(
   6453         soc_mem_read(unit,
   6454                      EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6455                      MEM_BLOCK_ALL, vc_swap_index, &vc_entry));
   6456 
   6457 #ifdef BCM_TRIDENT3_SUPPORT
   6458     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   6459         if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) {
   6460             action = MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index];
   6461         }
   6462     } else
   6463 #endif
   6464     {
   6465         action = 0;
   6466     }
   6467 
   6468     BCM_IF_ERROR_RETURN(
   6469         bcmi_tr_mpls_vc_swap_hash_index_get(unit, NULL, action, NULL, NULL,
   6470                                             &vc_entry, &hash_idx));
   6471     hash_input = &(bcmi_vc_swap_label_hash[unit][hash_idx]);
   6472     temp_hash = hash_input->head_link;
   6473     while (temp_hash) {
   6474         if (temp_hash->index == vc_swap_index) {
   6475             temp_nhop = prev_nhop = temp_hash->nhop_list;
   6476             while (temp_nhop) {
   6477                 if (temp_nhop->nh_index == nh_index) {
   6478                     if (temp_nhop == temp_hash->nhop_list) {
   6479                         temp_hash->nhop_list = temp_nhop->next;
   6480                     } else {
   6481                         prev_nhop->next = temp_nhop->next;
   6482                     }
   6483                     sal_free(temp_nhop);
   6484                     return BCM_E_NONE;
   6485                 }
   6486                 prev_nhop = temp_nhop;
   6487                 temp_nhop = temp_nhop->next;
   6488             }
   6489             return BCM_E_NOT_FOUND;
   6490         }
   6491         temp_hash = temp_hash->link;
   6492     }
   6493     return BCM_E_NOT_FOUND;
   6494 }
   6495 /*
   6496  * Function:
   6497  *       _bcm_tr_mpls_vc_and_swap_hash_nhop_add
   6498  * Purpose:
   6499  *       Add an nhop entry to vc and swap hash
   6500  * Parameters:
   6501  *       unit                  - (IN) Device Number
   6502  *       vc_swap_index   -(IN) Vc and swap table index
   6503  *       nh_index           -(IN) Next hop index
   6504  * Returns:
   6505  *       BCM_E_XXX
   6506  */
   6507 
   6508 STATIC int
   6509 _bcm_tr_mpls_vc_and_swap_hash_nhop_add (int unit, int vc_swap_index,
   6510                                                         int nh_index)
   6511 {
   6512     int hash_idx;
   6513     bcm_tr_mpls_vc_swap_table_hash_t *hash_input;
   6514     bcm_tr_mpls_vc_swap_table_hash_entry_t *temp_hash;
   6515     bcm_tr_mpls_vc_swap_table_nhop_list_t *new_entry;
   6516     bcm_tr_mpls_vc_swap_table_nhop_list_t *temp_nhop, *prev_nhop;
   6517     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
   6518 
   6519     BCM_IF_ERROR_RETURN(
   6520         soc_mem_read(unit,
   6521                      EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6522                      MEM_BLOCK_ALL, vc_swap_index, &vc_entry));
   6523 
   6524     BCM_IF_ERROR_RETURN(
   6525         bcmi_tr_mpls_vc_swap_hash_index_get(unit, NULL, 0, NULL, NULL,
   6526                                             &vc_entry, &hash_idx));
   6527 
   6528     new_entry = _bcm_tr_mpls_vc_swap_table_hash_nhop_alloc(unit, nh_index);
   6529     if (new_entry == NULL) {
   6530         return BCM_E_MEMORY;
   6531     }
   6532     hash_input = &(bcmi_vc_swap_label_hash[unit][hash_idx]);
   6533     temp_hash = hash_input->head_link;
   6534     while (temp_hash) {
   6535         if (temp_hash->index == vc_swap_index) {
   6536             temp_nhop = prev_nhop = temp_hash->nhop_list;
   6537             while (temp_nhop) {
   6538                 prev_nhop = temp_nhop;
   6539                 temp_nhop = temp_nhop->next;
   6540             }
   6541             if (prev_nhop == temp_nhop) {
   6542                 temp_hash->nhop_list = new_entry;
   6543             } else {
   6544                 prev_nhop->next = new_entry;
   6545             }
   6546             return BCM_E_NONE;
   6547         }
   6548         temp_hash = temp_hash->link;
   6549     }
   6550     /* No entry was found, return BCM_E_NOT_FOUND */
   6551     sal_free(new_entry);
   6552     return BCM_E_NOT_FOUND;
   6553 }
   6554 #endif  /* BCM_TRIUMPH3_SUPPORT*/
   6555 /*
   6556  * Function:
   6557  *      _bcm_tr_mpls_vc_and_swap_ref_count_adjust
   6558  * Purpose:
   6559  *      Increment / Decrement Reference Count for VC usage
   6560  * Parameters:
   6561  *      unit              Unit number
   6562  *      index            (IN) Entry Index
   6563  *      step              (IN) usage reference
   6564  */
   6565 
   6566 void
   6567 _bcm_tr_mpls_vc_and_swap_ref_count_adjust (int unit, int index, int step)
   6568 {
   6569     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   6570 
   6571     if (( mpls_info->vc_swap_ref_count[index] == 0 ) && (step < 0)) {
   6572          mpls_info->vc_swap_ref_count[index] = 0;
   6573     } else {
   6574          mpls_info->vc_swap_ref_count[index] += step;
   6575     }
   6576 
   6577 }
   6578 
   6579 STATIC void
   6580 _bcm_tr_mpls_vc_and_swap_ref_count_get(int unit, int index, int *cnt_value)
   6581 {
   6582     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   6583     *cnt_value = mpls_info->vc_swap_ref_count[index];
   6584 }
   6585 
   6586 STATIC void
   6587 _bcm_tr_mpls_vc_and_swap_ref_count_reset(int unit, int index)
   6588 {
   6589     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   6590     mpls_info->vc_swap_ref_count[index] = 0;
   6591 }
   6592 /*
   6593  * Function:
   6594  *     bcmi_tr_mpls_vc_swap_hash_key_get 
   6595  * Purpose:
   6596  *     Generate hash key from incoming entry
   6597  * Parameters:
   6598  *     IN  :  Unit
   6599  *     IN  :  mpls port entry
   6600  *     IN  :  next hop entry
   6601  *     IN  :  action
   6602  *     IN  :  VC table entry
   6603  *     IN  :  key buffer to be filled in 
   6604  * Returns:
   6605  *     BCM_E_XXX
   6606  */
   6607 int
   6608 bcmi_tr_mpls_vc_swap_hash_key_get(int unit, bcm_mpls_port_t *mpls_port,
   6609                              bcm_mpls_tunnel_switch_t *info, 
   6610                              bcm_l3_egress_t *egr_obj, int action,
   6611                              egr_mpls_vc_and_swap_label_table_entry_t *vc_entry,
   6612                              int *key)
   6613 {   
   6614 
   6615     if (key == NULL) {
   6616         return BCM_E_INTERNAL;
   6617     }
   6618     /* make sure that key is zeroed out from wherever it is coming. */
   6619     sal_memset(key, 0, sizeof(int) * BCM_TR_MPLS_VC_SWAP_KEY_LEN_IN_WORDS);
   6620 
   6621     /* Get hash key from various mpls_port, label info, egress_obj, hw_entry.
   6622         below is the key.
   6623         key[0] = label
   6624         key[1] = action
   6625 
   6626         All the fields will default to 0 if not present. 
   6627      */
   6628     if (mpls_port != NULL) {
   6629         key[0] = mpls_port->egress_label.label;
   6630         key[1] = action;
   6631 
   6632     } else if (info !=NULL) {
   6633 
   6634         key[0] = info->egress_label.label;
   6635         key[1] = action;
   6636 
   6637     } else if (egr_obj != NULL) {
   6638         key[0] = egr_obj->mpls_label;
   6639         key[1] = action;
   6640     } else if (vc_entry != NULL) {
   6641         key[0] = SOC_MEM_VC_SWAP_F32_GET(unit,
   6642                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6643                         vc_entry, MPLS_LABELf);
   6644 
   6645 #ifdef BCM_TRIDENT3_SUPPORT
   6646         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   6647             key[1] = action;
   6648         } else
   6649 #endif
   6650         {
   6651         key[1] = SOC_MEM_VC_SWAP_F32_GET(unit,
   6652                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6653                         vc_entry, MPLS_LABEL_ACTIONf);
   6654         }
   6655 
   6656     }
   6657 #if defined(BCM_SWAP_TO_SELF_SUPPORT)
   6658     if (soc_feature(unit, soc_feature_mpls_swap_label_preserve)) {
   6659         if (key[1] == _BCM_MPLS_ACTION_PRESERVED) {
   6660             key[0] = 0;
   6661             return BCM_E_NONE;
   6662         }
   6663     }
   6664 #endif
   6665 
   6666 /* if the label is invalid then set the key as 0 */
   6667     if (key[0] == BCM_MPLS_LABEL_INVALID) {
   6668         key[0] = 0;
   6669         key[1] = _BCM_MPLS_ACTION_NOOP;
   6670     }
   6671 
   6672     return BCM_E_NONE;
   6673 }
   6674 
   6675 /*
   6676  * Function:
   6677  *       _bcm_tr_mpls_vc_swap_compare 
   6678  * Purpose:
   6679  *       Compare two incoming entries
   6680  * Parameters:
   6681  *       IN  :  Unit
   6682  *       IN  :  mpls port entry
   6683  *       IN  :  next hop entry
   6684  *       IN  :  action
   6685  *       IN  :  VC table entry
   6686 
   6687  * Returns:
   6688  *       BCM_E_XXX
   6689  */
   6690 STATIC int
   6691 _bcm_tr_mpls_vc_swap_compare(int unit, bcm_mpls_port_t *mpls_port,
   6692                bcm_mpls_tunnel_switch_t *info, 
   6693                bcm_l3_egress_t *egr_obj,
   6694                egr_mpls_vc_and_swap_label_table_entry_t *in_vc_entry,
   6695                int label_action,
   6696                egr_mpls_vc_and_swap_label_table_entry_t *vc_entry)
   6697 {
   6698     bcm_mpls_label_t entry_label;
   6699     uint32 ttl, entry_label_action, cw, exp;
   6700     uint32 cfi, pri;
   6701     uint32 sd_tag, sd_tag_action_present, sd_tag_action_not_present;
   6702     uint32 exp_select, pri_mapping_ptr;
   6703     int map_inx;
   6704 
   6705     if (mpls_port != NULL) {
   6706          entry_label = SOC_MEM_VC_SWAP_F32_GET(unit, 
   6707                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6708                         vc_entry, MPLS_LABELf);
   6709          if (entry_label != mpls_port->egress_label.label) {
   6710              return BCM_E_NOT_FOUND;
   6711          }
   6712          entry_label_action = SOC_MEM_VC_SWAP_F32_GET(unit,
   6713                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,vc_entry, 
   6714                         MPLS_LABEL_ACTIONf);
   6715          if (label_action != entry_label_action) {
   6716              return BCM_E_NOT_FOUND;
   6717          }
   6718          ttl = SOC_MEM_VC_SWAP_F32_GET(unit,
   6719                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6720                         vc_entry, MPLS_TTLf);
   6721          if (mpls_port->egress_label.flags & BCM_MPLS_EGRESS_LABEL_TTL_SET &&
   6722              ttl != mpls_port->egress_label.ttl) {
   6723              return BCM_E_NOT_FOUND;
   6724          }
   6725          cw = SOC_MEM_VC_SWAP_F32_GET(unit,
   6726                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6727                         vc_entry, CW_INSERT_FLAGf);
   6728          if (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED && cw != 0x2) {
   6729              return BCM_E_NOT_FOUND;
   6730          } else if (mpls_port->flags & BCM_MPLS_PORT_CONTROL_WORD && cw != 0x1) {
   6731              return BCM_E_NOT_FOUND;
   6732          } else if ((cw != 0) &&
   6733              (!(mpls_port->flags & BCM_MPLS_PORT_CONTROL_WORD) &&
   6734              !(mpls_port->flags & BCM_MPLS_PORT_SEQUENCED))) {
   6735              return BCM_E_NOT_FOUND;
   6736          }
   6737          exp = SOC_MEM_VC_SWAP_F32_GET(unit,
   6738                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6739                         vc_entry, MPLS_EXPf);
   6740          pri = SOC_MEM_VC_SWAP_F32_GET(unit,
   6741                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6742                         vc_entry, NEW_PRIf);
   6743          cfi = SOC_MEM_VC_SWAP_F32_GET(unit,
   6744                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6745                         vc_entry, NEW_CFIf);
   6746          if ((mpls_port->egress_label.flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) ||
   6747              (mpls_port->egress_label.flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) {
   6748              if (exp != mpls_port->egress_label.exp) {
   6749                  return BCM_E_NOT_FOUND;
   6750              }
   6751              if (pri != mpls_port->egress_label.pkt_pri) {
   6752                  return BCM_E_NOT_FOUND;
   6753              }
   6754              if (cfi != mpls_port->egress_label.pkt_cfi) {
   6755                  return BCM_E_NOT_FOUND;
   6756              }
   6757          } else if (exp || pri || cfi) {
   6758              return BCM_E_NOT_FOUND;
   6759          }
   6760          sd_tag = SOC_MEM_VC_SWAP_F32_GET(unit,
   6761                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6762                         vc_entry, SD_TAG_VIDf);
   6763          sd_tag_action_present = SOC_MEM_VC_SWAP_F32_GET(unit,
   6764                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6765                         vc_entry, SD_TAG_ACTION_IF_PRESENTf);
   6766          sd_tag_action_not_present = SOC_MEM_VC_SWAP_F32_GET(unit,
   6767                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6768                         vc_entry, SD_TAG_ACTION_IF_NOT_PRESENTf);
   6769          if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) {
   6770              if (sd_tag != mpls_port->egress_service_vlan ||
   6771                  sd_tag_action_not_present != 0x1) {
   6772                  return BCM_E_NOT_FOUND;
   6773              }
   6774          } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) {
   6775              if (sd_tag != mpls_port->egress_service_vlan ||
   6776                  sd_tag_action_present != 0x1) {
   6777                  return BCM_E_NOT_FOUND;
   6778              }
   6779          } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_REPLACE) {
   6780               if (sd_tag != mpls_port->egress_service_vlan ||
   6781                  sd_tag_action_present != 0x2) {
   6782                  return BCM_E_NOT_FOUND;
   6783               }
   6784          } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_DELETE) {
   6785              if (sd_tag_action_present != 0x3) {
   6786                  return BCM_E_NOT_FOUND;
   6787              }
   6788          } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE) {
   6789              if (sd_tag_action_present != 0x4) {
   6790                  return BCM_E_NOT_FOUND;
   6791              }
   6792          } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_REPLACE) {
   6793              if (sd_tag_action_present != 0x5) {
   6794                  return BCM_E_NOT_FOUND;
   6795              }
   6796          } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_PRI_REPLACE) {
   6797              if (sd_tag_action_present != 0x6) {
   6798                  return BCM_E_NOT_FOUND;
   6799              }
   6800          } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE) {
   6801              if (sd_tag_action_present != 0x7) {
   6802                  return BCM_E_NOT_FOUND;
   6803              }
   6804          } else if (sd_tag_action_present) {
   6805              return BCM_E_NOT_FOUND;
   6806          }
   6807 
   6808 #ifdef BCM_TRIDENT3_SUPPORT
   6809         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   6810             if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6811                         vc_entry, SPECIAL_LABEL_PUSH_TYPEf)) {
   6812                 return BCM_E_NOT_FOUND;
   6813             }
   6814         }
   6815 #endif
   6816 
   6817     } else if (info != NULL) {
   6818 #ifdef BCM_TRIDENT3_SUPPORT
   6819         int vc_data_type = 0;
   6820 
   6821         if (SOC_MEM_FIELD_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6822                                 DATA_TYPEf)) {
   6823             vc_data_type = soc_mem_field32_get(unit,
   6824                                                EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6825                                                vc_entry, DATA_TYPEf);
   6826         }
   6827 
   6828         if (soc_feature(unit, soc_feature_td3_style_mpls) &&
   6829             (vc_data_type == _BCM_VC_SWAP_TBL_FLEX_DATA_TYPE)) {
   6830             uint32 flex_pdd_format[2];
   6831             int spl_label_push_type = 0;
   6832 
   6833             sal_memset(flex_pdd_format, 0, sizeof(flex_pdd_format));
   6834 
   6835             soc_mem_field_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6836                               (uint32 *) vc_entry,
   6837                               MPLS_PHP__MPLS_ENTRY_0_ACTION_SETf,
   6838                               (uint32 *) flex_pdd_format);
   6839 
   6840             ttl = soc_format_field32_get(unit,
   6841                       MPLS_ENTRY_ACTION_SETfmt,
   6842                       (uint32 *)flex_pdd_format, MPLS_TTLf);
   6843             if ( ttl != info->egress_label.ttl) {
   6844                 return BCM_E_NOT_FOUND;
   6845             }
   6846 
   6847             exp = soc_format_field32_get(unit,
   6848                       MPLS_ENTRY_ACTION_SETfmt,
   6849                       (uint32 *)flex_pdd_format, MPLS_EXPf);
   6850             if (exp != info->egress_label.exp) {
   6851                 return BCM_E_NOT_FOUND;
   6852             }
   6853 
   6854             pri = soc_format_field32_get(unit,
   6855                       MPLS_ENTRY_ACTION_SETfmt,
   6856                       (uint32 *)flex_pdd_format, NEW_PRIf);
   6857             if (pri != info->egress_label.pkt_pri) {
   6858                 return BCM_E_NOT_FOUND;
   6859             }
   6860 
   6861             cfi = soc_format_field32_get(unit,
   6862                       MPLS_ENTRY_ACTION_SETfmt,
   6863                       (uint32 *)flex_pdd_format, NEW_CFIf);
   6864             if (cfi != info->egress_label.pkt_cfi) {
   6865                 return BCM_E_NOT_FOUND;
   6866             }
   6867 
   6868             spl_label_push_type = soc_format_field32_get(unit,
   6869                                       MPLS_ENTRY_ACTION_SETfmt,
   6870                                       (uint32 *)flex_pdd_format,
   6871                                       SPECIAL_LABEL_PUSH_TYPEf);
   6872 
   6873             if (spl_label_push_type != info->egress_label.spl_label_push_type) {
   6874                 return BCM_E_NOT_FOUND;
   6875             }
   6876         } else
   6877 #endif
   6878         {
   6879             if (!(_BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, info->egress_label.flags))) {
   6880                 entry_label = SOC_MEM_VC_SWAP_F32_GET(unit,
   6881                                   EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6882                                   vc_entry, MPLS_LABELf);
   6883                 if (entry_label != info->egress_label.label) {
   6884                     return BCM_E_NOT_FOUND;
   6885                 }
   6886             }
   6887             entry_label_action = SOC_MEM_VC_SWAP_F32_GET(unit,
   6888                             EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6889                             vc_entry, MPLS_LABEL_ACTIONf);
   6890             if (label_action != entry_label_action) {
   6891                 return BCM_E_NOT_FOUND;
   6892             }
   6893             ttl = SOC_MEM_VC_SWAP_F32_GET(unit,
   6894                             EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6895                             vc_entry, MPLS_TTLf);
   6896             if ( ttl != info->egress_label.ttl) {
   6897                 return BCM_E_NOT_FOUND;
   6898             }
   6899             exp = SOC_MEM_VC_SWAP_F32_GET(unit,
   6900                             EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6901                             vc_entry, MPLS_EXPf);
   6902 
   6903             if (exp != info->egress_label.exp) {
   6904                 return BCM_E_NOT_FOUND;
   6905             }
   6906 
   6907             pri = SOC_MEM_VC_SWAP_F32_GET(unit,
   6908                             EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6909                             vc_entry, NEW_PRIf);
   6910 
   6911             if (pri != info->egress_label.pkt_pri) {
   6912                 return BCM_E_NOT_FOUND;
   6913             }
   6914 
   6915             cfi = SOC_MEM_VC_SWAP_F32_GET(unit,
   6916                             EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6917                             vc_entry, NEW_CFIf);
   6918 
   6919             if (cfi != info->egress_label.pkt_cfi) {
   6920                 return BCM_E_NOT_FOUND;
   6921             }
   6922 #ifdef BCM_TRIDENT3_SUPPORT
   6923             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   6924                 if ((soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6925                         vc_entry, SPECIAL_LABEL_PUSH_TYPEf)) !=
   6926                             info->egress_label.spl_label_push_type) {
   6927                     return BCM_E_NOT_FOUND;
   6928                 }
   6929             }
   6930 #endif
   6931         }
   6932      } else if (egr_obj != NULL) {
   6933         if (!(_BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, egr_obj->mpls_flags))) {
   6934             entry_label = SOC_MEM_VC_SWAP_F32_GET(unit,
   6935                                EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6936                                vc_entry, MPLS_LABELf);
   6937              if (entry_label != egr_obj->mpls_label) {
   6938                  return BCM_E_NOT_FOUND;
   6939              }
   6940          }
   6941          entry_label_action = SOC_MEM_VC_SWAP_F32_GET(unit,
   6942                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6943                         vc_entry, MPLS_LABEL_ACTIONf);
   6944          if (label_action != entry_label_action) {
   6945              return BCM_E_NOT_FOUND;
   6946          }
   6947          ttl = SOC_MEM_VC_SWAP_F32_GET(unit,
   6948                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6949                         vc_entry, MPLS_TTLf);
   6950          if ( ttl != egr_obj->mpls_ttl) {
   6951              return BCM_E_NOT_FOUND;
   6952          }
   6953 
   6954          if ((egr_obj->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) ||
   6955             (egr_obj->mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) {
   6956               exp = SOC_MEM_VC_SWAP_F32_GET(unit,
   6957                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6958                         vc_entry, MPLS_EXPf);
   6959               pri = SOC_MEM_VC_SWAP_F32_GET(unit,
   6960                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6961                         vc_entry, NEW_PRIf);
   6962               cfi = SOC_MEM_VC_SWAP_F32_GET(unit,
   6963                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6964                         vc_entry, NEW_CFIf);
   6965               exp_select = SOC_MEM_VC_SWAP_F32_GET(unit,
   6966                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6967                         vc_entry, MPLS_EXP_SELECTf);
   6968               if (exp_select != 0) {
   6969                   return BCM_E_NOT_FOUND;
   6970               }
   6971               if (exp != egr_obj->mpls_exp) {
   6972                   return BCM_E_NOT_FOUND;
   6973               }
   6974               if (pri != egr_obj->mpls_pkt_pri) {
   6975                   return BCM_E_NOT_FOUND;
   6976               }
   6977               if (cfi != egr_obj->mpls_pkt_cfi) {
   6978                   return BCM_E_NOT_FOUND;
   6979               }
   6980          } else if (egr_obj->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) {
   6981               exp_select = SOC_MEM_VC_SWAP_F32_GET(unit,
   6982                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6983                         vc_entry, MPLS_EXP_SELECTf);
   6984               pri_mapping_ptr = SOC_MEM_VC_SWAP_F32_GET(unit,
   6985                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6986                         vc_entry, MPLS_EXP_MAPPING_PTRf);
   6987               if (exp_select != 1) {
   6988                   return BCM_E_NOT_FOUND;
   6989               }
   6990               BCM_IF_ERROR_RETURN(
   6991                   _egr_qos_id2hw_idx(unit,egr_obj->mpls_qos_map_id,&map_inx));
   6992               if ( pri_mapping_ptr != map_inx) {
   6993                   return BCM_E_NOT_FOUND;
   6994               }
   6995          } else if ((egr_obj->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) &&
   6996                     (label_action != _BCM_MPLS_ACTION_SWAP)) {
   6997               exp_select = SOC_MEM_VC_SWAP_F32_GET(unit,
   6998                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   6999                         vc_entry, MPLS_EXP_SELECTf);
   7000               if (exp_select != 2) {
   7001                   return BCM_E_NOT_FOUND;
   7002               }
   7003               exp = SOC_MEM_VC_SWAP_F32_GET(unit,
   7004                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7005                         vc_entry, MPLS_EXPf);
   7006               if (exp != egr_obj->mpls_exp) {
   7007                   return BCM_E_NOT_FOUND;
   7008               }
   7009               pri_mapping_ptr = SOC_MEM_VC_SWAP_F32_GET(unit,
   7010                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7011                         vc_entry, MPLS_EXP_MAPPING_PTRf);
   7012 
   7013               if (egr_obj->mpls_qos_map_id == 0) { /* use default */
   7014                  map_inx = 0;
   7015               } else {
   7016                   BCM_IF_ERROR_RETURN(
   7017                   _egr_qos_id2hw_idx(unit,egr_obj->mpls_qos_map_id,&map_inx));
   7018               }
   7019               if (pri_mapping_ptr != map_inx) {
   7020                   return BCM_E_NOT_FOUND;              
   7021               }
   7022          } else if ((egr_obj->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) &&
   7023                     (label_action == _BCM_MPLS_ACTION_SWAP)) {
   7024               exp_select = SOC_MEM_VC_SWAP_F32_GET(unit,
   7025                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7026                         vc_entry, MPLS_EXP_SELECTf);
   7027               if (exp_select != 3) {
   7028                   return BCM_E_NOT_FOUND;
   7029               }
   7030               exp = SOC_MEM_VC_SWAP_F32_GET(unit,
   7031                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7032                         vc_entry, MPLS_EXPf);
   7033               if (exp != egr_obj->mpls_exp) {
   7034                   return BCM_E_NOT_FOUND;
   7035               }
   7036               pri_mapping_ptr = SOC_MEM_VC_SWAP_F32_GET(unit,
   7037                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7038                         vc_entry, MPLS_EXP_MAPPING_PTRf);
   7039 
   7040               if (egr_obj->mpls_qos_map_id == 0) { /* use default */
   7041                  map_inx = 0;
   7042               } else {
   7043                   BCM_IF_ERROR_RETURN(
   7044                   _egr_qos_id2hw_idx(unit,egr_obj->mpls_qos_map_id,&map_inx));
   7045               }
   7046               if (pri_mapping_ptr != map_inx) {
   7047                   return BCM_E_NOT_FOUND;              
   7048               }
   7049          }
   7050 #ifdef BCM_TRIDENT3_SUPPORT
   7051         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   7052             if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7053                         vc_entry, SPECIAL_LABEL_PUSH_TYPEf)) {
   7054                 return BCM_E_NOT_FOUND;
   7055             }
   7056         }
   7057 #endif
   7058 
   7059     } else if (in_vc_entry != NULL) {
   7060         if (sal_memcmp(in_vc_entry, vc_entry,
   7061             sizeof(egr_mpls_vc_and_swap_label_table_entry_t))) {
   7062             return BCM_E_NOT_FOUND;
   7063         }
   7064     }
   7065 
   7066     return BCM_E_NONE;
   7067 }
   7068 
   7069 
   7070 /*
   7071  * Function:
   7072  *     bcmi_tr_mpls_vc_swap_hash_index_get
   7073  * Purpose:
   7074  *     Get hash entry for an entry
   7075  * Parameters:
   7076  *     IN  :  Unit
   7077  *     IN  :  mpls port entry
   7078  *     IN  :  action
   7079  *     IN  :  next hop entry
   7080  *     IN  :  VC table entry
   7081  *     OUT :  index
   7082 
   7083  * Returns:
   7084  *     BCM_E_XXX
   7085  */
   7086 int 
   7087 bcmi_tr_mpls_vc_swap_hash_index_get(int unit, bcm_mpls_port_t *mpls_port, 
   7088                        int action, bcm_mpls_tunnel_switch_t *info, 
   7089                        bcm_l3_egress_t *egr_obj, 
   7090                        egr_mpls_vc_and_swap_label_table_entry_t *vc_entry, 
   7091                        int *idx)
   7092 {
   7093     int key[BCM_TR_MPLS_VC_SWAP_KEY_LEN_IN_WORDS];
   7094 
   7095     if ((mpls_port == NULL) && (egr_obj == NULL) && (vc_entry == NULL)
   7096         && (info == NULL)) {
   7097         return BCM_E_PARAM;
   7098     }
   7099 
   7100     sal_memset(key, 0, sizeof(int) * BCM_TR_MPLS_VC_SWAP_KEY_LEN_IN_WORDS);
   7101     /* Generate key for hash table lookup */
   7102     BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_key_get
   7103         (unit, mpls_port, info, egr_obj, action, vc_entry, key));
   7104     LOG_INFO(BSL_LS_SOC_MPLS, (BSL_META_U(unit,
   7105         "Printing Key : Label = %d , label_action = %d\n "), key[0], key[1]));
   7106 
   7107     *idx = _shr_crc16b(0, (uint8*)key, 
   7108         sizeof(int)* BYTES2BITS(BCM_TR_MPLS_VC_SWAP_KEY_LEN_IN_WORDS)) % 
   7109         BCM_TR_MPLS_VC_SWAP_HASH_BUCKETS;
   7110 
   7111     return BCM_E_NONE;
   7112 }
   7113 
   7114 /*
   7115  * Function:
   7116  *     bcmi_tr_mpls_vc_swap_hash_delete 
   7117  * Purpose:
   7118  *     Delete hash table entry
   7119  * Parameters:
   7120  *     IN  :  Unit
   7121  *     IN  :  hash table head
   7122  *     IN  :  table index
   7123  * Returns:
   7124  *     BCM_E_XXX
   7125  */
   7126 int 
   7127 bcmi_tr_mpls_vc_swap_hash_delete(int unit, bcm_tr_mpls_vc_swap_table_hash_t *hash,
   7128                                  int vc_swap_idx)
   7129 {
   7130 
   7131     bcm_tr_mpls_vc_swap_table_hash_entry_t *temp, *prev;
   7132 
   7133     if (hash == NULL) {
   7134         return BCM_E_INTERNAL;
   7135     }
   7136     prev = temp = hash->head_link;
   7137 
   7138     while (temp != NULL) {
   7139         if (temp->index == vc_swap_idx) {
   7140             if (temp == hash->head_link) {
   7141                 hash->head_link = temp->link;
   7142             } else {
   7143                 prev->link = temp->link;
   7144             } 
   7145             sal_free(temp);
   7146             return BCM_E_NONE;
   7147         } else {
   7148             prev = temp;
   7149             temp = temp->link;
   7150         }
   7151     } /* while */
   7152 
   7153     return BCM_E_NOT_FOUND;
   7154 }
   7155 
   7156 /*
   7157  * Function:
   7158  *     bcmi_tr_mpls_vc_swap_hash_cleanup 
   7159  * Purpose:
   7160  *     Clean/Free hash table
   7161  * Parameters:
   7162  *     IN :  Unit
   7163  * Returns:
   7164  *     void
   7165  */
   7166 STATIC void
   7167 bcmi_tr_mpls_vc_swap_hash_cleanup(int unit)
   7168 {
   7169 
   7170     bcm_tr_mpls_vc_swap_table_hash_entry_t *temp;
   7171     bcm_tr_mpls_vc_swap_table_hash_t *hash;
   7172     int i = 0;
   7173 #if defined(BCM_TRIUMPH3_SUPPORT)
   7174     bcm_tr_mpls_vc_swap_table_nhop_list_t *temp_nhop;
   7175 #endif
   7176 
   7177     for (; i < BCM_TR_MPLS_VC_SWAP_HASH_BUCKETS; i++) {
   7178         hash =  &(bcmi_vc_swap_label_hash[unit][i]);
   7179         temp = hash->head_link;
   7180 
   7181         while (temp != NULL) {
   7182             hash->head_link = temp->link;
   7183 #if defined(BCM_TRIUMPH3_SUPPORT)
   7184             if (soc_feature(unit,
   7185                             soc_feature_vc_and_swap_table_overlaid)) {
   7186                 temp_nhop = temp->nhop_list;
   7187                 while (temp_nhop) {
   7188                     temp->nhop_list = temp_nhop->next;
   7189                     sal_free(temp_nhop);
   7190                     temp_nhop = temp->nhop_list;
   7191                 }
   7192             }
   7193 #endif
   7194             sal_free(temp);
   7195             temp = hash->head_link;
   7196         }
   7197     }
   7198     if (bcmi_vc_swap_label_hash[unit]) {
   7199         sal_free(bcmi_vc_swap_label_hash[unit]);
   7200         bcmi_vc_swap_label_hash[unit] = NULL;
   7201     }
   7202 }
   7203 
   7204 
   7205 /*
   7206  * Function:
   7207  *     bcmi_tr_mpls_vc_swap_hash_entry_alloc 
   7208  * Purpose:
   7209  *     Allocates a hash table entry
   7210  * Parameters:
   7211  *     IN  :  Unit
   7212  *     OUT :  entry pointer.
   7213  * Returns:
   7214  *     BCM_E_XXX
   7215  */
   7216 
   7217 STATIC int 
   7218 bcmi_tr_mpls_vc_swap_hash_entry_alloc(int unit, 
   7219                 bcm_tr_mpls_vc_swap_table_hash_entry_t **entry)
   7220 {
   7221 
   7222     bcm_tr_mpls_vc_swap_table_hash_entry_t *new_entry;
   7223 
   7224     new_entry = sal_alloc( sizeof(bcm_tr_mpls_vc_swap_table_hash_entry_t),
   7225                     "hash_table_entry");
   7226 
   7227     if (new_entry == NULL) {
   7228         return BCM_E_MEMORY;
   7229     }
   7230 
   7231     /* Set the link to NULL. adding entry at tail. */
   7232     new_entry->link = NULL;
   7233     new_entry->nhop_list = NULL;
   7234     *entry = new_entry;
   7235 
   7236     return BCM_E_NONE;
   7237 }
   7238 
   7239 /*
   7240  * Function:
   7241  *     bcmi_tr_mpls_vc_swap_hash_insert 
   7242  * Purpose:
   7243  *     Insert vc entry into hash table
   7244  * Parameters:
   7245  *     IN  :  Unit
   7246  *     IN  :  hash table head
   7247  *     IN  :  table index
   7248  *     IN  :  hash index
   7249  *     IN  :  mpls port entry
   7250  *     IN  :  next hop entry
   7251  *     IN  :  VC table entry
   7252  *     OUT :  vc_swap_index
   7253  *     IN  :  Compare Option
   7254  * Returns:
   7255  *      BCM_E_XXX
   7256  */
   7257 int 
   7258 bcmi_tr_mpls_vc_swap_hash_insert(int unit, 
   7259             bcm_tr_mpls_vc_swap_table_hash_t *hash,
   7260             int table_idx, bcm_mpls_port_t *mpls_port, 
   7261             bcm_mpls_tunnel_switch_t *info, bcm_l3_egress_t *egr_obj, 
   7262             egr_mpls_vc_and_swap_label_table_entry_t *in_vc_entry,
   7263             int action, int *vc_swap_index, int cmp)
   7264 {
   7265 
   7266     bcm_tr_mpls_vc_swap_table_hash_entry_t *new_entry = NULL;
   7267     bcm_tr_mpls_vc_swap_table_hash_entry_t *temp, *prev;
   7268     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
   7269     
   7270     if (hash == NULL) {
   7271         return BCM_E_INTERNAL;
   7272     }
   7273     prev = temp = hash->head_link;
   7274 
   7275     while (temp != NULL) {
   7276         if (cmp) {
   7277             BCM_IF_ERROR_RETURN(soc_mem_read(unit, 
   7278                 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7279                 MEM_BLOCK_ALL, temp->index, &vc_entry));
   7280              
   7281             if (BCM_SUCCESS(_bcm_tr_mpls_vc_swap_compare
   7282                 (unit, mpls_port, info, egr_obj, in_vc_entry, action, &vc_entry))) {
   7283                 /* 
   7284                  * Entry already exists. 
   7285                  * return BCM_E_EXISTS to increase refcount. 
   7286                  */
   7287                *vc_swap_index = temp->index;
   7288                return BCM_E_EXISTS;
   7289             }
   7290         }
   7291         prev = temp;
   7292         temp = temp->link;
   7293     }
   7294     /* Entry does not exist, add a new one. */
   7295     BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_entry_alloc
   7296         (unit, &new_entry));
   7297 
   7298     new_entry->index = table_idx;
   7299     
   7300     /* update the link table */
   7301     if (hash->head_link == NULL) {
   7302         hash->head_link = new_entry;
   7303     } else {
   7304         prev->link = new_entry;
   7305     } 
   7306 
   7307     *vc_swap_index = table_idx;
   7308     return BCM_E_NONE;
   7309 }
   7310 #if defined(BCM_TRIUMPH3_SUPPORT)
   7311 /*
   7312  * Function:
   7313  *       _bcm_tr_mpls_vc_swap_hash_index_update
   7314  * Purpose:
   7315  *       Update the vc and swap table index in hash entry and
   7316  *       EGR_L3_NEXT_HOP table.
   7317  * Parameters:
   7318  *       unit                         - (IN) Device Number
   7319  *       hash                        -(IN) Hash input
   7320  *       new_vc_swap_index   - (IN) New vc and swap table index
   7321  *       old_vc_swap_index    - (IN) Old vc and swap table index
   7322  * Returns:
   7323  *       BCM_E_XXX
   7324  */
   7325 
   7326 STATIC int
   7327 _bcm_tr_mpls_vc_swap_hash_index_update (int unit,
   7328                      bcm_tr_mpls_vc_swap_table_hash_t *hash,
   7329                      int new_vc_swap_index,
   7330                      int old_vc_swap_index)
   7331 {
   7332     bcm_tr_mpls_vc_swap_table_hash_entry_t *temp_hash;
   7333     bcm_tr_mpls_vc_swap_table_nhop_list_t *temp_nhop;
   7334     soc_field_t vc_swap_idxf;
   7335 
   7336     if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   7337         vc_swap_idxf = MPLS__VC_AND_SWAP_INDEXf ;
   7338     } else {
   7339         vc_swap_idxf = VC_AND_SWAP_INDEXf;
   7340     }
   7341 
   7342     if (hash == NULL) {
   7343         return BCM_E_INTERNAL;
   7344     }
   7345     temp_hash = hash->head_link;
   7346     while (temp_hash) {
   7347         if (temp_hash->index == old_vc_swap_index) {
   7348             temp_hash->index = new_vc_swap_index;
   7349             temp_nhop = temp_hash->nhop_list;
   7350             while (temp_nhop) {
   7351                 BCM_IF_ERROR_RETURN
   7352                     (soc_mem_field32_modify(unit, EGR_L3_NEXT_HOPm,
   7353                                             temp_nhop->nh_index,
   7354                                             vc_swap_idxf,
   7355                                             new_vc_swap_index));
   7356                 temp_nhop = temp_nhop->next;
   7357             }
   7358             return BCM_E_NONE;
   7359         }
   7360         temp_hash = temp_hash->link;
   7361     }
   7362     return BCM_E_NOT_FOUND;
   7363 }
   7364 #endif  /* BCM_TRIUMPH3_SUPPORT */
   7365 
   7366 /*
   7367  * Function:
   7368  *      _bcmi_tr_mpls_entry_set_key
   7369  * Purpose:
   7370  *     Convert key part of application format to HW entry
   7371  * Parameters:
   7372  *     IN  :  Unit
   7373  *     IN  :  info
   7374  *     OUT :  ment
   7375  * Returns:
   7376  *      BCM_E_XXX
   7377  */
   7378 STATIC int
   7379 _bcmi_tr_mpls_entry_set_key(int unit, bcm_mpls_tunnel_switch_t *info,
   7380                            mpls_entry_entry_t *ment)
   7381 {
   7382     bcm_module_t mod_out;
   7383     bcm_port_t port_out;
   7384     bcm_trunk_t trunk_id;
   7385     int rv, gport_id;
   7386     soc_mem_t mem = MPLS_ENTRYm;
   7387     soc_field_t validf = VALIDf;
   7388 
   7389     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
   7390         mem = MPLS_ENTRY_SINGLEm;
   7391         validf = BASE_VALIDf;
   7392     }
   7393 
   7394     sal_memset(ment, 0, sizeof(mpls_entry_entry_t));
   7395 
   7396     if (info->port == BCM_GPORT_INVALID) {
   7397         /* Global label, mod/port not part of lookup key */
   7398         if (SOC_MEM_FIELD_VALID(unit, mem, MODULE_IDf)) {
   7399             soc_mem_field32_set(unit, mem, ment, MODULE_IDf, 0);
   7400         }
   7401         soc_mem_field32_set(unit, mem, ment, PORT_NUMf, 0);
   7402         if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) {
   7403             soc_mem_field32_set(unit, mem, ment, MPLS_LABELf, info->label);
   7404         } else {
   7405             return BCM_E_PARAM;
   7406         }
   7407 
   7408         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   7409             soc_mem_field32_set(unit, mem, ment, BASE_VALID_0f, 3);
   7410             soc_mem_field32_set(unit, mem, ment, BASE_VALID_1f, 7);
   7411         } else if (SOC_MEM_FIELD_VALID(unit, mem, BASE_VALIDf)) {
   7412             soc_mem_field32_set(unit, mem, ment, BASE_VALIDf, 1);
   7413         } else {
   7414             soc_mem_field32_set(unit, mem, ment, validf, 1);
   7415         }
   7416         return BCM_E_NONE;
   7417     }
   7418 
   7419     rv = _bcm_esw_gport_resolve(unit, info->port, &mod_out,
   7420                                 &port_out, &trunk_id, &gport_id);
   7421     BCM_IF_ERROR_RETURN(rv);
   7422 
   7423     if (BCM_GPORT_IS_TRUNK(info->port)) {
   7424         soc_mem_field32_set(unit, mem, ment, Tf, 1);
   7425         soc_mem_field32_set(unit, mem, ment, TGIDf, trunk_id);
   7426     } else {
   7427         if (SOC_MEM_FIELD_VALID(unit, mem, MODULE_IDf)) {
   7428             soc_mem_field32_set(unit, mem, ment, MODULE_IDf, mod_out);
   7429         }
   7430         soc_mem_field32_set(unit, mem, ment, PORT_NUMf, port_out);
   7431     }
   7432     if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) {
   7433         soc_mem_field32_set(unit, mem, ment, MPLS_LABELf, info->label);
   7434     } else {
   7435         return BCM_E_PARAM;
   7436     }
   7437 
   7438     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   7439         soc_mem_field32_set(unit, mem, ment, BASE_VALID_0f, 3);
   7440         soc_mem_field32_set(unit, mem, ment, BASE_VALID_1f, 7);
   7441     } else if (SOC_MEM_FIELD_VALID(unit, mem, BASE_VALIDf)){
   7442         soc_mem_field32_set(unit, mem, ment, BASE_VALIDf, 1);
   7443     } else {
   7444         soc_mem_field32_set(unit, mem, ment, validf, 1);
   7445     }
   7446 
   7447     return BCM_E_NONE;
   7448 }
   7449 
   7450 /*
   7451  * Function:
   7452  *      _bcm_tr_mpls_get_vc_and_swap_table_index
   7453  * Purpose:
   7454  *     Obtain Index into  VC_AND_SWAP_TABLE
   7455  * Parameters:
   7456  *     IN  :  Unit
   7457  *     IN  :  num_vc
   7458  *     IN  :  mpls port entry
   7459  *     IN  :  next hop entry
   7460  *     IN  :  action
   7461  *     OUT :  vc_swap_index
   7462  * Returns:
   7463  *      BCM_E_XXX
   7464  */
   7465 int
   7466 _bcm_tr_mpls_get_vc_and_swap_table_index (int unit, int flags,
   7467                         bcm_mpls_port_t *mpls_port, 
   7468                         bcm_mpls_tunnel_switch_t *info, 
   7469                         bcm_l3_egress_t *egr_obj, 
   7470                         egr_mpls_vc_and_swap_label_table_entry_t *vc_entry,
   7471                         int action, int *vc_swap_index)
   7472 {
   7473     int hash_idx, num_vc;
   7474     int imin; 
   7475     int rv;
   7476     int action_flags = _BCM_MPLS_ACTION_GET(flags);
   7477     int free_idx = 0, offset = 0;
   7478     bcm_tr_mpls_vc_swap_table_hash_t *hash_input;
   7479 
   7480     if (bcmi_vc_swap_label_hash[unit] == NULL) {
   7481         return BCM_E_INTERNAL;
   7482     }
   7483 
   7484     imin = soc_mem_index_min(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
   7485     num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
   7486 
   7487     /* we are dividng the table in half to manage counted and 
   7488      * non-counted entries. 
   7489      */
   7490     num_vc /= 2;
   7491 
   7492     BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_index_get(
   7493         unit, mpls_port, action, info, egr_obj, vc_entry, &hash_idx));
   7494 
   7495     /* Try getting index from 2nd half of MPLS_VC_AND_SWAP table */
   7496     if (!(action_flags & _BCM_MPLS_ACTION_SEQUENCE)) {
   7497         for (free_idx = imin; free_idx < num_vc + imin; free_idx++) {
   7498             if (!(_BCM_MPLS_VC_NON_COUNT_USED_GET(unit, free_idx) ||
   7499                   (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid) &&
   7500                   _bcm_vp_used_get(unit, free_idx, _bcmVpTypeL2Gre)))) {
   7501                 break;
   7502             }
   7503         }
   7504     }
   7505 
   7506     if ((free_idx == (num_vc + imin)) || 
   7507         (action_flags &  _BCM_MPLS_ACTION_SEQUENCE)) {
   7508 
   7509         /* Get index from 1st half of MPLS_VC_AND_SWAP table */
   7510         for (free_idx = imin; free_idx < num_vc + imin; free_idx++) {
   7511             if (!_BCM_MPLS_VC_COUNT_USED_GET(unit, free_idx - imin)) {
   7512                 break;
   7513             }
   7514         }
   7515         if (free_idx == num_vc + imin) {
   7516             return  BCM_E_RESOURCE;
   7517         }
   7518         _BCM_MPLS_VC_COUNT_USED_SET(unit, free_idx - imin);
   7519         offset = imin;
   7520     } else {
   7521         _BCM_MPLS_VC_NON_COUNT_USED_SET(unit, free_idx - imin);
   7522         offset = num_vc + imin;
   7523     }
   7524 
   7525     hash_input = &(bcmi_vc_swap_label_hash[unit][hash_idx]);
   7526 
   7527     if (flags & _BCM_MPLS_ACTION_LABEL_ALLOC) {
   7528         /* insert the entry without comparison */
   7529         rv = bcmi_tr_mpls_vc_swap_hash_insert(unit, hash_input, 
   7530             free_idx + offset, mpls_port, info, 
   7531             egr_obj, vc_entry, action, vc_swap_index, FALSE);
   7532 
   7533     } else {
   7534         /* insert the entry with comparison */
   7535         rv = bcmi_tr_mpls_vc_swap_hash_insert(unit, hash_input, 
   7536             free_idx + offset, mpls_port, info, 
   7537             egr_obj, vc_entry, action, vc_swap_index, TRUE);
   7538     }
   7539 
   7540     if (BCM_FAILURE(rv)) { 
   7541 
   7542         if (offset == imin) {
   7543             _BCM_MPLS_VC_COUNT_USED_CLR(unit, free_idx - imin);
   7544         } else {
   7545             _BCM_MPLS_VC_NON_COUNT_USED_CLR(unit, free_idx - imin);
   7546         }
   7547 
   7548         if (rv != BCM_E_EXISTS) {
   7549             LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
   7550                 "Hash Entry insertion failed  = %d\n"), rv));
   7551             return rv;
   7552         }
   7553     }
   7554 #ifdef BCM_TRIDENT3_SUPPORT
   7555     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   7556         if ((info != NULL) && (rv == BCM_E_EXISTS) &&
   7557             (info->action == BCM_MPLS_SWITCH_ACTION_PHP)) {
   7558             int index;
   7559             mpls_entry_entry_t ment;
   7560             BCM_IF_ERROR_RETURN(_bcmi_tr_mpls_entry_set_key(unit, info, &ment));
   7561             rv = soc_mem_search(unit, MPLS_ENTRYm,
   7562                 MEM_BLOCK_ANY, &index, &ment, &ment, 0);
   7563             if (rv != SOC_E_NOT_FOUND) {
   7564                 return rv;
   7565             }
   7566         }
   7567     }
   7568 #endif
   7569     /* Increase refcount on table idx */ 
   7570     if (*vc_swap_index >= 0) {
   7571        _bcm_tr_mpls_vc_and_swap_ref_count_adjust(unit, *vc_swap_index , 1);
   7572     }
   7573 
   7574     return BCM_E_NONE;
   7575 }
   7576 
   7577 /*
   7578  * Function:
   7579  *       _bcm_tr_mpls_vc_and_swap_table_reset
   7580  * Purpose:
   7581  *       Reset  VC_AND_SWAP_TABLE entry
   7582  * Parameters:
   7583  *           IN :  Unit
   7584  *           IN : vc_swap_index
   7585  * Returns:
   7586  *            BCM_E_XXX
   7587  */
   7588 int
   7589 _bcm_tr_mpls_vc_and_swap_table_index_reset (int unit, int vc_swap_index)
   7590 {
   7591     egr_mpls_vc_and_swap_label_table_entry_t  vc_entry;
   7592     int rv = BCM_E_NONE;
   7593     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   7594     int num_vc, idx;
   7595     bcm_tr_mpls_vc_swap_table_hash_t *hash_input;
   7596     int action = 0;
   7597     
   7598     /* Entry 0 is reserved with _bcm_tr_mpls_default_entry_setup during init */
   7599     if (vc_swap_index == VC_AND_SWAP_TABLE_RESV_INDEX) {
   7600         LOG_INFO(BSL_LS_BCM_L3,
   7601                  (BSL_META_U(unit,"Not resetting reserved index: %d in "
   7602                          "VC AND SWAP TABLE\n"), VC_AND_SWAP_TABLE_RESV_INDEX));
   7603         return BCM_E_NONE;
   7604     }
   7605     if ( mpls_info->vc_swap_ref_count[vc_swap_index] != 0 ) {
   7606          return BCM_E_NONE;
   7607     }
   7608     if (bcmi_vc_swap_label_hash[unit] == NULL) {
   7609         return BCM_E_INTERNAL;
   7610     }
   7611     num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
   7612     num_vc /= 2;
   7613 
   7614     BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7615         MEM_BLOCK_ALL, vc_swap_index, &vc_entry));
   7616 
   7617 #ifdef BCM_TRIDENT3_SUPPORT
   7618     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   7619         if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) {
   7620             action = MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index];
   7621         }
   7622     } else
   7623 #endif
   7624     {
   7625         action = 0;
   7626     }
   7627 
   7628     BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_index_get(
   7629         unit, NULL, action, NULL, NULL, &vc_entry, &idx));
   7630 
   7631     /* remove the entry from sw hash table */
   7632     hash_input = &(bcmi_vc_swap_label_hash[unit][idx]);
   7633     BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_delete(
   7634         unit, hash_input, vc_swap_index));
   7635 
   7636     if (vc_swap_index >= num_vc) {
   7637         _BCM_MPLS_VC_NON_COUNT_USED_CLR(unit, vc_swap_index - num_vc);
   7638     } else {
   7639         _BCM_MPLS_VC_COUNT_USED_CLR(unit, vc_swap_index);
   7640     }
   7641 
   7642     sal_memset(&vc_entry, 0,
   7643               sizeof(egr_mpls_vc_and_swap_label_table_entry_t));
   7644 
   7645     rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7646               MEM_BLOCK_ALL, vc_swap_index,
   7647               &vc_entry);
   7648 
   7649 #if defined(BCM_TRIDENT3_SUPPORT)
   7650     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   7651         if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) {
   7652             mpls_info->egr_vc_swap_lbl_action[vc_swap_index] =
   7653                 _BCM_MPLS_ACTION_NOOP;
   7654         }
   7655     }
   7656 #endif
   7657     return rv;
   7658 }
   7659 
   7660 /*
   7661  * Function:
   7662  *       _bcm_tr_mpls_vc_and_swap_table_entry_set
   7663  * Purpose:
   7664  *       Set  VC_AND_SWAP_TABLE entry
   7665  * Parameters:
   7666  *           IN :  Unit
   7667  *           IN : vc_swap_index
   7668  * Returns:
   7669  *            BCM_E_XXX
   7670  */
   7671 STATIC int
   7672 _bcm_tr_mpls_vc_and_swap_table_entry_set (int unit, 
   7673                                        bcm_mpls_port_t *mpls_port,
   7674                                        bcm_mpls_tunnel_switch_t *info,
   7675                                        bcm_l3_egress_t *egr_obj,
   7676                                        int label_action,
   7677                                        egr_mpls_vc_and_swap_label_table_entry_t *vc_entry,
   7678                                        int hw_map_idx, int vc_swap_index)
   7679 {
   7680     bcm_mpls_label_t mpls_label = BCM_MPLS_LABEL_INVALID;
   7681     uint8 mpls_ttl = 0;
   7682     uint32 mpls_flags = 0;
   7683     uint8 mpls_exp = 0; 
   7684     uint8 mpls_pkt_pri = 0; 
   7685     uint8 mpls_pkt_cfi = 0; 
   7686 #if (defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT))
   7687     int   mpls_ecn_map_id = ECN_MAP_ID_INVALID;
   7688     int   mpls_int_cn_map_id = ECN_MAP_ID_INVALID;
   7689 #endif
   7690     uint8 spl_label_action = 0;
   7691     int   action = 0;
   7692     int   php_swap_to_self = 0;
   7693 #if defined(BCM_TRIDENT3_SUPPORT)
   7694     int mapping_ptr = 0;
   7695     uint32 flex_pdd_format[2];
   7696     uint32 cancun_ver;
   7697 #endif
   7698 
   7699 #if defined(BCM_TRIDENT3_SUPPORT)
   7700     /* data fields: flex view uses PDD */
   7701     sal_memset(flex_pdd_format, 0, sizeof(flex_pdd_format));
   7702     if (SOC_IS_TRIDENT3X(unit)) {
   7703         SOC_IF_ERROR_RETURN(soc_cancun_version_get(unit, &cancun_ver));
   7704     }
   7705 #endif
   7706     if (mpls_port != NULL) {
   7707          mpls_label = mpls_port->egress_label.label;
   7708          mpls_ttl = mpls_port->egress_label.ttl;
   7709          mpls_flags = mpls_port->egress_label.flags;
   7710          mpls_pkt_pri = mpls_port->egress_label.pkt_pri;
   7711          mpls_pkt_cfi = mpls_port->egress_label.pkt_cfi;
   7712          mpls_exp = mpls_port->egress_label.exp;
   7713 #if (defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT))
   7714          if (soc_feature(unit, soc_feature_mpls_ecn)) {
   7715             if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP) {
   7716                 mpls_ecn_map_id = mpls_port->egress_label.ecn_map_id;
   7717             }
   7718             if (mpls_flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP) {
   7719                 if (soc_feature(unit, soc_feature_intcn_to_exp_nosupport)) {
   7720                     return BCM_E_UNAVAIL;
   7721                 }
   7722                 mpls_int_cn_map_id = mpls_port->egress_label.int_cn_map_id;
   7723             }
   7724          }
   7725 #endif         
   7726     } else if (info != NULL) {
   7727          mpls_label = info->egress_label.label;
   7728          mpls_ttl = info->egress_label.ttl;
   7729          mpls_flags = info->egress_label.flags;
   7730          mpls_pkt_pri = info->egress_label.pkt_pri;
   7731          mpls_pkt_cfi = info->egress_label.pkt_cfi;
   7732          mpls_exp = info->egress_label.exp;
   7733          spl_label_action = info->egress_label.spl_label_push_type;
   7734          action = info->action;
   7735 #if (defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT))
   7736          if (soc_feature(unit, soc_feature_mpls_ecn)) {
   7737              if (mpls_flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP) {
   7738                  if (soc_feature(unit, soc_feature_intcn_to_exp_nosupport)) {
   7739                      return BCM_E_UNAVAIL;
   7740                  }
   7741                  mpls_int_cn_map_id = info->egress_label.int_cn_map_id;
   7742              } 
   7743 
   7744              if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP) {
   7745                  mpls_ecn_map_id = info->egress_label.ecn_map_id;
   7746              }
   7747          }
   7748 #endif           
   7749     } else if (egr_obj != NULL) {
   7750          mpls_label = egr_obj->mpls_label;
   7751          mpls_ttl = egr_obj->mpls_ttl;
   7752          mpls_flags = egr_obj->mpls_flags;
   7753          mpls_pkt_pri = egr_obj->mpls_pkt_pri;
   7754          mpls_pkt_cfi = egr_obj->mpls_pkt_cfi;
   7755          mpls_exp = egr_obj->mpls_exp;
   7756 #if (defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT))
   7757          if (soc_feature(unit, soc_feature_mpls_ecn)) {
   7758             if (mpls_flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP) {
   7759                 if (soc_feature(unit, soc_feature_intcn_to_exp_nosupport)) {
   7760                     return BCM_E_UNAVAIL;
   7761                 }
   7762                 mpls_int_cn_map_id = egr_obj->mpls_ecn_map_id;
   7763             }
   7764             if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP) {
   7765                 mpls_ecn_map_id = egr_obj->mpls_ecn_map_id;
   7766             }
   7767          }
   7768 #endif 
   7769     }
   7770 
   7771         if ((mpls_exp > 7) || (mpls_pkt_pri > 7) ||
   7772             (mpls_pkt_cfi > 1)) {
   7773             return BCM_E_PARAM;
   7774         }
   7775 
   7776         sal_memset(vc_entry, 0, 
   7777                    sizeof(egr_mpls_vc_and_swap_label_table_entry_t));
   7778 
   7779         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   7780             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7781                     vc_entry, SPECIAL_LABEL_PUSH_TYPEf, spl_label_action);
   7782         }
   7783         if (_BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, mpls_flags) ||
   7784                 ((soc_feature(unit, soc_feature_td3_style_mpls)) && 
   7785                  (action & BCM_MPLS_SWITCH_ACTION_PHP))) {
   7786             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   7787 #if defined(BCM_TRIDENT3_SUPPORT)
   7788                 if (((SOC_IS_TRIDENT3(unit) && (cancun_ver >= SOC_CANCUN_VERSION_DEF_6_0_0))  ||
   7789                      (SOC_IS_MAVERICK2(unit) && (cancun_ver >= SOC_CANCUN_VERSION_DEF_4_0_0)) ||
   7790                      (SOC_IS_HELIX5(unit) && (cancun_ver >= SOC_CANCUN_VERSION_DEF_4_0_0))) &&
   7791                     (action & BCM_MPLS_SWITCH_ACTION_PHP)) {
   7792                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   7793                             flex_pdd_format, CONTAINER_IDf, 0);
   7794                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   7795                             flex_pdd_format, LABEL_SELECTf, 0);
   7796                     soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7797                             vc_entry, EDIT_CTRL_IDf,
   7798                             15);
   7799 
   7800                 } else {
   7801                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   7802                             flex_pdd_format, LABEL_SELECTf,
   7803                                     1);
   7804                     /* CANCUN has fixed the container 3 for swap to self */
   7805                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   7806                             flex_pdd_format, CONTAINER_IDf,
   7807                             3);
   7808                 }
   7809 
   7810                 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   7811                         flex_pdd_format, MPLS_PUSH_ACTIONf,
   7812                                 _BCM_MPLS_ACTION_PUSH);
   7813 
   7814                 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7815                         vc_entry, FLOW_SELECT_CTRL_IDf,
   7816                         5);
   7817 
   7818                 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7819                         vc_entry, DATA_TYPEf,
   7820                         5);
   7821                 /*For PHP/SWAPTOSELF by default Keep the old EXP value 
   7822                  *from the last label decapped (swap label).*/
   7823                 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   7824                         flex_pdd_format, MPLS_EXP_SELECTf, 3);
   7825 
   7826                 if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) {
   7827                     MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index] =
   7828                         _BCM_MPLS_ACTION_PRESERVED;
   7829                 }
   7830 #endif
   7831                 php_swap_to_self = TRUE;
   7832             } else {
   7833             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7834                                 vc_entry, MPLS_LABEL_ACTIONf, 
   7835                                 _BCM_MPLS_ACTION_PRESERVED);
   7836             }
   7837         } else {
   7838             if (BCM_XGS3_L3_MPLS_LBL_VALID(mpls_label)) {
   7839                 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7840                                     vc_entry, MPLS_LABELf,
   7841                                     mpls_label);
   7842                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   7843 #if defined(BCM_TRIDENT3_SUPPORT)
   7844                     if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) {
   7845                         MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index] =
   7846                             label_action;
   7847                     }
   7848 #endif
   7849                     if (label_action == _BCM_MPLS_ACTION_SWAP) {
   7850                         /*VC SWAP HW Tbl supports Label actions NOOP,PUSH in TD3.
   7851                          *Record software defined label actions in software
   7852                          *state to reuse existing code for L3MPLS*/
   7853                         soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7854                                 vc_entry, MPLS_LABEL_ACTIONf,
   7855                                 _BCM_MPLS_ACTION_PUSH);
   7856                     } else {
   7857 
   7858                         soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7859                                 vc_entry, MPLS_LABEL_ACTIONf,
   7860                                 label_action);
   7861                     }
   7862                 } else {
   7863                 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7864                                     vc_entry, MPLS_LABEL_ACTIONf,
   7865                                     label_action);
   7866                 }
   7867 
   7868             } else {
   7869                 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7870                                     vc_entry, MPLS_LABEL_ACTIONf,
   7871                                     _BCM_MPLS_ACTION_NOOP);
   7872             }
   7873         }
   7874         if (mpls_flags & BCM_MPLS_EGRESS_LABEL_TTL_SET) {
   7875             if (php_swap_to_self) {
   7876 #if defined(BCM_TRIDENT3_SUPPORT)
   7877                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   7878                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   7879                             flex_pdd_format, MPLS_TTLf, mpls_ttl);
   7880                 }
   7881 #endif
   7882             } else {
   7883             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
   7884                                 vc_entry, MPLS_TTLf,
   7885                                 mpls_ttl);
   7886             }
   7887         } else {
   7888             if (php_swap_to_self) {
   7889 #if defined(BCM_TRIDENT3_SUPPORT)
   7890                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   7891                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   7892                             flex_pdd_format, MPLS_TTLf, 0x0);
   7893                 }
   7894 #endif
   7895              } else {
   7896                 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
   7897                                 vc_entry, MPLS_TTLf, 0x0);
   7898              }
   7899        }
   7900 #ifdef BCM_MONTEREY_SUPPORT
   7901             if (soc_feature(unit, soc_feature_roe) ||
   7902                 soc_feature(unit, soc_feature_roe_custom)) {
   7903                  if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ROE_BARE_MPLS) {
   7904                     soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7905                                     vc_entry, BARE_MPLSf, 0x1);
   7906                   } else {
   7907                     soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7908                                     vc_entry, BARE_MPLSf, 0x0);
   7909                   }
   7910              }
   7911 #endif
   7912 #if (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT))
   7913         if (soc_feature(unit, soc_feature_mpls_entropy) && (mpls_port != NULL)) {
   7914             if ((mpls_port->flags & BCM_MPLS_PORT_ENTROPY_ENABLE) ||
   7915                 (mpls_flags & BCM_MPLS_EGRESS_LABEL_ENTROPY_ENABLE)) {
   7916                 if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7917                                     MPLS_INSERT_ENTROPY_LABELf)) {
   7918                      soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7919                                             vc_entry, MPLS_INSERT_ENTROPY_LABELf, 0x1);
   7920                 }
   7921             }
   7922         }
   7923 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_APACHE_SUPPORT) */
   7924         if (mpls_port != NULL) {
   7925             if (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED) {
   7926                 /* Append control word with sequence number */
   7927                 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
   7928                                 vc_entry, CW_INSERT_FLAGf, 0x2);
   7929             } else if (mpls_port->flags & BCM_MPLS_PORT_CONTROL_WORD) {
   7930                 /* Append control word with NO sequence number */
   7931                 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
   7932                                 vc_entry, CW_INSERT_FLAGf, 0x1);
   7933             }
   7934             if ((mpls_port->flags & BCM_MPLS_PORT_COUNTED) ||
   7935                 (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED)) {
   7936                  soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7937                                 vc_entry, UPDATE_PW_INIT_COUNTERSf, 0x1);
   7938             }
   7939         }
   7940         if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) ||
   7941             (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) {
   7942 
   7943             if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) ||
   7944                 (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ||
   7945                 (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_REMARK)) {
   7946                 return  BCM_E_PARAM;
   7947             }
   7948 
   7949             if (php_swap_to_self) {
   7950 #if defined(BCM_TRIDENT3_SUPPORT)
   7951                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   7952                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   7953                             flex_pdd_format, MPLS_EXP_SELECTf, 0x0);
   7954 
   7955                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   7956                             flex_pdd_format, MPLS_EXPf, mpls_exp);
   7957 
   7958                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   7959                             flex_pdd_format, NEW_PRIf, mpls_pkt_pri);
   7960 
   7961                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   7962                             flex_pdd_format, NEW_CFIf, mpls_pkt_cfi);
   7963                 }
   7964 #endif
   7965             } else {
   7966             /* Use the specified EXP, PRI and CFI */
   7967             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7968                                 vc_entry, MPLS_EXP_SELECTf, 
   7969                                 0x0); /* USE_FIXED */
   7970             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7971                                 vc_entry, MPLS_EXPf, 
   7972                                 mpls_exp);
   7973             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7974                                 vc_entry, NEW_PRIf, 
   7975                                 mpls_pkt_pri);
   7976             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7977                                 vc_entry, NEW_CFIf, 
   7978                                 mpls_pkt_cfi);
   7979             }
   7980         } else if (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) {
   7981             if (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET) {
   7982                 return BCM_E_PARAM;
   7983             }
   7984 
   7985             if (php_swap_to_self) {
   7986 #if defined(BCM_TRIDENT3_SUPPORT)
   7987                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   7988                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   7989                             flex_pdd_format, MPLS_EXP_SELECTf, 0x1);
   7990 
   7991                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   7992                             flex_pdd_format, MPLS_EXP_MAPPING_PTRf, 
   7993                             hw_map_idx);
   7994                 }
   7995 #endif
   7996             } else {
   7997             /* Use EXP-map for EXP, PRI and CFI */
   7998             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   7999                                 vc_entry, MPLS_EXP_SELECTf, 
   8000                                 0x1); /* USE_MAPPING */
   8001             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8002                                 vc_entry, MPLS_EXP_MAPPING_PTRf,
   8003                                 hw_map_idx);
   8004             }
   8005         } else if ((label_action != _BCM_MPLS_ACTION_SWAP) && 
   8006                         (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ) { 
   8007             /* Use EXP from incoming label. If there is no incoming label,
   8008              * use the specified EXP value. Use EXP-map for PRI/CFI.
   8009              */
   8010             if (php_swap_to_self) {
   8011 #if defined(BCM_TRIDENT3_SUPPORT)
   8012                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   8013                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   8014                             flex_pdd_format, MPLS_EXP_SELECTf, 0x2);
   8015 
   8016                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   8017                             flex_pdd_format, MPLS_EXPf, mpls_exp);
   8018 
   8019                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   8020                             flex_pdd_format, MPLS_EXP_MAPPING_PTRf, 
   8021                             hw_map_idx);
   8022                 }
   8023 #endif
   8024             } else {
   8025             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8026                                 vc_entry, MPLS_EXP_SELECTf,
   8027                                 0x2); /* USE_INNER */
   8028             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
   8029                                 vc_entry, MPLS_EXPf, 
   8030                                 mpls_exp); 
   8031 
   8032             /* Use EXP-PRI-map for PRI/CFI */
   8033             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8034                                 vc_entry, MPLS_EXP_MAPPING_PTRf,
   8035                                 hw_map_idx);
   8036             }
   8037         } else if ((label_action == _BCM_MPLS_ACTION_SWAP) && 
   8038                         (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ) {
   8039 
   8040             if (php_swap_to_self) {
   8041 #if defined(BCM_TRIDENT3_SUPPORT)
   8042                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   8043                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   8044                             flex_pdd_format, MPLS_EXP_SELECTf, 0x3);
   8045 
   8046                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   8047                             flex_pdd_format, MPLS_EXPf, mpls_exp);
   8048 
   8049                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   8050                             flex_pdd_format, MPLS_EXP_MAPPING_PTRf, 
   8051                             hw_map_idx);
   8052                 }
   8053 #endif
   8054             } else {
   8055               soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8056                                 vc_entry, MPLS_EXP_SELECTf,
   8057                                 0x3); /* USE_SWAP */
   8058               soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
   8059                                 vc_entry, MPLS_EXPf, mpls_exp); 
   8060               /* Use EXP-PRI-map for PRI/CFI */
   8061               soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8062                                 vc_entry, MPLS_EXP_MAPPING_PTRf,
   8063                                 hw_map_idx);
   8064             }
   8065         }
   8066 #if defined(BCM_TRIDENT3_SUPPORT)
   8067         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   8068             if (info != NULL && (info->action & BCM_MPLS_SWITCH_ACTION_PHP)) {
   8069                 if ((info->pkt_pri > 7) || (info->pkt_cfi > 1)) {
   8070                     return BCM_E_PARAM;
   8071                 }
   8072 
   8073                 if (info->flags2 & BCM_MPLS_SWITCH2_VLAN_PRI_SET) {
   8074                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   8075                         flex_pdd_format, PRI_CFI_SELf, 0);
   8076                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   8077                         flex_pdd_format, DOT1P_MAPPING_PTRf,
   8078                         (info->pkt_pri << 1) | info->pkt_cfi);
   8079                 } else if (info->flags2 & BCM_MPLS_SWITCH2_VLAN_PRI_PHB_REMARK) {
   8080                     BCM_IF_ERROR_RETURN(
   8081                         _bcm_tr2_qos_id2idx(unit, info->qos_map_id, &mapping_ptr));
   8082                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   8083                         flex_pdd_format, PRI_CFI_SELf, 1);
   8084                     soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   8085                         flex_pdd_format, DOT1P_MAPPING_PTRf, mapping_ptr);
   8086                 }
   8087             }
   8088         }
   8089 #endif
   8090 #if (defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT))
   8091         if (soc_feature(unit, soc_feature_mpls_ecn)) {
   8092             if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP) && 
   8093                 (mpls_int_cn_map_id != ECN_MAP_ID_INVALID) &&
   8094                 (!soc_feature(unit, soc_feature_intcn_to_exp_nosupport))) {
   8095                 int ecn_map_index;
   8096                 int ecn_map_type;
   8097                 int ecn_map_num;
   8098                 int ecn_map_hw_idx;
   8099                 ecn_map_type = mpls_int_cn_map_id & 
   8100                                 _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK;
   8101                 ecn_map_index = mpls_int_cn_map_id & 
   8102                                 _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK;
   8103                 ecn_map_num = 
   8104                     soc_mem_index_count(unit, EGR_INT_CN_TO_EXP_MAPPING_TABLEm) / 
   8105                     _BCM_ECN_MAX_ENTRIES_PER_MAP;
   8106                 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_INTCN2EXP) {
   8107                     return BCM_E_PARAM;
   8108                 }
   8109                 if (ecn_map_index >= ecn_map_num) {
   8110                     return BCM_E_PARAM;
   8111                 }
   8112                 BCM_IF_ERROR_RETURN(
   8113                     bcmi_ecn_map_id2hw_idx(unit, mpls_int_cn_map_id, &ecn_map_hw_idx));
   8114                 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8115                                     vc_entry, INT_CN_TO_EXP_MAPPING_PTRf,
   8116                                     ecn_map_hw_idx);
   8117                 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST) {
   8118                     soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8119                                         vc_entry, INT_CN_TO_EXP_PRIORITYf, 1);
   8120 
   8121                 } else {
   8122                     soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8123                                         vc_entry, INT_CN_TO_EXP_PRIORITYf, 0);
   8124 
   8125                 }
   8126             }
   8127             if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP) && 
   8128                 (mpls_ecn_map_id != ECN_MAP_ID_INVALID)) {
   8129                 int ecn_map_index;
   8130                 int ecn_map_type;
   8131                 int ecn_map_num;
   8132                 int ecn_map_hw_idx;
   8133                 soc_mem_t mem;
   8134                 soc_field_t ipecn_to_exp_ptr;
   8135                 soc_field_t ipecn_to_exp_priority;
   8136                 ecn_map_type = mpls_ecn_map_id & 
   8137                                 _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK;
   8138                 ecn_map_index = mpls_ecn_map_id & 
   8139                                 _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK;
   8140 #if defined(BCM_TRIDENT3_SUPPORT)
   8141                 if(soc_feature(unit, soc_feature_td3_style_mpls)) {
   8142                     mem = EGR_PKT_ECN_TO_EXP_MAPPING_1m;
   8143                 } else
   8144 #endif
   8145                 {
   8146                     mem = EGR_IP_ECN_TO_EXP_MAPPING_TABLEm;
   8147                 }
   8148                 ecn_map_num = 
   8149                     soc_mem_index_count(unit, mem) /
   8150                     _BCM_ECN_MAX_ENTRIES_PER_MAP;
   8151                 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP) {
   8152                     return BCM_E_PARAM;
   8153                 }
   8154                 if (ecn_map_index >= ecn_map_num) {
   8155                     return BCM_E_PARAM;
   8156                 }
   8157 
   8158                 BCM_IF_ERROR_RETURN(
   8159                     bcmi_ecn_map_id2hw_idx(unit, mpls_ecn_map_id, &ecn_map_hw_idx));
   8160                 
   8161 #if defined(BCM_TRIDENT3_SUPPORT)
   8162                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   8163                     ipecn_to_exp_ptr = PKT_ECN_TO_EXP_MAPPING_PTRf;
   8164                     ipecn_to_exp_priority = PKT_ECN_TO_EXP_PRIORITYf;
   8165                     /*Remap EXP to encode ECN.*/
   8166                 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8167                             vc_entry, ECN_MAPPING_ENABLEf, 1);
   8168                     /*Use EGR_PKT_ECN_TO_EXP_MAPPING_2 for vc labels*/
   8169                     soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8170                             vc_entry, ECN_MAPPING_TABLE_SELECTf, 1);
   8171 
   8172                 } else
   8173 #endif
   8174                 {
   8175                     ipecn_to_exp_ptr = IP_ECN_TO_EXP_MAPPING_PTRf;
   8176                     ipecn_to_exp_priority = IP_ECN_TO_EXP_PRIORITYf;
   8177                 }
   8178                 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8179                                     vc_entry, ipecn_to_exp_ptr,
   8180                                     ecn_map_hw_idx);
   8181                 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST) {
   8182                     soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8183                                         vc_entry, ipecn_to_exp_priority, 1);
   8184 
   8185                 } else {
   8186                     soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8187                                         vc_entry, ipecn_to_exp_priority, 0);
   8188                 }
   8189             }
   8190                 }
   8191 #endif
   8192 
   8193 #if defined(BCM_TRIDENT3_SUPPORT)
   8194         if (php_swap_to_self) {
   8195             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   8196                 soc_mem_field_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8197                         (uint32 *)vc_entry, MPLS_PHP__MPLS_ENTRY_0_ACTION_SETf,
   8198                         flex_pdd_format);
   8199             }
   8200         }
   8201 #endif
   8202         return BCM_E_NONE;
   8203 }
   8204 #if defined(BCM_TRIUMPH3_SUPPORT)
   8205 /*
   8206  * Function:
   8207  *       _bcm_tr_mpls_vc_and_swap_table_entry_adjust
   8208  * Purpose:
   8209  *       Move the vc and swap table entry to another index.
   8210  *       The original index should be occupied by
   8211  *       EGR_DVP_ATTRIBUTE_1
   8212  * Parameters:
   8213  *       unit     - (IN) Device Number
   8214  *       VP      -(IN) virtual port number
   8215  * Returns:
   8216  *       BCM_E_XXX
   8217  */
   8218 
   8219 int
   8220 _bcm_tr_mpls_vc_and_swap_table_entry_adjust (int unit, int vp)
   8221 {
   8222     int hash_idx, num_vc;
   8223     int imin = 0;
   8224     int rv, ref_count;
   8225     int free_idx = 0, offset = 0;
   8226     int old_vc_swap_index, vc_swap_index;
   8227     bcm_tr_mpls_vc_swap_table_hash_t *hash_input;
   8228     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
   8229     int action = 0;
   8230 
   8231     if (bcmi_vc_swap_label_hash[unit] == NULL) {
   8232         return BCM_E_INTERNAL;
   8233     }
   8234     rv = bcm_tr_mpls_lock(unit);
   8235     _BCM_MPLS_CLEANUP(rv);
   8236 
   8237     /* The entry is not occupied. */
   8238     if (!_BCM_MPLS_VC_NON_COUNT_USED_GET(unit, vp)) {
   8239         bcm_tr_mpls_unlock(unit);
   8240         return BCM_E_NONE;
   8241     }
   8242 
   8243     imin = soc_mem_index_min(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
   8244     num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
   8245 
   8246     /* we are dividng the table in half to manage counted and
   8247      * non-counted entries.
   8248      */
   8249     num_vc /= 2;
   8250 
   8251     old_vc_swap_index = vp + num_vc;
   8252     rv = soc_mem_read(unit,
   8253                       EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8254                       MEM_BLOCK_ALL, old_vc_swap_index, &vc_entry);
   8255     _BCM_MPLS_CLEANUP(rv);
   8256     /* Try getting index from 2nd half of MPLS_VC_AND_SWAP table */
   8257     for (free_idx = imin; free_idx < num_vc + imin; free_idx++) {
   8258         if (!(_BCM_MPLS_VC_NON_COUNT_USED_GET(unit, free_idx) ||
   8259               _bcm_vp_used_get(unit, free_idx, _bcmVpTypeL2Gre))) {
   8260             break;
   8261         }
   8262     }
   8263     if (free_idx == (num_vc + imin)) {
   8264         /* Get index from 1st half of MPLS_VC_AND_SWAP table */
   8265         for (free_idx = imin; free_idx < num_vc + imin; free_idx++) {
   8266             if (!_BCM_MPLS_VC_COUNT_USED_GET(unit, free_idx - imin)) {
   8267                 break;
   8268             }
   8269         }
   8270         if (free_idx == num_vc + imin) {
   8271             bcm_tr_mpls_unlock(unit);
   8272             return  BCM_E_RESOURCE;
   8273         }
   8274         _BCM_MPLS_VC_COUNT_USED_SET(unit, free_idx - imin);
   8275         offset = imin;
   8276     } else {
   8277         _BCM_MPLS_VC_NON_COUNT_USED_SET(unit, free_idx - imin);
   8278         offset = num_vc + imin;
   8279     }
   8280 
   8281     vc_swap_index = free_idx + offset;
   8282     rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8283                        MEM_BLOCK_ALL, vc_swap_index,
   8284                        &vc_entry);
   8285     _BCM_MPLS_CLEANUP(rv);
   8286 
   8287 #ifdef BCM_TRIDENT3_SUPPORT
   8288     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   8289         if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) {
   8290             action = MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index];
   8291         }
   8292     } else
   8293 #endif
   8294     {
   8295         action = 0;
   8296     }
   8297     /* Update nhop entry and EGR_L3_NEXT_HOP table */
   8298     rv = bcmi_tr_mpls_vc_swap_hash_index_get(unit, NULL, action, NULL, NULL,
   8299                                              &vc_entry, &hash_idx);
   8300     _BCM_MPLS_CLEANUP(rv);
   8301     hash_input = &(bcmi_vc_swap_label_hash[unit][hash_idx]);
   8302     rv = _bcm_tr_mpls_vc_swap_hash_index_update(unit,
   8303                                                 hash_input, vc_swap_index,
   8304                                                 old_vc_swap_index);
   8305     _BCM_MPLS_CLEANUP(rv);
   8306     /* Clear the original entry */
   8307     rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8308                        MEM_BLOCK_ALL, old_vc_swap_index,
   8309                        soc_mem_entry_null(unit,
   8310                                           EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm));
   8311     _BCM_MPLS_CLEANUP(rv);
   8312     /* Adjust the ref count */
   8313     _bcm_tr_mpls_vc_and_swap_ref_count_get(unit, old_vc_swap_index, &ref_count);
   8314     _bcm_tr_mpls_vc_and_swap_ref_count_reset(unit, old_vc_swap_index);
   8315     _bcm_tr_mpls_vc_and_swap_ref_count_adjust(unit, vc_swap_index, ref_count);
   8316     bcm_tr_mpls_unlock(unit);
   8317     
   8318     return rv;
   8319 cleanup:
   8320     if (offset == imin) {
   8321         _BCM_MPLS_VC_COUNT_USED_CLR(unit, free_idx - imin);
   8322     } else {
   8323         _BCM_MPLS_VC_NON_COUNT_USED_CLR(unit, free_idx - imin);
   8324     }
   8325     bcm_tr_mpls_unlock(unit);
   8326     return rv;
   8327 }
   8328 #endif
   8329 /*
   8330  * Function:
   8331  *      _bcm_tr_mpls_pw_init_counter_set
   8332  * Purpose:
   8333  *      Obtain the pw_init counter index, Set the EGR L3 NH entry parameter
   8334  * Parameters:
   8335  *      unit   - (IN) SOC unit #
   8336  *      egr_nh_info  - (IN/OUT) Egress NHOP Internal Structurel
   8337  * Returns:
   8338  *      BCM_E_XXX
   8339  */     
   8340 
   8341 STATIC int
   8342 _bcm_tr_mpls_pw_init_counter_set (int unit, 
   8343                    uint32 pw_seq_number, _bcm_tr_egr_nh_info_t  *egr_nh_info)
   8344 {
   8345     int  pw_init_cnt=-1;
   8346     egr_pw_init_counters_entry_t pw_init_entry;
   8347     egr_pw_init_counters_x_entry_t pw_init_entry_x;
   8348     egr_pw_init_counters_y_entry_t pw_init_entry_y;    
   8349     int  vc_swap_index;
   8350     uint32 num_pw_mask;
   8351 
   8352 #ifdef BCM_TRIDENT3_SUPPORT
   8353     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   8354         egr_sequence_number_table_entry_t td3_pw_init_entry;
   8355 
   8356         vc_swap_index =  egr_nh_info->vc_swap_index;
   8357 
   8358         /* pw_init_counter index is from the LSB bits of vc_and_swap_index */
   8359         num_pw_mask = soc_mem_index_count(unit, EGR_SEQUENCE_NUMBER_TABLEm) - 1;
   8360         pw_init_cnt = vc_swap_index & num_pw_mask;
   8361 
   8362         _BCM_MPLS_PW_INIT_USED_SET(unit, pw_init_cnt);
   8363 
   8364         egr_nh_info->pw_init_cnt = pw_init_cnt;
   8365 
   8366         sal_memset(&td3_pw_init_entry, 0, sizeof(egr_sequence_number_table_entry_t));
   8367         soc_EGR_SEQUENCE_NUMBER_TABLEm_field_set(unit, &td3_pw_init_entry, SEQUENCE_NUMBERf,
   8368                 (uint32 *)&pw_seq_number);
   8369 
   8370         pw_init_cnt = EGR_PW_SEQNUM_VCSWAP_OFFSET + pw_init_cnt;
   8371         WRITE_EGR_SEQUENCE_NUMBER_TABLEm(unit, MEM_BLOCK_ALL, pw_init_cnt,
   8372                 &td3_pw_init_entry);
   8373     } else 
   8374 #endif
   8375     {
   8376     if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERSm)) {
   8377         vc_swap_index =  egr_nh_info->vc_swap_index;
   8378 
   8379         /* pw_init_counter index is from the LSB bits of vc_and_swap_index */
   8380         num_pw_mask = soc_mem_index_count(unit, EGR_PW_INIT_COUNTERSm) - 1;
   8381         pw_init_cnt = vc_swap_index & num_pw_mask;
   8382 
   8383         _BCM_MPLS_PW_INIT_USED_SET(unit, pw_init_cnt);
   8384 
   8385         egr_nh_info->pw_init_cnt = pw_init_cnt;
   8386 
   8387         sal_memset(&pw_init_entry, 0, sizeof(egr_pw_init_counters_entry_t));
   8388         soc_EGR_PW_INIT_COUNTERSm_field32_set(unit, &pw_init_entry, SEQ_NUMf, 
   8389                                               pw_seq_number);
   8390 
   8391         WRITE_EGR_PW_INIT_COUNTERSm(unit, MEM_BLOCK_ALL, pw_init_cnt,
   8392                                     &pw_init_entry);
   8393         if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERS_Xm)) {
   8394             sal_memset(&pw_init_entry_x, 0, sizeof(egr_pw_init_counters_x_entry_t));
   8395             soc_EGR_PW_INIT_COUNTERS_Xm_field32_set(unit, &pw_init_entry_x, 
   8396                                                     SEQ_NUMf, pw_seq_number);
   8397 
   8398             WRITE_EGR_PW_INIT_COUNTERS_Xm(unit, MEM_BLOCK_ALL, pw_init_cnt,
   8399                                           &pw_init_entry_x);
   8400         }
   8401         if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERS_Ym)) {
   8402             sal_memset(&pw_init_entry_y, 0, sizeof(egr_pw_init_counters_y_entry_t));
   8403             soc_EGR_PW_INIT_COUNTERS_Ym_field32_set(unit, &pw_init_entry_y, 
   8404                                                     SEQ_NUMf, pw_seq_number);
   8405 
   8406             WRITE_EGR_PW_INIT_COUNTERS_Ym(unit, MEM_BLOCK_ALL, pw_init_cnt,
   8407                                           &pw_init_entry_y);
   8408         }
   8409 
   8410     }
   8411     }
   8412     return BCM_E_NONE;
   8413 
   8414 }
   8415 
   8416 /*
   8417  * Function:
   8418  *      _bcm_tr_mpls_pw_init_counter_delete
   8419  * Purpose:
   8420  *      Get L2 MPLS PW Stats
   8421  * Parameters:
   8422  *      unit   - (IN) SOC unit #
   8423  * Returns:
   8424  *      BCM_E_XXX
   8425  */     
   8426 
   8427 STATIC int
   8428 _bcm_tr_mpls_pw_init_counter_delete (int unit, int nh_index)
   8429 {
   8430     int  pw_init_cnt=-1,rv;
   8431     egr_l3_next_hop_entry_t egr_nh;
   8432     egr_pw_init_counters_entry_t pw_init_entry;
   8433     egr_pw_init_counters_x_entry_t pw_init_entry_x;
   8434     egr_pw_init_counters_y_entry_t pw_init_entry_y;
   8435 #if defined(BCM_TRIDENT3_SUPPORT)
   8436     uint32 num_pw_mask;
   8437 #endif
   8438     int vc_swap_index = 0;
   8439     int num_vc = 0;
   8440 
   8441 #if defined(BCM_TRIDENT3_SUPPORT)
   8442     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   8443         if (SOC_MEM_IS_VALID(unit, EGR_SEQUENCE_NUMBER_TABLEm)) {
   8444             egr_sequence_number_table_entry_t td3_pw_init_entry;
   8445             rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   8446                     nh_index, &egr_nh);
   8447             if (rv < 0) {
   8448                 return rv;
   8449             }
   8450 
   8451          if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   8452               pw_init_cnt =
   8453                    soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   8454                                      MPLS__PW_INIT_NUMf);
   8455          } else {
   8456               pw_init_cnt =
   8457                    soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   8458                                      PW_INIT_NUMf);
   8459          }
   8460 
   8461          num_pw_mask = soc_mem_index_count(unit, EGR_SEQUENCE_NUMBER_TABLEm) - 1;
   8462          pw_init_cnt &= num_pw_mask;
   8463 
   8464             sal_memset(&td3_pw_init_entry, 0, sizeof(egr_sequence_number_table_entry_t));
   8465             WRITE_EGR_SEQUENCE_NUMBER_TABLEm(unit, MEM_BLOCK_ALL, pw_init_cnt,
   8466                     &td3_pw_init_entry);
   8467 
   8468             _BCM_MPLS_PW_INIT_USED_CLR (unit, pw_init_cnt);
   8469         }
   8470     } else
   8471 #endif
   8472     {
   8473     if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERSm)) {
   8474          rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   8475                       nh_index, &egr_nh);
   8476          if (rv < 0) {
   8477               return rv;
   8478          }
   8479 
   8480             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   8481                 pw_init_cnt =
   8482                     soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   8483                             MPLS__PW_INIT_NUMf);
   8484                 vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   8485                             MPLS__VC_AND_SWAP_INDEXf);
   8486             } else {
   8487                 pw_init_cnt =
   8488                     soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   8489                             PW_INIT_NUMf);
   8490                 vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   8491                             VC_AND_SWAP_INDEXf);
   8492             }
   8493 
   8494             /* Validate if vc_swap_index is in upper half or lower half of swap table.
   8495              * If in lower half then delete count references otherwise do nothing
   8496              */
   8497             num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
   8498             if (vc_swap_index < num_vc/2) {
   8499 
   8500                 sal_memset(&pw_init_entry, 0, sizeof(egr_pw_init_counters_entry_t));
   8501                 WRITE_EGR_PW_INIT_COUNTERSm(unit, MEM_BLOCK_ALL, pw_init_cnt,
   8502                         &pw_init_entry);
   8503                 if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERS_Xm)) {
   8504                     sal_memset(&pw_init_entry_x, 0, sizeof(egr_pw_init_counters_x_entry_t));
   8505                     WRITE_EGR_PW_INIT_COUNTERS_Xm(unit, MEM_BLOCK_ALL, pw_init_cnt,
   8506                             &pw_init_entry_x);
   8507                 }
   8508                 if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERS_Ym)) {
   8509                     sal_memset(&pw_init_entry_y, 0, sizeof(egr_pw_init_counters_y_entry_t));
   8510                     WRITE_EGR_PW_INIT_COUNTERS_Ym(unit, MEM_BLOCK_ALL, pw_init_cnt,
   8511                             &pw_init_entry_y);
   8512                 }
   8513 
   8514                 _BCM_MPLS_PW_INIT_USED_CLR (unit, pw_init_cnt);
   8515             }
   8516         }
   8517     }
   8518     return BCM_E_NONE;
   8519 }
   8520 
   8521 /*
   8522  * Function:
   8523  *      _bcm_tr_mpls_pw_term_counter_set
   8524  * Purpose:
   8525  *      Obtain the pw_term counter index
   8526  * Parameters:
   8527  *      unit   - (IN) SOC unit #
   8528  *      ment  - (IN/OUT) MPLS Entry Structure
   8529  * Returns:
   8530  *      BCM_E_XXX
   8531  */     
   8532 
   8533 int
   8534 _bcm_tr_mpls_pw_term_counter_set (int unit, int  *pw_term_cnt)
   8535 {
   8536     int num_pw_term=-1;
   8537     int pw_idx=0;
   8538     ing_pw_term_counters_entry_t pw_term_entry;
   8539     ing_pw_term_seq_num_entry_t pw_term_seq_num_entry;
   8540 
   8541     if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) {
   8542          num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm);
   8543          for (pw_idx = 0; pw_idx < num_pw_term; pw_idx++) { 
   8544               if (!_BCM_MPLS_PW_TERM_USED_GET(unit, pw_idx)) {
   8545                     break;
   8546               }
   8547          }
   8548          if (pw_idx == num_pw_term) {
   8549               return BCM_E_RESOURCE;
   8550          }
   8551           _BCM_MPLS_PW_TERM_USED_SET(unit, pw_idx);
   8552 
   8553         sal_memset(&pw_term_entry, 0, sizeof(ing_pw_term_counters_entry_t));
   8554         (void) WRITE_ING_PW_TERM_COUNTERSm(unit, MEM_BLOCK_ALL, pw_idx,
   8555                                             &pw_term_entry);
   8556 
   8557         *pw_term_cnt  = pw_idx;
   8558     } else if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_SEQ_NUMm)) {
   8559         num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_SEQ_NUMm);
   8560         for (pw_idx = 0; pw_idx < num_pw_term; pw_idx++) {
   8561             if (!_BCM_MPLS_PW_TERM_USED_GET(unit, pw_idx)) {
   8562                 break;
   8563             }
   8564         }
   8565         if (pw_idx == num_pw_term) {
   8566             return BCM_E_RESOURCE;
   8567         }
   8568         _BCM_MPLS_PW_TERM_USED_SET(unit, pw_idx);
   8569         
   8570         sal_memset(&pw_term_seq_num_entry, 0, sizeof(ing_pw_term_seq_num_entry_t));
   8571         WRITE_ING_PW_TERM_SEQ_NUMm(unit, MEM_BLOCK_ALL, pw_idx,
   8572                                    &pw_term_seq_num_entry);
   8573 
   8574         *pw_term_cnt = pw_idx;
   8575     }
   8576     return BCM_E_NONE;
   8577 }
   8578 
   8579 /*
   8580  * Function:
   8581  *      _bcm_tr_mpls_pw_term_counter_delete
   8582  * Purpose:
   8583  *      Delete pw_term counter
   8584  * Parameters:
   8585  *      unit   - (IN) SOC unit #
   8586  * Returns:
   8587  *      BCM_E_XXX
   8588  */     
   8589 
   8590 STATIC int
   8591 _bcm_tr_mpls_pw_term_counter_delete (int unit,  int  pw_term_cnt)
   8592 {
   8593     ing_pw_term_counters_entry_t pw_term_entry;
   8594     ing_pw_term_seq_num_entry_t pw_term_seq_num_entry;
   8595 
   8596     if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) {
   8597          _BCM_MPLS_PW_TERM_USED_CLR(unit, pw_term_cnt);
   8598 
   8599          sal_memset(&pw_term_entry, 0, sizeof(ing_pw_term_counters_entry_t));
   8600          (void) WRITE_ING_PW_TERM_COUNTERSm(unit, MEM_BLOCK_ALL, pw_term_cnt,
   8601                                             &pw_term_entry);
   8602     } else if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_SEQ_NUMm)) {
   8603         _BCM_MPLS_PW_TERM_USED_CLR(unit, pw_term_cnt);
   8604 
   8605         sal_memset(&pw_term_seq_num_entry, 0, sizeof(ing_pw_term_seq_num_entry_t));
   8606         WRITE_ING_PW_TERM_SEQ_NUMm(unit, MEM_BLOCK_ALL, pw_term_cnt,
   8607                                    &pw_term_seq_num_entry);
   8608     }
   8609     return BCM_E_NONE;
   8610 }
   8611 
   8612 /*
   8613  * Function:
   8614  *      _bcm_tr_mpls_port_untagged_profile_set
   8615  * Purpose:
   8616  *      Set  VLan profile per Physical port entry
   8617  * Parameters:
   8618  *      unit   - (IN) SOC unit #
   8619  *      port  - (IN) Physical port
   8620  * Returns:
   8621  *      BCM_E_XXX
   8622  */     
   8623 
   8624 int
   8625 bcm_tr_mpls_port_untagged_profile_set (int unit, bcm_port_t port)
   8626 {
   8627     int rv;
   8628     bcm_vlan_action_set_t action;
   8629     uint32 ing_profile_idx = 0xffffffff;
   8630     int old_ing_profile_idx = -1;
   8631 
   8632     bcm_vlan_action_set_t_init(&action);
   8633     action.ut_outer = 0x0; /* No Op */
   8634     action.ut_inner = 0x0; /* No Op */
   8635 
   8636     SOC_IF_ERROR_RETURN(
   8637         _bcm_esw_port_tab_get(unit, port, TAG_ACTION_PROFILE_PTRf,
   8638                               &old_ing_profile_idx));
   8639 
   8640     rv = _bcm_trx_vlan_action_profile_entry_add(unit, &action, &ing_profile_idx);
   8641     if (rv < 0) {
   8642         return rv;
   8643     }
   8644 
   8645     rv = _bcm_esw_port_tab_set_without_portlock(unit, port, _BCM_CPU_TABS_NONE,
   8646                                                 TAG_ACTION_PROFILE_PTRf,
   8647                                                 ing_profile_idx);
   8648     if (rv < 0) {
   8649         return rv;
   8650     }
   8651 
   8652     if(old_ing_profile_idx != ING_ACTION_PROFILE_DEFAULT) {
   8653         rv = _bcm_trx_vlan_action_profile_entry_delete(unit, old_ing_profile_idx);
   8654     }
   8655 
   8656     return rv;
   8657 }
   8658 
   8659 /*
   8660  * Function:
   8661  *      bcm_tr_mpls_port_untagged_profile_reset
   8662  * Purpose:
   8663  *      Reset  VLan profile per Physical port entry
   8664  * Parameters:
   8665  *      unit   - (IN) SOC unit #
   8666  *      port  - (IN) Physical port
   8667  * Returns:
   8668  *      BCM_E_XXX
   8669  */     
   8670 
   8671 int
   8672 bcm_tr_mpls_port_untagged_profile_reset(int unit, bcm_port_t port)
   8673 {
   8674     int rv;
   8675     int ing_profile_idx = -1;
   8676 
   8677     SOC_IF_ERROR_RETURN(
   8678         _bcm_esw_port_tab_get(unit, port, TAG_ACTION_PROFILE_PTRf,
   8679                               &ing_profile_idx));
   8680 
   8681     rv = _bcm_trx_vlan_action_profile_entry_delete(unit, ing_profile_idx);
   8682     if (rv < 0) {
   8683         return rv;
   8684     }
   8685 
   8686     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   8687         /*Reset TAG_ACTION_PROFILE_PTR to 1 in TD3*/
   8688         rv = _bcm_esw_port_tab_set_without_portlock(unit, port, _BCM_CPU_TABS_NONE,
   8689                 TAG_ACTION_PROFILE_PTRf, 1);
   8690     } else {
   8691     rv = _bcm_esw_port_tab_set_without_portlock(unit, port, _BCM_CPU_TABS_NONE,
   8692                                                 TAG_ACTION_PROFILE_PTRf, 0);
   8693     }
   8694 
   8695     return rv;
   8696 }
   8697 
   8698 /*
   8699  * Function:
   8700  *      _bcm_tr_mpls_port_mtu_set
   8701  * Purpose:
   8702  *      Set  Vitual port MTU
   8703  * Returns:
   8704  *      BCM_E_XXX
   8705  */     
   8706 
   8707 int
   8708 _bcm_tr_mpls_port_mtu_set(int unit, int vp, int mtu)
   8709 {
   8710     int rv=BCM_E_UNAVAIL;
   8711     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   8712     
   8713     if (mtu == 0) {
   8714          mtu = 0x3FFF;
   8715     }
   8716 
   8717     rv = READ_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ALL, vp,
   8718             &egr_dvp_attribute);
   8719     if (BCM_SUCCESS(rv)) {
   8720         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   8721             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   8722                     &egr_dvp_attribute,
   8723                     DATA_TYPEf, 0x0);
   8724             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   8725                 &egr_dvp_attribute,
   8726                 COMMON__MTU_VALUEf, mtu);
   8727             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   8728                     &egr_dvp_attribute,
   8729                     COMMON__MTU_ENABLEf, 0x1);
   8730         } else {
   8731             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   8732                     &egr_dvp_attribute,
   8733                     VP_TYPEf, 0x0);
   8734             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   8735                 &egr_dvp_attribute,
   8736                 MTU_VALUEf, mtu);
   8737             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   8738                     &egr_dvp_attribute,
   8739                     MTU_ENABLEf, 0x1);
   8740         }
   8741 
   8742         rv = WRITE_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ALL, vp,
   8743                 &egr_dvp_attribute);
   8744     }
   8745     return rv;
   8746 
   8747 }
   8748 
   8749 /*
   8750  * Function:
   8751  *      _bcm_tr_mpls_port_mtu_clear
   8752  * Purpose:
   8753  *      Clear  Vitual port MTU
   8754  * Returns:
   8755  *      BCM_E_XXX
   8756  */     
   8757 
   8758 int
   8759 _bcm_tr_mpls_port_mtu_clear (int unit, int vp)
   8760 {
   8761     int rv=BCM_E_UNAVAIL;
   8762     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   8763     
   8764      rv =   soc_mem_read(unit, EGR_DVP_ATTRIBUTEm,
   8765                        MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
   8766      if (BCM_SUCCESS(rv)) {
   8767          if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   8768              if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
   8769                                         &egr_dvp_attribute, COMMON__MTU_ENABLEf)) {
   8770                   soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   8771                                                 COMMON__MTU_VALUEf, 0x0);
   8772                   soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   8773                                                 COMMON__MTU_ENABLEf, 0x0);
   8774                   rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTEm,
   8775                                                 MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
   8776              }
   8777          } else {
   8778              if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
   8779                                         &egr_dvp_attribute, MTU_ENABLEf)) {
   8780                   soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   8781                                                 MTU_VALUEf, 0x0);
   8782                   soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   8783                                                 MTU_ENABLEf, 0x0);
   8784                   rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTEm,
   8785                                                 MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
   8786              }
   8787          }
   8788      }
   8789      return rv;
   8790 }
   8791 
   8792 /*
   8793  * Function:
   8794  *      _bcm_tr_mpls_port_mtu_get
   8795  * Purpose:
   8796  *      Get  Vitual port MTU
   8797  * Returns:
   8798  *      BCM_E_XXX
   8799  */     
   8800 
   8801 int
   8802 _bcm_tr_mpls_port_mtu_get(int unit, int vp, int *mtu)
   8803 {
   8804     int rv=BCM_E_UNAVAIL;
   8805     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   8806 
   8807      rv =   soc_mem_read(unit, EGR_DVP_ATTRIBUTEm,
   8808                        MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
   8809      if (BCM_SUCCESS(rv)) {
   8810          if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   8811              if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
   8812                                         &egr_dvp_attribute, COMMON__MTU_ENABLEf)) {
   8813                   *mtu =  soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
   8814                                         &egr_dvp_attribute, COMMON__MTU_VALUEf);
   8815              }
   8816          } else {
   8817              if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
   8818                                         &egr_dvp_attribute, MTU_ENABLEf)) {
   8819                   *mtu =  soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
   8820                                         &egr_dvp_attribute, MTU_VALUEf);
   8821              }
   8822          }
   8823      }
   8824      return rv;
   8825 }
   8826 
   8827 /*
   8828  * Function:
   8829  *      _bcm_tr_mpls_sd_tag_set
   8830  * Purpose:
   8831  *      Program  SD_TAG settings
   8832  * Parameters:
   8833  *      unit           - (IN)  SOC unit #
   8834  *      mpls_port  - (IN)  MPLS VP
   8835  *      egr_nh_info  (IN/OUT) Egress NHop Info
   8836  * Returns:
   8837  *      BCM_E_XXX
   8838  */     
   8839 
   8840 STATIC int
   8841 _bcm_tr_mpls_sd_tag_set( int unit, bcm_mpls_port_t *mpls_port, 
   8842                          _bcm_tr_egr_nh_info_t  *egr_nh_info, 
   8843                          egr_mpls_vc_and_swap_label_table_entry_t *vc_entry,
   8844                          int *tpid_index )
   8845 {
   8846   int rv = BCM_E_NONE;
   8847 
   8848     if (mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) {
   8849         if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) {
   8850             if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   8851                 return  BCM_E_PARAM;
   8852             }
   8853             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8854                                 vc_entry, SD_TAG_VIDf,
   8855                                 mpls_port->egress_service_vlan);
   8856             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8857                                 vc_entry, SD_TAG_ACTION_IF_NOT_PRESENTf,
   8858                                 0x1); /* ADD */
   8859         }
   8860 
   8861         if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) {
   8862             if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   8863                 return  BCM_E_PARAM;
   8864             }
   8865             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8866                                 vc_entry, SD_TAG_VIDf,
   8867                                 mpls_port->egress_service_vlan);
   8868             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8869                                 vc_entry, SD_TAG_ACTION_IF_PRESENTf,
   8870                                 0x1); /* REPLACE_VID_TPID */
   8871         } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_REPLACE) {
   8872             if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   8873                 return  BCM_E_PARAM;
   8874             }
   8875             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8876                                 vc_entry, SD_TAG_VIDf,
   8877                                 mpls_port->egress_service_vlan);
   8878             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8879                                 vc_entry, SD_TAG_ACTION_IF_PRESENTf,
   8880                                 0x2); /* REPLACE_VID_ONLY */
   8881         } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_DELETE) {
   8882             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8883                                 vc_entry, SD_TAG_ACTION_IF_PRESENTf,
   8884                                 0x3); /* DELETE */
   8885         } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE) {
   8886             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   8887                if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   8888                    return  BCM_E_PARAM;
   8889                }
   8890                soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8891                                 vc_entry, SD_TAG_VIDf,
   8892                                 mpls_port->egress_service_vlan);
   8893                if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8894                                        SD_TAG_NEW_PRIf)) {
   8895                    soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8896                                 vc_entry, SD_TAG_NEW_PRIf,
   8897                                 mpls_port->pkt_pri);
   8898                }
   8899                if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8900                                        SD_TAG_NEW_CFIf)) {
   8901                    soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8902                                 vc_entry, SD_TAG_NEW_CFIf,
   8903                                 mpls_port->pkt_cfi);
   8904                }
   8905 
   8906                soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8907                                 vc_entry, SD_TAG_ACTION_IF_PRESENTf,
   8908                                 0x4); /* REPLACE_VID_PRI_TPID */
   8909             }else {
   8910                   return BCM_E_PARAM;
   8911             }
   8912         } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_REPLACE ) {
   8913             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   8914                 if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   8915                     return  BCM_E_PARAM;
   8916                 }
   8917                 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8918                                 vc_entry, SD_TAG_VIDf,
   8919                                 mpls_port->egress_service_vlan);
   8920 
   8921                 if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8922                                        SD_TAG_NEW_PRIf)) {
   8923                    soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8924                                 vc_entry, SD_TAG_NEW_PRIf,
   8925                                 mpls_port->pkt_pri);
   8926                 }
   8927                 if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8928                                        SD_TAG_NEW_CFIf)) {
   8929                    soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8930                                 vc_entry, SD_TAG_NEW_CFIf,
   8931                                 mpls_port->pkt_cfi);
   8932                 }
   8933 
   8934                 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8935                                 vc_entry, SD_TAG_ACTION_IF_PRESENTf,
   8936                                 0x5); /* REPLACE_VID_PRI */
   8937             } else {
   8938                  return BCM_E_PARAM;
   8939             }      
   8940         }else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_PRI_REPLACE ) {
   8941             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   8942                 if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8943                                        SD_TAG_NEW_PRIf)) {
   8944                    soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8945                                 vc_entry, SD_TAG_NEW_PRIf,
   8946                                 mpls_port->pkt_pri);
   8947                 }
   8948                 if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8949                                        SD_TAG_NEW_CFIf)) {
   8950                    soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8951                                 vc_entry, SD_TAG_NEW_CFIf,
   8952                                 mpls_port->pkt_cfi);
   8953                 }
   8954 
   8955                 soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8956                                 vc_entry, SD_TAG_ACTION_IF_PRESENTf,
   8957                                 0x6); /* REPLACE_PRI_ONLY */
   8958             } else {
   8959                  return BCM_E_PARAM;
   8960             }
   8961       
   8962         } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE ) {
   8963             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   8964                  soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8965                                 vc_entry, SD_TAG_ACTION_IF_PRESENTf,
   8966                                 0x7); /* REPLACE_TPID_ONLY */
   8967             } else {
   8968                  return BCM_E_PARAM;
   8969             }
   8970         }
   8971 
   8972         if ((mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) ||
   8973             (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) ||
   8974             (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE) ||
   8975             (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) {
   8976             _bcm_fb2_outer_tpid_tab_lock(unit);
   8977             /* TPID value is used */
   8978             rv = _bcm_fb2_outer_tpid_entry_add(unit, mpls_port->service_tpid, tpid_index);
   8979             _bcm_fb2_outer_tpid_tab_unlock(unit);
   8980             if (rv < 0) {
   8981                return rv;
   8982             }
   8983             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8984                                 vc_entry, SD_TAG_TPID_INDEXf, *tpid_index);
   8985         }
   8986 
   8987         BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   8988                                           MEM_BLOCK_ALL, egr_nh_info->vc_swap_index,
   8989                                           vc_entry));
   8990     } else {
   8991         
   8992         if ((mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID) ||
   8993             (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_INNER_VLAN) ||
   8994             (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_OUTER_VLAN)) {
   8995             if (soc_feature(unit, soc_feature_lltag)) {
   8996                 if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_PRI_REPLACE) {
   8997                     egr_nh_info->lltag_cfi = mpls_port->pkt_cfi;
   8998                     egr_nh_info->lltag_pri = mpls_port->pkt_pri;
   8999                 }
   9000                 egr_nh_info->lltag_vlan = mpls_port->match_subport_pkt_vid;
   9001             } else {
   9002                 return BCM_E_PARAM;
   9003             }
   9004             return BCM_E_NONE;
   9005         }
   9006 
   9007         if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) {
   9008             if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   9009 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 
   9010                 if (soc_feature(unit, soc_feature_vp_sharing)) {
   9011                     egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID;
   9012                 } else
   9013 #endif
   9014                 {
   9015                     return  BCM_E_PARAM;
   9016                 }
   9017             }
   9018             if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) {
   9019                 egr_nh_info->sd_tag_vlan = mpls_port->egress_service_vlan;
   9020             }
   9021             egr_nh_info->sd_tag_action_not_present = 0x1; /* ADD */
   9022         }
   9023 
   9024         if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) {
   9025             if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   9026 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 
   9027                 if (soc_feature(unit, soc_feature_vp_sharing)) {
   9028                     egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID;
   9029                 } else
   9030 #endif
   9031                 {
   9032                     return  BCM_E_PARAM;
   9033                 }
   9034             }
   9035             /* REPLACE_VID_TPID */
   9036             if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) {
   9037                 egr_nh_info->sd_tag_vlan = mpls_port->egress_service_vlan;
   9038             }
   9039             egr_nh_info->sd_tag_action_present = 0x1;
   9040         } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_REPLACE) {
   9041 
   9042             if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   9043 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 
   9044                 if (soc_feature(unit, soc_feature_vp_sharing)) {
   9045                     egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID;
   9046                 } else
   9047 #endif
   9048                 {
   9049                     return  BCM_E_PARAM;
   9050                 }
   9051             }
   9052             /* REPLACE_VID_ONLY */
   9053             if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) {
   9054                 egr_nh_info->sd_tag_vlan = mpls_port->egress_service_vlan;
   9055             }
   9056             egr_nh_info->sd_tag_action_present = 0x2;
   9057         } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_DELETE) {
   9058             egr_nh_info->sd_tag_action_present = 0x3; /* DELETE */
   9059         } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE) {
   9060             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   9061                 if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   9062 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 
   9063                     if (soc_feature(unit, soc_feature_vp_sharing)) {
   9064                         egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID;
   9065                     } else
   9066 #endif
   9067                     {
   9068                         return  BCM_E_PARAM;
   9069                     }
   9070                 }
   9071 
   9072                 /* REPLACE_VID_PRI_TPID */
   9073                 if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) {
   9074                     egr_nh_info->sd_tag_vlan = mpls_port->egress_service_vlan;
   9075                 }
   9076                 egr_nh_info->sd_tag_pri = mpls_port->pkt_pri;
   9077                 if (mpls_port->flags2 & BCM_MPLS_PORT2_SERVICE_CFI_REPLACE) {
   9078                     if ((mpls_port->pkt_cfi == 0) || (mpls_port->pkt_cfi == 1)) {
   9079                         egr_nh_info->sd_tag_cfi = mpls_port->pkt_cfi;
   9080                     } else {
   9081                         return BCM_E_PARAM;
   9082                     }
   9083                 } else {
   9084                     egr_nh_info->sd_tag_cfi = -1;
   9085                 }
   9086                 egr_nh_info->sd_tag_action_present = 0x4;
   9087             } else {
   9088                  return BCM_E_PARAM;
   9089             }
   9090         } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_REPLACE ) {
   9091             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   9092                 if (mpls_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   9093 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 
   9094                     if (soc_feature(unit, soc_feature_vp_sharing)) {
   9095                         egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID;
   9096                     } else
   9097 #endif
   9098                     {
   9099                         return  BCM_E_PARAM;
   9100                     }
   9101                 }
   9102 
   9103                 /* REPLACE_VID_PRI_ONLY */
   9104                 if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) {
   9105                     egr_nh_info->sd_tag_vlan = mpls_port->egress_service_vlan;
   9106                 }
   9107                 egr_nh_info->sd_tag_pri = mpls_port->pkt_pri;
   9108                 if (mpls_port->flags2 & BCM_MPLS_PORT2_SERVICE_CFI_REPLACE) {
   9109                     if ((mpls_port->pkt_cfi == 0) || (mpls_port->pkt_cfi == 1)) {
   9110                         egr_nh_info->sd_tag_cfi = mpls_port->pkt_cfi;
   9111                     } else {
   9112                         return BCM_E_PARAM;
   9113                     }
   9114                 } else {
   9115                     egr_nh_info->sd_tag_cfi = -1;
   9116                 }
   9117                 egr_nh_info->sd_tag_action_present = 0x5;
   9118             } else {
   9119                  return BCM_E_PARAM;
   9120             }
   9121         } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_PRI_REPLACE ) {
   9122             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   9123                  /* REPLACE_PRI_ONLY */
   9124                 egr_nh_info->sd_tag_pri = mpls_port->pkt_pri;
   9125                 if (mpls_port->flags2 & BCM_MPLS_PORT2_SERVICE_CFI_REPLACE) {
   9126                     if ((mpls_port->pkt_cfi == 0) || (mpls_port->pkt_cfi == 1)) {
   9127                         egr_nh_info->sd_tag_cfi = mpls_port->pkt_cfi;
   9128                     } else {
   9129                         return BCM_E_PARAM;
   9130                     }
   9131                 } else {
   9132                     egr_nh_info->sd_tag_cfi = -1;
   9133                 }
   9134                 egr_nh_info->sd_tag_action_present = 0x6;
   9135             } else {
   9136                  return BCM_E_PARAM;
   9137             }
   9138         } else if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE ) {
   9139             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   9140                  /* REPLACE_TPID_ONLY */
   9141                 egr_nh_info->sd_tag_action_present = 0x7;
   9142             } else {
   9143                 return BCM_E_PARAM;
   9144             }
   9145 
   9146         }
   9147 
   9148         if ((mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) ||
   9149             (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) ||
   9150             (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE) ||
   9151             (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) {
   9152             _bcm_fb2_outer_tpid_tab_lock(unit);
   9153             /* TPID value is used */
   9154             rv = _bcm_fb2_outer_tpid_entry_add(unit, mpls_port->service_tpid, tpid_index);
   9155             _bcm_fb2_outer_tpid_tab_unlock(unit);
   9156             if (rv < 0) {
   9157                return rv;
   9158             }
   9159             egr_nh_info->tpid_index = *tpid_index;
   9160         }
   9161     } 
   9162     return  BCM_E_NONE;
   9163 }
   9164 /*
   9165  * Function:
   9166  *      _bcm_tr_mpls_l2_old_nh_info_delete
   9167  * Purpose:
   9168  *      Delete old L2 MPLS Next Hop entry being replaced
   9169  * Parameters:
   9170  * Returns:
   9171  *      BCM_E_XXX
   9172  */
   9173 STATIC int
   9174 _bcm_tr_mpls_l2_old_nh_info_delete(int unit, bcm_mpls_port_t *mpls_port,
   9175                                    int nh_index, _bcm_mpls_old_nh_info_t *old_nh_info)
   9176 {
   9177     int old_vp_nh_index = -1;
   9178     int egress_nh_index = -1;
   9179     uint32 mpath_flag = 0;
   9180 
   9181     if (mpls_port->flags & BCM_MPLS_PORT_REPLACE &&
   9182         mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) {
   9183         old_vp_nh_index = old_nh_info->old_nh_index;
   9184         if (old_vp_nh_index == nh_index) {
   9185             old_vp_nh_index = -1;
   9186         }
   9187     }
   9188 
   9189     /* Handle old VC_SWAP index. */
   9190     if ((old_nh_info->old_vc_swap_idx != -1 && old_vp_nh_index == -1) ||
   9191         (old_nh_info->old_vc_swap_idx != -1 && (mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID))) {
   9192 #if defined(BCM_TRIUMPH3_SUPPORT)
   9193         if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) {
   9194             (void)_bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit,
   9195                     old_nh_info->old_vc_swap_idx,
   9196                     nh_index);
   9197         }
   9198 #endif
   9199         (void)_bcm_tr_mpls_vc_and_swap_ref_count_adjust(unit,
   9200                 old_nh_info->old_vc_swap_idx, -1);
   9201         (void)_bcm_tr_mpls_vc_and_swap_table_index_reset(unit,
   9202                 old_nh_info->old_vc_swap_idx);
   9203     }
   9204 
   9205     /* Delete old TPID, MAC indexes */
   9206     if (old_nh_info->old_tpid_idx != -1) {
   9207         (void)_bcm_fb2_outer_tpid_entry_delete(unit, old_nh_info->old_tpid_idx);
   9208     }
   9209 
   9210     if (mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) {
   9211         if (old_vp_nh_index == nh_index) {
   9212             old_vp_nh_index = -1;    
   9213         }
   9214  
   9215         if (mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) {
   9216             (void)bcm_xgs3_get_nh_from_egress_object(unit, mpls_port->egress_tunnel_if,
   9217                                                     &mpath_flag, 0, &egress_nh_index);
   9218         }
   9219 
   9220         if (old_nh_info->old_tunnel_if == mpls_port->egress_tunnel_if) {
   9221             if (! (mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
   9222                 if (egress_nh_index != -1) {
   9223                     BCM_XGS3_L3_ENT_REF_CNT_DEC
   9224                         (BCM_XGS3_L3_TBL_PTR(unit, next_hop), egress_nh_index, _BCM_SINGLE_WIDE);
   9225                 }
   9226             }
   9227         } else {
   9228             if (old_nh_info->old_tunnel_if != 0) {
   9229                BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0,
   9230                              (old_nh_info->old_tunnel_if - BCM_XGS3_EGRESS_IDX_MIN(unit))));
   9231                BCM_IF_ERROR_RETURN(_bcm_tr_mpls_delete_vp_nh(unit,
   9232                               nh_index, old_nh_info->old_tunnel_if));
   9233            }
   9234         }
   9235     }
   9236 
   9237     if (old_vp_nh_index != -1) {
   9238         /* Free the old_vp_next-hop entry. */
   9239         (void)_bcm_tr_mpls_l2_nh_info_delete(unit, old_vp_nh_index);
   9240     } else if (old_nh_info->old_macda_idx != -1) {
   9241         (void)_bcm_mac_da_profile_entry_delete(unit, old_nh_info->old_macda_idx);
   9242     }
   9243     return BCM_E_NONE;
   9244 }
   9245 /*
   9246  * Function:
   9247  *      _bcm_tr_mpls_l2_nh_info_add
   9248  * Purpose:
   9249  *      Create the L2 MPLS Next Hop entry
   9250  * Parameters:
   9251  * Returns:
   9252  *      BCM_E_XXX
   9253  */     
   9254 
   9255 STATIC int
   9256 _bcm_tr_mpls_l2_nh_info_add(int unit, bcm_mpls_port_t *mpls_port, int vp,
   9257                             int drop, int is_vpws, int *vp_nh_index, 
   9258                             bcm_port_t *local_port, int *is_local,
   9259                             _bcm_mpls_old_nh_info_t *old_nh_info)
   9260 {
   9261     egr_l3_next_hop_entry_t egr_nh;
   9262     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
   9263     _bcm_tr_ing_nh_info_t ing_nh_info;
   9264     _bcm_tr_egr_nh_info_t egr_nh_info;
   9265     bcm_l3_egress_t nh_info;
   9266     int gport_id, rv=0, num_vc=0;
   9267     int egress_nh_index = -1, old_vp_nh_index= -1;
   9268     bcm_module_t mod_out = 0;
   9269     bcm_port_t port_out = 0;
   9270     bcm_trunk_t trunk_id=0;
   9271     int action_present, action_not_present, tpid_index = -1;
   9272     int num_mpls_map, hw_map_idx;
   9273     void *entries[1];
   9274     _bcm_port_info_t *info;
   9275     uint32 mpath_flag=0;
   9276     bcm_port_t phys_port;
   9277     bcm_gport_t  gport;
   9278     uint32 port_flags;
   9279 #if defined(BCM_TRIUMPH2_SUPPORT)
   9280     int failover_vp, failover_nh_index = -1;
   9281     ing_dvp_table_entry_t failover_dvp;
   9282     uint32 protection_flags=0;
   9283 #endif /* BCM_TRIUMPH2_SUPPORT  */
   9284 #if defined(BCM_KATANA2_SUPPORT)
   9285     int       my_modid = 0;
   9286 #endif
   9287 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT)
   9288     int is_local_subport = 0;
   9289 #endif
   9290 #if defined(BCM_KATANA_SUPPORT)
   9291     bcm_module_t       module_id;            /* Module ID           */
   9292     bcm_port_t         port_id;              /* Port ID.            */
   9293     int                local_id;             /* Hardware ID.        */
   9294     int                extended_queue_id;    /* Subscriber queue    */
   9295     ing_queue_map_entry_t ing_queue_entry;
   9296 #endif /* BCM_KATANA_SUPPORT */
   9297     egr_mac_da_profile_entry_t macda;
   9298     int network_group=0;
   9299 
   9300     /* Initialize values */
   9301     *local_port = 0;
   9302     *is_local = 0;
   9303     ing_nh_info.mtu = 0; /*Default, especially if MTU_SIZE is not valid */ 
   9304     if (mpls_port->mtu != 0) {
   9305         ing_nh_info.mtu = mpls_port->mtu;
   9306     }  else if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) {
   9307         ing_nh_info.mtu =  
   9308             (1 << soc_mem_field_length(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) - 1;
   9309     }
   9310     ing_nh_info.port = -1;
   9311     ing_nh_info.module = -1;
   9312     ing_nh_info.trunk = -1;
   9313     ing_nh_info.qtag = -1;
   9314     ing_nh_info.tag_type = -1;
   9315 
   9316     egr_nh_info.dvp = vp;
   9317     egr_nh_info.entry_type = -1;
   9318     egr_nh_info.sd_tag_action_present = -1;
   9319     egr_nh_info.sd_tag_action_not_present = -1;
   9320     egr_nh_info.intf_num = -1;
   9321     egr_nh_info.sd_tag_vlan = -1;
   9322     egr_nh_info.sd_tag_pri = -1;
   9323     egr_nh_info.sd_tag_cfi = -1;
   9324     egr_nh_info.lltag_vlan = -1;
   9325     egr_nh_info.lltag_pri = -1;
   9326     egr_nh_info.lltag_cfi = -1;
   9327     egr_nh_info.macda_index = -1;
   9328     egr_nh_info.vc_swap_index = -1;
   9329     egr_nh_info.tpid_index = -1;
   9330     egr_nh_info.pw_init_cnt = -1;
   9331     egr_nh_info.vintf_ctr_index = -1;
   9332     egr_nh_info.flex_ctr_base_cnt_idx = -1;
   9333     egr_nh_info.dvp_network_group_id = 0;
   9334     egr_nh_info.class_id = -1;
   9335     egr_nh_info.oam_global_context_id = 0;
   9336 
   9337     old_nh_info->old_nh_index = *vp_nh_index;
   9338     old_nh_info->old_tunnel_if = 0;
   9339     old_nh_info->old_tpid_idx = -1;
   9340     old_nh_info->old_macda_idx = -1;
   9341     old_nh_info->old_vc_swap_idx = -1;
   9342 
   9343     if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   9344         network_group = mpls_port->network_group_id;
   9345         rv = _bcm_validate_splithorizon_network_group(unit,
   9346                 mpls_port->flags & BCM_MPLS_PORT_NETWORK, &network_group);
   9347         BCM_IF_ERROR_RETURN(rv);
   9348         egr_nh_info.dvp_network_group_id = network_group;
   9349     }
   9350     if ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) &&
   9351         (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ) {
   9352             egr_nh_info.dvp_is_network = 1;
   9353     } else {
   9354             egr_nh_info.dvp_is_network = 0;
   9355     }
   9356     if ((mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) ||
   9357             (mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
   9358         rv = bcm_tr_mpls_get_vp_nh (unit, *vp_nh_index, &old_nh_info->old_tunnel_if);
   9359         if (rv == BCM_E_NOT_FOUND) {
   9360             old_nh_info->old_tunnel_if = 0;
   9361         } else if (BCM_FAILURE(rv)) {
   9362             return rv;
   9363         }
   9364     }
   9365 
   9366     if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
   9367         if ((*vp_nh_index > soc_mem_index_max(unit, EGR_L3_NEXT_HOPm)) ||
   9368             (*vp_nh_index < soc_mem_index_min(unit, EGR_L3_NEXT_HOPm)))  {
   9369             return BCM_E_PARAM;
   9370         }
   9371         /* Read the existing egress next_hop entry */
   9372         rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
   9373                           *vp_nh_index, &egr_nh);
   9374         BCM_IF_ERROR_RETURN(rv);
   9375     } else {
   9376        /* Allocate MPLS VP Next Hop */
   9377         BCM_IF_ERROR_RETURN(_bcm_tr_mpls_create_vp_nh 
   9378                             (unit, mpls_port->egress_tunnel_if, vp_nh_index, mpls_port));
   9379         if ((mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) && (!old_nh_info->old_tunnel_if)) {
   9380             /* increase the reference count to indicates the given next hop is used by mpls port*/
   9381             BCM_XGS3_L3_ENT_REF_CNT_INC
   9382                 (BCM_XGS3_L3_TBL_PTR(unit, next_hop), *vp_nh_index, _BCM_SINGLE_WIDE);
   9383 
   9384        }
   9385     }
   9386 
   9387     /*
   9388      * Indexes in the first half of EGR_MPLS_VC_AND_SWAP_LABEL_TABLE
   9389      * also get used as the index into the EGR_PW_INIT_COUNTERS table.
   9390      * Set num_vc to half the EGR_MPLS_VC_AND_SWAP_LABEL_TABLE size.
   9391      */
   9392     num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
   9393     num_vc /= 2;
   9394 
   9395     if (mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) {
   9396 
   9397         num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
   9398         if (mpls_port->egress_label.qos_map_id == 0) {
   9399             hw_map_idx = 0; /* use default */
   9400         } else {
   9401             BCM_IF_ERROR_RETURN(_egr_qos_id2hw_idx(unit,
   9402                             mpls_port->egress_label.qos_map_id,&hw_map_idx));
   9403         }
   9404 
   9405         if (hw_map_idx < 0 || hw_map_idx >= num_mpls_map) {
   9406             rv = BCM_E_PARAM;
   9407             goto cleanup;
   9408         }
   9409 
   9410         /* Egressing into an MPLS tunnel */
   9411         if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, mpls_port->egress_tunnel_if)) {
   9412             /* invalid egress object */
   9413             rv = BCM_E_PARAM;
   9414             goto cleanup;
   9415         } else if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
   9416             /* Be sure that the existing entry is already setup to
   9417              * egress into an MPLS tunnel. If not, return BCM_E_PARAM.
   9418              */
   9419             egr_nh_info.entry_type = 
   9420                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]);
   9421             if (egr_nh_info.entry_type != 0x1) { /* != MPLS_MACDA_PROFILE */
   9422                 rv = BCM_E_PARAM;
   9423                 goto cleanup;
   9424             }
   9425 
   9426             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   9427                 /* TD2 should defines BCM_TRIUMPH3_SUPPORT */
   9428 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   9429                 if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   9430                     egr_nh_info.flex_ctr_base_cnt_idx = 
   9431                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9432                              MPLS__FLEX_CTR_BASE_COUNTER_IDXf);
   9433                     egr_nh_info.flex_ctr_pool_num = 
   9434                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9435                              MPLS__FLEX_CTR_POOL_NUMBERf);
   9436                     egr_nh_info.flex_ctr_offset_mode = 
   9437                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9438                              MPLS__FLEX_CTR_OFFSET_MODEf);
   9439                 } else
   9440 #endif
   9441                 if (soc_feature(unit, soc_feature_gport_service_counters)) {
   9442                     egr_nh_info.vintf_ctr_index = 
   9443                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9444                              MPLS__VINTF_CTR_IDXf);
   9445                 }
   9446             }
   9447 
   9448             /* Remember old MAC_DA_PROFILE_INDEX,  VC_AND_SWAP_INDEX */
   9449             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   9450                 old_nh_info->old_macda_idx =
   9451                     soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   9452                                                 MPLS__MAC_DA_PROFILE_INDEXf);
   9453                 old_nh_info->old_vc_swap_idx =
   9454                     soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   9455                                                 MPLS__VC_AND_SWAP_INDEXf);
   9456             } else {
   9457                 old_nh_info->old_macda_idx =
   9458                     soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   9459                                                 MAC_DA_PROFILE_INDEXf);
   9460                 old_nh_info->old_vc_swap_idx =
   9461                     soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   9462                                                 VC_AND_SWAP_INDEXf);
   9463             }
   9464 
   9465             /* Remember old TPID index if it's used */
   9466             rv = soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   9467                               MEM_BLOCK_ALL, old_nh_info->old_vc_swap_idx, &vc_entry);
   9468             _BCM_MPLS_CLEANUP(rv);
   9469             action_present =
   9470                 soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit,
   9471                                                  &vc_entry,
   9472                                                  SD_TAG_ACTION_IF_PRESENTf);
   9473             action_not_present =
   9474                 soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit,
   9475                                                  &vc_entry,
   9476                                                  SD_TAG_ACTION_IF_NOT_PRESENTf);
   9477             if ((action_not_present == 0x1) || (action_present == 0x1)) {
   9478                 /* If SD tag action is ADD or REPLACE_VID_TPID, the tpid
   9479                  * index of the entry getting replaced is valid. Save
   9480                  * the old tpid index to be deleted later.
   9481                  */
   9482                 old_nh_info->old_tpid_idx =
   9483                     soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit,
   9484                                                  &vc_entry, SD_TAG_TPID_INDEXf);
   9485             }
   9486 
   9487             /* Remember old vc_nh_index */
   9488             old_vp_nh_index = *vp_nh_index;
   9489 
   9490             /* Allocate MPLS VP Next Hop */
   9491             if (old_nh_info->old_tunnel_if != mpls_port->egress_tunnel_if) {
   9492                 BCM_IF_ERROR_RETURN(_bcm_tr_mpls_create_vp_nh
   9493                                     (unit, mpls_port->egress_tunnel_if, vp_nh_index,
   9494                                      mpls_port));
   9495             }
   9496         }
   9497 
   9498         /* 
   9499          * Get egress next-hop index from egress object and
   9500          * increment egress object reference count. 
   9501          */
   9502         if (old_vp_nh_index != *vp_nh_index) {
   9503             rv = bcm_xgs3_get_nh_from_egress_object(unit, mpls_port->egress_tunnel_if,
   9504                     &mpath_flag, 1, &egress_nh_index);
   9505         } else {
   9506             if ((mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) &&
   9507                 (mpls_port->flags & BCM_MPLS_PORT_REPLACE) &&
   9508                 (old_nh_info->old_tunnel_if != mpls_port->egress_tunnel_if)) {
   9509                 rv = bcm_xgs3_get_nh_from_egress_object(unit, mpls_port->egress_tunnel_if,
   9510                          &mpath_flag, 1, &egress_nh_index);
   9511             } else {
   9512                 rv = bcm_xgs3_get_nh_from_egress_object(unit, mpls_port->egress_tunnel_if,
   9513                          &mpath_flag, 0, &egress_nh_index);
   9514             }
   9515         }
   9516         _BCM_MPLS_CLEANUP(rv);
   9517 
   9518         rv = bcm_xgs3_nh_get(unit, egress_nh_index, &nh_info);
   9519         _BCM_MPLS_CLEANUP(rv);
   9520 
   9521 #if defined(BCM_KATANA_SUPPORT)
   9522         if (SOC_IS_KATANAX(unit)) {
   9523             ing_l3_next_hop_entry_t in_nh;
   9524 
   9525             rv = soc_mem_read (unit, ING_L3_NEXT_HOPm,
   9526                         MEM_BLOCK_ALL, egress_nh_index, &in_nh);
   9527             _BCM_MPLS_CLEANUP(rv);
   9528             ing_nh_info.qtag = soc_ING_L3_NEXT_HOPm_field32_get(unit, &in_nh,
   9529                                           EH_QUEUE_TAGf);
   9530             ing_nh_info.tag_type = soc_ING_L3_NEXT_HOPm_field32_get(unit,
   9531                                           &in_nh,
   9532                                           EH_TAG_TYPEf);
   9533         }
   9534 #endif
   9535 
   9536         /* make sure (mod/port) is local(single modid) view */
   9537         rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
   9538                        nh_info.module, nh_info.port, 
   9539                        &nh_info.module, &nh_info.port);
   9540         BCM_IF_ERROR_RETURN(rv);
   9541 
   9542         if (nh_info.flags & BCM_L3_TGID) {
   9543             ing_nh_info.port = -1;
   9544             ing_nh_info.module = -1;
   9545             ing_nh_info.trunk = nh_info.trunk;
   9546             trunk_id =  nh_info.trunk;
   9547         } else {
   9548             ing_nh_info.port = nh_info.port;
   9549             port_out = nh_info.port;
   9550             ing_nh_info.module = nh_info.module;
   9551             mod_out = nh_info.module;
   9552             ing_nh_info.trunk = -1; 
   9553         }
   9554 
   9555         egr_nh_info.intf_num = nh_info.intf;
   9556         egr_nh_info.entry_type = 0x1; /* MPLS_MACDA_PROFILE */
   9557         egr_nh_info.oam_global_context_id = nh_info.oam_global_context_id;
   9558 
   9559         sal_memset(&macda, 0, sizeof(egr_mac_da_profile_entry_t));
   9560         soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, 
   9561                              &macda, MAC_ADDRESSf, nh_info.mac_addr);
   9562         entries[0] = &macda;
   9563         rv = _bcm_mac_da_profile_entry_add(unit, entries, 1,
   9564                                            (uint32 *) &egr_nh_info.macda_index);
   9565         _BCM_MPLS_CLEANUP(rv);
   9566 
   9567         if ((mpls_port->flags & BCM_MPLS_PORT_COUNTED) ||
   9568             (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED)) {
   9569 
   9570             rv = _bcm_tr_mpls_get_vc_and_swap_table_index (unit, 
   9571                                    _BCM_MPLS_ACTION_SEQUENCE, 
   9572                                    mpls_port, NULL, NULL, NULL,
   9573                                    _BCM_MPLS_ACTION_PUSH,
   9574                                    &egr_nh_info.vc_swap_index);
   9575             _BCM_MPLS_CLEANUP(rv);
   9576 
   9577             rv = _bcm_tr_mpls_pw_init_counter_set (unit, mpls_port->pw_seq_number, &egr_nh_info);
   9578             _BCM_MPLS_CLEANUP(rv);
   9579 
   9580         } else {
   9581 
   9582             rv = _bcm_tr_mpls_get_vc_and_swap_table_index (unit, 0,
   9583                                    mpls_port, NULL, NULL, NULL,
   9584                                    _BCM_MPLS_ACTION_PUSH,
   9585                                    &egr_nh_info.vc_swap_index);
   9586             _BCM_MPLS_CLEANUP(rv);
   9587         }
   9588         /* Program the MPLS_VC_AND_SWAP table entry */
   9589         rv = _bcm_tr_mpls_vc_and_swap_table_entry_set(unit, mpls_port, NULL, NULL,
   9590                                                  _BCM_MPLS_ACTION_PUSH, &vc_entry, hw_map_idx,
   9591                                                  egr_nh_info.vc_swap_index);
   9592         _BCM_MPLS_CLEANUP(rv);
   9593         /* SD_TAG setting */
   9594         rv = _bcm_tr_mpls_sd_tag_set(unit, mpls_port, &egr_nh_info, &vc_entry, &tpid_index);
   9595         _BCM_MPLS_CLEANUP(rv);
   9596 
   9597         rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   9598                            MEM_BLOCK_ALL, egr_nh_info.vc_swap_index,
   9599                            &vc_entry);
   9600         _BCM_MPLS_CLEANUP(rv);
   9601     } else {
   9602         if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
   9603             /* Be sure that the existing entry is not egressing into
   9604              * an MPLS tunnel. If it is, return BCM_E_PARAM.
   9605              */
   9606             egr_nh_info.entry_type = 
   9607                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]);
   9608             if (egr_nh_info.entry_type != 0x2) { /* != MPLS_SD_TAG_ACTIONS */
   9609                 rv = BCM_E_PARAM;
   9610                 goto cleanup;
   9611             }
   9612 
   9613             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   9614                 action_present =
   9615                      soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   9616                                                  SD_TAG__SD_TAG_ACTION_IF_PRESENTf);
   9617                 action_not_present =
   9618                      soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   9619                                                  SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf);
   9620             } else {
   9621                 action_present =
   9622                      soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   9623                                                  SD_TAG_ACTION_IF_PRESENTf);
   9624                 action_not_present =
   9625                      soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   9626                                                  SD_TAG_ACTION_IF_NOT_PRESENTf);
   9627             }
   9628             if ((action_not_present == 0x1) || (action_present == 0x1)) {
   9629                 /* If SD tag action is ADD or REPLACE_VID_TPID, the tpid
   9630                  * index of the entry getting replaced is valid. Save
   9631                  * the old tpid index to be deleted later.
   9632                  */
   9633                 if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   9634                     old_nh_info->old_tpid_idx =
   9635                           soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   9636                                                  SD_TAG__SD_TAG_TPID_INDEXf);
   9637                 } else {
   9638                     old_nh_info->old_tpid_idx =
   9639                           soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   9640                                                  SD_TAG_TPID_INDEXf);
   9641                 }
   9642             }
   9643 
   9644             if (soc_feature(unit, soc_feature_mpls_enhanced) && 
   9645                     soc_feature(unit, soc_feature_gport_service_counters)) {
   9646                 egr_nh_info.vintf_ctr_index = 
   9647                    soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9648                         SD_TAG__VINTF_CTR_IDXf);
   9649             }
   9650             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   9651                 /* TD2 should defines BCM_TRIUMPH3_SUPPORT */
   9652 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   9653                 if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   9654                     egr_nh_info.flex_ctr_base_cnt_idx =
   9655                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9656                              SD_TAG__FLEX_CTR_BASE_COUNTER_IDXf);
   9657                     egr_nh_info.flex_ctr_pool_num =
   9658                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9659                              SD_TAG__FLEX_CTR_POOL_NUMBERf);
   9660                     egr_nh_info.flex_ctr_offset_mode =
   9661                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9662                              SD_TAG__FLEX_CTR_OFFSET_MODEf);
   9663                 } else
   9664 #endif
   9665                 if (soc_feature(unit, soc_feature_gport_service_counters)) {
   9666                     egr_nh_info.vintf_ctr_index =
   9667                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9668                              SD_TAG__VINTF_CTR_IDXf);
   9669                 }
   9670             }
   9671         }
   9672 
   9673         egr_nh_info.entry_type = 0x2; /* MPLS_SD_TAG_ACTIONS */
   9674 
   9675         if ((mpls_port->criteria != BCM_MPLS_PORT_MATCH_VLAN) ||
   9676             (mpls_port->port != BCM_GPORT_INVALID)) {
   9677             rv = _bcm_esw_gport_resolve(unit, mpls_port->port, &mod_out,
   9678                                         &port_out, &trunk_id, &gport_id);
   9679             _BCM_MPLS_CLEANUP(rv);
   9680         }
   9681 
   9682         if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
   9683             ing_nh_info.module = -1;
   9684             ing_nh_info.port = -1;
   9685             ing_nh_info.trunk = trunk_id;
   9686         } else {
   9687             ing_nh_info.module = mod_out;
   9688             ing_nh_info.port = port_out;
   9689             ing_nh_info.trunk = -1;
   9690         }
   9691 
   9692         /* SD_TAG setting */
   9693         rv = _bcm_tr_mpls_sd_tag_set(unit, mpls_port, &egr_nh_info, &vc_entry, &tpid_index);
   9694         _BCM_MPLS_CLEANUP(rv);
   9695 
   9696     }
   9697 
   9698     /* CLASS ID */
   9699     if (mpls_port->egress_class_id != BCM_CLASS_ID_INVALID) {
   9700         int len = 0;
   9701 
   9702         if ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) &&
   9703                 (mpls_port->egress_class_id == nh_info.intf_class)) {
   9704             /*
   9705              * if you want to have same interface class, then
   9706              * add it through next hop.
   9707              */
   9708             return BCM_E_PARAM;
   9709         }
   9710 
   9711         len = soc_mem_field_length(unit, EGR_L3_NEXT_HOPm, MPLS__CLASS_IDf);
   9712         if (mpls_port->egress_class_id >= (1 << len)) {
   9713             return BCM_E_PARAM;
   9714         }
   9715 
   9716         egr_nh_info.class_id = mpls_port->egress_class_id;
   9717     } else if (mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) {
   9718         egr_nh_info.class_id = nh_info.intf_class;
   9719     }
   9720 
   9721     /* Update the physical port's SW state */
   9722     rv = _bcm_esw_modid_is_local(unit, ing_nh_info.module, is_local);
   9723     _BCM_MPLS_CLEANUP(rv);
   9724 
   9725 #if defined(BCM_HGPROXY_COE_SUPPORT)
   9726     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   9727         BCM_GPORT_IS_SET(mpls_port->port) &&
   9728         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit,
   9729             mpls_port->port)) {
   9730 
   9731         if(_bcmi_coe_subport_mod_port_physical_port_get(unit, mod_out,
   9732 				port_out, &phys_port) == BCM_E_NONE) {
   9733             is_local_subport = 1;
   9734         }
   9735     }
   9736 
   9737     if (is_local_subport) {
   9738         _bcm_port_info_access(unit, phys_port, &info);
   9739         info->vp_count++;
   9740         /* Update the physical port's attributes */
   9741         rv = bcm_esw_port_vlan_member_get(unit, phys_port, &port_flags);
   9742         _BCM_MPLS_CLEANUP(rv);
   9743 
   9744         rv = bcm_esw_port_vlan_member_set(unit, phys_port, port_flags);
   9745         _BCM_MPLS_CLEANUP(rv);
   9746     } else
   9747 #endif
   9748 
   9749 #if defined(BCM_KATANA2_SUPPORT)
   9750     if (BCM_GPORT_IS_SET(mpls_port->port) &&
   9751         _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit,
   9752             mpls_port->port)) {
   9753         rv = bcm_esw_stk_my_modid_get(unit, &my_modid);
   9754         _BCM_MPLS_CLEANUP(rv);
   9755         if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_out) == BCM_E_NONE) {
   9756             rv = _bcm_kt2_modport_to_pp_port_get(
   9757                      unit, mod_out, port_out, &phys_port);
   9758             _BCM_MPLS_CLEANUP(rv);
   9759             if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, phys_port)){
   9760                 is_local_subport = 1;
   9761             }
   9762         }
   9763     }
   9764 
   9765     if (is_local_subport) {
   9766         _bcm_port_info_access(unit, phys_port, &info);
   9767         info->vp_count++;
   9768         /* Update the physical port's attributes */
   9769         rv = bcm_esw_port_vlan_member_get(unit, phys_port, &port_flags);
   9770         _BCM_MPLS_CLEANUP(rv);
   9771 
   9772         rv = bcm_esw_port_vlan_member_set(unit, phys_port, port_flags);
   9773         _BCM_MPLS_CLEANUP(rv);
   9774     } else
   9775 #endif
   9776 
   9777     if (*is_local) {
   9778 
   9779         BCM_GPORT_MODPORT_SET(gport, ing_nh_info.module, ing_nh_info.port);
   9780         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &phys_port));
   9781 
   9782         _bcm_port_info_access(unit, phys_port, &info);
   9783         info->vp_count++;
   9784         /* Update the physical port's attributes */
   9785         rv = bcm_esw_port_vlan_member_get(unit, phys_port, &port_flags);
   9786         _BCM_MPLS_CLEANUP(rv);
   9787 
   9788         rv = bcm_esw_port_vlan_member_set(unit, phys_port, port_flags);
   9789         _BCM_MPLS_CLEANUP(rv);
   9790 
   9791     }
   9792 
   9793     /* If associated with a trunk, update each local physical port's SW state */
   9794     if (ing_nh_info.trunk != -1) {
   9795 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
   9796         int        max_num_port = SOC_MAX_NUM_PP_PORTS;
   9797         bcm_port_t local_member_array[SOC_MAX_NUM_PP_PORTS];
   9798 #else
   9799         int        max_num_port = SOC_MAX_NUM_PORTS;
   9800         bcm_port_t local_member_array[SOC_MAX_NUM_PORTS];
   9801 #endif
   9802         int local_member_count;
   9803         int idx;
   9804         uint32 port_flags;
   9805 
   9806         rv = _bcm_esw_trunk_local_members_get(unit, trunk_id,
   9807                 max_num_port, local_member_array, &local_member_count);
   9808         _BCM_MPLS_CLEANUP(rv);
   9809 
   9810         for (idx = 0; idx < local_member_count; idx++) {
   9811             _bcm_port_info_access(unit, local_member_array[idx], &info);
   9812             info->vp_count++;
   9813 
   9814             /* Update the physical port's attributes */
   9815             rv = bcm_esw_port_vlan_member_get(unit, local_member_array[idx], &port_flags);
   9816             _BCM_MPLS_CLEANUP(rv);
   9817             rv = bcm_esw_port_vlan_member_set(unit, local_member_array[idx], port_flags);
   9818             _BCM_MPLS_CLEANUP(rv);
   9819         }
   9820     }
   9821 
   9822     /* Write INITIAL_ING_L3_NEXT_HOP entry */
   9823     rv = _bcm_tr_mpls_INITIAL_ING_L3_NEXT_HOP_add(unit, 
   9824                                              &ing_nh_info, *vp_nh_index, 
   9825                                              local_port, is_local);
   9826     _BCM_MPLS_CLEANUP(rv);
   9827 
   9828     /* Write EGR_L3_NEXT_HOP entry */
   9829     rv = _bcm_tr_mpls_EGR_L3_NEXT_HOP_add(unit, &egr_nh_info, 
   9830                                           mpls_port->flags2, *vp_nh_index,
   9831                                           is_local, is_vpws, drop);
   9832     _BCM_MPLS_CLEANUP(rv);
   9833 
   9834 #if defined(INCLUDE_XFLOW_MACSEC) && defined(BCM_MONTEREY_SUPPORT)
   9835     if (soc_feature(unit, soc_feature_xflow_macsec) &&
   9836         BCM_XGS3_L3_EGRESS_IDX_VALID(unit, mpls_port->egress_tunnel_if) &&
   9837         SOC_IS_MONTEREY(unit)) {
   9838         egr_l3_next_hop_entry_t egr_tunnel_nh;
   9839         rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, egress_nh_index, &egr_tunnel_nh);
   9840         _BCM_MPLS_CLEANUP(rv);
   9841 
   9842         if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_tunnel_nh,
   9843                     MPLS__MACSEC_ENCRYPTf)) {
   9844             rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, *vp_nh_index, &egr_nh);
   9845             _BCM_MPLS_CLEANUP(rv);
   9846             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9847                     MPLS__MACSEC_ENCRYPTf, 1);
   9848             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9849                     MPLS__HG_MODIFY_ENABLEf,
   9850                     soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_tunnel_nh,
   9851                         MPLS__HG_MODIFY_ENABLEf));
   9852             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9853                     MPLS__HG_MC_DST_PORT_NUMf,
   9854                     soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_tunnel_nh,
   9855                         MPLS__HG_MC_DST_PORT_NUMf));
   9856             rv = soc_mem_write (unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, *vp_nh_index,
   9857                     &egr_nh);
   9858 
   9859             _BCM_MPLS_CLEANUP(rv);
   9860         }
   9861     }
   9862 #endif
   9863 #if defined(BCM_TRIUMPH3_SUPPORT)
   9864     if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   9865        egr_l3_next_hop_entry_t egr_nh;
   9866        rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, *vp_nh_index, &egr_nh);
   9867        _BCM_MPLS_CLEANUP(rv);
   9868 
   9869        if (SOC_IS_TRIUMPH3(unit) && soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
   9870            MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf)) {
   9871            soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9872                MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf,
   9873                (mpls_port->flags2 &
   9874                BCM_MPLS_PORT2_TUNNEL_HEADER_EGRESS_VLAN_TRANSLATION) != 0);
   9875        }
   9876        rv = soc_mem_write (unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, *vp_nh_index,
   9877             &egr_nh);
   9878 
   9879        _BCM_MPLS_CLEANUP(rv);
   9880     }
   9881 #endif
   9882 
   9883 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   9884     if (soc_feature(unit, soc_feature_egress_failover)) {
   9885         egr_l3_next_hop_entry_t egr_nh;
   9886         int local_failover_id=0,prot_type=0;
   9887         if (mpls_port->egress_failover_id!=0) {
   9888             local_failover_id=mpls_port->egress_failover_id;
   9889             _BCM_GET_FAILOVER_TYPE(local_failover_id, prot_type);
   9890             if (prot_type & _BCM_FAILOVER_1_1_MC_PROTECTION_MODE) {
   9891                 _BCM_GET_FAILOVER_ID(local_failover_id);
   9892 
   9893                 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm,
   9894                             MEM_BLOCK_ANY, *vp_nh_index, &egr_nh));
   9895 
   9896                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9897                         MPLS__PROT_GROUPf, local_failover_id);
   9898 
   9899                 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   9900                         MEM_BLOCK_ALL, *vp_nh_index, &egr_nh);
   9901             }
   9902         }
   9903     }
   9904 #endif
   9905 #ifdef BCM_KATANA_SUPPORT
   9906     if (soc_feature(unit, soc_feature_extended_queueing)) {
   9907         if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(mpls_port->per_flow_queue_base)) ||
   9908             (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP
   9909                                        (mpls_port->per_flow_queue_base)) ||
   9910             (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP
   9911                                        (mpls_port->per_flow_queue_base))) {
   9912             _BCM_MPLS_CLEANUP(_bcm_esw_gport_resolve(unit,
   9913                                             mpls_port->per_flow_queue_base,
   9914                                             &port_id,
   9915                                             &module_id,
   9916                                             &extended_queue_id,
   9917                                             &local_id));
   9918             if (((mpls_port->qos_map_id >> _BCM_QOS_MAP_SHIFT) ==
   9919                               _BCM_QOS_MAP_TYPE_ING_QUEUE_OFFSET_MAP_TABLE) &&
   9920                 ((mpls_port->qos_map_id & _BCM_QOS_MAP_TYPE_MASK) <=
   9921                    _BCM_QOS_MAP_ING_QUEUE_OFFSET_MAX)) {
   9922             /*  ING_QUEUE_MAP needs to be configured */
   9923                 sal_memset(&ing_queue_entry, 0, sizeof(ing_queue_map_entry_t));
   9924                 soc_mem_field32_set(unit, ING_QUEUE_MAPm, &ing_queue_entry,
   9925                                     QUEUE_SET_BASEf, extended_queue_id);
   9926                 soc_mem_field32_set(unit, ING_QUEUE_MAPm, &ing_queue_entry,
   9927                              QUEUE_OFFSET_PROFILE_INDEXf,
   9928                              (mpls_port->qos_map_id & _BCM_QOS_MAP_TYPE_MASK));
   9929                 _BCM_MPLS_CLEANUP(BCM_XGS3_MEM_WRITE(unit, ING_QUEUE_MAPm,
   9930                                                        extended_queue_id,
   9931                                                        &ing_queue_entry));
   9932                 /* Derive actual queue from qos map */
   9933                 ing_nh_info.tag_type = EH_TAG_TYPE_ING_QUEUE_MAP;
   9934                 ing_nh_info.qtag = extended_queue_id;
   9935 
   9936                 /* Update ING_QUEUE_MAP reference count */
   9937                 _bcm_tr_mpls_ing_queue_map_ref_count_adjust (unit,
   9938                                                              extended_queue_id,
   9939                                                              +1);
   9940 
   9941             } else {
   9942                 /* use extended_queue_id as Queue */
   9943                 ing_nh_info.tag_type = EH_TAG_TYPE_EXPLICT_QUEUE;
   9944                 ing_nh_info.qtag = extended_queue_id;
   9945             }
   9946         }
   9947         if ((mpls_port->flags & BCM_MPLS_PORT_REPLACE) &&
   9948                 (0 == mpls_port->per_flow_queue_base)) {
   9949             if (ing_nh_info.qtag > 0) {
   9950                 if (ing_nh_info.tag_type == EH_TAG_TYPE_ING_QUEUE_MAP)  {
   9951                     /* Update ING_QUEUE_MAP reference count */
   9952                     _bcm_tr_mpls_ing_queue_map_ref_count_adjust (unit,
   9953                                                                ing_nh_info.qtag,
   9954                                                                -1);
   9955                     /*  ING_QUEUE_MAP needs to be reset */
   9956                     _BCM_MPLS_CLEANUP(
   9957                      _bcm_tr_mpls_ing_queue_map_index_reset (unit,
   9958                                                              ing_nh_info.qtag));
   9959                 }
   9960                 ing_nh_info.qtag = 0;
   9961                 ing_nh_info.tag_type = EH_TAG_TYPE_NONE;  /* No HQOS */
   9962             }
   9963         }
   9964     }
   9965 #endif /* BCM_KATANA_SUPPORT */
   9966     /* Write ING_L3_NEXT_HOP entry */
   9967     rv = _bcm_tr_mpls_ING_L3_NEXT_HOP_add(unit, &ing_nh_info,
   9968                                             *vp_nh_index, drop);
   9969     _BCM_MPLS_CLEANUP(rv);
   9970 
   9971 #if defined(BCM_TRIUMPH2_SUPPORT)
   9972     if (soc_feature(unit, soc_feature_mpls_failover)) {
   9973         if (BCM_SUCCESS(_bcm_esw_failover_mpls_check(unit, mpls_port))) {
   9974             failover_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id);
   9975             if (failover_vp != -1) {
   9976                 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, failover_vp, &failover_dvp);
   9977                 _BCM_MPLS_CLEANUP(rv);
   9978 
   9979                 failover_nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &failover_dvp,
   9980                                                    NEXT_HOP_INDEXf);
   9981             }
   9982 
   9983             if (_BCM_MULTICAST_IS_SET(mpls_port->failover_mc_group)) {
   9984                  protection_flags |= _BCM_FAILOVER_1_PLUS_PROTECTION;
   9985             }
   9986             if (mpls_port->flags & BCM_MPLS_PORT_FAILOVER) {
   9987                   bcm_failover_t failover_id;
   9988                   int multicast_group;
   9989                   rv = _bcm_esw_failover_prot_nhi_get(unit, failover_nh_index,
   9990                                 &failover_id, &old_nh_info->old_nh_index, &multicast_group);
   9991                   _BCM_MPLS_CLEANUP(rv);
   9992                   /* coverity[negative_returns : FALSE] */
   9993                   rv = _bcm_esw_failover_prot_nhi_create(unit, protection_flags, failover_nh_index,
   9994                                 (uint32) *vp_nh_index, mpls_port->failover_mc_group, mpls_port->failover_id);
   9995                   _BCM_MPLS_CLEANUP(rv);
   9996 
   9997                   if (old_nh_info->old_nh_index == 0) {
   9998                       old_nh_info->old_nh_index = -1;
   9999                   }
  10000             } else {
  10001                  rv = _bcm_esw_failover_prot_nhi_create(unit, protection_flags, (uint32) *vp_nh_index,
  10002                      failover_nh_index, mpls_port->failover_mc_group, mpls_port->failover_id);
  10003 
  10004                  _BCM_MPLS_CLEANUP(rv);
  10005             }
  10006        } else if ((mpls_port->flags & BCM_MPLS_PORT_REPLACE)  &&
  10007                     (mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL)&&
  10008                     (old_vp_nh_index != *vp_nh_index) &&
  10009                     (mpls_port->flags & BCM_MPLS_PORT_FAILOVER)) {
  10010 
  10011              rv = _bcm_esw_failover_prot_nhi_update(unit, old_vp_nh_index, (uint32) *vp_nh_index );
  10012             _BCM_MPLS_CLEANUP(rv);
  10013       }
  10014     }
  10015 #endif /* BCM_TRIUMPH2_SUPPORT  */
  10016 #if defined(BCM_TRIUMPH3_SUPPORT)
  10017     if ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) &&
  10018         soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) {
  10019         rv = _bcm_tr_mpls_vc_and_swap_hash_nhop_add(unit,
  10020                                                     egr_nh_info.vc_swap_index,
  10021                                                     *vp_nh_index);
  10022         _BCM_MPLS_CLEANUP(rv);
  10023     }
  10024 #endif
  10025     return rv;
  10026 
  10027 cleanup:
  10028     if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  10029         (void) bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, *vp_nh_index);
  10030     }
  10031     if (egress_nh_index != -1) {
  10032         (void) bcm_xgs3_nh_del(unit, 0, egress_nh_index);
  10033     }
  10034     if (tpid_index != -1) {
  10035         (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
  10036     }
  10037     if (egr_nh_info.macda_index != -1) {
  10038         (void) _bcm_mac_da_profile_entry_delete(unit, egr_nh_info.macda_index);
  10039     }
  10040     if (egr_nh_info.vc_swap_index >= 0) {
  10041          _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit,
  10042                              egr_nh_info.vc_swap_index, -1);
  10043          (void) _bcm_tr_mpls_vc_and_swap_table_index_reset (unit, 
  10044                              egr_nh_info.vc_swap_index);
  10045     }
  10046     return rv;
  10047 }
  10048 
  10049 STATIC int
  10050 _bcm_tr_mpls_l2_nh_info_delete(int unit, int nh_index)
  10051 {
  10052     int rv=BCM_E_NONE, is_local, old_macda_idx = -1, old_vc_swap_idx = -1;
  10053     int action_present, action_not_present, old_tpid_idx = -1;
  10054     bcm_if_t tunnel_if = 0;
  10055     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
  10056     initial_ing_l3_next_hop_entry_t initial_ing_nh;
  10057     ing_l3_next_hop_entry_t ing_nh;
  10058     egr_l3_next_hop_entry_t egr_nh;
  10059     bcm_module_t modid = 0;
  10060     bcm_trunk_t trunk_id = 0;
  10061     _bcm_port_info_t *info;
  10062     bcm_port_t phys_port = 0;
  10063     uint32 port_flags;
  10064     uint32 dest_type, dest_val;
  10065     int is_trunk = 0;
  10066 #if defined(BCM_KATANA2_SUPPORT)
  10067     bcm_port_t pp_port = -1;
  10068 #endif
  10069 #if defined(BCM_KATANA_SUPPORT)
  10070     int qtag, qtag_type;
  10071 #endif
  10072 #if defined(BCM_HGPROXY_COE_SUPPORT)
  10073     int local_port;
  10074 #endif
  10075 
  10076     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 
  10077                                   MEM_BLOCK_ANY, nh_index, &egr_nh));
  10078     BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 
  10079                                   MEM_BLOCK_ANY, nh_index, &ing_nh));
  10080     BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_ING_L3_NEXT_HOPm, 
  10081                                   MEM_BLOCK_ANY, nh_index, &initial_ing_nh));
  10082 
  10083     if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]) == 0x1) {
  10084         /* Egressing into an MPLS tunnel */
  10085         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  10086               old_macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  10087                                                          MPLS__MAC_DA_PROFILE_INDEXf);
  10088               old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  10089                                                          MPLS__VC_AND_SWAP_INDEXf);
  10090         } else {
  10091               old_macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  10092                                                            MAC_DA_PROFILE_INDEXf);
  10093               old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  10094                                                            VC_AND_SWAP_INDEXf);
  10095         }
  10096         /* Get old TPID index if it's used */
  10097         rv = soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10098                           MEM_BLOCK_ALL, old_vc_swap_idx, &vc_entry);
  10099         BCM_IF_ERROR_RETURN(rv);
  10100         action_present =
  10101             soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit,
  10102                                              &vc_entry,
  10103                                              SD_TAG_ACTION_IF_PRESENTf);
  10104         action_not_present =
  10105             soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit,
  10106                                              &vc_entry,
  10107                                              SD_TAG_ACTION_IF_NOT_PRESENTf);
  10108         if ((action_not_present == 0x1) || (action_present == 0x1)) {
  10109             /* If SD tag action is ADD or REPLACE_VID_TPID, the tpid
  10110              * index of the entry is valid. Save
  10111              * the old tpid index to be deleted later.
  10112              */
  10113               old_tpid_idx =
  10114                    soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit,
  10115                                              &vc_entry, SD_TAG_TPID_INDEXf);
  10116         }
  10117 
  10118         /* Find the tunnel_if */
  10119         rv = bcm_tr_mpls_get_vp_nh (unit, nh_index, &tunnel_if);
  10120         if ( rv < 0) {
  10121             return rv;
  10122         }
  10123 
  10124         rv = _bcm_tr_mpls_pw_init_counter_delete (unit, nh_index);
  10125         if ( rv < 0) {
  10126             return rv;
  10127         }
  10128     } else if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 
  10129                                                 nh_entry_type_field[unit]) == 0x2) {
  10130         /* egressing into a regular port */
  10131         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  10132               action_present =
  10133                       soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  10134                                             SD_TAG__SD_TAG_ACTION_IF_PRESENTf);
  10135               action_not_present =
  10136                       soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  10137                                             SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf);
  10138         } else {
  10139               action_present =
  10140                       soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  10141                                             SD_TAG_ACTION_IF_PRESENTf);
  10142               action_not_present =
  10143                       soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  10144                                             SD_TAG_ACTION_IF_NOT_PRESENTf);
  10145         }
  10146         if ((action_not_present == 0x1) || (action_present == 0x1)) {
  10147             /* If SD tag action is ADD or REPLACE_VID_TPID, the tpid
  10148              * index of the entry is valid. Save
  10149              * the old tpid index to be deleted later.
  10150              */
  10151                 if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  10152                     old_tpid_idx =
  10153                           soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  10154                                                  SD_TAG__SD_TAG_TPID_INDEXf);
  10155                 } else {
  10156                     old_tpid_idx =
  10157                           soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  10158                                                  SD_TAG_TPID_INDEXf);
  10159                 }
  10160 
  10161         }
  10162     } else {
  10163         return BCM_E_NOT_FOUND;
  10164     }
  10165 
  10166 #if defined(BCM_TRIUMPH2_SUPPORT)
  10167     if (soc_feature(unit, soc_feature_mpls_failover)) {
  10168         rv = _bcm_esw_failover_prot_nhi_cleanup(unit, nh_index);
  10169         if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) {
  10170             return rv;
  10171         }
  10172     }
  10173 #endif /* BCM_TRIUMPH2_SUPPORT  */
  10174 
  10175     /* Update the physical port's SW state */
  10176 
  10177     /*Read trunk_id,phy_port,modid*/
  10178     if (soc_feature(unit, soc_feature_generic_dest)) {
  10179         dest_val = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm,
  10180                 &ing_nh, DESTINATIONf, &dest_type);
  10181         if (dest_type == SOC_MEM_FIF_DEST_LAG) {
  10182             /* Trunk group */
  10183             trunk_id = dest_val & SOC_MEM_FIF_DGPP_TGID_MASK;
  10184             is_trunk = 1;
  10185         } else {
  10186             phys_port = dest_val & SOC_MEM_FIF_DGPP_PORT_MASK;
  10187             modid     = (dest_val & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
  10188                 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
  10189         }
  10190     } else {
  10191     modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
  10192         if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
  10193             is_trunk = 1;
  10194             trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf);
  10195         } else {
  10196             phys_port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh,
  10197                     PORT_NUMf);
  10198         }
  10199     }
  10200 #if defined(BCM_HGPROXY_COE_SUPPORT)
  10201     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
  10202         _bcm_xgs5_subport_coe_mod_local(unit, modid)) {
  10203 
  10204         if (soc_feature(unit, soc_feature_generic_dest)) {
  10205             dest_val = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm,
  10206                                 &ing_nh, DESTINATIONf, &dest_type);
  10207             phys_port = dest_val & SOC_MEM_FIF_DGPP_PORT_MASK;
  10208         } else {
  10209             phys_port =
  10210                 soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf);
  10211         }
  10212             BCM_IF_ERROR_RETURN(
  10213                 _bcmi_coe_subport_mod_port_physical_port_get(unit, modid,
  10214                                                              phys_port,
  10215                                                              &local_port));
  10216             _bcm_port_info_access(unit, local_port, &info);
  10217             info->vp_count--;
  10218             /* Update the physical port's attributes */
  10219             BCM_IF_ERROR_RETURN(bcm_esw_port_vlan_member_get(unit,
  10220                 local_port, &port_flags));
  10221             BCM_IF_ERROR_RETURN(bcm_esw_port_vlan_member_set(unit,
  10222                 local_port, port_flags));
  10223     } else 
  10224 #endif
  10225     {
  10226         BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, modid, &is_local));
  10227         if (is_local && !is_trunk) {
  10228             if (soc_feature(unit, soc_feature_sysport_remap)) { 
  10229                 BCM_XLATE_SYSPORT_S2P(unit, &phys_port); 
  10230             }
  10231             _bcm_port_info_access(unit, phys_port, &info);
  10232             info->vp_count--;
  10233             /* Update the physical port's attributes */
  10234             BCM_IF_ERROR_RETURN
  10235                 (bcm_esw_port_vlan_member_get(unit, phys_port, &port_flags));
  10236             BCM_IF_ERROR_RETURN
  10237                 /* coverity[stack_use_callee] */
  10238                 /* coverity[stack_use_overflow] */
  10239                 (bcm_esw_port_vlan_member_set(unit, phys_port, port_flags));
  10240         }
  10241     }
  10242 
  10243 #if defined(BCM_KATANA2_SUPPORT)
  10244     if (soc_feature(unit, soc_feature_linkphy_coe) ||
  10245         soc_feature(unit, soc_feature_subtag_coe)) {
  10246         /* For LinkPHY/SubportPktTag pp_ports, check if the mod is a valid one */
  10247         if (_bcm_kt2_mod_is_coe_mod_check(unit, modid) == BCM_E_NONE) {
  10248             BCM_IF_ERROR_RETURN(
  10249                 _bcm_kt2_modport_to_pp_port_get(unit, modid,
  10250                     phys_port, &pp_port));
  10251             /*For KT2, pp_port >=42 are used for LinkPHY/SubportPktTag subport.
  10252             * Get the subport info associated with the pp_port and form the
  10253             * subport_gport */
  10254             if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, pp_port)){
  10255                 _bcm_port_info_access(unit, pp_port, &info);
  10256                 info->vp_count--;
  10257                 /* Update the physical port's attributes */
  10258                 BCM_IF_ERROR_RETURN(bcm_esw_port_vlan_member_get(unit,
  10259                             pp_port, &port_flags));
  10260                 BCM_IF_ERROR_RETURN(bcm_esw_port_vlan_member_set(unit,
  10261                             pp_port, port_flags));
  10262             }
  10263         }
  10264     }
  10265 #endif
  10266 
  10267     /* If associated with a trunk, update each local physical port's SW state */
  10268     if (is_trunk) {
  10269         int idx;
  10270         uint32 port_flags;
  10271 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
  10272         int        max_num_port = SOC_MAX_NUM_PP_PORTS;
  10273         bcm_port_t local_member_array[SOC_MAX_NUM_PP_PORTS];
  10274 #else
  10275         int        max_num_port = SOC_MAX_NUM_PORTS;
  10276         bcm_port_t local_member_array[SOC_MAX_NUM_PORTS];
  10277 #endif
  10278         int local_member_count;
  10279 
  10280         rv = _bcm_esw_trunk_local_members_get(unit, trunk_id,
  10281                                               max_num_port, local_member_array,
  10282                                               &local_member_count);
  10283         /* The resource(next_hop/vx_and_swap entry etc.) should be cleared even
  10284          * if local members can't be got.
  10285          */
  10286         if (BCM_E_NONE == rv) {
  10287             for (idx = 0; idx < local_member_count; idx++) {
  10288                 _bcm_port_info_access(unit, local_member_array[idx], &info);
  10289                 info->vp_count--;
  10290 
  10291                 /* Update the physical port's attributes */
  10292                 BCM_IF_ERROR_RETURN(
  10293                     bcm_esw_port_vlan_member_get(unit, local_member_array[idx],
  10294                                                  &port_flags));
  10295                 BCM_IF_ERROR_RETURN(
  10296                     bcm_esw_port_vlan_member_set(unit, local_member_array[idx],
  10297                                                  port_flags));
  10298             }
  10299         }
  10300     }
  10301 #if defined(BCM_KATANA_SUPPORT)     
  10302     if (soc_feature(unit, soc_feature_extended_queueing)) {
  10303         qtag = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, EH_QUEUE_TAGf);
  10304         qtag_type = soc_ING_L3_NEXT_HOPm_field32_get(unit,
  10305                                                      &ing_nh, EH_TAG_TYPEf);
  10306         if ((qtag > 0) && (qtag_type == EH_TAG_TYPE_ING_QUEUE_MAP)) {
  10307            /* Update ING_QUEUE_MAP reference count */
  10308            _bcm_tr_mpls_ing_queue_map_ref_count_adjust (unit, qtag, -1);
  10309 
  10310            /*  ING_QUEUE_MAP needs to be reset */
  10311            BCM_IF_ERROR_RETURN(
  10312                _bcm_tr_mpls_ing_queue_map_index_reset (unit, qtag));
  10313         }
  10314     }
  10315 #endif /* BCM_KATANA_SUPPORT */
  10316 
  10317     /* Clear ING_L3_NEXT_HOP entry */
  10318     sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t));
  10319     BCM_IF_ERROR_RETURN (soc_mem_write (unit, ING_L3_NEXT_HOPm,
  10320                                    MEM_BLOCK_ALL, nh_index, &ing_nh));
  10321 
  10322     /* Clear INITIAL_ING_L3_NEXT_HOP entry */
  10323     sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t));
  10324     BCM_IF_ERROR_RETURN (soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm,
  10325                                    MEM_BLOCK_ALL, nh_index, &initial_ing_nh));
  10326 
  10327     /* Delete old TPID, MAC, tunnel next-hop and VC_SWAP indexes */
  10328     if (old_vc_swap_idx != -1) {
  10329 #if defined(BCM_TRIUMPH3_SUPPORT)
  10330         if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) {
  10331             BCM_IF_ERROR_RETURN(
  10332                 _bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit,
  10333                                                           old_vc_swap_idx,
  10334                                                           nh_index));
  10335         }
  10336 #endif
  10337          _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, old_vc_swap_idx, -1);
  10338          BCM_IF_ERROR_RETURN
  10339              (_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, old_vc_swap_idx));
  10340     }
  10341     if (old_macda_idx != -1) {
  10342         rv = _bcm_mac_da_profile_entry_delete(unit, old_macda_idx);
  10343         BCM_IF_ERROR_RETURN(rv);
  10344     }
  10345     if (old_tpid_idx != -1) {
  10346         (void) _bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx);
  10347     }
  10348     if (tunnel_if != 0) {
  10349         rv = bcm_xgs3_nh_del(unit, 0, 
  10350                              (tunnel_if - BCM_XGS3_EGRESS_IDX_MIN(unit)));
  10351         BCM_IF_ERROR_RETURN(rv);
  10352     }
  10353 
  10354     BCM_IF_ERROR_RETURN(_bcm_tr_mpls_delete_vp_nh ( unit, nh_index, tunnel_if ));
  10355 
  10356     /* Clear EGR_L3_NEXT_HOP entry */
  10357     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
  10358     BCM_IF_ERROR_RETURN (soc_mem_write(unit, EGR_L3_NEXT_HOPm,
  10359                                    MEM_BLOCK_ALL, nh_index, &egr_nh));
  10360 
  10361     /* Free the next-hop entry. */
  10362     rv = bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, nh_index);
  10363     return rv;
  10364 }
  10365 
  10366 /* Translate hardware table index into map ID used by API */
  10367 int
  10368 _egr_idx2id(int unit, int hw_map_idx)
  10369 {
  10370     int num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
  10371     int id;
  10372 
  10373     for (id = 0; id < num_exp_map; id++) {
  10374         if (_BCM_EGR_MPLS_MAP_USED_GET(unit, id)) {
  10375             if (MPLS_INFO(unit)->egr_mpls_hw_idx[id] == (uint32)hw_map_idx) {
  10376                 return id;
  10377             }
  10378         }
  10379     }
  10380     return -1;
  10381 }
  10382 
  10383 STATIC int
  10384 _bcm_tr_mpls_l2_nh_info_get(int unit, int vp, bcm_mpls_port_t *mpls_port, 
  10385                             int nh_index)
  10386 {
  10387     ing_l3_next_hop_entry_t ing_nh;
  10388     egr_l3_next_hop_entry_t egr_nh;
  10389     egr_l3_next_hop_entry_t egr_l3_nh;
  10390     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
  10391     int vc_swap_idx, action_present, action_not_present;
  10392     bcm_module_t mod_out, mod_in;
  10393     bcm_port_t port_out, port_in;
  10394     bcm_trunk_t trunk_id;
  10395     int ttl = 0, entry_type, ix;
  10396     int network_port_flag = 0, tpid_index = 0;
  10397     bcm_if_t tunnel_if = 0;
  10398     _bcm_vp_info_t vp_info;
  10399 #if defined(BCM_KATANA2_SUPPORT)
  10400     bcm_port_t pp_port = 0;
  10401 #endif
  10402 #if defined(BCM_KATANA2_SUPPORT) | defined(BCM_HGPROXY_COE_SUPPORT)
  10403     int is_local_subport = 0;
  10404 #endif
  10405 #if defined(BCM_KATANA_SUPPORT)
  10406     ing_queue_map_entry_t ing_queue_entry;
  10407     int qtag, qtag_type;
  10408 #endif
  10409 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  10410     int egress_failover_id;
  10411 #endif
  10412     uint32 dest_type=0,dest_val=0;
  10413     int is_trunk = 0;
  10414 
  10415 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
  10416     int ecn_map_id;
  10417     int ecn_map_hw_index;
  10418     int ecn_map_pri;
  10419     soc_field_t ipecn_to_exp_ptr;
  10420     soc_field_t ipecn_to_exp_priority;
  10421 #endif
  10422 
  10423     uint32 base_class_id = 0;
  10424     int base_nh_entry_type = 0;
  10425     int nh_idx = 0,vc_data_type = 0;
  10426 #if defined(BCM_TRIDENT3_SUPPORT)
  10427     uint32 mpls_format[2];
  10428 #endif
  10429 
  10430     /* Read the HW entries */
  10431     BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  10432                                       nh_index, &ing_nh));
  10433     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  10434                                       nh_index, &egr_nh));
  10435     entry_type =  soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]);
  10436   
  10437         /* Egressing into an MPLS tunnel, find the tunnel_if */
  10438     if (entry_type == 0x1) {
  10439         mpls_port->flags |= BCM_MPLS_PORT_EGRESS_TUNNEL;
  10440         BCM_IF_ERROR_RETURN(
  10441             bcm_tr_mpls_get_vp_nh(unit, nh_index, &tunnel_if));
  10442         mpls_port->egress_tunnel_if = tunnel_if;
  10443         mpls_port->flags |= BCM_MPLS_PORT_NETWORK;
  10444         network_port_flag = TRUE; 
  10445 
  10446         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  10447             if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  10448                                     MPLS__HG_MODIFY_ENABLEf)) {
  10449                 mpls_port->flags2 |= BCM_MPLS_PORT2_PROXY_MODE;
  10450             }
  10451         }
  10452 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  10453         if (soc_feature(unit, soc_feature_mpls_nh_ttl_control)) {
  10454             if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  10455                                     MPLS__DISABLE_TTL_DECREMENTf)) {
  10456                 mpls_port->flags2 |= BCM_MPLS_PORT2_KEEP_TTL;
  10457             }
  10458         }
  10459 #endif
  10460         /* Calculate next hop index. */
  10461         if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, tunnel_if)) {
  10462             nh_idx = tunnel_if - BCM_XGS3_EGRESS_IDX_MIN(unit);
  10463         } else {
  10464             nh_idx = tunnel_if - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
  10465         }
  10466 
  10467         if ((nh_idx > 0) && (nh_idx < BCM_XGS3_L3_NH_TBL_SIZE(unit))) {
  10468 
  10469            if (soc_feature(unit, soc_feature_egr_nh_class_id_valid)) {
  10470 
  10471                 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm,
  10472                                 MEM_BLOCK_ANY,
  10473                                 nh_idx, &egr_l3_nh));
  10474 
  10475                 base_nh_entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
  10476                                                              &egr_l3_nh,
  10477                                                              ENTRY_TYPEf);
  10478                 if (base_nh_entry_type == 0) {
  10479                     /* Get class id for l3 unicast Nhs.
  10480                      */
  10481                     base_class_id = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
  10482                                                              &egr_l3_nh,
  10483                                                              L3__CLASS_IDf);
  10484                 } else if (base_nh_entry_type == 1) {
  10485                    /* Get class id for mpls unicast Nhs.
  10486                      */
  10487                     base_class_id = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
  10488                                                              &egr_l3_nh,
  10489                                                              MPLS__CLASS_IDf);
  10490                 }
  10491 
  10492                 mpls_port->egress_class_id = soc_EGR_L3_NEXT_HOPm_field32_get(
  10493                                                              unit, &egr_nh,
  10494                                                              MPLS__CLASS_IDf);
  10495 
  10496 
  10497                 if (base_class_id == mpls_port->egress_class_id) {
  10498                     /* if l3 nh class id and mpls class id is same
  10499                      *  then the value has come from l3 nh.
  10500                      *  User must had sent invalid class if mpls port.
  10501                      *  We dont allow same class ids in mpls port and base l3 nh.
  10502                      */
  10503                     mpls_port->egress_class_id = BCM_CLASS_ID_INVALID;
  10504                 }
  10505             } else {
  10506                 mpls_port->egress_class_id = BCM_CLASS_ID_INVALID;
  10507             }
  10508         } else {
  10509             return BCM_E_PARAM;
  10510         }
  10511     } else if (entry_type == 0x2) {
  10512         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  10513             if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  10514                                     SD_TAG__HG_MODIFY_ENABLEf)) {
  10515                 mpls_port->flags2 |= BCM_MPLS_PORT2_PROXY_MODE;
  10516             }
  10517 
  10518             if (soc_feature(unit, soc_feature_egr_nh_class_id_valid)) {
  10519                 mpls_port->egress_class_id = soc_EGR_L3_NEXT_HOPm_field32_get(
  10520                                                              unit, &egr_nh,
  10521                                                              SD_TAG__CLASS_IDf);
  10522                 if (mpls_port->egress_class_id == 0) {
  10523                     mpls_port->egress_class_id = BCM_CLASS_ID_INVALID;
  10524                 }
  10525 
  10526             }
  10527         }
  10528     }
  10529 
  10530     entry_type = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf);
  10531 
  10532     if (entry_type == 0x2) {
  10533 
  10534         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  10535             if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
  10536                 if (!(soc_feature(unit, soc_feature_td3_style_mpls))) {
  10537                 mpls_port->network_group_id = soc_EGR_L3_NEXT_HOPm_field32_get(
  10538                                     unit, &egr_nh, MPLS__DVP_NETWORK_GROUPf);
  10539                 }
  10540             } else {
  10541                 mpls_port->network_group_id = soc_EGR_L3_NEXT_HOPm_field32_get(
  10542                                     unit, &egr_nh, MPLS__DVP_IS_NETWORK_PORTf);
  10543             }
  10544         } else {
  10545             mpls_port->network_group_id = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  10546                                                              DVP_IS_NETWORK_PORTf);
  10547         }
  10548 
  10549         BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  10550         if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
  10551             network_port_flag = TRUE;
  10552         }
  10553 
  10554         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  10555             vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  10556                                                        MPLS__VC_AND_SWAP_INDEXf);
  10557         } else {
  10558             vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  10559                                                        VC_AND_SWAP_INDEXf);
  10560         }
  10561 
  10562         BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
  10563                                       MEM_BLOCK_ANY, vc_swap_idx, &vc_entry));
  10564 
  10565         if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10566                                 &vc_entry, MPLS_LABEL_ACTIONf)) {
  10567 
  10568             if (SOC_MEM_FIELD_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10569                         DATA_TYPEf)) {
  10570                 vc_data_type = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10571                         &vc_entry, DATA_TYPEf);
  10572             }
  10573 
  10574             if (vc_data_type == _BCM_VC_SWAP_TBL_FLEX_DATA_TYPE) {
  10575                 /*TD3 PHP/SWAPTOSELF VCSWAP Entry*/
  10576 #if defined(BCM_TRIDENT3_SUPPORT)
  10577                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  10578                     sal_memset(mpls_format, 0, sizeof(mpls_format));
  10579                     soc_mem_field_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10580                             (uint32 *) &vc_entry,
  10581                             MPLS_ENTRY_ACTION_SETfmt,
  10582                             (uint32 *) mpls_format);
  10583                     mpls_port->egress_label.label = soc_format_field32_get(unit, 
  10584                             MPLS_ENTRY_ACTION_SETfmt,
  10585                             (uint32 *)mpls_format, MPLS_LABELf);
  10586 
  10587                     ttl = soc_format_field32_get(unit, 
  10588                             MPLS_ENTRY_ACTION_SETfmt,
  10589                             (uint32 *)mpls_format, MPLS_TTLf);
  10590 
  10591                     if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  10592                                 (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x0) {
  10593                         /* Use the specified EXP, PRI and CFI */
  10594                         mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_SET;
  10595                         mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_SET;
  10596                         mpls_port->egress_label.exp =
  10597                             soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  10598                                     (uint32 *)mpls_format, MPLS_EXPf);
  10599                         mpls_port->egress_label.pkt_pri =
  10600                             soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  10601                                     (uint32 *)mpls_format, NEW_PRIf);
  10602                         mpls_port->egress_label.pkt_cfi =
  10603                             soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  10604                                     (uint32 *)mpls_format, NEW_CFIf);
  10605                     } else if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  10606                                 (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x1) {
  10607                         /* Use EXP-map for EXP, PRI and CFI */
  10608                         mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_REMARK;
  10609                         mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK;
  10610                         ix = soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  10611                                 (uint32 *)mpls_format, MPLS_EXP_MAPPING_PTRf);
  10612                         BCM_IF_ERROR_RETURN(
  10613                                 _egr_qos_hw_idx2id(unit, ix, &mpls_port->egress_label.qos_map_id));
  10614 
  10615                     } else if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  10616                                 (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x2) {
  10617                         /* Use EXP from incoming MPLS label. If no incoming label, use the specified
  10618                          * EXP value. Use EXP-map for PRI/CFI.
  10619                          */
  10620                         mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_COPY;
  10621                         mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK;
  10622                         mpls_port->egress_label.exp =
  10623                             soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  10624                                     (uint32 *)mpls_format, MPLS_EXPf);
  10625                         ix = soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  10626                                 (uint32 *)mpls_format, MPLS_EXP_MAPPING_PTRf);
  10627 
  10628                         BCM_IF_ERROR_RETURN(
  10629                                 _egr_qos_hw_idx2id(unit, ix, &mpls_port->egress_label.qos_map_id));
  10630                     }
  10631                 }
  10632 #endif
  10633             } else {
  10634             mpls_port->egress_label.label = 
  10635                 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10636                                     &vc_entry, MPLS_LABELf);
  10637             ttl =  soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10638                                     &vc_entry, MPLS_TTLf);
  10639             if (ttl) {
  10640                 mpls_port->egress_label.ttl = ttl;
  10641                 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET;
  10642             } else {
  10643                 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_TTL_DECREMENT;
  10644             }
  10645             if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10646                                     &vc_entry, MPLS_EXP_SELECTf) == 0x0) {
  10647                 /* Use the specified EXP, PRI and CFI */
  10648                 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_SET;
  10649                 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_SET;
  10650                 mpls_port->egress_label.exp =
  10651                     soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10652                                         &vc_entry, MPLS_EXPf);
  10653                 mpls_port->egress_label.pkt_pri =
  10654                     soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10655                                         &vc_entry, NEW_PRIf);
  10656                 mpls_port->egress_label.pkt_cfi =
  10657                     soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10658                                         &vc_entry, NEW_CFIf);
  10659             } else if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10660                                            &vc_entry, MPLS_EXP_SELECTf) == 0x1) {
  10661                 /* Use EXP-map for EXP, PRI and CFI */
  10662                 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_REMARK;
  10663                 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK;
  10664                 ix = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10665                                         &vc_entry, MPLS_EXP_MAPPING_PTRf);
  10666                 BCM_IF_ERROR_RETURN(
  10667                     _egr_qos_hw_idx2id(unit, ix, &mpls_port->egress_label.qos_map_id));
  10668 
  10669             } else if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10670                                            &vc_entry, MPLS_EXP_SELECTf) == 0x2) {
  10671                 /* Use EXP from incoming MPLS label. If no incoming label, use the specified
  10672                  * EXP value. Use EXP-map for PRI/CFI.
  10673                  */
  10674                 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_COPY;
  10675                 mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK;
  10676                 mpls_port->egress_label.exp =
  10677                     soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10678                                         &vc_entry, MPLS_EXPf);
  10679                 ix = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10680                                          &vc_entry, MPLS_EXP_MAPPING_PTRf);
  10681 
  10682                 BCM_IF_ERROR_RETURN(
  10683                     _egr_qos_hw_idx2id(unit, ix, &mpls_port->egress_label.qos_map_id));
  10684             }
  10685 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
  10686             if (soc_feature(unit, soc_feature_mpls_ecn)) {
  10687                 int rv;
  10688                     if (!soc_feature(unit, soc_feature_intcn_to_exp_nosupport)) {
  10689                 ecn_map_hw_index = soc_mem_field32_get(unit, 
  10690                                                        EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10691                                                        &vc_entry, 
  10692                                                        INT_CN_TO_EXP_MAPPING_PTRf);
  10693                 rv = bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_index, 
  10694                                             _BCM_XGS5_MPLS_ECN_MAP_TYPE_INTCN2EXP, 
  10695                                             &ecn_map_id);  
  10696                 if (BCM_SUCCESS(rv)) {
  10697                     mpls_port->egress_label.int_cn_map_id = ecn_map_id;
  10698                     ecn_map_pri = soc_mem_field32_get(unit, 
  10699                                                       EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10700                                                       &vc_entry, 
  10701                                                       INT_CN_TO_EXP_PRIORITYf);
  10702                     if (ecn_map_pri) {
  10703                         mpls_port->egress_label.flags |= 
  10704                             BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST;
  10705                     }
  10706                     mpls_port->egress_label.flags |= 
  10707                         BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP;
  10708                 }
  10709                     }
  10710 #if defined(BCM_TRIDENT3_SUPPORT)
  10711                     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  10712                         ipecn_to_exp_ptr = PKT_ECN_TO_EXP_MAPPING_PTRf;
  10713                         ipecn_to_exp_priority = PKT_ECN_TO_EXP_PRIORITYf;
  10714                     } else
  10715 #endif
  10716                     {
  10717                         ipecn_to_exp_ptr = IP_ECN_TO_EXP_MAPPING_PTRf;
  10718                         ipecn_to_exp_priority = IP_ECN_TO_EXP_PRIORITYf;
  10719                     }
  10720                 ecn_map_hw_index = soc_mem_field32_get(unit, 
  10721                                                        EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10722                             &vc_entry, ipecn_to_exp_ptr);
  10723 
  10724                 rv = bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_index, 
  10725                                             _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP, 
  10726                                             &ecn_map_id);  
  10727                 if (BCM_SUCCESS(rv)) {
  10728                     mpls_port->egress_label.ecn_map_id = ecn_map_id;
  10729                     ecn_map_pri = soc_mem_field32_get(unit, 
  10730                                                       EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10731                                                       &vc_entry, 
  10732                                 ipecn_to_exp_priority);
  10733                     if (ecn_map_pri) {
  10734                         mpls_port->egress_label.flags |= 
  10735                             BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST;
  10736                     }
  10737                     mpls_port->egress_label.flags |= 
  10738                         BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP;                    
  10739                 }                
  10740             }
  10741 #endif /* BCM_TOMAHAWK2_SUPPORT */            
  10742             }
  10743         } else {
  10744             /*Return egress label as zero for default VCSWAP label entry*/
  10745             if (vc_swap_idx == 0) {
  10746                 mpls_port->egress_label.label = 0;
  10747             }
  10748         }
  10749         if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10750                                 &vc_entry, CW_INSERT_FLAGf) == 0x2) {
  10751             mpls_port->flags |= BCM_MPLS_PORT_SEQUENCED;
  10752         } else if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10753                                        &vc_entry, CW_INSERT_FLAGf) == 0x1) {
  10754             mpls_port->flags |= BCM_MPLS_PORT_CONTROL_WORD;
  10755         }
  10756         if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10757                                 &vc_entry, UPDATE_PW_INIT_COUNTERSf)) {
  10758             mpls_port->flags |= BCM_MPLS_PORT_COUNTED;
  10759         }
  10760 #ifdef BCM_MONTEREY_SUPPORT
  10761         if (soc_feature(unit, soc_feature_roe) ||
  10762             soc_feature(unit, soc_feature_roe_custom)) {
  10763             if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10764                                     BARE_MPLSf)) {
  10765                 if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10766                                         &vc_entry, BARE_MPLSf)) {
  10767                     mpls_port->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_ROE_BARE_MPLS;
  10768                 }
  10769             }
  10770         }
  10771 #endif
  10772 #if (defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT))
  10773         if (soc_feature(unit, soc_feature_mpls_entropy)) {
  10774              if (soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10775                                     MPLS_INSERT_ENTROPY_LABELf)) {
  10776                   if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10777                                 &vc_entry, MPLS_INSERT_ENTROPY_LABELf)) {
  10778                         mpls_port->egress_label.flags |= 
  10779                             BCM_MPLS_EGRESS_LABEL_ENTROPY_ENABLE;
  10780                   }
  10781              }
  10782         }
  10783 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_APACHE_SUPPORT) */
  10784 
  10785         if (soc_feature(unit, soc_feature_generic_dest)) {
  10786             dest_val = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm,
  10787                     &ing_nh, DESTINATIONf, &dest_type);
  10788 
  10789             if (dest_type == SOC_MEM_FIF_DEST_LAG) {
  10790                 /* Trunk group */
  10791                 trunk_id = dest_val & SOC_MEM_FIF_DGPP_TGID_MASK;
  10792                 is_trunk = 1;
  10793             } else {
  10794                 port_in = dest_val & SOC_MEM_FIF_DGPP_PORT_MASK;
  10795                 mod_in  = (dest_val & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
  10796                     SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
  10797             }
  10798         } else {
  10799             is_trunk = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf);
  10800             trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf);
  10801             if(!is_trunk) {
  10802             mod_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
  10803             port_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf);
  10804             }
  10805         }
  10806 
  10807         if (is_trunk) {
  10808             BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id);
  10809         } else {
  10810 
  10811 #if defined(BCM_HGPROXY_COE_SUPPORT)
  10812             if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
  10813 
  10814                 if(_bcm_xgs5_subport_coe_mod_port_local(unit, mod_in, port_in)) {
  10815                     is_local_subport = 1;
  10816                 }
  10817 
  10818                 if (is_local_subport) {
  10819                     /* Encode type and fill in the associated (mod,port) */
  10820                     _BCM_SUBPORT_COE_PORT_ID_SET(mpls_port->port, mod_in, port_in);
  10821                     /* Set the bit on the outgoing param indicating this is subtag type */
  10822                     _BCM_SUBPORT_COE_PORT_TYPE_SET(mpls_port->port, _BCM_SUBPORT_COE_TYPE_SUBTAG);
  10823                 }
  10824             }
  10825 #endif
  10826 
  10827 #if defined(BCM_KATANA2_SUPPORT)
  10828             if (soc_feature(unit, soc_feature_linkphy_coe) ||
  10829                 soc_feature(unit, soc_feature_subtag_coe)) {
  10830                 if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_in) == BCM_E_NONE) {
  10831                     BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(
  10832                         unit, mod_in, port_in, &pp_port));
  10833                     if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, pp_port)){
  10834                         is_local_subport = 1;
  10835                     }
  10836                 }
  10837 
  10838                 if (is_local_subport) {
  10839                     _BCM_KT2_SUBPORT_PORT_ID_SET(mpls_port->port, pp_port);
  10840                     if (BCM_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm,
  10841                         pp_port)) {
  10842                         _BCM_KT2_SUBPORT_PORT_TYPE_SET(mpls_port->port,
  10843                             _BCM_KT2_SUBPORT_TYPE_LINKPHY);
  10844                     } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm,
  10845                         pp_port)) {
  10846                         _BCM_KT2_SUBPORT_PORT_TYPE_SET(mpls_port->port,
  10847                             _BCM_KT2_SUBPORT_TYPE_SUBTAG);
  10848                     } else {
  10849                         return BCM_E_PORT;
  10850                     }
  10851                 }
  10852             }
  10853 #endif
  10854 
  10855 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT)
  10856             if (is_local_subport) {
  10857                 /* gport assigned above */
  10858             } else
  10859 #endif
  10860             {
  10861                 BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit,
  10862                          BCM_STK_MODMAP_GET, mod_in, port_in, &mod_out, &port_out));
  10863                 if ((mpls_port->criteria == BCM_MPLS_PORT_MATCH_VLAN) &&
  10864                     port_out == 0) {
  10865                     mpls_port->port = BCM_GPORT_INVALID;
  10866                 } else {
  10867                     BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out);
  10868                 }
  10869             }
  10870         }
  10871 
  10872         if (network_port_flag) {
  10873 
  10874             action_present =
  10875                 soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit,
  10876                                              &vc_entry, SD_TAG_ACTION_IF_PRESENTf);
  10877             action_not_present =
  10878                 soc_EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm_field32_get(unit,
  10879                                              &vc_entry, SD_TAG_ACTION_IF_NOT_PRESENTf);
  10880 
  10881             switch (action_present) {
  10882 
  10883             case 0:
  10884                 if (action_not_present == 1) {
  10885                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  10886                 }
  10887                 mpls_port->egress_service_vlan =
  10888                     soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry, SD_TAG_VIDf);
  10889                 break;
  10890 
  10891             case 1:
  10892                 if (action_not_present == 1) {
  10893                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  10894                 }
  10895                 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE;
  10896                 mpls_port->egress_service_vlan =
  10897                     soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry, SD_TAG_VIDf);
  10898                 break;
  10899 
  10900             case 2:
  10901                 if (action_not_present == 1) {
  10902                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  10903                 }
  10904                 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_REPLACE;
  10905                 mpls_port->egress_service_vlan =
  10906                     soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry, SD_TAG_VIDf);
  10907                 break;
  10908 
  10909             case 3:
  10910                 if (action_not_present == 1) {
  10911                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  10912                 }
  10913                 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_DELETE;
  10914                 mpls_port->egress_service_vlan = BCM_VLAN_INVALID;
  10915                 break;
  10916 
  10917             case 4:
  10918                 if (action_not_present == 1) {
  10919                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  10920                 }
  10921                 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE;
  10922                 mpls_port->egress_service_vlan = 
  10923                     soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
  10924                                         &vc_entry, SD_TAG_VIDf);
  10925                 mpls_port->pkt_pri = 
  10926                     soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
  10927                                         &vc_entry, SD_TAG_NEW_PRIf);
  10928                 break;    
  10929 
  10930             case 5:
  10931                 if (action_not_present == 1) {
  10932                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  10933                 }
  10934                 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_PRI_REPLACE;
  10935                 mpls_port->egress_service_vlan = 
  10936                     soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
  10937                                         &vc_entry, SD_TAG_VIDf);
  10938                 mpls_port->pkt_pri = 
  10939                     soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
  10940                                         &vc_entry, SD_TAG_NEW_PRIf);
  10941                 break; 
  10942                 
  10943             case 6:
  10944                 if (action_not_present == 1) {
  10945                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  10946                 }
  10947                 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_PRI_REPLACE;
  10948                 mpls_port->pkt_pri = 
  10949                     soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
  10950                                         &vc_entry, SD_TAG_NEW_PRIf);
  10951                 break; 
  10952                 
  10953             case 7:
  10954                 if (action_not_present == 1) {
  10955                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  10956                 }
  10957                 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_TPID_REPLACE;
  10958                 break; 
  10959 
  10960             default:
  10961                 break;
  10962             }
  10963             if ((mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) ||
  10964                 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) ||
  10965                 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE) ||
  10966                 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) {
  10967                 tpid_index = soc_mem_field32_get(unit,
  10968                                  EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  10969                                  &vc_entry, SD_TAG_TPID_INDEXf);
  10970                 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_get(unit,
  10971                                         &mpls_port->service_tpid, tpid_index));
  10972             }
  10973         } else {
  10974 
  10975              if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  10976                      action_present =
  10977                                soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  10978                                                            SD_TAG__SD_TAG_ACTION_IF_PRESENTf);
  10979                      action_not_present = 
  10980                                soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  10981                                                            SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf);
  10982              } else {
  10983                      action_present =
  10984                                soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  10985                                                            SD_TAG_ACTION_IF_PRESENTf);
  10986                      action_not_present =
  10987                                soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  10988                                                            SD_TAG_ACTION_IF_NOT_PRESENTf);
  10989               }
  10990 
  10991             switch (action_present) {
  10992 
  10993             case 0:
  10994                 if (action_not_present == 1) {
  10995                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  10996                 }
  10997                 if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  10998                     mpls_port->egress_service_vlan =
  10999                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
  11000                                                                 SD_TAG__SD_TAG_VIDf);
  11001                 } else {
  11002                     mpls_port->egress_service_vlan =
  11003                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
  11004                                                                 SD_TAG_VIDf);
  11005                 }
  11006                 break;
  11007 
  11008             case 1:
  11009                 if (action_not_present == 1) {
  11010                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  11011                 }
  11012                 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE;
  11013                 if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  11014                     mpls_port->egress_service_vlan =
  11015                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
  11016                                                                 SD_TAG__SD_TAG_VIDf);
  11017                 } else {
  11018                     mpls_port->egress_service_vlan =
  11019                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
  11020                                                                 SD_TAG_VIDf);
  11021                 }
  11022                 break;
  11023 
  11024             case 2:
  11025                 if (action_not_present == 1) {
  11026                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  11027                 }
  11028                 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_REPLACE;
  11029                 if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  11030                     mpls_port->egress_service_vlan =
  11031                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
  11032                                                                 SD_TAG__SD_TAG_VIDf);
  11033                 } else {
  11034                     mpls_port->egress_service_vlan =
  11035                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
  11036                                                                 SD_TAG_VIDf);
  11037                 }
  11038                 break;
  11039 
  11040             case 3:
  11041                 if (action_not_present == 1) {
  11042                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  11043                 }
  11044                 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_DELETE;
  11045                 mpls_port->egress_service_vlan = BCM_VLAN_INVALID;
  11046                 break;
  11047 
  11048             case 4:
  11049                 if (action_not_present == 1) {
  11050                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  11051                 }
  11052                 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE;
  11053                 if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  11054                     mpls_port->egress_service_vlan =
  11055                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  11056                                             SD_TAG__SD_TAG_VIDf);
  11057                     if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
  11058                        SD_TAG__NEW_PRIf)) {
  11059                         mpls_port->pkt_pri =
  11060                             soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  11061                                                 SD_TAG__NEW_PRIf);
  11062                     }
  11063                     if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
  11064                        SD_TAG__SD_TAG_REMARK_CFIf)) {
  11065                         if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  11066                             SD_TAG__SD_TAG_REMARK_CFIf)) {
  11067                             mpls_port->flags2 |= BCM_MPLS_PORT2_SERVICE_CFI_REPLACE;
  11068                         }
  11069                     }
  11070                     if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
  11071                        SD_TAG__NEW_CFIf)) {
  11072                         mpls_port->pkt_cfi =
  11073                             soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  11074                                                 SD_TAG__NEW_CFIf);
  11075                     }
  11076                 }
  11077                 break;    
  11078 
  11079             case 5:
  11080                 if (action_not_present == 1) {
  11081                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  11082                 }
  11083                 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_PRI_REPLACE;
  11084                 if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  11085                     mpls_port->egress_service_vlan =
  11086                         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  11087                                             SD_TAG__SD_TAG_VIDf);
  11088                     if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
  11089                        SD_TAG__NEW_PRIf)) {
  11090                         mpls_port->pkt_pri =
  11091                             soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  11092                                                 SD_TAG__NEW_PRIf);
  11093                     }
  11094                     if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
  11095                        SD_TAG__SD_TAG_REMARK_CFIf)) {
  11096                         if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  11097                             SD_TAG__SD_TAG_REMARK_CFIf)) {
  11098                             mpls_port->flags2 |= BCM_MPLS_PORT2_SERVICE_CFI_REPLACE;
  11099                         }
  11100                     }
  11101                     if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
  11102                        SD_TAG__NEW_CFIf)) {
  11103                         mpls_port->pkt_cfi =
  11104                             soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  11105                                                 SD_TAG__NEW_CFIf);
  11106                     }
  11107                 }
  11108                 break; 
  11109                 
  11110             case 6:
  11111                 if (action_not_present == 1) {
  11112                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  11113                 }
  11114                 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_PRI_REPLACE;
  11115                 if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  11116                     if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
  11117                         SD_TAG__NEW_PRIf)) {
  11118                         mpls_port->pkt_pri =
  11119                             soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  11120                                                 SD_TAG__NEW_PRIf);
  11121                     }
  11122                     if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
  11123                        SD_TAG__SD_TAG_REMARK_CFIf)) {
  11124                         if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  11125                             SD_TAG__SD_TAG_REMARK_CFIf)) {
  11126                             mpls_port->flags2 |= BCM_MPLS_PORT2_SERVICE_CFI_REPLACE;
  11127                         }
  11128                     }
  11129                     if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
  11130                        SD_TAG__NEW_CFIf)) {
  11131                         mpls_port->pkt_cfi =
  11132                             soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  11133                                                 SD_TAG__NEW_CFIf);
  11134                     }
  11135                 }
  11136                 break; 
  11137                 
  11138             case 7:
  11139                 if (action_not_present == 1) {
  11140                     mpls_port->flags |= BCM_MPLS_PORT_SERVICE_VLAN_ADD;
  11141                 }
  11142                 mpls_port->flags |= BCM_MPLS_PORT_SERVICE_TPID_REPLACE;
  11143                 break; 
  11144 
  11145             default:
  11146                 break;
  11147             }
  11148             if ((mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) ||
  11149                 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) ||
  11150                 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE) ||
  11151                 (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) {
  11152                  if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  11153                      tpid_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
  11154                                       &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf);
  11155                  } else {
  11156                      tpid_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
  11157                                       &egr_nh, SD_TAG_TPID_INDEXf);
  11158                  }
  11159                  BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_get(unit,
  11160                                          &mpls_port->service_tpid, tpid_index));
  11161             }
  11162         }
  11163 
  11164         if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, DROPf)) {
  11165             mpls_port->flags |= BCM_MPLS_PORT_DROP;
  11166         }
  11167 #if defined(BCM_TRIUMPH3_SUPPORT)
  11168     if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  11169        if (SOC_IS_TRIUMPH3(unit) && soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
  11170            MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf)) {
  11171            if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  11172                MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf)) {
  11173                mpls_port->flags2 |= BCM_MPLS_PORT2_TUNNEL_HEADER_EGRESS_VLAN_TRANSLATION;
  11174            }
  11175        }
  11176     }
  11177 #endif
  11178 #if defined(BCM_KATANA_SUPPORT)
  11179         if (soc_feature(unit, soc_feature_extended_queueing)) {
  11180             qtag = soc_ING_L3_NEXT_HOPm_field32_get(unit,
  11181                                                  &ing_nh, EH_QUEUE_TAGf);
  11182             qtag_type = soc_ING_L3_NEXT_HOPm_field32_get(unit,
  11183                                                  &ing_nh, EH_TAG_TYPEf);
  11184             if (qtag_type == EH_TAG_TYPE_ING_QUEUE_MAP) {
  11185                 sal_memset(&ing_queue_entry, 0, sizeof(ing_queue_map_entry_t));
  11186                 BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_QUEUE_MAPm,
  11187                                                  MEM_BLOCK_ANY,
  11188                                                  qtag, &ing_queue_entry));
  11189                 mpls_port->qos_map_id = soc_ING_QUEUE_MAPm_field32_get(unit,
  11190                                &ing_queue_entry, QUEUE_OFFSET_PROFILE_INDEXf);
  11191                 mpls_port->qos_map_id |=
  11192                     (_BCM_QOS_MAP_TYPE_ING_QUEUE_OFFSET_MAP_TABLE
  11193                                                     << _BCM_QOS_MAP_SHIFT);
  11194             }
  11195             if (qtag_type > EH_TAG_TYPE_NONE) {
  11196                 /* We need to have a cosq function which returns the gport for 
  11197                    the queue. Currently, creating the gport of type 
  11198                    subscriber queue locally */
  11199 #ifdef BCM_KATANA2_SUPPORT
  11200                 if (SOC_IS_KATANA2(unit)) {
  11201                     bcm_kt2_cosq_subscriber_qid_set(unit, &qtag, qtag);
  11202                 } else
  11203 #endif
  11204                 {
  11205                     BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_SET(qtag, qtag);
  11206                 }
  11207                 qtag |= soc_ING_L3_NEXT_HOPm_field32_get(unit,
  11208                                                     &ing_nh, PORT_NUMf) << 16;
  11209                 mpls_port->per_flow_queue_base = qtag;
  11210             }
  11211         }
  11212 #endif /* BCM_KATANA_SUPPORT */        
  11213 #ifdef BCM_TRIDENT2PLUS_SUPPORT
  11214         if (soc_feature(unit, soc_feature_egress_failover)) {
  11215             egress_failover_id = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, MPLS__PROT_GROUPf);
  11216             if(egress_failover_id > 0)
  11217                 mpls_port->egress_failover_id = egress_failover_id;
  11218         }
  11219 #endif
  11220     } else {
  11221         return BCM_E_NOT_FOUND;
  11222     }
  11223 
  11224     return BCM_E_NONE;
  11225 }
  11226 
  11227 /*
  11228  * Function:
  11229  *      _bcm_tr_mpls_match_trunk_idx_get
  11230  * Purpose:
  11231  *      Obtain Trunk_Idx
  11232  * Parameters:
  11233  *      unit    - (IN) Device Number
  11234  *      mod_id - (IN) Module Id
  11235  *      port_id  - (IN) Port Id
  11236  *      src_trk_idx - (OUT) trunk_idx
  11237  * Returns:
  11238  *      BCM_E_XXX
  11239  */
  11240 
  11241 STATIC int
  11242 _bcm_tr_mpls_match_trunk_idx_get(int unit,
  11243                                   bcm_module_t mod_id,
  11244                                   bcm_port_t port_id,
  11245                                   int *src_trk_idx)
  11246 {
  11247     int num_bits_for_port = 0;
  11248 
  11249 #if defined(BCM_KATANA2_SUPPORT)
  11250     if (soc_feature(unit, soc_feature_linkphy_coe) ||
  11251         soc_feature(unit, soc_feature_subtag_coe)) {
  11252             BCM_IF_ERROR_RETURN(_bcm_kt2_pp_port_to_modport_get(
  11253                 unit, port_id, &mod_id, &port_id));
  11254     }
  11255 #endif
  11256 
  11257 #if defined(BCM_TRIDENT_SUPPORT)
  11258     if (soc_feature(unit, soc_feature_src_modid_base_index)) {
  11259         source_trunk_map_modbase_entry_t modbase_entry;
  11260 
  11261          BCM_IF_ERROR_RETURN
  11262               (soc_mem_read(unit, SOURCE_TRUNK_MAP_MODBASEm, 
  11263                              MEM_BLOCK_ANY, mod_id, &modbase_entry));
  11264          *src_trk_idx =	soc_mem_field32_get(unit, 
  11265                                        SOURCE_TRUNK_MAP_MODBASEm,
  11266                                        &modbase_entry, BASEf) + port_id;
  11267     } else 
  11268 #endif
  11269     { 
  11270          num_bits_for_port = 
  11271                    _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit));
  11272          *src_trk_idx = (mod_id << num_bits_for_port) | port_id;
  11273     }
  11274     return BCM_E_NONE;
  11275 }
  11276 
  11277 int
  11278 bcm_tr_mpls_trunk_member_add(int unit, bcm_trunk_t trunk_id, 
  11279         int trunk_member_count, bcm_port_t *trunk_member_array)
  11280 {
  11281     int rv = BCM_E_NONE;
  11282     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  11283     int i, my_modid, stm_idx, vp;
  11284 
  11285     rv = _bcm_trunk_id_validate(unit, trunk_id);
  11286     if (BCM_FAILURE(rv)) {
  11287         return BCM_E_PORT;
  11288     }
  11289     if (!mpls_info->initialized) {
  11290         LOG_ERROR(BSL_LS_BCM_MPLS,
  11291                   (BSL_META_U(unit,
  11292                               "MPLS module not initialized. \n")));
  11293         return BCM_E_INIT;
  11294     }
  11295 
  11296     vp = mpls_info->trunk_vp_map[trunk_id];
  11297     if (vp != -1) {
  11298         BCM_IF_ERROR_RETURN(
  11299             bcm_esw_stk_my_modid_get(unit, &my_modid));
  11300         /* Get index to source trunk map table */
  11301         
  11302         for (i = 0; i < trunk_member_count; i++) {
  11303             BCM_IF_ERROR_RETURN
  11304                 (_bcm_esw_src_mod_port_table_index_get(unit, my_modid, 
  11305                                           trunk_member_array[i], &stm_idx));
  11306             BCM_IF_ERROR_RETURN
  11307                 (soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  11308                                         stm_idx, SOURCE_VPf, vp));
  11309             if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) {
  11310                 BCM_IF_ERROR_RETURN
  11311                     (soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  11312                                             stm_idx, SVP_VALIDf, 1));
  11313             }
  11314             BCM_IF_ERROR_RETURN
  11315                 (_bcm_esw_port_tab_set(unit, trunk_member_array[i], 
  11316                                        _BCM_CPU_TABS_NONE,
  11317                                        PORT_OPERATIONf, 0x1)); /* L2_SVP */
  11318         }
  11319     }
  11320 
  11321     return BCM_E_NONE;
  11322 }
  11323 
  11324 int
  11325 bcm_tr_mpls_trunk_member_delete(int unit, bcm_trunk_t trunk_id, 
  11326         int trunk_member_count, bcm_port_t *trunk_member_array)
  11327 {
  11328     int rv = BCM_E_NONE;
  11329     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  11330     int i, my_modid, stm_idx, vp;
  11331 
  11332     rv = _bcm_trunk_id_validate(unit, trunk_id);
  11333     if (BCM_FAILURE(rv)) {
  11334         return BCM_E_PORT;
  11335     }
  11336 
  11337     vp = mpls_info->trunk_vp_map[trunk_id];
  11338     if (vp != -1) {
  11339         BCM_IF_ERROR_RETURN(
  11340             bcm_esw_stk_my_modid_get(unit, &my_modid));
  11341         /* Get index to source trunk map table */
  11342         
  11343         for (i = 0; i < trunk_member_count; i++) {
  11344             BCM_IF_ERROR_RETURN
  11345                 (_bcm_esw_src_mod_port_table_index_get(unit, my_modid, 
  11346                                           trunk_member_array[i], &stm_idx));
  11347             BCM_IF_ERROR_RETURN
  11348                 (soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  11349                                         stm_idx, SOURCE_VPf, 0));
  11350             if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) {
  11351                 BCM_IF_ERROR_RETURN
  11352                     (soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  11353                                             stm_idx, SVP_VALIDf, 0));
  11354             }
  11355             BCM_IF_ERROR_RETURN
  11356                 (_bcm_esw_port_tab_set(unit, trunk_member_array[i], 
  11357                                        _BCM_CPU_TABS_NONE,
  11358                                        PORT_OPERATIONf, 0)); /* L2_SVP */
  11359         }
  11360     }
  11361 
  11362     return BCM_E_NONE;
  11363 }
  11364 
  11365 /*
  11366  * Function:
  11367  *      bcm_tr_mpls_match_trunk_add
  11368  * Purpose:
  11369  *      Assign SVP of an MPLS Trunk port
  11370  * Parameters:
  11371  *      unit    - (IN) Device Number
  11372  *      tgid - (IN) Trunk group Id
  11373  *      vp  - (IN) Source Virtual Port
  11374  * Returns:
  11375  *      BCM_E_XXX
  11376  */
  11377 
  11378 int
  11379  bcm_tr_mpls_match_trunk_add(int unit, bcm_trunk_t tgid, int vp)
  11380 {
  11381     int port_idx;
  11382     bcm_module_t my_modid;
  11383 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
  11384     int max_num_port = SOC_MAX_NUM_PP_PORTS;
  11385 #else
  11386     int max_num_port = SOC_MAX_NUM_PORTS;
  11387 #endif
  11388     int * local_src_trk_idx = NULL;
  11389     int * local_port_out = NULL;
  11390     int local_member_count;
  11391     int rv = BCM_E_NONE;
  11392     int src_trk_idx = -1;
  11393     bcm_port_t port_out;
  11394 
  11395     local_src_trk_idx = sal_alloc(sizeof(int) * max_num_port, "local source Trunk index");
  11396     if (NULL == local_src_trk_idx) {
  11397         return BCM_E_MEMORY;
  11398     }
  11399     sal_memset(local_src_trk_idx, 0, sizeof(int) * max_num_port);
  11400     local_port_out = sal_alloc(sizeof(int) * max_num_port, "Local port out");
  11401     if (NULL == local_port_out) {
  11402         sal_free(local_src_trk_idx);
  11403         return BCM_E_MEMORY;
  11404     }
  11405     sal_memset(local_port_out, 0, sizeof(int) * max_num_port);
  11406     rv = bcm_esw_stk_my_modid_get(unit, &my_modid);
  11407     if (BCM_FAILURE(rv)) {
  11408         sal_free(local_src_trk_idx);
  11409         sal_free(local_port_out);
  11410         return rv;
  11411     }
  11412     rv = _bcm_esw_trunk_local_members_get(unit, tgid,
  11413                 max_num_port, local_port_out, &local_member_count);
  11414     if (BCM_FAILURE(rv)) {
  11415         sal_free(local_src_trk_idx);
  11416         sal_free(local_port_out);
  11417         return rv;
  11418     }
  11419     for (port_idx = 0; port_idx < local_member_count; port_idx++) {
  11420         rv = _bcm_tr_mpls_match_trunk_idx_get(unit,
  11421                     my_modid, local_port_out[port_idx], &src_trk_idx);
  11422         if (BCM_FAILURE(rv)) {
  11423             sal_free(local_src_trk_idx);
  11424             sal_free(local_port_out);
  11425             return rv;
  11426         }
  11427         local_src_trk_idx[port_idx] = src_trk_idx;
  11428 
  11429         rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  11430                                  src_trk_idx, SOURCE_VPf, vp);
  11431         if (BCM_FAILURE(rv)) {
  11432              goto trunk_cleanup;
  11433         }
  11434         if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) {
  11435             rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  11436                                  src_trk_idx, SVP_VALIDf, 1);
  11437             if (BCM_FAILURE(rv)) {
  11438                 goto trunk_cleanup;
  11439             }
  11440         }
  11441 
  11442         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  11443             rv = _bcm_esw_port_tab_set(unit, local_port_out[port_idx],
  11444                     _BCM_CPU_TABS_BOTH,
  11445                     PORT_OPERATIONf, 0x1);
  11446         } else {
  11447         rv = _bcm_esw_port_tab_set_without_portlock(
  11448                  unit, local_port_out[port_idx], _BCM_CPU_TABS_NONE,
  11449                  PORT_OPERATIONf, 0x1); /* L2_SVP */
  11450         }
  11451         if (BCM_FAILURE(rv)) {
  11452             goto trunk_cleanup;
  11453         }
  11454  
  11455         /* Set TAG_ACTION_PROFILE_PTR */ 
  11456         rv = bcm_tr_mpls_port_untagged_profile_set(unit, local_port_out[port_idx]); 
  11457         if (BCM_FAILURE(rv)) { 
  11458             goto trunk_cleanup; 
  11459         } 
  11460     }
  11461     sal_free(local_src_trk_idx);
  11462     sal_free(local_port_out);
  11463     return BCM_E_NONE;
  11464 
  11465  trunk_cleanup:
  11466     for (;port_idx >= 0; port_idx--) {
  11467         src_trk_idx = local_src_trk_idx[port_idx];
  11468         port_out = local_port_out[port_idx];
  11469         rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  11470                                  src_trk_idx, SOURCE_VPf, 0);
  11471         if (rv < 0) {
  11472             sal_free(local_src_trk_idx);
  11473             sal_free(local_port_out);
  11474             return rv;
  11475         }
  11476         if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) {
  11477             rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  11478                                  src_trk_idx, SVP_VALIDf, 0);
  11479         }
  11480         if (BCM_SUCCESS(rv)) {
  11481 
  11482             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  11483                 rv = _bcm_esw_port_tab_set(unit, port_out,
  11484                         _BCM_CPU_TABS_BOTH,
  11485                         PORT_OPERATIONf, 0);
  11486             } else {
  11487             rv = _bcm_esw_port_tab_set_without_portlock(
  11488                      unit, port_out, _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0);
  11489         }
  11490     }
  11491     }
  11492     sal_free(local_src_trk_idx);
  11493     sal_free(local_port_out);
  11494     return rv;
  11495 }
  11496 
  11497 /*
  11498  * Function:
  11499  *      bcm_tr_mpls_match_trunk_delete
  11500  * Purpose:
  11501  *      Remove SVP of an MPLS Trunk port
  11502  * Parameters:
  11503  *      unit    - (IN) Device Number
  11504  *      tgid - (IN) Trunk group Id
  11505  *      vp  - (IN) Source Virtual Port
  11506  * Returns:
  11507  *      BCM_E_XXX
  11508  */
  11509 
  11510 int
  11511 bcm_tr_mpls_match_trunk_delete(int unit, bcm_trunk_t tgid, int vp)
  11512 {
  11513     int port_idx;
  11514     bcm_module_t my_modid;
  11515 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
  11516     int max_num_port = SOC_MAX_NUM_PP_PORTS;
  11517     int local_src_trk_idx[SOC_MAX_NUM_PP_PORTS];
  11518     int local_port_out[SOC_MAX_NUM_PP_PORTS];
  11519 #else
  11520     int max_num_port = SOC_MAX_NUM_PORTS;
  11521     int local_src_trk_idx[SOC_MAX_NUM_PORTS];
  11522     int local_port_out[SOC_MAX_NUM_PORTS];
  11523 #endif
  11524     int local_member_count;
  11525     int rv = BCM_E_NONE;
  11526     int src_trk_idx = -1;
  11527     bcm_port_t port_out;
  11528 
  11529     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
  11530 
  11531     BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid,
  11532                 max_num_port, local_port_out, &local_member_count));
  11533 
  11534     for (port_idx = 0; port_idx < local_member_count; port_idx++) {
  11535         BCM_IF_ERROR_RETURN(_bcm_tr_mpls_match_trunk_idx_get(unit,
  11536                     my_modid, local_port_out[port_idx], &src_trk_idx));
  11537         local_src_trk_idx[port_idx] = src_trk_idx;
  11538 
  11539         rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  11540                                  src_trk_idx, SOURCE_VPf, 0);
  11541         if (BCM_FAILURE(rv)) {
  11542              goto trunk_cleanup;
  11543         }
  11544         if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) {
  11545             rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  11546                                  src_trk_idx, SVP_VALIDf, 0);
  11547             if (BCM_FAILURE(rv)) {
  11548                 goto trunk_cleanup;
  11549             }
  11550         }
  11551 
  11552         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  11553             rv = _bcm_esw_port_tab_set(unit, local_port_out[port_idx],
  11554                     _BCM_CPU_TABS_BOTH,
  11555                     PORT_OPERATIONf, 0x0);
  11556         } else {
  11557         rv = _bcm_esw_port_tab_set_without_portlock(
  11558                  unit, local_port_out[port_idx], _BCM_CPU_TABS_NONE,
  11559                  PORT_OPERATIONf, 0x0); /* L2_SVP */
  11560         }
  11561         if (BCM_FAILURE(rv)) {
  11562              goto trunk_cleanup;
  11563         }
  11564 
  11565          /* Reset TAG_ACTION_PROFILE_PTR */
  11566          /* coverity[stack_use_callee] */
  11567          /* coverity[stack_use_overflow] */
  11568          rv = bcm_tr_mpls_port_untagged_profile_reset(unit, local_port_out[port_idx]);
  11569          BCM_IF_ERROR_RETURN(rv);
  11570     }
  11571 
  11572     return BCM_E_NONE;
  11573 
  11574  trunk_cleanup:
  11575     for (;port_idx >= 0; port_idx--) {
  11576         src_trk_idx = local_src_trk_idx[port_idx];
  11577         port_out = local_port_out[port_idx];
  11578         (void)soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  11579                                  src_trk_idx, SOURCE_VPf, vp);
  11580         if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) {
  11581             (void)soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  11582                                  src_trk_idx, SVP_VALIDf, 1);
  11583         }
  11584 
  11585         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  11586             rv = _bcm_esw_port_tab_set(unit, port_out,
  11587                     _BCM_CPU_TABS_BOTH,
  11588                     PORT_OPERATIONf, 0x1);
  11589         } else {
  11590         (void)_bcm_esw_port_tab_set_without_portlock(unit, port_out,
  11591                                                      _BCM_CPU_TABS_NONE,
  11592                                                      PORT_OPERATIONf, 0x1);
  11593     }
  11594     }
  11595     return rv;
  11596 }
  11597 
  11598 /*
  11599  * Function:
  11600  *		_bcm_tr_mpls_match_vlan_entry_update
  11601  * Purpose:
  11602  *		Update MPLS Match Vlan_xlate Entry 
  11603  * Parameters:
  11604  *  IN :  Unit
  11605  *  IN :  vlan_xlate_entry
  11606  *  OUT :  vlan_xlate_entry
  11607 
  11608  */
  11609 
  11610 STATIC int
  11611 _bcm_tr_mpls_match_vlan_entry_update(int unit, bcm_mpls_port_t *mpls_port,
  11612         uint32 *vent, uint32 *return_ent)
  11613 {
  11614     uint32  vp, key_type, value;
  11615     soc_mem_t mem;
  11616 
  11617 #if defined(BCM_TRIDENT3_SUPPORT)
  11618     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  11619         mem = VLAN_XLATE_1_DOUBLEm;
  11620     } else
  11621 #endif
  11622     {
  11623         mem = VLAN_XLATEm;
  11624     }
  11625 
  11626     if ((vent == NULL) || (return_ent == NULL)) {
  11627         return BCM_E_PARAM;
  11628     }
  11629 
  11630     /* Check if Key_Type identical */
  11631     key_type = soc_mem_field32_get(unit, mem, vent, KEY_TYPEf);
  11632     value = soc_mem_field32_get(unit, mem, return_ent, KEY_TYPEf);
  11633     if (key_type != value) {
  11634          return BCM_E_PARAM;
  11635     }
  11636 
  11637     value = soc_mem_field32_get(unit, mem, return_ent, MPLS_ACTIONf);
  11638     /* SVP_VALID and L3_IIF_VALID overlay high and low bits of MPLS_ACTION. */
  11639     if (SOC_MEM_FIELD_VALID(unit, mem, L3_IIF_VALIDf)) {
  11640         value |= 0x1;
  11641     } else {
  11642         value = 0x1;
  11643     }
  11644     /* Retain original Keys -- Update data only */
  11645     soc_mem_field32_set(unit, mem, return_ent, MPLS_ACTIONf, value);
  11646     if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  11647         soc_mem_field32_set(unit, mem, return_ent, DISABLE_VLAN_CHECKSf, 1);
  11648     }
  11649     vp = soc_mem_field32_get(unit, mem, vent, SOURCE_VPf);
  11650     soc_mem_field32_set(unit, mem, return_ent, SOURCE_VPf, vp);
  11651     /*set default tag action profile ptr*/
  11652 #if defined(BCM_TRIDENT3_SUPPORT)
  11653     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  11654         soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 1);
  11655     }
  11656 #endif
  11657 
  11658    return BCM_E_NONE;
  11659 }
  11660 
  11661 
  11662 /*
  11663  * Function:
  11664  *		_bcm_tr_mpls_match_label_entry_update
  11665  * Purpose:
  11666  *		Update Match MPLS Entry 
  11667  * Parameters:
  11668  *  IN :  Unit
  11669  *  IN :  mpls_entry
  11670  *  OUT :  mpls_entry
  11671 
  11672  */
  11673 
  11674 STATIC void
  11675 _bcm_tr_mpls_match_label_entry_update(int unit, bcm_mpls_port_t *mpls_port, 
  11676                                                                      mpls_entry_entry_t *ment, 
  11677                                                                      mpls_entry_entry_t *return_ment)
  11678 {
  11679     uint32 value;
  11680     bcm_module_t mod_id;
  11681     bcm_port_t port_id;
  11682     bcm_trunk_t trunk_id;
  11683     bcm_mpls_label_t match_label;
  11684 
  11685     value = soc_MPLS_ENTRYm_field32_get (unit, ment, Tf);
  11686     if (value) {
  11687          soc_MPLS_ENTRYm_field32_set(unit, return_ment, Tf, value);
  11688          trunk_id = soc_MPLS_ENTRYm_field32_get (unit, ment, TGIDf);
  11689          soc_MPLS_ENTRYm_field32_set(unit, return_ment, TGIDf, trunk_id);
  11690     } else {
  11691          mod_id = soc_MPLS_ENTRYm_field32_get (unit, ment, MODULE_IDf);
  11692          soc_MPLS_ENTRYm_field32_set(unit, return_ment, MODULE_IDf, mod_id);
  11693          port_id = soc_MPLS_ENTRYm_field32_get (unit, ment, PORT_NUMf);
  11694          soc_MPLS_ENTRYm_field32_set(unit, return_ment, PORT_NUMf, port_id);
  11695     }
  11696 
  11697     match_label = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS_LABELf);
  11698     soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS_LABELf, match_label);
  11699     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  11700         soc_MPLS_ENTRYm_field32_set(unit, return_ment, BASE_VALID_0f, 3);
  11701         soc_MPLS_ENTRYm_field32_set(unit, return_ment, BASE_VALID_1f, 7);
  11702     } else {
  11703     soc_MPLS_ENTRYm_field32_set(unit, return_ment, VALIDf, 1);
  11704     }
  11705     value = soc_MPLS_ENTRYm_field32_get(unit, ment, SOURCE_VPf);
  11706     soc_MPLS_ENTRYm_field32_set(unit, return_ment, SOURCE_VPf, value);
  11707     soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS_ACTION_IF_BOSf, 0x1); /* L2 SVP */
  11708     soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS_ACTION_IF_NOT_BOSf, 0x0);
  11709     value = soc_MPLS_ENTRYm_field32_get(unit, ment, CW_CHECK_CTRLf);
  11710     soc_MPLS_ENTRYm_field32_set(unit, return_ment, CW_CHECK_CTRLf, value);
  11711     value = soc_MPLS_ENTRYm_field32_get(unit, ment, PW_TERM_NUM_VALIDf);
  11712     soc_MPLS_ENTRYm_field32_set(unit, return_ment, PW_TERM_NUM_VALIDf, value);
  11713     if(value) {
  11714         value = soc_MPLS_ENTRYm_field32_get(unit, ment, PW_TERM_NUMf);
  11715         soc_MPLS_ENTRYm_field32_set(unit, return_ment, PW_TERM_NUMf, value);
  11716     } 
  11717 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  11718     else {
  11719         if ((soc_feature(unit, soc_feature_mpls_enhanced)) &&
  11720              (soc_feature(unit,soc_feature_advanced_flex_counter))) {
  11721              value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__FLEX_CTR_POOL_NUMBERf);
  11722              soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__FLEX_CTR_POOL_NUMBERf, value);
  11723              value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__FLEX_CTR_BASE_COUNTER_IDXf);
  11724              soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__FLEX_CTR_BASE_COUNTER_IDXf, value);
  11725              value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__FLEX_CTR_OFFSET_MODEf);
  11726              soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__FLEX_CTR_OFFSET_MODEf, value);
  11727         }
  11728     }
  11729 #endif
  11730 
  11731     value = soc_MPLS_ENTRYm_field32_get(unit, ment, DECAP_USE_EXP_FOR_PRIf);
  11732     soc_MPLS_ENTRYm_field32_set(unit, return_ment, DECAP_USE_EXP_FOR_PRIf, 
  11733                                                            value);
  11734     value = soc_MPLS_ENTRYm_field32_get(unit, ment, EXP_MAPPING_PTRf);
  11735     soc_MPLS_ENTRYm_field32_set(unit, return_ment, EXP_MAPPING_PTRf, value);
  11736     value = soc_MPLS_ENTRYm_field32_get(unit, ment, NEW_PRIf);
  11737     soc_MPLS_ENTRYm_field32_set(unit, return_ment, NEW_PRIf, value);
  11738     if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRUST_OUTER_DOT1P_PTRf)) {
  11739          value = soc_MPLS_ENTRYm_field32_get(unit, ment, TRUST_OUTER_DOT1P_PTRf);
  11740          soc_MPLS_ENTRYm_field32_set(unit, return_ment, TRUST_OUTER_DOT1P_PTRf, 
  11741                                                            value);
  11742     }
  11743 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT)
  11744         if (soc_feature(unit, soc_feature_mpls_entropy)) {
  11745             if ((mpls_port->flags & BCM_MPLS_PORT_ENTROPY_ENABLE) ||
  11746                 (mpls_port->flags2 & BCM_MPLS_PORT2_INGRESS_ENTROPY_ENABLE)) {
  11747                 if (soc_mem_field_valid(unit, MPLS_ENTRYm,
  11748                                     ENTROPY_LABEL_PRESENTf)) {
  11749                      soc_MPLS_ENTRYm_field32_set(unit, return_ment,
  11750                                             ENTROPY_LABEL_PRESENTf, 0x1);
  11751                      soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS_ACTION_IF_BOSf,
  11752                                     0x0); /* INVALID */
  11753                      if (SOC_IS_APACHE(unit)) {
  11754                          soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS_ACTION_IF_NOT_BOSf,
  11755                                  0x6); /* POP_SVP_ENTROPY */
  11756                      } else {
  11757                          soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS_ACTION_IF_NOT_BOSf,
  11758                                  0x4); /* POP_SVP_ENTROPY */
  11759                      }
  11760                 }
  11761             } else if (soc_mem_field_valid(unit, MPLS_ENTRYm,
  11762                                     ENTROPY_LABEL_PRESENTf)) {
  11763                 soc_MPLS_ENTRYm_field32_set(unit, return_ment,
  11764                                     ENTROPY_LABEL_PRESENTf, 0x0);
  11765             }
  11766         }
  11767 #endif
  11768 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
  11769     if (soc_feature(unit, soc_feature_mpls_ecn)) {
  11770 #if defined(BCM_TRIDENT3_SUPPORT)
  11771         if(soc_feature(unit, soc_feature_td3_style_mpls)) {
  11772             value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__EXP_TO_ECN_MAPPING_PTRf);
  11773             soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__EXP_TO_ECN_MAPPING_PTRf, value);
  11774         } else
  11775 #endif
  11776         {
  11777          value = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__EXP_TO_IP_ECN_MAPPING_PTRf);
  11778          soc_MPLS_ENTRYm_field32_set(unit, return_ment, MPLS__EXP_TO_IP_ECN_MAPPING_PTRf, value);
  11779     }
  11780     }
  11781 #endif
  11782    if (soc_mem_field_valid(unit, MPLS_ENTRYm,DO_NOT_CHANGE_PAYLOAD_DSCPf)) {
  11783        value =
  11784            soc_MPLS_ENTRYm_field32_get(unit, ment, DO_NOT_CHANGE_PAYLOAD_DSCPf);
  11785        soc_MPLS_ENTRYm_field32_set(
  11786            unit, return_ment, DO_NOT_CHANGE_PAYLOAD_DSCPf, value);
  11787    }
  11788    return;
  11789 }
  11790 
  11791 /*
  11792  * Function:
  11793  *           _bcm_tr_mpls_vpless_failover_nh_index_find
  11794  * Purpose:
  11795  *           Traverse the EGR_L3_NEXT_HOP table to find next hop 
  11796  *           index for the failover mpls port of the same VP(vpless mpls port). 
  11797  * Parameters:
  11798  *           IN :  Unit
  11799  *           IN :  vp - the same vp for primary and vpless failover mpls ports 
  11800  *           IN :  primary_nh_index - primary mpls port next hop index 
  11801  *          OUT :  fo_nh_index - the failover mpls port next hop index
  11802  * Returns:
  11803  *      BCM_E_XXX
  11804  */
  11805 int
  11806 _bcm_tr_mpls_vpless_failover_nh_index_find (int unit, int vp, 
  11807                             int primary_nh_index, int *fo_nh_index)
  11808 {
  11809     /* Indexes to iterate over memories, chunks and entries */
  11810     int             chnk_idx, ent_idx, chnk_idx_max, mem_idx_max;
  11811     int             buf_size, chunksize, chnk_end;
  11812     uint32          *tbl_chnk;
  11813     egr_l3_next_hop_entry_t *egr_nh;
  11814     int             rv = BCM_E_NONE;
  11815     soc_mem_t mem;
  11816     int dvp;
  11817     int entry_type;
  11818 
  11819     *fo_nh_index = 0;
  11820     mem = EGR_L3_NEXT_HOPm;
  11821     chunksize = 0x400; /* 1k */
  11822     buf_size = sizeof(egr_l3_next_hop_entry_t) * chunksize;
  11823     tbl_chnk = soc_cm_salloc(unit, buf_size, "egr_l3_next_hop traverse");
  11824     if (NULL == tbl_chnk) {
  11825         return BCM_E_MEMORY;
  11826     }
  11827 
  11828     mem_idx_max = soc_mem_index_max(unit, mem);
  11829     for (chnk_idx = soc_mem_index_min(unit, mem);
  11830          chnk_idx <= mem_idx_max;
  11831          chnk_idx += chunksize) {
  11832         sal_memset((void *)tbl_chnk, 0, buf_size);
  11833 
  11834         chnk_idx_max =
  11835             ((chnk_idx + chunksize) <= mem_idx_max) ?
  11836             chnk_idx + chunksize - 1: mem_idx_max;
  11837 
  11838         soc_mem_lock(unit, mem);
  11839         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
  11840                                 chnk_idx, chnk_idx_max, tbl_chnk);
  11841         if (SOC_FAILURE(rv)) {
  11842             soc_mem_unlock(unit, mem);
  11843             soc_cm_sfree(unit, tbl_chnk);
  11844             return rv;
  11845         }
  11846         chnk_end = (chnk_idx_max - chnk_idx);
  11847         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
  11848             egr_nh = soc_mem_table_idx_to_pointer(unit, mem, 
  11849                                              egr_l3_next_hop_entry_t *,
  11850                                              tbl_chnk, ent_idx);
  11851 
  11852             entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 
  11853                                             egr_nh, nh_entry_type_field[unit]);
  11854             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  11855                 dvp = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
  11856                         egr_nh, MPLS__DVPf);
  11857             } else {
  11858                 dvp = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
  11859                         egr_nh, DVPf);
  11860             }
  11861 
  11862             if ((entry_type == 1) && 
  11863                 (dvp == vp) && ((ent_idx+chnk_idx) != primary_nh_index)) {
  11864                 *fo_nh_index = ent_idx+chnk_idx;
  11865                 soc_mem_unlock(unit, mem);
  11866                 soc_cm_sfree(unit, tbl_chnk);
  11867                 return BCM_E_NONE;
  11868             }  
  11869         }
  11870         soc_mem_unlock(unit, mem);
  11871     }
  11872     soc_cm_sfree(unit, tbl_chnk);
  11873     return BCM_E_NOT_FOUND;
  11874 }
  11875 
  11876 /*
  11877  * Function:
  11878  *        _bcm_tr_mpls_match_vlan_entry_set
  11879  * Purpose:
  11880  *       Set MPLS Match Vlan Entry 
  11881  * Parameters:
  11882  *  IN :  Unit
  11883  *  IN :  mpls_port
  11884  *  IN :  vlan_xlate_entry
  11885  * Returns:
  11886  *      BCM_E_XXX
  11887  */
  11888 
  11889 STATIC int
  11890 _bcm_tr_mpls_match_vlan_entry_set(int unit, bcm_mpls_port_t *mpls_port, uint32 *vent)
  11891 {
  11892     uint32 return_vent[SOC_MAX_MEM_WORDS];
  11893     int rv = BCM_E_UNAVAIL;
  11894     int index;
  11895     soc_mem_t mem;
  11896 
  11897     if (vent == NULL) {
  11898         return rv;
  11899     }
  11900 #if defined(BCM_TRIDENT3_SUPPORT)
  11901     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  11902         mem = VLAN_XLATE_1_DOUBLEm;
  11903     } else
  11904 #endif
  11905     {
  11906         mem = VLAN_XLATEm;
  11907     }
  11908 
  11909     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index,
  11910                         vent, return_vent, 0);
  11911 
  11912     if (rv == SOC_E_NONE) {
  11913          BCM_IF_ERROR_RETURN(
  11914               _bcm_tr_mpls_match_vlan_entry_update (unit, mpls_port, vent, return_vent));
  11915 
  11916          rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index,
  11917                  return_vent);
  11918     } else if (rv != SOC_E_NOT_FOUND) {
  11919         return rv;
  11920     } else {
  11921          if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  11922              return BCM_E_NOT_FOUND;
  11923          } else {
  11924               rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, vent);
  11925          }
  11926     }
  11927 
  11928     return rv;
  11929 }
  11930 
  11931 /*
  11932  * Function:
  11933  *		_bcm_tr_mpls_match_label_entry_set
  11934  * Purpose:
  11935  *		Set MPLS Match Label Entry 
  11936  * Parameters:
  11937  *  IN :  Unit
  11938  *  IN :  mpls_port
  11939  *  IN :  mpls_entry
  11940  * Returns:
  11941  *		BCM_E_XXX
  11942  */
  11943 
  11944 STATIC int
  11945 _bcm_tr_mpls_match_label_entry_set(int unit, bcm_mpls_port_t *mpls_port, mpls_entry_entry_t *ment)
  11946 {
  11947     mpls_entry_entry_t return_ment;
  11948     int rv = BCM_E_UNAVAIL;
  11949     int index;
  11950 
  11951     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
  11952                         ment, &return_ment, 0);
  11953 
  11954     if (rv == SOC_E_NONE) {
  11955          (void) _bcm_tr_mpls_match_label_entry_update (unit, mpls_port, ment, &return_ment);
  11956          rv = soc_mem_write(unit, MPLS_ENTRYm,
  11957                                            MEM_BLOCK_ALL, index,
  11958                                            &return_ment);
  11959     } else if (rv != SOC_E_NOT_FOUND) {
  11960         return rv;
  11961     } else {
  11962              rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, ment);
  11963     }
  11964 
  11965     return rv;
  11966 }
  11967 
  11968 /*
  11969  * Function:
  11970  *      _bcm_tr_mpls_match_clear
  11971  * Purpose:
  11972  *      Clear MPLS Match Software State
  11973  * Parameters:
  11974  *      unit    - (IN) Device Number
  11975  *      vp  - (IN) Source Virtual Port
  11976  * Returns:
  11977  *      void
  11978  */
  11979 
  11980 void
  11981 bcm_tr_mpls_match_clear (int unit, int vp)
  11982 {
  11983     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  11984 
  11985     mpls_info->match_key[vp].flags = 0;
  11986     mpls_info->match_key[vp].match_vlan = 0;
  11987     mpls_info->match_key[vp].match_inner_vlan = 0;
  11988     mpls_info->match_key[vp].match_label = 0;
  11989     mpls_info->match_key[vp].trunk_id = -1;
  11990     mpls_info->match_key[vp].port = 0;
  11991     mpls_info->match_key[vp].modid = -1;
  11992     mpls_info->match_key[vp].index = 0;
  11993 
  11994     return;
  11995 }
  11996 
  11997 /*
  11998  * Function:
  11999  *		bcm_tr_mpls_entry_internal_qos_set
  12000  * Purpose:
  12001  *		Set MPLS Entry QoS parameters
  12002  * Parameters:
  12003  *  IN :  Unit
  12004  *  IN :  mpls_port
  12005  *  IN :  mpls_entry
  12006  * Returns:
  12007  *		BCM_E_XXX
  12008  */
  12009 
  12010 void
  12011 bcm_tr_mpls_entry_internal_qos_set(int unit, bcm_mpls_port_t *mpls_port, 
  12012                                                                           bcm_mpls_tunnel_switch_t  *info, mpls_entry_entry_t *ment)
  12013 {
  12014     soc_mem_t mem = MPLS_ENTRYm;
  12015 
  12016     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  12017         mem = MPLS_ENTRY_SINGLEm;
  12018     }
  12019 
  12020     if (mpls_port != NULL ) {
  12021         if (mpls_port->flags & BCM_MPLS_PORT_INT_PRI_MAP) {
  12022             soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf,
  12023                                         0x1); /* MAP_PRI_AND_CNG */
  12024             /* Use specified EXP-map to determine internal prio/color */
  12025             soc_mem_field32_set(unit, mem, ment, EXP_MAPPING_PTRf,
  12026                 mpls_port->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK);
  12027         } else if ((mpls_port->flags & BCM_MPLS_PORT_INT_PRI_SET) &&
  12028                    (mpls_port->flags & BCM_MPLS_PORT_COLOR_MAP)) {
  12029             soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf,
  12030                                         0x2); /* NEW_PRI_MAP_CNG */
  12031             /* Use the specified internal priority value */
  12032             soc_mem_field32_set(unit, mem, ment, NEW_PRIf,
  12033                                         mpls_port->int_pri);
  12034             /* Use specified EXP-map to determine internal color */
  12035             soc_mem_field32_set(unit, mem, ment, EXP_MAPPING_PTRf,
  12036                 mpls_port->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK);
  12037         } else if (mpls_port->flags & BCM_MPLS_PORT_INT_PRI_SET) {
  12038             soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf, 0x2);
  12039             if (soc_mem_field_valid(unit, MPLS_ENTRYm,
  12040                                     TRUST_OUTER_DOT1P_PTRf)) {
  12041                 soc_mem_field32_set(unit, mem, ment,
  12042                                             TRUST_OUTER_DOT1P_PTRf,
  12043                                             _BCM_TR_MPLS_PRI_CNG_MAP_NONE);
  12044             }
  12045             soc_mem_field32_set(unit, mem, ment, NEW_PRIf,
  12046                                         mpls_port->int_pri);
  12047         } else {
  12048             /* Trust the encapsulated packet's 802.1p pri/cfi, 
  12049              * and use the incoming ports mapping.
  12050              */
  12051             soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf,
  12052                                         0x0); /* NONE */
  12053             if (soc_mem_field_valid(unit, MPLS_ENTRYm,
  12054                                     TRUST_OUTER_DOT1P_PTRf)) {
  12055                 soc_mem_field32_set(unit, mem, ment,
  12056                                             TRUST_OUTER_DOT1P_PTRf,
  12057                                             _BCM_TR_MPLS_PRI_CNG_MAP_IDENTITY);
  12058             }
  12059         }
  12060     }else if ( info != NULL ) {
  12061         if (info->flags & BCM_MPLS_SWITCH_INT_PRI_MAP) {
  12062             soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf,
  12063                                         0x1); /* MAP_PRI_AND_CNG */
  12064             /* Use specified EXP-map to determine internal prio/color */
  12065             soc_mem_field32_set(unit, mem, ment, EXP_MAPPING_PTRf,
  12066                 info->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK);
  12067         } else if ((info->flags & BCM_MPLS_SWITCH_INT_PRI_SET) &&
  12068                    (info->flags & BCM_MPLS_SWITCH_COLOR_MAP)) {
  12069             soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf,
  12070                                         0x2); /* NEW_PRI_MAP_CNG */
  12071             /* Use the specified internal priority value */
  12072             soc_mem_field32_set(unit, mem, ment, NEW_PRIf,
  12073                                         info->int_pri);
  12074             /* Use specified EXP-map to determine internal color */
  12075             soc_mem_field32_set(unit, mem, ment, EXP_MAPPING_PTRf,
  12076                 info->exp_map & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK);
  12077         } else if (info->flags & BCM_MPLS_SWITCH_INT_PRI_SET) {
  12078             soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf, 0x2);
  12079             if (soc_mem_field_valid(unit, MPLS_ENTRYm,
  12080                                     TRUST_OUTER_DOT1P_PTRf)) {
  12081                 soc_mem_field32_set(unit, mem, ment,
  12082                                             TRUST_OUTER_DOT1P_PTRf,
  12083                                             _BCM_TR_MPLS_PRI_CNG_MAP_NONE);
  12084             }
  12085             soc_mem_field32_set(unit, mem, ment, NEW_PRIf,
  12086                                         info->int_pri);
  12087         } else {
  12088             /* Trust the encapsulated packet's 802.1p pri/cfi, 
  12089              * and use the incoming ports mapping.
  12090              */
  12091             soc_mem_field32_set(unit, mem, ment, DECAP_USE_EXP_FOR_PRIf,
  12092                                         0x0); /* NONE */
  12093             if (soc_mem_field_valid(unit, MPLS_ENTRYm,
  12094                                     TRUST_OUTER_DOT1P_PTRf)) {
  12095                 soc_mem_field32_set(unit, mem, ment,
  12096                                             TRUST_OUTER_DOT1P_PTRf,
  12097                                             _BCM_TR_MPLS_PRI_CNG_MAP_IDENTITY);
  12098             }
  12099         }
  12100     }
  12101 }
  12102 
  12103 /*
  12104  * Function:
  12105  *      _bcm_tr_mpls_match_vp_find
  12106  * Purpose:
  12107  *      Find MPLS VP has the same match
  12108  * Parameters:
  12109  *      unit - (IN) SOC unit number.
  12110  *      vp1 - (IN) MPLS VP.
  12111  *      vp2 - (OUT) MPLS VP.
  12112  * Returns:
  12113  *      TRUE - Found
  12114  *      FALSE - Not Found
  12115  */
  12116 int
  12117 _bcm_tr_mpls_match_vp_find(int unit, int vp1, int *vp2)
  12118 {
  12119     int vp = 0;
  12120     int num_vp = 0;
  12121     bcm_mpls_label_t label1 = 0;
  12122     bcm_mpls_label_t label2 = 0;
  12123     _bcm_tr_mpls_match_port_info_t *mkey1 = NULL;
  12124     _bcm_tr_mpls_match_port_info_t *mkey2 = NULL;
  12125 
  12126     mkey1 = &(MPLS_INFO(unit)->match_key[vp1]);
  12127     label1 = mkey1->match_label;
  12128 
  12129     if (mkey1->flags != _BCM_MPLS_PORT_MATCH_TYPE_LABEL) {
  12130         return FALSE;
  12131     }
  12132 
  12133     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  12134     for (vp = 0; vp < num_vp; vp++) {
  12135         if (vp == vp1) {
  12136             continue;
  12137         }
  12138 
  12139         mkey2 = &(MPLS_INFO(unit)->match_key[vp]);
  12140         if (mkey2->flags == _BCM_MPLS_PORT_MATCH_TYPE_LABEL) {
  12141             label2 = mkey2->match_label;
  12142 
  12143             if (label1 == label2) {
  12144                 *vp2 = vp;
  12145                 return TRUE;
  12146             }
  12147         }
  12148     }
  12149 
  12150     return FALSE;
  12151 }
  12152 
  12153 /*
  12154  * Function:
  12155  *      _bcm_tr_mpls_match_add
  12156  * Purpose:
  12157  *      Assign match criteria of an MPLS port
  12158  * Parameters:
  12159  *      unit    - (IN) Device Number
  12160  *      mpls_port - (IN) mpls port information
  12161  *      vp  - (IN) Source Virtual Port
  12162  *      vpn - (IN) VPN
  12163  * Returns:
  12164  *      BCM_E_XXX
  12165  */
  12166 
  12167 int
  12168 _bcm_tr_mpls_match_add(int unit, bcm_mpls_port_t *mpls_port, int vp, int vpn,
  12169                        int hw_update)
  12170 {
  12171     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  12172     int rv = BCM_E_NONE, gport_id;
  12173     bcm_module_t mod_out;
  12174     bcm_port_t port_out;
  12175     bcm_trunk_t trunk_id;
  12176     int    src_trk_idx=0;  /*Source Trunk table index.*/
  12177     int vpless_failover_port = FALSE; /* the failover port without a dedicated vp */
  12178     bcm_mpls_label_t old_match_label;
  12179 #if defined(BCM_KATANA2_SUPPORT)
  12180     int my_modid = 0;
  12181 #endif
  12182 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT)
  12183     int is_local_subport = 0, local_port = 0;
  12184 #endif
  12185     int    vfi = 0;
  12186     _bcm_vp_info_t vp_info;
  12187     uint32 vent[SOC_MAX_MEM_WORDS];
  12188     soc_mem_t mem;
  12189 
  12190     sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  12191 #if defined(BCM_TRIDENT3_SUPPORT)
  12192     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  12193         mem = VLAN_XLATE_1_DOUBLEm;
  12194     } else
  12195 #endif
  12196     {
  12197         mem = VLAN_XLATEm;
  12198     }
  12199 
  12200 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  12201     if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_SHARE) {
  12202         mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_SHARE;
  12203         return BCM_E_NONE;
  12204     }
  12205 
  12206     if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, CLASS_IDf)) {
  12207         /* Ensure that class_id doesnt overcross CLASS_IDf */
  12208         int bit_num = 0;
  12209         if ((mpls_port->flags & (BCM_MPLS_PORT_COUNTED |
  12210             BCM_MPLS_PORT_SEQUENCED)) && (mpls_port->class_id)) {
  12211             return BCM_E_PARAM;
  12212         }
  12213         if (mpls_port->class_id) {
  12214             bit_num = soc_mem_field_length(unit, MPLS_ENTRYm, CLASS_IDf);
  12215             if (mpls_port->class_id > (( 1 << bit_num ) - 1)) {
  12216                 return BCM_E_PARAM;
  12217             }
  12218         }
  12219     }
  12220 #endif
  12221 
  12222     if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) {
  12223         if (mpls_port->criteria & BCM_MPLS_PORT_MATCH_LABEL) {
  12224             /* should use same entry as primary */
  12225             return BCM_E_NONE;
  12226         }
  12227         vpless_failover_port = TRUE;
  12228         vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp);
  12229     }
  12230 
  12231 
  12232     if ((mpls_port->criteria != BCM_MPLS_PORT_MATCH_LABEL) &&
  12233         (mpls_port->criteria != BCM_MPLS_PORT_MATCH_VLAN)) {
  12234          rv = _bcm_esw_gport_resolve(unit, mpls_port->port, &mod_out, 
  12235                                 &port_out, &trunk_id, &gport_id);
  12236          BCM_IF_ERROR_RETURN(rv);
  12237     }
  12238 
  12239     /* set default vlan_xlate key source field type as SGLP */
  12240     if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) {
  12241         soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  12242     }
  12243     /* VLAN Translation Action is valid for this lookup  */
  12244     if (SOC_MEM_FIELD_VALID(unit, mem, XLATE__VLAN_ACTION_VALIDf)) {
  12245         soc_mem_field32_set(unit, mem, vent, XLATE__VLAN_ACTION_VALIDf, 1);
  12246     }
  12247     if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_VLAN ) {
  12248         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  12249             soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  12250             soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  12251             soc_mem_field32_set(unit, mem, vent,
  12252                     DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OVID);
  12253             /*set default tag action profile ptr*/
  12254             soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 1);
  12255         } else {
  12256             soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  12257         }
  12258 
  12259         soc_mem_field32_set(unit, mem, vent, MPLS_ACTIONf, 0x1); /* SVP */
  12260         soc_mem_field32_set(unit, mem, vent, DISABLE_VLAN_CHECKSf, 1);
  12261         soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, vp);
  12262         if (!BCM_VLAN_VALID(mpls_port->match_vlan)) {
  12263              return BCM_E_PARAM;
  12264         }
  12265         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  12266                                         TR_VLXLT_HASH_KEY_TYPE_OVID);
  12267         soc_mem_field32_set(unit, mem, vent, OVIDf,
  12268                                         mpls_port->match_vlan);
  12269 
  12270         if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  12271             soc_mem_field32_set(unit, mem, vent, Tf, 1);
  12272             soc_mem_field32_set(unit, mem, vent, TGIDf, trunk_id);
  12273         } else {
  12274             soc_mem_field32_set(unit, mem, vent, MODULE_IDf, mod_out);
  12275             soc_mem_field32_set(unit, mem, vent, PORT_NUMf, port_out);
  12276         }
  12277         if (soc_feature(unit, soc_feature_vp_sharing)) {
  12278             BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  12279             if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) {
  12280                 _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
  12281                 soc_mem_field32_set(unit, mem, vent, VFIf, vfi);
  12282             }
  12283         }
  12284         rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent);
  12285         BCM_IF_ERROR_RETURN(rv);
  12286 
  12287         if (!(mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) {
  12288             mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN;
  12289             mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan;
  12290 
  12291             if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  12292                 mpls_info->match_key[vp].trunk_id = trunk_id;
  12293             } else {
  12294                 mpls_info->match_key[vp].port = port_out;
  12295                 mpls_info->match_key[vp].modid = mod_out;
  12296             }
  12297         }
  12298         if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  12299               bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
  12300         }
  12301     } else if (mpls_port->criteria ==
  12302                             BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN) {
  12303 
  12304         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  12305             soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  12306             soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  12307             soc_mem_field32_set(unit, mem, vent,
  12308                     DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID);
  12309             /*set default tag action profile ptr*/
  12310             soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 1);
  12311         } else {
  12312             soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  12313         }
  12314         soc_mem_field32_set(unit, mem, vent, MPLS_ACTIONf, 0x1); /* SVP */
  12315         soc_mem_field32_set(unit, mem, vent, DISABLE_VLAN_CHECKSf, 1);
  12316         soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, vp);
  12317         if (!BCM_VLAN_VALID(mpls_port->match_inner_vlan)) {
  12318             return BCM_E_PARAM;
  12319         }
  12320         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  12321                                     TR_VLXLT_HASH_KEY_TYPE_IVID);
  12322         soc_mem_field32_set(unit, mem, vent, IVIDf,
  12323                                     mpls_port->match_inner_vlan);
  12324 
  12325         if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  12326             soc_mem_field32_set(unit, mem, vent, Tf, 1);
  12327             soc_mem_field32_set(unit, mem, vent, TGIDf, trunk_id);
  12328         } else {
  12329             soc_mem_field32_set(unit, mem, vent, MODULE_IDf, mod_out);
  12330             soc_mem_field32_set(unit, mem, vent, PORT_NUMf, port_out);
  12331         }
  12332         if (soc_feature(unit, soc_feature_vp_sharing)) {
  12333             BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  12334             if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) {
  12335                 _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
  12336                 soc_mem_field32_set(unit, mem, vent, VFIf, vfi);
  12337             }
  12338         }
  12339         rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent);
  12340         BCM_IF_ERROR_RETURN(rv);
  12341 
  12342         if (!(mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) {
  12343             mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN;
  12344             mpls_info->match_key[vp].match_inner_vlan = mpls_port->match_inner_vlan;
  12345 
  12346             if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  12347                 mpls_info->match_key[vp].trunk_id = trunk_id;
  12348             } else {
  12349                 mpls_info->match_key[vp].port = port_out;
  12350                 mpls_info->match_key[vp].modid = mod_out;
  12351             }
  12352         }
  12353         if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  12354              bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
  12355         }
  12356     } else if (mpls_port->criteria == 
  12357                             BCM_MPLS_PORT_MATCH_PORT_VLAN_STACKED) {
  12358 
  12359         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  12360             soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  12361             soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  12362             soc_mem_field32_set(unit, mem, vent,
  12363                     DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
  12364             /*set default tag action profile ptr*/
  12365             soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 1);
  12366         } else {
  12367             soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  12368         }
  12369          soc_mem_field32_set(unit, mem, vent, MPLS_ACTIONf, 0x1); /* SVP */
  12370          soc_mem_field32_set(unit, mem, vent, DISABLE_VLAN_CHECKSf, 1);
  12371          soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, vp);
  12372          if (!BCM_VLAN_VALID(mpls_port->match_vlan) || 
  12373                 !BCM_VLAN_VALID(mpls_port->match_inner_vlan)) {
  12374               return BCM_E_PARAM;
  12375          }
  12376          soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  12377                    TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
  12378          soc_mem_field32_set(unit, mem, vent, OVIDf,
  12379                    mpls_port->match_vlan);
  12380          soc_mem_field32_set(unit, mem, vent, IVIDf,
  12381                    mpls_port->match_inner_vlan);
  12382          if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  12383             soc_mem_field32_set(unit, mem, vent, Tf, 1);
  12384             soc_mem_field32_set(unit, mem, vent, TGIDf, trunk_id);
  12385          } else {
  12386             soc_mem_field32_set(unit, mem, vent, MODULE_IDf, mod_out);
  12387             soc_mem_field32_set(unit, mem, vent, PORT_NUMf, port_out);
  12388          }
  12389          if (soc_feature(unit, soc_feature_vp_sharing)) {
  12390              BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  12391              if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) {
  12392                  _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
  12393                  soc_mem_field32_set(unit, mem, vent, VFIf, vfi);
  12394              }
  12395          }
  12396          rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent);
  12397          BCM_IF_ERROR_RETURN(rv);
  12398 
  12399          if (!(mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) {
  12400              mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED;
  12401              mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan;
  12402              mpls_info->match_key[vp].match_inner_vlan = mpls_port->match_inner_vlan;
  12403              if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  12404                 mpls_info->match_key[vp].trunk_id = trunk_id;
  12405              } else {
  12406                 mpls_info->match_key[vp].port = port_out;
  12407                 mpls_info->match_key[vp].modid = mod_out;
  12408              }
  12409          }
  12410          if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  12411              bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
  12412          }
  12413     } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_VLAN_PRI) {
  12414 
  12415         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  12416             soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  12417             soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  12418             soc_mem_field32_set(unit, mem, vent,
  12419                     DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_PRI_CFI);
  12420             /*set default tag action profile ptr*/
  12421             soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 1);
  12422         } else {
  12423             soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  12424         }
  12425          soc_mem_field32_set(unit, mem, vent, MPLS_ACTIONf, 0x1); /* SVP */
  12426          soc_mem_field32_set(unit, mem, vent, DISABLE_VLAN_CHECKSf, 1);
  12427          soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, vp);
  12428          soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  12429                                            TR_VLXLT_HASH_KEY_TYPE_PRI_CFI);
  12430           /* match_vlan : Bits 12-15 contains VLAN_PRI + CFI, vlan=BCM_E_NONE */
  12431           soc_mem_field32_set(unit, mem, vent, OTAGf,
  12432                                              mpls_port->match_vlan);
  12433           if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  12434                soc_mem_field32_set(unit, mem, vent, Tf, 1);
  12435                soc_mem_field32_set(unit, mem, vent, TGIDf, trunk_id);
  12436           } else {
  12437                soc_mem_field32_set(unit, mem, vent, MODULE_IDf, mod_out);
  12438                soc_mem_field32_set(unit, mem, vent, PORT_NUMf, port_out);
  12439           }
  12440           if (soc_feature(unit, soc_feature_vp_sharing)) {
  12441               BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  12442               if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) {
  12443                   _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
  12444                   soc_mem_field32_set(unit, mem, vent, VFIf, vfi);
  12445               }
  12446           }
  12447 #if defined(BCM_TRIUMPH2_SUPPORT)
  12448           if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TRUST_OUTER_DOT1Pf)) {
  12449               source_vp_entry_t svp;
  12450               BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
  12451               soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_OUTER_DOT1Pf, 1);
  12452               BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp));
  12453           }
  12454 #endif /* BCM_TRIUMPH2_SUPPORT */
  12455 
  12456           rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent);
  12457           BCM_IF_ERROR_RETURN(rv);
  12458 
  12459           if (!(mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) {
  12460               mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN_PRI;
  12461               mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan;
  12462 
  12463               if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  12464                    mpls_info->match_key[vp].trunk_id = trunk_id;
  12465               } else {
  12466                    mpls_info->match_key[vp].port = port_out;
  12467                    mpls_info->match_key[vp].modid = mod_out;
  12468               }
  12469           }
  12470           if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  12471                bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
  12472           }
  12473     } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_VLAN_TAG) {
  12474 
  12475         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  12476             soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  12477             soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  12478             soc_mem_field32_set(unit, mem, vent,
  12479                                 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OTAG);
  12480             /*set default tag action profile ptr*/
  12481             soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 1);
  12482         } else {
  12483             soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  12484         }
  12485 
  12486         soc_mem_field32_set(unit, mem, vent, MPLS_ACTIONf, 0x1); /* SVP */
  12487         soc_mem_field32_set(unit, mem, vent, DISABLE_VLAN_CHECKSf, 1);
  12488         soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, vp);
  12489 
  12490         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  12491                                         TR_VLXLT_HASH_KEY_TYPE_OTAG);
  12492         soc_mem_field32_set(unit, mem, vent, OTAGf,
  12493                                         mpls_port->match_vlan);
  12494 
  12495         if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  12496             soc_mem_field32_set(unit, mem, vent, Tf, 1);
  12497             soc_mem_field32_set(unit, mem, vent, TGIDf, trunk_id);
  12498         } else {
  12499             soc_mem_field32_set(unit, mem, vent, MODULE_IDf, mod_out);
  12500             soc_mem_field32_set(unit, mem, vent, PORT_NUMf, port_out);
  12501         }
  12502         if (soc_feature(unit, soc_feature_vp_sharing)) {
  12503             BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  12504             if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) {
  12505                 _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
  12506                 soc_mem_field32_set(unit, mem, vent, VFIf, vfi);
  12507             }
  12508         }
  12509 
  12510 #if defined(BCM_TRIUMPH2_SUPPORT)
  12511         if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TRUST_OUTER_DOT1Pf)) {
  12512             source_vp_entry_t svp;
  12513             BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
  12514             soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_OUTER_DOT1Pf, 1);
  12515             BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp));
  12516         }
  12517 #endif /* BCM_TRIUMPH2_SUPPORT */
  12518 
  12519         rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent);
  12520         BCM_IF_ERROR_RETURN(rv);
  12521 
  12522         if (!(mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) {
  12523             mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN_TAG;
  12524             mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan;
  12525 
  12526             if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  12527                 mpls_info->match_key[vp].trunk_id = trunk_id;
  12528             } else {
  12529                 mpls_info->match_key[vp].port = port_out;
  12530                 mpls_info->match_key[vp].modid = mod_out;
  12531             }
  12532         }
  12533         if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  12534             bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
  12535         }
  12536 
  12537     } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN_TAG) {
  12538 
  12539         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  12540             soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  12541             soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  12542             soc_mem_field32_set(unit, mem, vent,
  12543                     DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_ITAG);
  12544             /*set default tag action profile ptr*/
  12545             soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf, 1);
  12546         } else {
  12547             soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  12548         }
  12549         soc_mem_field32_set(unit, mem, vent, MPLS_ACTIONf, 0x1); /* SVP */
  12550         soc_mem_field32_set(unit, mem, vent, DISABLE_VLAN_CHECKSf, 1);
  12551         soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, vp);
  12552 
  12553         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  12554                                             TR_VLXLT_HASH_KEY_TYPE_ITAG);
  12555         soc_mem_field32_set(unit, mem, vent, ITAGf,
  12556                                             mpls_port->match_inner_vlan);
  12557 
  12558         if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  12559             soc_mem_field32_set(unit, mem, vent, Tf, 1);
  12560             soc_mem_field32_set(unit, mem, vent, TGIDf, trunk_id);
  12561         } else {
  12562             soc_mem_field32_set(unit, mem, vent, MODULE_IDf, mod_out);
  12563             soc_mem_field32_set(unit, mem, vent, PORT_NUMf, port_out);
  12564         }
  12565         if (soc_feature(unit, soc_feature_vp_sharing)) {
  12566             BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  12567             if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) {
  12568                 _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
  12569                 soc_mem_field32_set(unit, mem, vent, VFIf, vfi);
  12570             }
  12571         }
  12572         rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent);
  12573         BCM_IF_ERROR_RETURN(rv);
  12574 
  12575         if (!(mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) {
  12576             mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN_TAG;
  12577             mpls_info->match_key[vp].match_inner_vlan = mpls_port->match_inner_vlan;
  12578 
  12579             if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  12580                 mpls_info->match_key[vp].trunk_id = trunk_id;
  12581             } else {
  12582                 mpls_info->match_key[vp].port = port_out;
  12583                 mpls_info->match_key[vp].modid = mod_out;
  12584             }
  12585         }
  12586         if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  12587             bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
  12588         }
  12589     } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT) {
  12590 
  12591         if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  12592 #ifdef BCM_TOMAHAWK_SUPPORT
  12593             if (SOC_IS_TOMAHAWKX(unit)) {
  12594                 if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE) ||
  12595                     ((mpls_info->match_key[vp].port != port_out) ||
  12596                     (mpls_info->match_key[vp].modid != mod_out) ||
  12597                     ((mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) &&
  12598                     (mpls_info->match_key[vp].trunk_id != trunk_id)))) {
  12599              rv = bcm_tr_mpls_match_trunk_add(unit, trunk_id, vp);
  12600                 }
  12601             } else
  12602 #endif
  12603             {
  12604                 rv = bcm_tr_mpls_match_trunk_add(unit, trunk_id, vp);
  12605             }
  12606              if (rv >= 0) {
  12607                  if (!(mpls_info->match_key[vp].flags &
  12608                               _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) {
  12609                     /* Delete references associated with old port in mpls_port */
  12610                     if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  12611                         if ((mpls_info->match_key[vp].port != port_out) ||
  12612                             (mpls_info->match_key[vp].modid != mod_out) ||
  12613                             ((mpls_info->match_key[vp].flags &
  12614                               _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) &&
  12615                              (mpls_info->match_key[vp].trunk_id != trunk_id))) {
  12616                             BCM_IF_ERROR_RETURN(_bcm_tr_mpls_match_delete(unit, vp, NULL, TRUE));
  12617                         }
  12618                     }
  12619                      mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_TRUNK;
  12620                      mpls_info->match_key[vp].trunk_id = trunk_id;
  12621                      mpls_info->trunk_vp_map[trunk_id] = vp;
  12622                      mpls_info->match_key[vp].port  = port_out;
  12623                      mpls_info->match_key[vp].modid = mod_out;
  12624                  }
  12625              }
  12626              BCM_IF_ERROR_RETURN(rv);       
  12627         } else {
  12628             int is_local;
  12629 
  12630             BCM_IF_ERROR_RETURN
  12631                 ( _bcm_esw_modid_is_local(unit, mod_out, &is_local));
  12632 
  12633             /* Get index to source trunk map table */
  12634             BCM_IF_ERROR_RETURN(
  12635                    _bcm_esw_src_mod_port_table_index_get(unit, mod_out,
  12636                      port_out, &src_trk_idx));
  12637         
  12638             rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 
  12639                                         src_trk_idx, SOURCE_VPf, vp);
  12640             BCM_IF_ERROR_RETURN(rv);
  12641             if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) {
  12642                 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  12643                                  src_trk_idx, SVP_VALIDf, 1);
  12644                 BCM_IF_ERROR_RETURN(rv);
  12645             }
  12646 
  12647 #if defined(BCM_HGPROXY_COE_SUPPORT)
  12648             if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
  12649                 BCM_GPORT_IS_SET(mpls_port->port) &&
  12650                 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit,
  12651                     mpls_port->port)) {
  12652                 local_port = mpls_port->port;
  12653                 is_local_subport = 1;
  12654             } else
  12655 #endif
  12656 
  12657 #if defined(BCM_KATANA2_SUPPORT)
  12658             if (BCM_GPORT_IS_SET(mpls_port->port) &&
  12659                 _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit,
  12660                     mpls_port->port)) {
  12661                 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
  12662                 if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_out) == BCM_E_NONE) {
  12663                     BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(
  12664                              unit, mod_out, port_out, &local_port));
  12665                     if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, local_port)){
  12666                         is_local_subport = 1;
  12667                     }
  12668                 }
  12669             }
  12670 #endif
  12671 
  12672 #if defined(BCM_HGPROXY_COE_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
  12673             if (is_local_subport) {
  12674 
  12675                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  12676                     rv = _bcm_esw_port_tab_set(unit, local_port,
  12677                             _BCM_CPU_TABS_BOTH,
  12678                             PORT_OPERATIONf, 0x1);
  12679                 } else {
  12680                 rv = _bcm_esw_port_tab_set_without_portlock(
  12681                          unit, local_port, _BCM_CPU_TABS_NONE, PORT_OPERATIONf,
  12682                          0x1); /* L2_SVP */
  12683                 }
  12684                 BCM_IF_ERROR_RETURN(rv);
  12685 
  12686                 /* Set TAG_ACTION_PROFILE_PTR */
  12687                 rv = bcm_tr_mpls_port_untagged_profile_set(unit, local_port);
  12688                 BCM_IF_ERROR_RETURN(rv);
  12689             } else
  12690 #endif
  12691             if (is_local) {
  12692                 /* Convert system ports to physical ports */ 
  12693                 if (soc_feature(unit, soc_feature_sysport_remap)) { 
  12694                     BCM_XLATE_SYSPORT_S2P(unit, &port_out); 
  12695                 }
  12696 
  12697                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  12698                     rv = _bcm_esw_port_tab_set(unit, port_out,
  12699                             _BCM_CPU_TABS_BOTH,
  12700                             PORT_OPERATIONf, 0x1);
  12701                 } else {
  12702                 rv = soc_mem_field32_modify(unit, PORT_TABm, port_out,
  12703                                         PORT_OPERATIONf, 0x1); /* L2_SVP */
  12704                 }
  12705                 BCM_IF_ERROR_RETURN(rv);
  12706 
  12707 #ifdef BCM_TOMAHAWK_SUPPORT
  12708                 if (SOC_IS_TOMAHAWKX(unit)) {
  12709                     if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE) ||
  12710                         ((mpls_info->match_key[vp].port != port_out) ||
  12711                         (mpls_info->match_key[vp].modid != mod_out) ||
  12712                         ((mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) &&
  12713                         (mpls_info->match_key[vp].trunk_id != trunk_id)))) {
  12714                         rv = bcm_tr_mpls_port_untagged_profile_set(unit, port_out);
  12715                         BCM_IF_ERROR_RETURN(rv);
  12716                     }
  12717                 } else
  12718 #endif
  12719                 {
  12720                 /* Set TAG_ACTION_PROFILE_PTR */
  12721                 rv = bcm_tr_mpls_port_untagged_profile_set(unit, port_out);
  12722                 BCM_IF_ERROR_RETURN(rv);
  12723             }
  12724             }
  12725 
  12726             /* Delete references associated with old port in mpls_port */
  12727             if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  12728                 if ((mpls_info->match_key[vp].port != port_out) ||
  12729                     (mpls_info->match_key[vp].modid != mod_out) ||
  12730                     ((mpls_info->match_key[vp].flags &
  12731                       _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) &&
  12732                      (mpls_info->match_key[vp].trunk_id != trunk_id))) {
  12733                     BCM_IF_ERROR_RETURN(_bcm_tr_mpls_match_delete(unit, vp, NULL, TRUE));
  12734                 }
  12735             }
  12736             /*
  12737              * The vp has been created based on trunk.
  12738              * When a new port is added into the trunk, a match will be
  12739              * added for the vp through bcm_port_match_add.
  12740              */
  12741             if ((mpls_info->match_key[vp].flags != _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) &&
  12742                (!(mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE))) {
  12743                 mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_PORT;
  12744                 mpls_info->match_key[vp].index = src_trk_idx;
  12745                 mpls_info->match_key[vp].port  = port_out;
  12746                 mpls_info->match_key[vp].modid = mod_out;
  12747             }
  12748         }
  12749     } else if ((mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL) ||
  12750                (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL_PORT)) {
  12751 
  12752         mpls_entry_entry_t ment, return_ment;
  12753         int old_pw_term_cntr_idx=-1, new_pw_term_cntr_idx=-1;
  12754         int entry_index=-1;
  12755         int old_mpls_entry_rv = BCM_E_NONE;
  12756 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  12757         uint32 flex_ctr_poolnum=0;
  12758         uint32 flex_ctr_basectr_idx=0;
  12759         uint32 flex_ctr_offset_mode=0;
  12760 #endif 
  12761 #ifdef BCM_TRIUMPH2_SUPPORT
  12762         int old_vintf_cntr_idx = -1;
  12763 #endif
  12764 
  12765 
  12766         sal_memset(&ment, 0, sizeof(mpls_entry_entry_t));
  12767         if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL_PORT) {
  12768             /* Check for Port_independent Label mapping */
  12769             rv = bcm_tr_mpls_port_independent_range (unit, mpls_port->match_label, mpls_port->port);
  12770             if (rv < 0) {
  12771                 return rv;
  12772             }
  12773             if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  12774                 soc_MPLS_ENTRYm_field32_set(unit, &ment, Tf, 1);
  12775                 soc_MPLS_ENTRYm_field32_set(unit, &ment, TGIDf, trunk_id);
  12776                 if (vpless_failover_port == FALSE) {
  12777                     mpls_info->match_key[vp].trunk_id = trunk_id;
  12778                 } else {
  12779                     mpls_info->match_key[vp].fo_trunk_id = trunk_id;
  12780                 }
  12781             } else {
  12782                 soc_MPLS_ENTRYm_field32_set(unit, &ment, MODULE_IDf, mod_out);
  12783                 soc_MPLS_ENTRYm_field32_set(unit, &ment, PORT_NUMf, port_out);
  12784                 if (vpless_failover_port == FALSE) {
  12785                     mpls_info->match_key[vp].port = port_out;
  12786                     mpls_info->match_key[vp].modid = mod_out;
  12787                 } else {
  12788                     mpls_info->match_key[vp].fo_port = port_out;
  12789                     mpls_info->match_key[vp].fo_modid = mod_out;
  12790                 }
  12791             }
  12792             mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT;
  12793         } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL) {
  12794             soc_MPLS_ENTRYm_field32_set(unit, &ment, MODULE_IDf, 0);
  12795             soc_MPLS_ENTRYm_field32_set(unit, &ment, PORT_NUMf, 0);
  12796             mpls_info->match_key[vp].port = 0;
  12797             mpls_info->match_key[vp].modid = 0;
  12798             mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_LABEL;
  12799         }
  12800         /* Use old label to get old mpls entry for replace operation */
  12801         old_match_label = mpls_info->match_key[vp].match_label;
  12802         soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_LABELf, 
  12803                                     old_match_label);
  12804 
  12805         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  12806             soc_MPLS_ENTRYm_field32_set(unit, &ment, BASE_VALID_0f, 3);
  12807             soc_MPLS_ENTRYm_field32_set(unit, &ment, BASE_VALID_1f, 7);
  12808         } else {
  12809         soc_MPLS_ENTRYm_field32_set(unit, &ment, VALIDf, 1);
  12810         }
  12811         soc_MPLS_ENTRYm_field32_set(unit, &ment, SOURCE_VPf, vp);
  12812         soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_BOSf, 
  12813                                     0x1); /* L2 SVP */
  12814         soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_NOT_BOSf, 
  12815                                     0x0); /* INVALID */
  12816 
  12817         if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  12818             /* Find Entry within Hardware */
  12819             old_mpls_entry_rv = soc_mem_search(unit, MPLS_ENTRYm, 
  12820                                                MEM_BLOCK_ANY, &entry_index,
  12821                                                &ment, &return_ment, 0);
  12822 
  12823             /* Obtain old pw_term counter-index and old label flex stat index */
  12824             if (BCM_SUCCESS(old_mpls_entry_rv)) {
  12825                 if (soc_MPLS_ENTRYm_field32_get(unit, &return_ment,
  12826                                             PW_TERM_NUM_VALIDf)) {
  12827                     old_pw_term_cntr_idx = soc_MPLS_ENTRYm_field32_get(unit,
  12828                                                &return_ment,PW_TERM_NUMf);
  12829                 }
  12830 #ifdef BCM_TRIUMPH2_SUPPORT
  12831                 if (soc_feature(unit, soc_feature_gport_service_counters)) {
  12832                     if (soc_MPLS_ENTRYm_field32_get(unit, &return_ment,
  12833                                                     USE_VINTF_CTR_IDXf)) {
  12834                         old_vintf_cntr_idx = soc_MPLS_ENTRYm_field32_get(unit,
  12835                                                  &return_ment, VINTF_CTR_IDXf);
  12836                     }
  12837                 }
  12838 #endif /* BCM_TRIUMPH2_SUPPORT  */
  12839 
  12840 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  12841                 if ((soc_feature(unit, soc_feature_mpls_enhanced)) &&
  12842                      (soc_feature(unit,soc_feature_advanced_flex_counter))) {
  12843                     /* Store Flex counter values */
  12844                     flex_ctr_poolnum = soc_MPLS_ENTRYm_field32_get(unit,
  12845                                                                    &return_ment,
  12846                                                     MPLS__FLEX_CTR_POOL_NUMBERf);
  12847                     if(flex_ctr_poolnum) {
  12848                         soc_MPLS_ENTRYm_field32_set(unit, &ment,
  12849                                                     MPLS__FLEX_CTR_POOL_NUMBERf,
  12850                                                     flex_ctr_poolnum);
  12851                     }
  12852                     flex_ctr_basectr_idx = soc_MPLS_ENTRYm_field32_get(unit,
  12853                                                                &return_ment,
  12854                                               MPLS__FLEX_CTR_BASE_COUNTER_IDXf);
  12855                     if(flex_ctr_basectr_idx) {
  12856                         soc_MPLS_ENTRYm_field32_set(unit, &ment,
  12857                                               MPLS__FLEX_CTR_BASE_COUNTER_IDXf,
  12858                                               flex_ctr_basectr_idx);
  12859                     }
  12860                     flex_ctr_offset_mode = soc_MPLS_ENTRYm_field32_get(unit,
  12861                                                                   &return_ment,
  12862                                                   MPLS__FLEX_CTR_OFFSET_MODEf);
  12863                     soc_MPLS_ENTRYm_field32_set(unit, &ment,
  12864                                                 MPLS__FLEX_CTR_OFFSET_MODEf,
  12865                                                 flex_ctr_offset_mode);
  12866                 }
  12867 #endif /* (BCM_KATANA_SUPPORT) || (BCM_TRIUMPH3_SUPPORT) */
  12868 
  12869 #if defined(BCM_TRIDENT2_SUPPORT)
  12870                 if (soc_feature(unit, soc_feature_vp_lag)) {
  12871                     int svp = soc_MPLS_ENTRYm_field32_get(unit, &return_ment, SOURCE_VPf);
  12872                     if (_bcm_vp_used_get(unit, svp, _bcmVpTypeVpLag)) {
  12873                         soc_MPLS_ENTRYm_field32_set(unit, &ment, SOURCE_VPf, svp);
  12874                     }
  12875                 }
  12876 #endif
  12877             }
  12878         }
  12879 
  12880         /* Add the new MPLS label for the new entry*/
  12881         soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_LABELf,
  12882                                     mpls_port->match_label);
  12883 
  12884         if (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED) {
  12885             /* Control word is present, check sequence number */
  12886             soc_MPLS_ENTRYm_field32_set(unit, &ment, CW_CHECK_CTRLf, 
  12887                                         0x3); /* CW_CHECK_LOOSE */
  12888             
  12889 
  12890         } else if (mpls_port->flags & BCM_MPLS_PORT_CONTROL_WORD) {
  12891             /* Control word is present, but no sequence number check */
  12892             soc_MPLS_ENTRYm_field32_set(unit, &ment, CW_CHECK_CTRLf, 
  12893                                         0x1); /* CW_NO_CHECK */
  12894         }
  12895         if (((mpls_port->flags & BCM_MPLS_PORT_COUNTED) ||
  12896             (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED))) {
  12897                /*  Obtain pw_term_counter */
  12898                BCM_IF_ERROR_RETURN(
  12899                    _bcm_tr_mpls_pw_term_counter_set (unit, &new_pw_term_cntr_idx));
  12900                if ( new_pw_term_cntr_idx != -1) {
  12901                    soc_MPLS_ENTRYm_field32_set(unit, &ment, PW_TERM_NUMf, new_pw_term_cntr_idx);
  12902                    soc_MPLS_ENTRYm_field32_set(unit, &ment, PW_TERM_NUM_VALIDf, 1);
  12903                }
  12904         }
  12905 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  12906         else if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, CLASS_IDf)) {
  12907             soc_MPLS_ENTRYm_field32_set(unit, &ment, CLASS_IDf, mpls_port->class_id);
  12908         }
  12909 #endif
  12910 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_SABER2_SUPPORT)
  12911         if (soc_mem_field_valid(unit, MPLS_ENTRYm, PW_CC_TYPEf)) {
  12912             if (mpls_port->vccv_type == bcmMplsPortControlChannelGalUnderPw) {
  12913                 soc_MPLS_ENTRYm_field32_set(unit, &ment,
  12914                     MPLS_ACTION_IF_NOT_BOSf, 0x1);
  12915             }
  12916         }
  12917 #endif
  12918 
  12919         (void) bcm_tr_mpls_entry_internal_qos_set(unit, mpls_port, NULL, &ment);
  12920 
  12921 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)
  12922         if (soc_feature(unit, soc_feature_mpls_entropy)) {
  12923             if ((mpls_port->flags & BCM_MPLS_PORT_ENTROPY_ENABLE) ||
  12924                 (mpls_port->flags2 & BCM_MPLS_PORT2_INGRESS_ENTROPY_ENABLE)) {
  12925                 if (soc_mem_field_valid(unit, MPLS_ENTRYm,
  12926                                     ENTROPY_LABEL_PRESENTf)) {
  12927                      soc_MPLS_ENTRYm_field32_set(unit, &ment,
  12928                                             ENTROPY_LABEL_PRESENTf, 0x1);
  12929                      soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_BOSf, 
  12930                                     0x0); /* INVALID */
  12931                      
  12932                      if (SOC_IS_APACHE(unit)) {
  12933                          soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_NOT_BOSf, 
  12934                                  0x6); /* POP_SVP_ENTROPY */
  12935                      } else {
  12936                          soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_NOT_BOSf, 
  12937                                  0x4); /* POP_SVP_ENTROPY */
  12938                      }
  12939                 }
  12940             }
  12941         }
  12942 
  12943         /* VCCV defines 3 control-channels */
  12944         if (soc_mem_field_valid(unit, MPLS_ENTRYm, PW_CC_TYPEf)) {
  12945             soc_MPLS_ENTRYm_field32_set(unit, &ment, PW_CC_TYPEf, 
  12946                                        mpls_port->vccv_type);
  12947         }
  12948 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) */
  12949 
  12950 #ifdef BCM_TRIUMPH2_SUPPORT
  12951         if (soc_feature(unit, soc_feature_gport_service_counters)) {
  12952             if ((mpls_port->flags & BCM_MPLS_PORT_REPLACE) &&
  12953                 (old_vintf_cntr_idx != -1)) {
  12954                 if (old_match_label != mpls_port->match_label) {
  12955                     /* If MPLS label stat is used for this MPLS_ENTRY then
  12956                     * it must be released first using stat_detach*/
  12957                     LOG_ERROR(BSL_LS_BCM_MPLS,
  12958                               (BSL_META_U(unit,
  12959                                           "The flex stat counter %d for the "
  12960                                           "old label %d must be detached first\n before performing "
  12961                                           "the MPLS label replace action.\n"),
  12962                                old_vintf_cntr_idx, old_match_label));
  12963                     return BCM_E_INTERNAL;
  12964                 } else {
  12965                      /* copy the old label flex sat counter index if old_label == new_label*/
  12966                      soc_MPLS_ENTRYm_field32_set(unit, &ment,
  12967                                                  USE_VINTF_CTR_IDXf, 1);
  12968                      soc_MPLS_ENTRYm_field32_set(unit, &ment, VINTF_CTR_IDXf,
  12969                                                  old_vintf_cntr_idx);
  12970                 }
  12971             }
  12972         }
  12973 #endif /* BCM_TRIUMPH2_SUPPORT */
  12974 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
  12975         if (soc_feature(unit, soc_feature_mpls_ecn)) {
  12976             if (mpls_port->flags2 & BCM_MPLS_PORT2_INGRESS_ECN_MAP) {
  12977                 int ecn_map_index;
  12978                 int ecn_map_hw_idx;
  12979                 int ecn_map_type;
  12980                 int ecn_map_num;
  12981 
  12982                 ecn_map_type = mpls_port->ecn_map_id & 
  12983                                _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK;
  12984                 ecn_map_index = mpls_port->ecn_map_id & 
  12985                                 _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK;
  12986 #if defined(BCM_TRIDENT3_SUPPORT)
  12987                 if(soc_feature(unit, soc_feature_td3_style_mpls)) {
  12988                     mem = ING_EXP_TO_ECN_MAPPING_1m;
  12989                 } else
  12990 #endif
  12991                 {
  12992                     mem = ING_EXP_TO_IP_ECN_MAPPINGm;
  12993                 }
  12994 
  12995                 ecn_map_num = 
  12996                     soc_mem_index_count(unit, mem) /
  12997                     _BCM_ECN_MAX_ENTRIES_PER_MAP;
  12998                 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_EXP2ECN) {
  12999                     return BCM_E_PARAM;
  13000                 }
  13001                 if (ecn_map_index >= ecn_map_num) {
  13002                     return BCM_E_PARAM;
  13003                 }
  13004                 if (!bcmi_xgs5_ecn_map_used_get(unit, ecn_map_index, 
  13005                                                 _bcmEcnmapTypeExp2Ecn)) {
  13006                     return BCM_E_PARAM; 
  13007                 }
  13008                 BCM_IF_ERROR_RETURN(
  13009                     bcmi_ecn_map_id2hw_idx(unit, mpls_port->ecn_map_id, &ecn_map_hw_idx));
  13010 
  13011 #if defined(BCM_TRIDENT3_SUPPORT)
  13012                 if(soc_feature(unit, soc_feature_td3_style_mpls)) {
  13013                     soc_MPLS_ENTRYm_field32_set(unit, &ment,
  13014                             EXP_TO_ECN_MAPPING_PTRf,
  13015                             ecn_map_hw_idx);
  13016                 } else
  13017 #endif
  13018                 {
  13019                 soc_MPLS_ENTRYm_field32_set(unit, &ment, 
  13020                                             EXP_TO_IP_ECN_MAPPING_PTRf, 
  13021                                             ecn_map_hw_idx);
  13022             }
  13023         }
  13024         }
  13025 #endif /* BCM_TOMAHAWK2_SUPPORT */
  13026 
  13027 
  13028         if (soc_mem_field_valid(unit, MPLS_ENTRYm, DO_NOT_CHANGE_PAYLOAD_DSCPf)) {
  13029             if (_BCM_MPLS_VPN_IS_VPLS(vpn) || _BCM_MPLS_VPN_IS_VPWS(vpn)) {            
  13030                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13031                     soc_MPLS_ENTRYm_field32_set(unit, &ment,
  13032                                             DO_NOT_CHANGE_PAYLOAD_DSCPf, 0);
  13033                 } else {
  13034                     soc_MPLS_ENTRYm_field32_set(unit, &ment,
  13035                                             DO_NOT_CHANGE_PAYLOAD_DSCPf, 1);
  13036                 }
  13037             }
  13038         }
  13039 
  13040         /* Add the new MPLS entry */
  13041         if (hw_update) {
  13042             rv = _bcm_tr_mpls_match_label_entry_set(unit, mpls_port, &ment);
  13043         }
  13044 
  13045         /* update the new label in match key of the VP*/
  13046         if (BCM_SUCCESS(rv)) {
  13047             mpls_info->match_key[vp].match_label = mpls_port->match_label;
  13048         }
  13049 
  13050         /* Delete the old MPLS entry */
  13051         if (BCM_SUCCESS(rv) && (mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  13052             int failover_vp = -1;
  13053             bcm_mpls_label_t failover_match_label = -1;
  13054 
  13055             failover_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id);
  13056             if ((failover_vp >= 0) &&
  13057                 _bcm_vp_used_get(unit, failover_vp, _bcmVpTypeMpls)) {
  13058                 failover_match_label = mpls_info->match_key[failover_vp].match_label;
  13059             }
  13060 
  13061             if ((old_pw_term_cntr_idx != -1) &&
  13062                 (new_pw_term_cntr_idx != old_pw_term_cntr_idx)) {
  13063                 /* Delete old pw_term counter associated with old mpls label */
  13064                 (void) _bcm_tr_mpls_pw_term_counter_delete (unit,
  13065                      old_pw_term_cntr_idx);
  13066             }
  13067             /*
  13068              * When replace match criteria of primary port,  old match entry keeps
  13069              * unchanged if 1: new match info is same as old one; 2: backup port
  13070              * has the same match info.
  13071              */
  13072             if ((old_mpls_entry_rv == BCM_E_NONE) 
  13073                 && (old_match_label != mpls_port->match_label)){
  13074                 if ((failover_match_label != -1) && (old_match_label == failover_match_label)) {
  13075                     soc_MPLS_ENTRYm_field32_set(unit, &return_ment, SOURCE_VPf, failover_vp);
  13076                     BCM_IF_ERROR_RETURN(soc_mem_write(unit, MPLS_ENTRYm,
  13077                                            MEM_BLOCK_ALL, entry_index,
  13078                                            &return_ment));
  13079                 } else {
  13080                     BCM_IF_ERROR_RETURN(soc_mem_delete(unit, MPLS_ENTRYm,
  13081                         MEM_BLOCK_ANY, &return_ment));
  13082                 }
  13083             }
  13084         }
  13085     } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_NONE) {
  13086         (void) bcm_tr_mpls_match_clear (unit, vp);
  13087         mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_NONE;
  13088         if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  13089             bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
  13090         }
  13091     }
  13092 #if defined(BCM_KATANA2_SUPPORT)
  13093     else if ((mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID) ||
  13094             (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_INNER_VLAN) ||
  13095             (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_OUTER_VLAN)) {
  13096 
  13097         int is_local = 0;    
  13098 
  13099         BCM_IF_ERROR_RETURN
  13100             (_bcm_esw_modid_is_local(unit, mod_out, &is_local));
  13101 
  13102         if (is_local) {
  13103             /* Convert system ports to physical ports */ 
  13104             if (soc_feature(unit, soc_feature_sysport_remap)) { 
  13105                 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 
  13106             }
  13107             /*TD3:VT_PORT_TYPE_SELECT_1f*/
  13108             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13109                 rv = _bcm_esw_port_tab_set(unit, port_out,
  13110                         _BCM_CPU_TABS_BOTH,
  13111                         VT_PORT_TYPE_SELECT_1f, 1);
  13112             } else {
  13113             rv = soc_mem_field32_modify(unit, PORT_TABm, port_out,
  13114                             VT_PORT_TYPE_SELECTf, 1);/*default*/ 
  13115             }
  13116             BCM_IF_ERROR_RETURN(rv);  
  13117         }
  13118         
  13119         if (!soc_feature(unit, soc_feature_lltag)) {
  13120             return BCM_E_UNAVAIL;
  13121         }
  13122 
  13123         soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1);
  13124         soc_mem_field32_set(unit, mem, vent, LLTAG__MPLS_ACTIONf, 0x1); /* SVP */
  13125         soc_mem_field32_set(unit, mem, vent, LLTAG__DISABLE_VLAN_CHECKSf, 1);
  13126         soc_mem_field32_set(unit, mem, vent, LLTAG__SOURCE_VPf, vp);
  13127         if (!BCM_VLAN_VALID(mpls_port->match_subport_pkt_vid)) {
  13128             return BCM_E_PARAM;
  13129         }
  13130 
  13131         if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID) {
  13132             soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13133                                         KT2_PT_XLT_KEY_TYPE_LLVID);
  13134         } else if (mpls_port->criteria ==
  13135                 BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_INNER_VLAN) {
  13136             soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13137                                         KT2_PT_XLT_KEY_TYPE_LLVID_IVID);
  13138             soc_mem_field32_set(unit, mem, vent, LLTAG__IVIDf,
  13139                                         mpls_port->match_inner_vlan);
  13140         } else {
  13141             soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13142                                         KT2_PT_XLT_KEY_TYPE_LLVID_OVID);
  13143             soc_mem_field32_set(unit, mem, vent, LLTAG__OVIDf,
  13144                                         mpls_port->match_vlan);
  13145         }
  13146 
  13147         soc_mem_field32_set(unit, mem, vent, LLTAG__LLVIDf,
  13148                                     mpls_port->match_subport_pkt_vid);
  13149 
  13150         if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  13151             soc_mem_field32_set(unit, mem, vent, LLTAG__Tf, 1);
  13152             soc_mem_field32_set(unit, mem, vent, LLTAG__TGIDf, trunk_id);
  13153             mpls_info->match_key[vp].trunk_id = trunk_id;
  13154         } else {
  13155             soc_mem_field32_set(unit, mem, vent, LLTAG__MODULE_IDf, mod_out);
  13156             soc_mem_field32_set(unit, mem, vent, LLTAG__PORT_NUMf, port_out);
  13157             mpls_info->match_key[vp].port = port_out;
  13158             mpls_info->match_key[vp].modid = mod_out;
  13159         }
  13160         rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent);
  13161         BCM_IF_ERROR_RETURN(rv);
  13162             /*Update S/W information only after match entry set successfully*/
  13163         if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID) {
  13164             if (is_local) {
  13165 
  13166                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13167                     rv = _bcm_esw_port_tab_set(unit, port_out,
  13168                             _BCM_CPU_TABS_BOTH,
  13169                             VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_LLVID);
  13170                 } else {
  13171                 rv = soc_mem_field32_modify(unit, PORT_TABm, port_out,
  13172                     VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_LLVID);  
  13173                 }
  13174                 BCM_IF_ERROR_RETURN(rv);
  13175             }
  13176             mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_PORT_SUBPORT_PKT_VID;
  13177         } else if (mpls_port->criteria == 
  13178                 BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_INNER_VLAN) {
  13179             if (is_local) {
  13180 
  13181                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13182                     rv = _bcm_esw_port_tab_set(unit, port_out,
  13183                             _BCM_CPU_TABS_BOTH,
  13184                             VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_LLVID_IVID);
  13185                 } else {
  13186                 rv = soc_mem_field32_modify(unit, PORT_TABm, port_out,
  13187                     VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_LLVID_IVID);  
  13188                 }
  13189                 BCM_IF_ERROR_RETURN(rv);
  13190             }
  13191             mpls_info->match_key[vp].flags = 
  13192                 _BCM_MPLS_PORT_MATCH_TYPE_PORT_SUBPORT_PKT_VID_INNER_VLAN;
  13193             mpls_info->match_key[vp].match_inner_vlan = mpls_port->match_inner_vlan;
  13194         } else {
  13195             if (is_local) {
  13196 
  13197                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13198                     rv = _bcm_esw_port_tab_set(unit, port_out,
  13199                             _BCM_CPU_TABS_BOTH,
  13200                             VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_LLVID_OVID);
  13201                 } else {
  13202                 rv = soc_mem_field32_modify(unit, PORT_TABm, port_out,
  13203                     VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_LLVID_OVID);  
  13204                 }
  13205                 BCM_IF_ERROR_RETURN(rv);
  13206             }
  13207             mpls_info->match_key[vp].flags = 
  13208                 _BCM_MPLS_PORT_MATCH_TYPE_PORT_SUBPORT_PKT_VID_OUTER_VLAN;
  13209             mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan;
  13210         }
  13211 
  13212         mpls_info->match_key[vp].match_subport_pkt_vid = mpls_port->match_subport_pkt_vid;
  13213         if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  13214             mpls_info->match_key[vp].trunk_id = trunk_id;
  13215         } else {
  13216             mpls_info->match_key[vp].port = port_out;
  13217             mpls_info->match_key[vp].modid = mod_out;
  13218         }
  13219 
  13220         if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  13221              bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
  13222         }
  13223     }
  13224 #endif /* end BCM_KATANA2-SUPPORT */
  13225     else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_VLAN) {
  13226         if (!soc_mem_field_valid(unit, mem, SOURCE_TYPEf)) {
  13227             return BCM_E_PARAM;
  13228         }
  13229         soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 0);
  13230         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13231             soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  13232             soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  13233             soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OVID);
  13234             /*set default tag action profile ptr*/
  13235             soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf,
  13236                                 1);
  13237         } else {
  13238             soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  13239         }
  13240 
  13241         soc_mem_field32_set(unit, mem, vent, MPLS_ACTIONf, 0x1); /* SVP */
  13242         soc_mem_field32_set(unit, mem, vent, DISABLE_VLAN_CHECKSf, 1);
  13243         soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, vp);
  13244         if (!BCM_VLAN_VALID(mpls_port->match_vlan)) {
  13245             return BCM_E_PARAM;
  13246         }
  13247         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13248                             TR_VLXLT_HASH_KEY_TYPE_OVID);
  13249         soc_mem_field32_set(unit, mem, vent, OVIDf, mpls_port->match_vlan);
  13250 
  13251         /* incoming port not used in lookup key, set field to all 1's */
  13252         soc_mem_field32_set(unit, mem, vent, GLPf,
  13253                             SOC_VLAN_XLATE_GLP_WILDCARD(unit));
  13254 
  13255         if (soc_feature(unit, soc_feature_vp_sharing)) {
  13256             BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  13257             if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) {
  13258                 _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
  13259                 soc_mem_field32_set(unit, mem, vent, VFIf, vfi);
  13260             }
  13261         }
  13262         rv = _bcm_tr_mpls_match_vlan_entry_set(unit, mpls_port, vent);
  13263         BCM_IF_ERROR_RETURN(rv);
  13264 
  13265         if (!(mpls_info->match_key[vp].flags &
  13266             _BCM_MPLS_PORT_MATCH_TYPE_SHARE)) {
  13267             mpls_info->match_key[vp].flags = _BCM_MPLS_PORT_MATCH_TYPE_VLAN;
  13268             mpls_info->match_key[vp].match_vlan = mpls_port->match_vlan;
  13269         }
  13270         if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  13271               bcm_tr_mpls_port_match_count_adjust(unit, vp, 1);
  13272         }
  13273     }
  13274     return rv;
  13275 }
  13276 
  13277 /*
  13278  * Function:
  13279  *      _bcm_tr_mpls_match_delete
  13280  * Purpose:
  13281  *      Delete match criteria of an MPLS port
  13282  * Parameters:
  13283  *      unit    - (IN) Device Number
  13284  *      mpls_port - (IN) mpls port information
  13285  *      vp  - (IN) Source Virtual Port
  13286  * Returns:
  13287  *      BCM_E_XXX
  13288  */
  13289 
  13290 int
  13291 _bcm_tr_mpls_match_delete(int unit, int vp, bcm_mpls_port_t *mpls_port,
  13292                           int sw_clear)
  13293 {
  13294     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  13295     int rv=BCM_E_NONE;
  13296     bcm_trunk_t trunk_id;
  13297     int    src_trk_idx=0;   /*Source Trunk table index.*/
  13298     int    mod_id_idx=0;   /* Module_Id */
  13299     int port;
  13300     int vpless_failover_port = FALSE;
  13301 #if defined(BCM_KATANA2_SUPPORT)
  13302     bcm_port_t pp_port = 0;
  13303 #endif
  13304 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT)
  13305     int is_local_subport = 0;
  13306     int local_port = 0;
  13307 #endif
  13308     uint32 vent[SOC_MAX_MEM_WORDS];
  13309     soc_mem_t mem;
  13310 
  13311 #if defined(BCM_TRIDENT3_SUPPORT)
  13312     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13313         mem = VLAN_XLATE_1_DOUBLEm;
  13314     } else
  13315 #endif
  13316     {
  13317         mem = VLAN_XLATEm;
  13318     }
  13319 
  13320     sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  13321 
  13322     if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) {
  13323         vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp);
  13324         if (mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_LABEL) {
  13325             /* label entry belongs to primary port */
  13326             return BCM_E_NONE;
  13327         }
  13328         vpless_failover_port = TRUE;
  13329     }
  13330 
  13331     /* Get module id for unit. */
  13332     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &mod_id_idx));
  13333 
  13334     if (mpls_info->match_key[vp].flags == _BCM_MPLS_PORT_MATCH_TYPE_NONE) {
  13335         if (sw_clear) {
  13336             (void) bcm_tr_mpls_match_clear (unit, vp);
  13337             bcm_tr_mpls_port_match_count_adjust(unit, vp, -1);
  13338         }
  13339     } else if (mpls_info->match_key[vp].flags ==
  13340                   _BCM_MPLS_PORT_MATCH_TYPE_VLAN) {
  13341 
  13342         /* default to SGLP type. TD2 */
  13343         if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) {
  13344             soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  13345         }
  13346 
  13347         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13348             soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  13349             soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  13350             soc_mem_field32_set(unit, mem, vent,
  13351                     DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OVID);
  13352         } else {
  13353             soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  13354         }
  13355         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13356                                     TR_VLXLT_HASH_KEY_TYPE_OVID);
  13357         soc_mem_field32_set(unit, mem, vent, OVIDf,
  13358                                     mpls_info->match_key[vp].match_vlan);
  13359         if (mpls_info->match_key[vp].modid != -1) {
  13360             soc_mem_field32_set(unit, mem, vent, MODULE_IDf,
  13361                                         mpls_info->match_key[vp].modid);
  13362             soc_mem_field32_set(unit, mem, vent, PORT_NUMf,
  13363                                         mpls_info->match_key[vp].port);
  13364         } else if (mpls_info->match_key[vp].trunk_id != -1) {
  13365             soc_mem_field32_set(unit, mem, vent, Tf, 1);
  13366             soc_mem_field32_set(unit, mem, vent, TGIDf,
  13367                                         mpls_info->match_key[vp].trunk_id);
  13368         } else {
  13369             if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) {
  13370                 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 0);
  13371             }
  13372             /* incoming port not used in lookup key, set field to all 1's */
  13373             soc_mem_field32_set(unit, mem, vent, GLPf,
  13374                                 SOC_VLAN_XLATE_GLP_WILDCARD(unit));
  13375         }
  13376         rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent);
  13377         if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_NONE)) {
  13378             /*  if we are not able to search for matching entry then we
  13379              *  return BCM_E_NONE. so it is good to clean the local
  13380              *  state also.
  13381              */
  13382             if (sw_clear) {
  13383                 (void) bcm_tr_mpls_match_clear (unit, vp);
  13384                 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1);
  13385             }
  13386         }
  13387 
  13388         BCM_IF_ERROR_RETURN(rv);
  13389     } else if  (mpls_info->match_key[vp].flags == 
  13390                      _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN) {
  13391 
  13392         /* default to SGLP type. TD2 */
  13393         if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) {
  13394             soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  13395         }
  13396 
  13397         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13398             soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  13399             soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  13400             soc_mem_field32_set(unit, mem, vent,
  13401                     DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID);
  13402         } else {
  13403             soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  13404         }
  13405         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 
  13406                                     TR_VLXLT_HASH_KEY_TYPE_IVID);
  13407         soc_mem_field32_set(unit, mem, vent, IVIDf,
  13408                                     mpls_info->match_key[vp].match_inner_vlan);
  13409         if (mpls_info->match_key[vp].modid != -1) {
  13410             soc_mem_field32_set(unit, mem, vent, MODULE_IDf, 
  13411                                         mpls_info->match_key[vp].modid);
  13412             soc_mem_field32_set(unit, mem, vent, PORT_NUMf, 
  13413                                         mpls_info->match_key[vp].port);
  13414         } else {
  13415             soc_mem_field32_set(unit, mem, vent, Tf, 1);
  13416             soc_mem_field32_set(unit, mem, vent, TGIDf, 
  13417                                         mpls_info->match_key[vp].trunk_id);
  13418         }
  13419         rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent);
  13420         if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_NONE)) {
  13421             /*  if we are not able to search for matching entry then we
  13422              *  return BCM_E_NONE. so it is good to clean the local
  13423              *  state also.
  13424              */
  13425 
  13426             if (sw_clear) {
  13427                 (void) bcm_tr_mpls_match_clear (unit, vp);
  13428                 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1);
  13429             }
  13430         }
  13431 
  13432         BCM_IF_ERROR_RETURN(rv);
  13433         
  13434     }else if (mpls_info->match_key[vp].flags == 
  13435                     _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED) {
  13436 
  13437         /* default to SGLP type. TD2 */
  13438         if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) {
  13439             soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  13440         }
  13441 
  13442         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13443                                     TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
  13444         soc_mem_field32_set(unit, mem, vent, OVIDf,
  13445                                     mpls_info->match_key[vp].match_vlan);
  13446         soc_mem_field32_set(unit, mem, vent, IVIDf,
  13447                               mpls_info->match_key[vp].match_inner_vlan);
  13448         if (mpls_info->match_key[vp].modid != -1) {
  13449             soc_mem_field32_set(unit, mem, vent, MODULE_IDf,
  13450                                         mpls_info->match_key[vp].modid);
  13451             soc_mem_field32_set(unit, mem, vent, PORT_NUMf,
  13452                                         mpls_info->match_key[vp].port);
  13453         } else {
  13454             soc_mem_field32_set(unit, mem, vent, Tf, 1);
  13455             soc_mem_field32_set(unit, mem, vent, TGIDf,
  13456                                         mpls_info->match_key[vp].trunk_id);
  13457         }
  13458         rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent);
  13459         if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_NONE)) {
  13460             /*  if we are not able to search for matching entry then we
  13461              *  return BCM_E_NONE. so it is good to clean the local
  13462              *  state also.
  13463              */
  13464 
  13465             if (sw_clear) {
  13466                 (void) bcm_tr_mpls_match_clear (unit, vp);
  13467                 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1);
  13468             }
  13469         }
  13470 
  13471         BCM_IF_ERROR_RETURN(rv);
  13472 
  13473     } else if	(mpls_info->match_key[vp].flags ==
  13474                                                _BCM_MPLS_PORT_MATCH_TYPE_VLAN_PRI) {
  13475 
  13476         /* default to SGLP type. TD2 */
  13477         if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) {
  13478             soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  13479         }
  13480 
  13481         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13482             soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  13483             soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  13484             soc_mem_field32_set(unit, mem, vent,
  13485                     DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_PRI_CFI);
  13486         } else {
  13487             soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  13488         }
  13489         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13490                                                       TR_VLXLT_HASH_KEY_TYPE_PRI_CFI);
  13491         soc_mem_field32_set(unit, mem, vent, OTAGf,
  13492                                                        mpls_info->match_key[vp].match_vlan);
  13493         if (mpls_info->match_key[vp].modid != -1) {
  13494               soc_mem_field32_set(unit, mem, vent, MODULE_IDf,
  13495                                                       mpls_info->match_key[vp].modid);
  13496               soc_mem_field32_set(unit, mem, vent, PORT_NUMf,
  13497                                                       mpls_info->match_key[vp].port);
  13498         } else {
  13499               soc_mem_field32_set(unit, mem, vent, Tf, 1);
  13500               soc_mem_field32_set(unit, mem, vent, TGIDf,
  13501                                                       mpls_info->match_key[vp].trunk_id);
  13502         }
  13503         rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent);
  13504         if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_NONE)) {
  13505             /*  if we are not able to search for matching entry then we
  13506              *  return BCM_E_NONE. so it is good to clean the local
  13507              *  state also.
  13508              */
  13509 
  13510             if (sw_clear) {
  13511                 (void) bcm_tr_mpls_match_clear (unit, vp);
  13512                 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1);
  13513             }
  13514         }
  13515 
  13516         BCM_IF_ERROR_RETURN(rv);
  13517 
  13518 #if defined(BCM_TRIUMPH2_SUPPORT)
  13519         if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TRUST_OUTER_DOT1Pf)) {
  13520             source_vp_entry_t svp;
  13521             BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
  13522             soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_OUTER_DOT1Pf, 0);
  13523             BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp));
  13524         }
  13525 #endif /* BCM_TRIUMPH2_SUPPORT */
  13526 
  13527     } else if (mpls_info->match_key[vp].flags ==
  13528                       _BCM_MPLS_PORT_MATCH_TYPE_VLAN_TAG) {
  13529         /* default to SGLP type. TD2 */
  13530         if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) {
  13531             soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  13532         }
  13533 
  13534         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13535             soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  13536             soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  13537             soc_mem_field32_set(unit, mem, vent,
  13538                     DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OTAG);
  13539         } else {
  13540             soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  13541         }
  13542         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13543                 TR_VLXLT_HASH_KEY_TYPE_OTAG);
  13544         soc_mem_field32_set(unit, mem, vent, OTAGf,
  13545                 mpls_info->match_key[vp].match_vlan);
  13546         if (mpls_info->match_key[vp].modid != -1) {
  13547             soc_mem_field32_set(unit, mem, vent, MODULE_IDf,
  13548                     mpls_info->match_key[vp].modid);
  13549             soc_mem_field32_set(unit, mem, vent, PORT_NUMf,
  13550                     mpls_info->match_key[vp].port);
  13551         } else {
  13552             soc_mem_field32_set(unit, mem, vent, Tf, 1);
  13553             soc_mem_field32_set(unit, mem, vent, TGIDf,
  13554                     mpls_info->match_key[vp].trunk_id);
  13555         }
  13556         rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent);
  13557         if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_NONE)) {
  13558             /*  if we are not able to search for matching entry then we
  13559              *  return BCM_E_NONE. so it is good to clean the local
  13560              *  state also.
  13561              */
  13562             if (sw_clear) {
  13563                 (void) bcm_tr_mpls_match_clear (unit, vp);
  13564                 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1);
  13565             }
  13566         }
  13567 
  13568         BCM_IF_ERROR_RETURN(rv);
  13569 
  13570     } else if (mpls_info->match_key[vp].flags ==
  13571                          _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN_TAG) {
  13572         /* default to SGLP type. TD2 */
  13573         if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) {
  13574             soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  13575         }
  13576 
  13577         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13578             soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  13579             soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  13580             soc_mem_field32_set(unit, mem, vent,
  13581                     DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_ITAG);
  13582         } else {
  13583             soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  13584         }
  13585         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13586                 TR_VLXLT_HASH_KEY_TYPE_ITAG);
  13587         soc_mem_field32_set(unit, mem, vent, ITAGf,
  13588                 mpls_info->match_key[vp].match_inner_vlan);
  13589         if (mpls_info->match_key[vp].modid != -1) {
  13590             soc_mem_field32_set(unit, mem, vent, MODULE_IDf,
  13591                     mpls_info->match_key[vp].modid);
  13592             soc_mem_field32_set(unit, mem, vent, PORT_NUMf,
  13593                     mpls_info->match_key[vp].port);
  13594         } else {
  13595             soc_mem_field32_set(unit, mem, vent, Tf, 1);
  13596             soc_mem_field32_set(unit, mem, vent, TGIDf,
  13597                     mpls_info->match_key[vp].trunk_id);
  13598         }
  13599         rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent);
  13600         if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_NONE)) {
  13601             /*  if we are not able to search for matching entry then we
  13602              *  return BCM_E_NONE. so it is good to clean the local
  13603              *  state also.
  13604              */
  13605 
  13606             if (sw_clear) {
  13607                 (void) bcm_tr_mpls_match_clear (unit, vp);
  13608                 bcm_tr_mpls_port_match_count_adjust(unit, vp, -1);
  13609             }
  13610         }
  13611 
  13612         BCM_IF_ERROR_RETURN(rv);
  13613 
  13614     } else if (mpls_info->match_key[vp].flags ==
  13615                                              _BCM_MPLS_PORT_MATCH_TYPE_SHARE) {
  13616         bcm_module_t mod_out = -1;
  13617         bcm_port_t port_out = -1;
  13618         int    gport_id =-1;
  13619         bcm_trunk_t trunk_id;
  13620 
  13621         if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) {
  13622             soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  13623         }
  13624 
  13625         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13626             soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  13627             soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  13628         } else {
  13629             soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  13630         }
  13631 
  13632         if (BCM_MPLS_PORT_MATCH_PORT_VLAN == mpls_port->criteria) {
  13633             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13634                 soc_mem_field32_set(unit, mem, vent,
  13635                         DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OVID);
  13636             }
  13637             soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13638                                         TR_VLXLT_HASH_KEY_TYPE_OVID);
  13639             soc_mem_field32_set(unit, mem, vent, OVIDf,
  13640                                         mpls_port->match_vlan);
  13641         } else if (BCM_MPLS_PORT_MATCH_PORT_VLAN_STACKED == mpls_port->criteria) {
  13642             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13643                 soc_mem_field32_set(unit, mem, vent,
  13644                         DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
  13645             }
  13646             soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13647                                         TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
  13648             soc_mem_field32_set(unit, mem, vent, OVIDf,
  13649                                         mpls_port->match_vlan);
  13650             soc_mem_field32_set(unit, mem, vent, IVIDf,
  13651                                         mpls_port->match_inner_vlan);
  13652         } else if (BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN == mpls_port->criteria) {
  13653             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13654                 soc_mem_field32_set(unit, mem, vent,
  13655                         DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID);
  13656             }
  13657             soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13658                                         TR_VLXLT_HASH_KEY_TYPE_IVID);
  13659             soc_mem_field32_set(unit, mem, vent, IVIDf,
  13660                                         mpls_port->match_inner_vlan);
  13661         } else if (BCM_MPLS_PORT_MATCH_VLAN_PRI == mpls_port->criteria) {
  13662             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13663                 soc_mem_field32_set(unit, mem, vent,
  13664                         DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_PRI_CFI);
  13665             }
  13666             soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13667                                         TR_VLXLT_HASH_KEY_TYPE_PRI_CFI);
  13668             soc_mem_field32_set(unit, mem, vent, OTAGf,
  13669                                         mpls_port->match_vlan);
  13670         } else if (BCM_MPLS_PORT_MATCH_PORT_VLAN_TAG == mpls_port->criteria) {
  13671             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13672                 soc_mem_field32_set(unit, mem, vent,
  13673                         DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OTAG);
  13674             }
  13675             soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13676                     TR_VLXLT_HASH_KEY_TYPE_OTAG);
  13677             soc_mem_field32_set(unit, mem, vent, OTAGf,
  13678                     mpls_port->match_vlan);
  13679 
  13680         } else if (BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN_TAG == mpls_port->criteria) {
  13681             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13682                 soc_mem_field32_set(unit, mem, vent,
  13683                         DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_ITAG);
  13684             }
  13685             soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13686                     TR_VLXLT_HASH_KEY_TYPE_ITAG);
  13687             soc_mem_field32_set(unit, mem, vent, ITAGf,
  13688                     mpls_port->match_inner_vlan);
  13689 
  13690         } else {
  13691             return BCM_E_UNAVAIL;
  13692         }
  13693         rv = _bcm_esw_gport_resolve(unit, mpls_port->port, &mod_out,
  13694                                     &port_out, &trunk_id, &gport_id);
  13695         BCM_IF_ERROR_RETURN(rv);
  13696 
  13697         if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  13698             soc_mem_field32_set(unit, mem, vent, Tf, 1);
  13699             soc_mem_field32_set(unit, mem, vent, TGIDf, trunk_id);
  13700         } else {
  13701             soc_mem_field32_set(unit, mem, vent, MODULE_IDf, mod_out);
  13702             soc_mem_field32_set(unit, mem, vent, PORT_NUMf, port_out);
  13703         }
  13704         rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent);
  13705         BCM_IF_ERROR_RETURN(rv);
  13706 
  13707         bcm_tr_mpls_port_match_count_adjust(unit, vp, -1);
  13708     } else if ((mpls_info->match_key[vp].flags ==  _BCM_MPLS_PORT_MATCH_TYPE_PORT)
  13709                || ((mpls_info->match_key[vp].flags == _BCM_MPLS_PORT_MATCH_TYPE_TRUNK)
  13710                    && (mpls_port != NULL) && (!BCM_GPORT_IS_TRUNK(mpls_port->port)))) {
  13711 
  13712         int is_local;
  13713         bcm_module_t mod_out;
  13714         bcm_port_t port_out;
  13715         int gport_id;
  13716 
  13717         if (mpls_info->match_key[vp].flags == _BCM_MPLS_PORT_MATCH_TYPE_PORT) {
  13718             src_trk_idx = mpls_info->match_key[vp].index;
  13719         } else {
  13720             /*
  13721              * The vp has been created based on trunk.
  13722              * When a new port is deleted from the trunk, a match will be deleted
  13723              * for the vp through bcm_port_match_delete.
  13724              */
  13725             if (mpls_port == NULL) {
  13726                 return BCM_E_PARAM;
  13727             }
  13728             BCM_IF_ERROR_RETURN(
  13729                 _bcm_esw_gport_resolve(unit, mpls_port->port, &mod_out,
  13730                                        &port_out, &trunk_id, &gport_id));
  13731             /* Get index to source trunk map table */
  13732             BCM_IF_ERROR_RETURN(
  13733                 _bcm_esw_src_mod_port_table_index_get(
  13734                     unit, mod_out, port_out, &src_trk_idx));
  13735        }
  13736 
  13737          rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 
  13738                                   src_trk_idx, SOURCE_VPf, 0);
  13739          BCM_IF_ERROR_RETURN(rv);
  13740          if (SOC_MEM_FIELD_VALID(unit,SOURCE_TRUNK_MAP_TABLEm,SVP_VALIDf)) {
  13741             rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  13742                                  src_trk_idx, SVP_VALIDf, 0);
  13743             BCM_IF_ERROR_RETURN(rv);
  13744          }
  13745 
  13746          BCM_IF_ERROR_RETURN(_bcm_esw_src_modid_port_get( unit, src_trk_idx,
  13747                                                           &mod_id_idx, &port));
  13748          BCM_IF_ERROR_RETURN
  13749              ( _bcm_esw_modid_is_local(unit, mod_id_idx, &is_local));
  13750 
  13751 #if defined(BCM_HGPROXY_COE_SUPPORT)
  13752     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) {
  13753 
  13754         if (is_local == 0) {
  13755             if(_bcm_xgs5_subport_coe_mod_port_local(unit, mod_id_idx, port)) {
  13756                 is_local_subport = 1;
  13757                 local_port = mpls_port->port;
  13758             }
  13759         }
  13760     } else
  13761 #endif
  13762 
  13763 #if defined(BCM_KATANA2_SUPPORT)
  13764          if (soc_feature(unit, soc_feature_linkphy_coe) ||
  13765             soc_feature(unit, soc_feature_subtag_coe)) {
  13766              if (is_local == 0) {
  13767                  is_local_subport = 0;
  13768                  if (_bcm_kt2_mod_is_coe_mod_check(unit, mod_id_idx) == BCM_E_NONE) {
  13769                      rv = _bcm_kt2_modport_to_pp_port_get(
  13770                               unit, mod_id_idx, port, &pp_port);
  13771                      if (_bcm_kt2_is_pp_port_linkphy_subtag(unit, pp_port)){
  13772                             is_local_subport = 1;
  13773                             local_port = pp_port;
  13774                      }
  13775                  }
  13776              }
  13777          }
  13778 #endif
  13779 
  13780 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_HGPROXY_COE_SUPPORT)
  13781         if (is_local_subport) {
  13782 
  13783             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13784                 rv = _bcm_esw_port_tab_set(unit, local_port,
  13785                         _BCM_CPU_TABS_BOTH,
  13786                         PORT_OPERATIONf, 0x0);
  13787             } else {
  13788             rv = _bcm_esw_port_tab_set_without_portlock(
  13789                      unit, local_port, _BCM_CPU_TABS_NONE, PORT_OPERATIONf,
  13790                      0x0); /* Normal */
  13791             }
  13792             BCM_IF_ERROR_RETURN(rv);
  13793 
  13794             /* Set TAG_ACTION_PROFILE_PTR */
  13795             rv = bcm_tr_mpls_port_untagged_profile_reset(unit, local_port);
  13796             BCM_IF_ERROR_RETURN(rv);
  13797         } else
  13798 #endif
  13799          if (is_local) {
  13800              /* Convert system ports to physical ports */ 
  13801              if (soc_feature(unit, soc_feature_sysport_remap)) { 
  13802                  BCM_XLATE_SYSPORT_S2P(unit, &port); 
  13803              }
  13804 
  13805              if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13806                  rv = _bcm_esw_port_tab_set(unit, port,
  13807                          _BCM_CPU_TABS_BOTH,
  13808                          PORT_OPERATIONf, 0x0);
  13809              } else {
  13810              rv = soc_mem_field32_modify(unit, PORT_TABm, port,
  13811                                            PORT_OPERATIONf, 0x0); /* NORMAL */
  13812              }
  13813              BCM_IF_ERROR_RETURN(rv);
  13814     
  13815              /* Reset TAG_ACTION_PROFILE_PTR */
  13816              rv = bcm_tr_mpls_port_untagged_profile_reset(unit, port);
  13817              BCM_IF_ERROR_RETURN(rv);
  13818          }
  13819 
  13820         if (sw_clear) {
  13821             (void) bcm_tr_mpls_match_clear (unit, vp);
  13822         }
  13823     } else if  (mpls_info->match_key[vp].flags == 
  13824                   _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) {
  13825          trunk_id = mpls_info->match_key[vp].trunk_id;
  13826          rv = bcm_tr_mpls_match_trunk_delete(unit, trunk_id, vp);
  13827          BCM_IF_ERROR_RETURN(rv);
  13828          mpls_info->trunk_vp_map[trunk_id] = -1;
  13829 
  13830         if (sw_clear) {
  13831             (void) bcm_tr_mpls_match_clear (unit, vp);
  13832         }
  13833     } else if ((mpls_info->match_key[vp].flags & 
  13834                      _BCM_MPLS_PORT_MATCH_TYPE_LABEL) ||
  13835                    (mpls_info->match_key[vp].flags == 
  13836                      _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT)) {
  13837         mpls_entry_entry_t ment, ret_ment;
  13838         int pw_cnt;
  13839         int svp = 0;
  13840 
  13841         sal_memset(&ment, 0, sizeof(mpls_entry_entry_t));
  13842         sal_memset(&ret_ment, 0, sizeof(mpls_entry_entry_t));
  13843         if (vpless_failover_port) {
  13844             if (mpls_info->match_key[vp].fo_modid != -1) {
  13845                 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__MODULE_IDf,
  13846                                         mpls_info->match_key[vp].fo_modid);
  13847                 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__PORT_NUMf,
  13848                                         mpls_info->match_key[vp].fo_port);
  13849             } else {
  13850                 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__Tf, 1);
  13851                 soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__TGIDf,
  13852                                        mpls_info->match_key[vp].fo_trunk_id);
  13853             }
  13854         } else {
  13855             if (mpls_info->match_key[vp].modid != -1) {
  13856                 soc_MPLS_ENTRYm_field32_set(unit, &ment, MODULE_IDf, 
  13857                                         mpls_info->match_key[vp].modid);
  13858                 soc_MPLS_ENTRYm_field32_set(unit, &ment, PORT_NUMf, 
  13859                                         mpls_info->match_key[vp].port);
  13860             } else {
  13861                 soc_MPLS_ENTRYm_field32_set(unit, &ment, Tf, 1);
  13862                 soc_MPLS_ENTRYm_field32_set(unit, &ment, TGIDf, 
  13863                                         mpls_info->match_key[vp].trunk_id);
  13864             }
  13865         }
  13866         soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_LABELf,
  13867                                     mpls_info->match_key[vp].match_label);
  13868 
  13869         rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &src_trk_idx,
  13870                                     &ment, &ret_ment, 0);
  13871 
  13872         if (rv == SOC_E_NONE) {
  13873             if  (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, PW_TERM_NUM_VALIDf)) {
  13874                 pw_cnt = soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, PW_TERM_NUMf);
  13875                 (void) _bcm_tr_mpls_pw_term_counter_delete (unit, pw_cnt);
  13876                  soc_MPLS_ENTRYm_field32_set(unit, &ret_ment, PW_TERM_NUM_VALIDf, 0);
  13877                  soc_MPLS_ENTRYm_field32_set(unit, &ret_ment, PW_TERM_NUMf, 0);
  13878             }
  13879 
  13880 #ifdef BCM_TRIUMPH2_SUPPORT
  13881             if (soc_feature(unit, soc_feature_gport_service_counters)) {
  13882                 if ((0 != soc_MPLS_ENTRYm_field32_get(unit, &ret_ment,
  13883                                                   USE_VINTF_CTR_IDXf)) &&
  13884                       (0 != soc_MPLS_ENTRYm_field32_get(unit, &ret_ment,
  13885                                                   VINTF_CTR_IDXf))) {
  13886                        /* Release MPLS label stat use, if any */
  13887                        _bcm_flex_stat_handle_t mpls_fsh;
  13888                        _BCM_FLEX_STAT_HANDLE_CLEAR(mpls_fsh);
  13889                        _BCM_FLEX_STAT_HANDLE_COPY(mpls_fsh, ment);
  13890                        _bcm_esw_flex_stat_ext_handle_free(unit,
  13891                                                    _bcmFlexStatTypeMplsLabel,
  13892                                                    mpls_fsh);
  13893                 }
  13894             }
  13895 #endif /* BCM_TRIUMPH2_SUPPORT  */
  13896 
  13897             svp = soc_mem_field32_get(unit, MPLS_ENTRYm, &ret_ment, SOURCE_VPf);
  13898             if (svp == vp) {
  13899                 if (_bcm_tr_mpls_match_vp_find(unit, vp, &svp)) {
  13900                     soc_mem_field32_set(unit, MPLS_ENTRYm, &ret_ment, SOURCE_VPf, svp);
  13901                     rv = soc_mem_write(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, src_trk_idx, &ret_ment);
  13902                 } else {
  13903                     rv = soc_mem_delete(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &ret_ment);
  13904                 }
  13905             }
  13906 
  13907             if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_NONE)) {
  13908                 if (vpless_failover_port) {
  13909                     mpls_info->match_key[vp].fo_trunk_id = -1;
  13910                     mpls_info->match_key[vp].fo_port = 0;
  13911                     mpls_info->match_key[vp].fo_modid = -1;
  13912                 } else {
  13913                     if (sw_clear) {
  13914                         if (mpls_info->match_key[vp].flags & 
  13915                             _BCM_MPLS_PORT_MATCH_TYPE_NONE) {
  13916                             bcm_tr_mpls_port_match_count_adjust(unit, vp, -1);
  13917                         }
  13918                         (void) bcm_tr_mpls_match_clear (unit, vp);
  13919                     }
  13920                 }
  13921             }
  13922             BCM_IF_ERROR_RETURN(rv);
  13923         }
  13924     }   
  13925 #if defined(BCM_KATANA2_SUPPORT)
  13926     else if ((mpls_info->match_key[vp].flags == 
  13927                 BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID) ||
  13928             (mpls_info->match_key[vp].flags == 
  13929                 BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_INNER_VLAN) ||
  13930             (mpls_info->match_key[vp].flags == 
  13931                 BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_OUTER_VLAN)) {
  13932         int is_local = 0;
  13933         
  13934         BCM_IF_ERROR_RETURN
  13935              ( _bcm_esw_modid_is_local(unit, mod_id_idx, &is_local));
  13936 
  13937         /* default to SGLP type. TD2 */
  13938         if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) {
  13939             soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  13940         }
  13941 
  13942         soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  13943         if (mpls_info->match_key[vp].flags == 
  13944                 BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID) {
  13945             soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13946                                         KT2_PT_XLT_KEY_TYPE_LLVID);        
  13947         } else if (mpls_info->match_key[vp].flags == 
  13948                 BCM_MPLS_PORT_MATCH_PORT_SUBPORT_PKT_VID_OUTER_VLAN) {
  13949             soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13950                                         KT2_PT_XLT_KEY_TYPE_LLVID_OVID);   
  13951             soc_mem_field32_set(unit, mem, vent, LLTAG__OVIDf,
  13952                                     mpls_info->match_key[vp].match_vlan);
  13953         } else {
  13954             soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
  13955                                         KT2_PT_XLT_KEY_TYPE_LLVID_IVID); 
  13956             soc_mem_field32_set(unit, mem, vent, LLTAG__IVIDf,
  13957                                     mpls_info->match_key[vp].match_inner_vlan);
  13958         }
  13959         
  13960         soc_mem_field32_set(unit, mem, vent, LLTAG__LLVIDf,
  13961                                     mpls_info->match_key[vp].match_subport_pkt_vid);
  13962         if (mpls_info->match_key[vp].modid != -1) {
  13963             soc_mem_field32_set(unit, mem, vent, LLTAG__MODULE_IDf,
  13964                                         mpls_info->match_key[vp].modid);
  13965             soc_mem_field32_set(unit, mem, vent, LLTAG__PORT_NUMf,
  13966                                         mpls_info->match_key[vp].port);
  13967         } else {
  13968             soc_mem_field32_set(unit, mem, vent, LLTAG__Tf, 1);
  13969             soc_mem_field32_set(unit, mem, vent, LLTAG__TGIDf,
  13970                                         mpls_info->match_key[vp].trunk_id);
  13971         }
  13972         rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent);
  13973         BCM_IF_ERROR_RETURN(rv);
  13974         if (is_local) {
  13975             pp_port = mpls_info->match_key[vp].port;
  13976             if (soc_feature(unit, soc_feature_sysport_remap)) { 
  13977                 BCM_XLATE_SYSPORT_S2P(unit, &pp_port); 
  13978             }
  13979 
  13980             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13981                 rv = _bcm_esw_port_tab_set(unit, pp_port,
  13982                         _BCM_CPU_TABS_BOTH,
  13983                         VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_OVID);
  13984             } else {
  13985             rv = soc_mem_field32_modify(unit, PORT_TABm, pp_port,
  13986                             VT_KEY_TYPEf, KT2_PT_XLT_KEY_TYPE_OVID);/*default*/ 
  13987             }
  13988             BCM_IF_ERROR_RETURN(rv);  
  13989 
  13990             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  13991                 rv = _bcm_esw_port_tab_set(unit, pp_port,
  13992                         _BCM_CPU_TABS_BOTH,
  13993                         VT_PORT_TYPE_SELECT_1f, 1);
  13994             } else {
  13995             rv = soc_mem_field32_modify(unit, PORT_TABm, pp_port,
  13996                             VT_PORT_TYPE_SELECTf, 1);/*default*/ 
  13997             }
  13998             BCM_IF_ERROR_RETURN(rv);  
  13999         }
  14000         
  14001         if (sw_clear) {
  14002             (void) bcm_tr_mpls_match_clear (unit, vp);
  14003             bcm_tr_mpls_port_match_count_adjust(unit, vp, -1);
  14004         }
  14005     }
  14006 #endif /* end BCM_KATANA2_SUPPORT */
  14007     return rv;
  14008 }
  14009 
  14010 /*
  14011  * Function:
  14012  *  _bcm_tr_mpls_failover_nw_port_match_get
  14013  * Purpose:
  14014  *  Get match criteria of an MPLS port
  14015  * Parameters:
  14016  *  unit    - (IN) Device Number
  14017  *  mpls_port - (IN) mpls port information
  14018  *  vp  - (IN) Source Virtual Port
  14019  *  return_ment - (OUT) matched entry
  14020  * Returns:
  14021  *  BCM_E_XXX
  14022  */
  14023 int
  14024 _bcm_tr_mpls_failover_nw_port_match_get(int unit, bcm_mpls_port_t *mpls_port,
  14025                                          int vp, mpls_entry_entry_t *return_ment)
  14026 {
  14027 
  14028     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  14029     mpls_entry_entry_t ment;
  14030     int entry_index = -1;
  14031     int key_type = 0; /* mpls_key_type */
  14032     int rv = BCM_E_NONE;
  14033     bcm_module_t mod_out;
  14034     bcm_port_t port_out;
  14035     bcm_trunk_t trunk_id;
  14036     bcm_gport_t gport_id;
  14037 
  14038     /* return not found if both inputs are invalid. */
  14039     if ((mpls_port == NULL) && (vp == -1)) {
  14040         return BCM_E_NOT_FOUND;
  14041     }
  14042 
  14043     sal_memset(&ment, 0, sizeof(mpls_entry_entry_t));
  14044     if (mpls_port != NULL) {
  14045         if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL_PORT) {
  14046             /* Check for Port_independent Label mapping */
  14047             rv = bcm_tr_mpls_port_independent_range (unit, mpls_port->match_label, mpls_port->port);
  14048             if (rv < 0) {
  14049                 return rv;
  14050             }
  14051 
  14052             rv = _bcm_esw_gport_resolve(unit, mpls_port->port, &mod_out,
  14053                     &port_out, &trunk_id, &gport_id);
  14054             BCM_IF_ERROR_RETURN(rv);
  14055 
  14056             if (BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  14057                 soc_MPLS_ENTRYm_field32_set(unit, &ment, Tf, 1);
  14058                 soc_MPLS_ENTRYm_field32_set(unit, &ment, TGIDf, mpls_port->port);
  14059             } else {
  14060                 soc_MPLS_ENTRYm_field32_set(unit, &ment, MODULE_IDf, mod_out);
  14061                 soc_MPLS_ENTRYm_field32_set(unit, &ment, PORT_NUMf, port_out);
  14062             }
  14063 
  14064         } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL) {
  14065             soc_MPLS_ENTRYm_field32_set(unit, &ment, MODULE_IDf, 0);
  14066             soc_MPLS_ENTRYm_field32_set(unit, &ment, PORT_NUMf, 0);
  14067         } else {
  14068             return BCM_E_NOT_FOUND;
  14069         }
  14070 
  14071         /* Use old label to get old mpls entry for replace operation */
  14072         soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_LABELf,
  14073                 mpls_port->match_label);
  14074         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  14075             soc_MPLS_ENTRYm_field32_set(unit, &ment, BASE_VALID_0f, 3);
  14076             soc_MPLS_ENTRYm_field32_set(unit, &ment, BASE_VALID_1f, 7);
  14077         } else {
  14078         soc_MPLS_ENTRYm_field32_set(unit, &ment, VALIDf, 1);
  14079         }
  14080         soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_BOSf,
  14081                 0x1); /* L2 SVP */
  14082         soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_NOT_BOSf,
  14083                 0x0); /* INVALID */
  14084         soc_MPLS_ENTRYm_field32_set(unit, &ment, KEY_TYPEf, key_type);
  14085     } else {
  14086 
  14087         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  14088             return BCM_E_NOT_FOUND;
  14089         }
  14090 
  14091         if ((mpls_info->match_key[vp].flags &
  14092                     _BCM_MPLS_PORT_MATCH_TYPE_LABEL) ||
  14093                 (mpls_info->match_key[vp].flags ==
  14094                  _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT)) {
  14095 
  14096             if (mpls_info->match_key[vp].flags &
  14097                     _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT) {
  14098 
  14099                 if (mpls_info->match_key[vp].trunk_id != -1) {
  14100                     soc_MPLS_ENTRYm_field32_set(unit, &ment, Tf, 1);
  14101                     soc_MPLS_ENTRYm_field32_set(unit, &ment, TGIDf,
  14102                             mpls_info->match_key[vp].trunk_id);
  14103                 } else {
  14104                     soc_MPLS_ENTRYm_field32_set(unit, &ment, MODULE_IDf,
  14105                             mpls_info->match_key[vp].modid);
  14106                     soc_MPLS_ENTRYm_field32_set(unit, &ment, PORT_NUMf,
  14107                             mpls_info->match_key[vp].port);
  14108                 }
  14109             }
  14110 
  14111             soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_LABELf,
  14112                     mpls_info->match_key[vp].match_label);
  14113             soc_MPLS_ENTRYm_field32_set(unit, &ment, KEY_TYPEf, key_type);
  14114 
  14115         } else {
  14116             return BCM_E_NOT_FOUND;
  14117         }
  14118     }
  14119 
  14120     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &entry_index,
  14121             &ment, return_ment, 0);
  14122 
  14123     return rv;
  14124 }
  14125 
  14126 
  14127 #ifdef BCM_TRIDENT2_SUPPORT
  14128 /*
  14129  * Function:
  14130  *      _bcm_td2_mpls_match_vp_replace
  14131  * Purpose:
  14132  *      Replace vp value in mpls vp's match entry.
  14133  * Parameters:
  14134  *      unit - (IN) SOC unit number.
  14135  *      vp - (IN) mpls vp whose match entry is being replaced.
  14136  *      new_vp - (IN) New vp value.
  14137  *      old_vp - (OUT) Old vp value.
  14138  * Returns:
  14139  *      BCM_X_XXX
  14140  */
  14141 STATIC int
  14142 _bcm_td2_mpls_match_vp_replace(int unit, int vp, int new_vp, int *old_vp)
  14143 {
  14144     int i = 0;
  14145     int rv = BCM_E_NONE;
  14146     int key_type = bcmVlanTranslateKeyInvalid;
  14147     int port = 0;
  14148     int my_modid = 0;
  14149     int stm_idx = 0;
  14150     int entry_index = 0;
  14151     int local_port[SOC_MAX_NUM_PORTS];
  14152     int local_port_count = 0;
  14153     int match_trunk_id = 0;
  14154     int match_modid = 0;
  14155     int match_port = 0;
  14156     soc_mem_t mem;
  14157     uint32 svp_valid;
  14158     uint32 match_label;
  14159     uint32 vent[SOC_MAX_MEM_WORDS];
  14160     uint32 ment[SOC_MAX_MEM_WORDS];
  14161     source_trunk_map_table_entry_t stm_entry;
  14162     _bcm_tr_mpls_match_port_info_t *mkey = NULL;
  14163 
  14164     mkey = &(MPLS_INFO(unit)->match_key[vp]);
  14165 
  14166 #define _BCM_VLXLT_KTYPE_ASSIGN(_ktype, _k) \
  14167     do { \
  14168         if (_ktype == bcmVlanTranslateKeyInvalid) { \
  14169             _ktype = _k; \
  14170         } \
  14171     } while(0)
  14172 
  14173     switch(mkey->flags) {
  14174         case _BCM_MPLS_PORT_MATCH_TYPE_VLAN:
  14175             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortOuter);
  14176             /* Fall through */
  14177         case _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN:
  14178             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortInner);
  14179             /* Fall through */
  14180         case _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED:
  14181             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortDouble);
  14182             /* Fall through */
  14183         case _BCM_MPLS_PORT_MATCH_TYPE_VLAN_PRI:
  14184             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortOuterPri);
  14185             /* Construct lookup key */
  14186             sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  14187 
  14188 #if defined(BCM_TRIDENT3_SUPPORT)
  14189             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  14190                 mem = VLAN_XLATE_1_DOUBLEm;
  14191 
  14192                 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  14193                 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  14194             } else
  14195 #endif
  14196             {
  14197                 mem = VLAN_XLATEm;
  14198 
  14199                 soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1);
  14200             }
  14201 
  14202             if (mkey->modid != -1) {
  14203                 BCM_GPORT_MODPORT_SET(port, mkey->modid, mkey->port);
  14204             } else {
  14205                 BCM_GPORT_TRUNK_SET(port, mkey->trunk_id);
  14206             }
  14207 
  14208             BCM_IF_ERROR_RETURN(
  14209                 _bcm_trx_vlan_translate_entry_assemble(unit, &vent,
  14210                                                        port, key_type,
  14211                                                        mkey->match_inner_vlan,
  14212                                                        mkey->match_vlan));
  14213             soc_mem_lock(unit, mem);
  14214             /* Lookup existing entry */
  14215             rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL,
  14216                                 &entry_index, &vent, &vent, 0);
  14217             if (BCM_FAILURE(rv)) {
  14218                 soc_mem_unlock(unit, mem);
  14219                 return rv;
  14220             }
  14221             /* Replace entry's VP value */
  14222             *old_vp = soc_mem_field32_get(unit, mem, vent, SOURCE_VPf);
  14223             soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, new_vp);
  14224 
  14225             /* Insert new entry */
  14226             rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, &vent);
  14227             soc_mem_unlock(unit, mem);
  14228             if (rv == SOC_E_EXISTS) {
  14229                 rv = BCM_E_NONE;
  14230             } else {
  14231                 return BCM_E_INTERNAL;
  14232             }
  14233             break;
  14234         case _BCM_MPLS_PORT_MATCH_TYPE_PORT:
  14235             mem = SOURCE_TRUNK_MAP_TABLEm;
  14236 
  14237             soc_mem_lock(unit, mem);
  14238 
  14239             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
  14240                               mkey->index, &stm_entry);
  14241             if (BCM_FAILURE(rv)) {
  14242                 soc_mem_unlock(unit, mem);
  14243                 return rv;
  14244             }
  14245             /* Resolve SVP Mode */
  14246             if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) {
  14247                 svp_valid = soc_mem_field32_get(unit, mem,
  14248                                                 &stm_entry, SVP_VALIDf);
  14249                 if (svp_valid == 0) {
  14250                     soc_mem_unlock(unit, mem);
  14251                     return BCM_E_INTERNAL;
  14252                 }
  14253             }
  14254             *old_vp = soc_mem_field32_get(unit, mem,
  14255                                           &stm_entry, SOURCE_VPf);
  14256             rv = soc_mem_field32_modify(unit, mem, mkey->index,
  14257                                         SOURCE_VPf, new_vp);
  14258 
  14259             soc_mem_unlock(unit, mem);
  14260             break;
  14261         case _BCM_MPLS_PORT_MATCH_TYPE_TRUNK:
  14262             mem = SOURCE_TRUNK_MAP_TABLEm;
  14263 
  14264             /* Get module id for unit. */
  14265             BCM_IF_ERROR_RETURN(
  14266                 bcm_esw_stk_my_modid_get(unit, &my_modid));
  14267 
  14268             BCM_IF_ERROR_RETURN(
  14269                 _bcm_esw_trunk_local_members_get(unit, mkey->trunk_id,
  14270                                                  SOC_MAX_NUM_PORTS,
  14271                                                  local_port,
  14272                                                  &local_port_count));
  14273             soc_mem_lock(unit, mem);
  14274 
  14275             for (i = 0; i < local_port_count; i++) {
  14276                 /* Get index to source trunk map table */
  14277                 rv = _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
  14278                                                            local_port[i],
  14279                                                            &stm_idx);
  14280                 if (BCM_FAILURE(rv)) {
  14281                     soc_mem_unlock(unit, mem);
  14282                     return rv;
  14283                 }
  14284 
  14285                 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
  14286                                   stm_idx, &stm_entry);
  14287                 if (BCM_FAILURE(rv)) {
  14288                     soc_mem_unlock(unit, mem);
  14289                     return rv;
  14290                 }
  14291 
  14292                 /* Resolve SVP Mode */
  14293                 if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) {
  14294                     svp_valid = soc_mem_field32_get(unit, mem,
  14295                                                     &stm_entry, SVP_VALIDf);
  14296                     if (svp_valid == 0) {
  14297                         soc_mem_unlock(unit, mem);
  14298                         return BCM_E_INTERNAL;
  14299                     }
  14300                 }
  14301                 *old_vp = soc_mem_field32_get(unit, mem,
  14302                                               &stm_entry, SOURCE_VPf);
  14303 
  14304                 rv = soc_mem_field32_modify(unit, mem, stm_idx,
  14305                                             SOURCE_VPf, new_vp);
  14306                 if (BCM_FAILURE(rv)) {
  14307                     soc_mem_unlock(unit, mem);
  14308                     return rv;
  14309                 }
  14310             }
  14311 
  14312             soc_mem_unlock(unit, mem);
  14313             break;
  14314         case _BCM_MPLS_PORT_MATCH_TYPE_LABEL:
  14315         case _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT:
  14316             match_trunk_id = mkey->trunk_id;
  14317             match_modid = mkey->modid;
  14318             match_port = mkey->port;
  14319             match_label = mkey->match_label;
  14320 
  14321             sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  14322             mem = MPLS_ENTRYm;
  14323 #if defined(BCM_TRIDENT3_SUPPORT)
  14324             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  14325                 soc_mem_field32_set(unit, mem, &ment, BASE_VALID_0f, 3);
  14326                 soc_mem_field32_set(unit, mem, &ment, BASE_VALID_1f, 7);
  14327             } else
  14328 #endif
  14329             {
  14330                 soc_mem_field32_set(unit, mem, &ment, VALIDf, 1);
  14331             }
  14332 
  14333             if (match_trunk_id != -1) {
  14334                 soc_mem_field32_set(unit, mem, &ment, Tf, 1);
  14335                 soc_mem_field32_set(unit, mem, &ment, TGIDf, match_trunk_id);
  14336             } else {
  14337                 soc_mem_field32_set(unit, mem, &ment, MODULE_IDf, match_modid);
  14338                 soc_mem_field32_set(unit, mem, &ment, PORT_NUMf, match_port);
  14339             }
  14340 
  14341             soc_mem_field32_set(unit, mem, &ment, MPLS_LABELf, match_label);
  14342             soc_mem_lock(unit, mem);
  14343             rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY,
  14344                                 &entry_index, &ment, &ment, 0);
  14345 
  14346             if (rv == BCM_E_NOT_FOUND) {
  14347                 rv = BCM_E_PARAM;
  14348             }
  14349 
  14350             if (BCM_FAILURE(rv)) {
  14351                 soc_mem_unlock(unit, mem);
  14352                 return rv;
  14353             }
  14354 
  14355             /* Replace entry's VP value */
  14356             *old_vp = soc_mem_field32_get(unit, mem, &ment, SOURCE_VPf);
  14357             soc_mem_field32_set(unit, mem, &ment, SOURCE_VPf, new_vp);
  14358             /* Insert new entry */
  14359             rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, ment);
  14360 
  14361             soc_mem_unlock(unit, mem);
  14362 
  14363             if (rv == SOC_E_EXISTS) {
  14364                 rv = BCM_E_NONE;
  14365             } else {
  14366                 return BCM_E_INTERNAL;
  14367             }
  14368             break;
  14369         case _BCM_MPLS_PORT_MATCH_TYPE_NONE:
  14370             *old_vp = vp;
  14371             break;
  14372         default:
  14373             return BCM_E_PARAM;
  14374     }
  14375 
  14376 #undef _BCM_VLXLT_KTYPE_ASSIGN
  14377 
  14378     return rv;
  14379 }
  14380 
  14381 /*
  14382  * Function:
  14383  *      bcm_td2_mpls_port_source_vp_lag_set
  14384  * Purpose:
  14385  *      Set source vp LAG for a mpls virtual port.
  14386  * Parameters:
  14387  *      unit - (IN) SOC unit number.
  14388  *      gport - (IN) mpls virtual port GPORT ID.
  14389  *      vp_lag_vp - (IN) VP representing the VP LAG.
  14390  * Returns:
  14391  *      BCM_X_XXX
  14392  */
  14393 int
  14394 bcm_td2_mpls_port_source_vp_lag_set(int unit, bcm_gport_t gport,
  14395         int vp_lag_vp)
  14396 {
  14397     int vp, old_vp;
  14398 
  14399     if (!BCM_GPORT_IS_MPLS_PORT(gport)) {
  14400         return BCM_E_PARAM;
  14401     }
  14402     vp = BCM_GPORT_MPLS_PORT_ID_GET(gport);
  14403     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  14404         return BCM_E_PARAM;
  14405     }
  14406 
  14407     BCM_IF_ERROR_RETURN
  14408         (_bcm_td2_mpls_match_vp_replace(unit, vp, vp_lag_vp, &old_vp));
  14409 
  14410     return BCM_E_NONE;
  14411 }
  14412 
  14413 /*
  14414  * Function:
  14415  *      bcm_td2_mpls_port_source_vp_lag_clear
  14416  * Purpose:
  14417  *      Clear source VP LAG for a mpls virtual port.
  14418  * Parameters:
  14419  *      unit - (IN) SOC unit number.
  14420  *      gport - (IN) mpls virtual port GPORT ID.
  14421  *      vp_lag_vp - (IN) VP representing the VP LAG.
  14422  * Returns:
  14423  *      BCM_X_XXX
  14424  */
  14425 int
  14426 bcm_td2_mpls_port_source_vp_lag_clear(int unit, bcm_gport_t gport,
  14427         int vp_lag_vp)
  14428 {
  14429     int vp, old_vp;
  14430 
  14431     if (!BCM_GPORT_IS_MPLS_PORT(gport)) {
  14432         return BCM_E_PARAM;
  14433     }
  14434     vp = BCM_GPORT_MPLS_PORT_ID_GET(gport);
  14435     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  14436         return BCM_E_PARAM;
  14437     }
  14438 
  14439     BCM_IF_ERROR_RETURN
  14440         (_bcm_td2_mpls_match_vp_replace(unit, vp, vp, &old_vp));
  14441 
  14442     return BCM_E_NONE;
  14443 }
  14444 
  14445 /*
  14446  * Function:
  14447  *      bcm_td2_mpls_port_source_vp_lag_get
  14448  * Purpose:
  14449  *      Get source VP LAG for a mpls virtual port.
  14450  * Parameters:
  14451  *      unit - (IN) SOC unit number.
  14452  *      gport - (IN) mpls virtual port GPORT ID.
  14453  *      vp_lag_vp - (OUT) VP representing the VP LAG.
  14454  * Returns:
  14455  *      BCM_X_XXX
  14456  */
  14457 int
  14458 bcm_td2_mpls_port_source_vp_lag_get(int unit, bcm_gport_t gport,
  14459         int *vp_lag_vp)
  14460 {
  14461     int rv = BCM_E_NONE;
  14462     int key_type = bcmVlanTranslateKeyInvalid;
  14463     int port = 0;
  14464     int my_modid = 0;
  14465     int stm_idx = 0;
  14466     int entry_index = 0;
  14467     int local_port[SOC_MAX_NUM_PORTS];
  14468     int local_port_count = 0;
  14469     int match_trunk_id = 0;
  14470     int match_modid = 0;
  14471     int match_port = 0;
  14472     soc_mem_t mem;
  14473     bcm_gport_t vp;
  14474     uint32 svp_valid;
  14475     uint32 match_label;
  14476     uint32 vent[SOC_MAX_MEM_WORDS];
  14477     uint32 ment[SOC_MAX_MEM_WORDS];
  14478     source_trunk_map_table_entry_t stm_entry;
  14479     _bcm_tr_mpls_match_port_info_t *mkey = NULL;
  14480 
  14481     if (!BCM_GPORT_IS_MPLS_PORT(gport)) {
  14482         return BCM_E_PARAM;
  14483     }
  14484 
  14485     vp = BCM_GPORT_MPLS_PORT_ID_GET(gport);
  14486     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  14487         return BCM_E_PARAM;
  14488     }
  14489 
  14490     mkey = &(MPLS_INFO(unit)->match_key[vp]);
  14491 
  14492 #define _BCM_VLXLT_KTYPE_ASSIGN(_ktype, _k) \
  14493         do { \
  14494             if (_ktype == bcmVlanTranslateKeyInvalid) { \
  14495                 _ktype = _k; \
  14496             } \
  14497         } while(0)
  14498 
  14499     switch(mkey->flags) {
  14500         case _BCM_MPLS_PORT_MATCH_TYPE_VLAN:
  14501             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortOuter);
  14502             /* Fall through */
  14503         case _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN:
  14504             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortInner);
  14505             /* Fall through */
  14506         case _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED:
  14507             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortDouble);
  14508             /* Fall through */
  14509         case _BCM_MPLS_PORT_MATCH_TYPE_VLAN_PRI:
  14510             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortOuterPri);
  14511 
  14512             sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  14513 #if defined(BCM_TRIDENT3_SUPPORT)
  14514             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  14515                 mem = VLAN_XLATE_1_DOUBLEm;
  14516 
  14517                 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  14518                 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  14519             } else
  14520 #endif
  14521             {
  14522                 mem = VLAN_XLATEm;
  14523 
  14524                 soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1);
  14525             }
  14526 
  14527             if (mkey->modid != -1) {
  14528                 BCM_GPORT_MODPORT_SET(port, mkey->modid, mkey->port);
  14529             } else {
  14530                 BCM_GPORT_TRUNK_SET(port, mkey->trunk_id);
  14531             }
  14532             /* Construct lookup key */
  14533             BCM_IF_ERROR_RETURN(
  14534                 _bcm_trx_vlan_translate_entry_assemble(unit, vent,
  14535                                                        port, key_type,
  14536                                                        mkey->match_inner_vlan,
  14537                                                        mkey->match_vlan));
  14538             soc_mem_lock(unit, mem);
  14539             /* Lookup existing entry */
  14540             rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL,
  14541                                 &entry_index, vent, vent, 0);
  14542             soc_mem_unlock(unit, mem);
  14543             if (BCM_FAILURE(rv)) {
  14544                 return rv;
  14545             }
  14546             /* Get VP value representing VP LAG */
  14547             *vp_lag_vp = soc_mem_field32_get(unit, mem, vent, SOURCE_VPf);
  14548             break;
  14549         case _BCM_MPLS_PORT_MATCH_TYPE_PORT:
  14550             mem = SOURCE_TRUNK_MAP_TABLEm;
  14551 
  14552             soc_mem_lock(unit, mem);
  14553 
  14554             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
  14555                               mkey->index, &stm_entry);
  14556             soc_mem_unlock(unit, mem);
  14557             if (BCM_FAILURE(rv)) {
  14558                 return rv;
  14559             }
  14560             /* Resolve SVP Mode */
  14561             if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) {
  14562                 svp_valid = soc_mem_field32_get(unit, mem,
  14563                                                 &stm_entry, SVP_VALIDf);
  14564                 if (svp_valid == 0) {
  14565                     return BCM_E_INTERNAL;
  14566                 }
  14567             }
  14568             /* Get VP value representing VP LAG */
  14569             *vp_lag_vp = soc_mem_field32_get(unit, mem,
  14570                                              &stm_entry, SOURCE_VPf);
  14571             break;
  14572         case _BCM_MPLS_PORT_MATCH_TYPE_TRUNK:
  14573             mem = SOURCE_TRUNK_MAP_TABLEm;
  14574 
  14575             /* Get module id for unit. */
  14576             BCM_IF_ERROR_RETURN(
  14577                 bcm_esw_stk_my_modid_get(unit, &my_modid));
  14578 
  14579             BCM_IF_ERROR_RETURN(
  14580                 _bcm_esw_trunk_local_members_get(unit, mkey->trunk_id,
  14581                                                  SOC_MAX_NUM_PORTS,
  14582                                                  local_port,
  14583                                                  &local_port_count));
  14584 
  14585             /* Get index to source trunk map table,
  14586              * Only get it from the first member in LAG
  14587              */
  14588             rv = _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
  14589                                                        local_port[0],
  14590                                                        &stm_idx);
  14591             if (BCM_FAILURE(rv)) {
  14592                 return rv;
  14593             }
  14594 
  14595             soc_mem_lock(unit, mem);
  14596             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
  14597                               stm_idx, &stm_entry);
  14598             soc_mem_unlock(unit, mem);
  14599             if (BCM_FAILURE(rv)) {
  14600                 return rv;
  14601             }
  14602 
  14603             /* Resolve SVP Mode */
  14604             if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) {
  14605                 svp_valid = soc_mem_field32_get(unit, mem,
  14606                                                 &stm_entry, SVP_VALIDf);
  14607                 if (svp_valid == 0) {
  14608                     return BCM_E_INTERNAL;
  14609                 }
  14610             }
  14611             /* Get VP value representing VP LAG */
  14612             *vp_lag_vp = soc_mem_field32_get(unit, mem,
  14613                                              &stm_entry, SOURCE_VPf);
  14614             break;
  14615         case _BCM_MPLS_PORT_MATCH_TYPE_LABEL:
  14616         case _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT:
  14617             match_trunk_id = mkey->trunk_id;
  14618             match_modid = mkey->modid;
  14619             match_port = mkey->port;
  14620             match_label = mkey->match_label;
  14621 
  14622             sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  14623             mem = MPLS_ENTRYm;
  14624 #if defined(BCM_TRIDENT3_SUPPORT)
  14625             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  14626                 soc_mem_field32_set(unit, mem, &ment, BASE_VALID_0f, 3);
  14627                 soc_mem_field32_set(unit, mem, &ment, BASE_VALID_1f, 7);
  14628             } else
  14629 #endif
  14630             {
  14631                 soc_mem_field32_set(unit, mem, &ment, VALIDf, 1);
  14632             }
  14633 
  14634             if (match_trunk_id != -1) {
  14635                 soc_mem_field32_set(unit, mem, &ment, Tf, 1);
  14636                 soc_mem_field32_set(unit, mem, &ment, TGIDf, match_trunk_id);
  14637             } else {
  14638                 soc_mem_field32_set(unit, mem, &ment, MODULE_IDf, match_modid);
  14639                 soc_mem_field32_set(unit, mem, &ment, PORT_NUMf, match_port);
  14640             }
  14641 
  14642             soc_mem_field32_set(unit, mem, &ment, MPLS_LABELf, match_label);
  14643             soc_mem_lock(unit, mem);
  14644             rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY,
  14645                                 &entry_index, &ment, &ment, 0);
  14646 
  14647             if (rv == BCM_E_NOT_FOUND) {
  14648                 rv = BCM_E_PARAM;
  14649             }
  14650 
  14651             soc_mem_unlock(unit, mem);
  14652             if (BCM_FAILURE(rv)) {
  14653                 return rv;
  14654             }
  14655 
  14656             *vp_lag_vp = soc_mem_field32_get(unit, mem, &ment, SOURCE_VPf);
  14657             break;
  14658         default:
  14659             return BCM_E_PARAM;
  14660     }
  14661 
  14662 #undef _BCM_VLXLT_KTYPE_ASSIGN
  14663 
  14664     if (!_bcm_vp_used_get(unit, *vp_lag_vp, _bcmVpTypeVpLag)) {
  14665         return BCM_E_INTERNAL;
  14666     }
  14667 
  14668     return BCM_E_NONE;
  14669 }
  14670 
  14671 /*
  14672  * Function:
  14673  *      _bcm_td2_mpls_vplag_vp_update
  14674  * Purpose:
  14675  *      Update vplag vp according to MPLS port
  14676  * Parameters:
  14677  *      unit   - (IN) Device Number
  14678  *      gport  - (IN) MPLS port
  14679  * Returns:
  14680  *      BCM_E_XXX
  14681  */
  14682 STATIC int
  14683 _bcm_td2_mpls_vplag_vp_update(int unit, bcm_gport_t gport)
  14684 {
  14685     int rv = 0;
  14686     int vp = 0;
  14687     int vplag_vp = 0;
  14688     uint32 vfi = 0;
  14689     uint32 network_port = 0;
  14690     uint32 network_group = 0;
  14691     uint32 tpid_enable = 0;
  14692     uint32 sd_tag_mode = 0;
  14693     source_vp_entry_t svp_entry;
  14694     source_vp_entry_t svp_entry1;
  14695 
  14696     rv = bcm_td2_mpls_port_source_vp_lag_get(unit, gport, &vplag_vp);
  14697     if (BCM_SUCCESS(rv)) {
  14698         vp = BCM_GPORT_MPLS_PORT_ID_GET(gport);
  14699         BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp_entry));
  14700         BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vplag_vp, &svp_entry1));
  14701 
  14702         vfi = soc_SOURCE_VPm_field32_get(unit, &svp_entry, VFIf);
  14703         sd_tag_mode = soc_SOURCE_VPm_field32_get(unit, &svp_entry, SD_TAG_MODEf);
  14704         soc_SOURCE_VPm_field32_set(unit, &svp_entry1, VFIf, vfi);
  14705         soc_SOURCE_VPm_field32_set(unit, &svp_entry1, SD_TAG_MODEf, sd_tag_mode);
  14706 
  14707         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
  14708             network_group = soc_SOURCE_VPm_field32_get(unit, &svp_entry, NETWORK_GROUPf);
  14709             soc_SOURCE_VPm_field32_set(unit, &svp_entry1, NETWORK_GROUPf, network_group);
  14710         } else {
  14711             network_port = soc_SOURCE_VPm_field32_get(unit, &svp_entry, NETWORK_PORTf);
  14712             soc_SOURCE_VPm_field32_set(unit, &svp_entry1, NETWORK_PORTf, network_port);
  14713         }
  14714 #if defined(BCM_TRIDENT3_SUPPORT)
  14715         if (SOC_IS_TRIDENT3X(unit)) {
  14716             uint32 svp1[SOC_MAX_MEM_WORDS];
  14717             uint32 svp2[SOC_MAX_MEM_WORDS];
  14718             BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, svp1));
  14719             BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vplag_vp, svp2));
  14720             soc_SVP_ATTRS_1m_field_get(unit, &svp1, TPID_ENABLEf, &tpid_enable);
  14721             soc_SVP_ATTRS_1m_field_set(unit, &svp2, TPID_ENABLEf, &tpid_enable);
  14722             BCM_IF_ERROR_RETURN(WRITE_SVP_ATTRS_1m(unit, MEM_BLOCK_ALL, vplag_vp, &svp2));
  14723         } else
  14724 #endif
  14725         {
  14726             tpid_enable = soc_SOURCE_VPm_field32_get(unit, &svp_entry, TPID_ENABLEf);
  14727             soc_SOURCE_VPm_field32_set(unit, &svp_entry1, TPID_ENABLEf, tpid_enable);
  14728         }
  14729         BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vplag_vp, &svp_entry1));
  14730     }
  14731 
  14732     return BCM_E_NONE;
  14733 }
  14734 
  14735 #endif
  14736 
  14737 /*
  14738  * Function:
  14739  *      _bcm_tr_mpls_match_get
  14740  * Purpose:
  14741  *      Obtain match information of an MPLS port
  14742  * Parameters:
  14743  *      unit    - (IN) Device Number
  14744  *      mpls_port - (OUT) mpls port information
  14745  *      vp  - (IN) Source Virtual Port
  14746  * Returns:
  14747  *      BCM_E_XXX
  14748  */
  14749 
  14750 int
  14751 _bcm_tr_mpls_match_get(int unit, bcm_mpls_port_t *mpls_port, int vp)
  14752 {
  14753     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  14754     int num_bits_for_port, rv = BCM_E_NONE;
  14755     uint32 port_mask;
  14756     bcm_module_t mod_in=0, mod_out;
  14757     bcm_port_t port_in=0, port_out;
  14758     bcm_trunk_t trunk_id=0;
  14759     int    src_trk_idx=0;    /*Source Trunk table index.*/
  14760     int    mode_in=0;   /* Module_Id */
  14761     int vpless_failover_port = FALSE; /* the failover port without a dedicated vp */
  14762     int match_trunk_id;
  14763     int match_modid;
  14764     int match_port;
  14765 
  14766     if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) {    
  14767         vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp);
  14768 
  14769         if (!(mpls_info->match_key[vp].flags & 
  14770              _BCM_MPLS_PORT_MATCH_TYPE_LABEL)) {
  14771               vpless_failover_port = TRUE;
  14772          } 
  14773     }
  14774 
  14775     if (vpless_failover_port == FALSE) {
  14776         match_trunk_id = mpls_info->match_key[vp].trunk_id;
  14777         match_modid    = mpls_info->match_key[vp].modid;
  14778         match_port     = mpls_info->match_key[vp].port;
  14779     } else {
  14780         match_trunk_id = mpls_info->match_key[vp].fo_trunk_id;
  14781         match_modid    = mpls_info->match_key[vp].fo_modid;
  14782         match_port     = mpls_info->match_key[vp].fo_port;
  14783     }
  14784     
  14785     /* Get module id for unit. */
  14786     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &mode_in));
  14787 
  14788     if  (mpls_info->match_key[vp].flags &  _BCM_MPLS_PORT_MATCH_TYPE_VLAN) {
  14789 
  14790          mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT_VLAN;
  14791          mpls_port->match_vlan = mpls_info->match_key[vp].match_vlan;
  14792 
  14793         if (mpls_info->match_key[vp].trunk_id != -1) {
  14794              trunk_id = mpls_info->match_key[vp].trunk_id;
  14795              BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id);
  14796         } else if (mpls_info->match_key[vp].modid != -1) {
  14797              port_in = mpls_info->match_key[vp].port;
  14798              mod_in = mpls_info->match_key[vp].modid;
  14799              rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
  14800                                   mod_in, port_in, &mod_out, &port_out);
  14801              BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out);
  14802         } else {
  14803              mpls_port->criteria = BCM_MPLS_PORT_MATCH_VLAN;
  14804         }
  14805     } else if (mpls_info->match_key[vp].flags &  
  14806                  _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN) {
  14807          mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN;
  14808          mpls_port->match_inner_vlan = mpls_info->match_key[vp].match_inner_vlan;
  14809 
  14810         if (mpls_info->match_key[vp].trunk_id != -1) {
  14811              trunk_id = mpls_info->match_key[vp].trunk_id;
  14812              BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id);
  14813         } else {
  14814              port_in = mpls_info->match_key[vp].port;
  14815              mod_in = mpls_info->match_key[vp].modid;
  14816              rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
  14817                                   mod_in, port_in, &mod_out, &port_out);
  14818              BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out);
  14819         }
  14820     }else if (mpls_info->match_key[vp].flags &
  14821                     _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED) {
  14822 
  14823          mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT_VLAN_STACKED;
  14824          mpls_port->match_vlan = mpls_info->match_key[vp].match_vlan;
  14825          mpls_port->match_inner_vlan = mpls_info->match_key[vp].match_inner_vlan;
  14826 
  14827          if (mpls_info->match_key[vp].trunk_id != -1) {
  14828               trunk_id = mpls_info->match_key[vp].trunk_id;
  14829               BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id);
  14830          } else {
  14831               port_in = mpls_info->match_key[vp].port;
  14832               mod_in = mpls_info->match_key[vp].modid;
  14833               rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
  14834                              mod_in, port_in, &mod_out, &port_out);
  14835               BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out);
  14836          }
  14837     } else if  (mpls_info->match_key[vp].flags &  _BCM_MPLS_PORT_MATCH_TYPE_VLAN_PRI) {
  14838 
  14839          mpls_port->criteria = BCM_MPLS_PORT_MATCH_VLAN_PRI;
  14840          mpls_port->match_vlan = mpls_info->match_key[vp].match_vlan;
  14841 
  14842         if (mpls_info->match_key[vp].trunk_id != -1) {
  14843              trunk_id = mpls_info->match_key[vp].trunk_id;
  14844              BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id);
  14845         } else {
  14846              port_in = mpls_info->match_key[vp].port;
  14847              mod_in = mpls_info->match_key[vp].modid;
  14848              rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
  14849                                   mod_in, port_in, &mod_out, &port_out);
  14850              BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out);
  14851         }
  14852     } else if (mpls_info->match_key[vp].flags &
  14853                                  _BCM_MPLS_PORT_MATCH_TYPE_VLAN_TAG) {
  14854 
  14855         mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT_VLAN_TAG;
  14856         mpls_port->match_vlan = mpls_info->match_key[vp].match_vlan;
  14857 
  14858         if (mpls_info->match_key[vp].trunk_id != -1) {
  14859             trunk_id = mpls_info->match_key[vp].trunk_id;
  14860             BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id);
  14861         } else {
  14862             port_in = mpls_info->match_key[vp].port;
  14863             mod_in = mpls_info->match_key[vp].modid;
  14864             rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
  14865                     mod_in, port_in, &mod_out, &port_out);
  14866             BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out);
  14867         }
  14868 
  14869     } else if (mpls_info->match_key[vp].flags &
  14870                                  _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN_TAG) {
  14871 
  14872         mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN_TAG;
  14873         mpls_port->match_inner_vlan = mpls_info->match_key[vp].match_inner_vlan;
  14874 
  14875         if (mpls_info->match_key[vp].trunk_id != -1) {
  14876             trunk_id = mpls_info->match_key[vp].trunk_id;
  14877             BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id);
  14878         } else {
  14879             port_in = mpls_info->match_key[vp].port;
  14880             mod_in = mpls_info->match_key[vp].modid;
  14881             rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
  14882                     mod_in, port_in, &mod_out, &port_out);
  14883             BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out);
  14884         }
  14885 
  14886     } else if (mpls_info->match_key[vp].flags &
  14887                    _BCM_MPLS_PORT_MATCH_TYPE_PORT) {
  14888 
  14889          src_trk_idx = mpls_info->match_key[vp].index;
  14890 
  14891          if (soc_feature(unit, soc_feature_src_modid_base_index)) {
  14892               source_trunk_map_modbase_entry_t modbase_entry;
  14893 
  14894               BCM_IF_ERROR_RETURN
  14895                    (soc_mem_read(unit, SOURCE_TRUNK_MAP_MODBASEm, 
  14896                                        MEM_BLOCK_ANY,  mode_in, &modbase_entry));
  14897               port_in = src_trk_idx - soc_mem_field32_get(unit, 
  14898                                        SOURCE_TRUNK_MAP_MODBASEm,
  14899                                        &modbase_entry, BASEf);
  14900          } else {
  14901               num_bits_for_port =
  14902                    _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit));
  14903                                        port_mask = (1 << num_bits_for_port) - 1;
  14904 
  14905               port_in = src_trk_idx & port_mask;
  14906               mod_in = src_trk_idx >> num_bits_for_port;
  14907          }
  14908 
  14909         mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT;
  14910         rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
  14911                                mod_in, port_in, &mod_out, &port_out);
  14912          BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out);
  14913     }else if (mpls_info->match_key[vp].flags &
  14914                   _BCM_MPLS_PORT_MATCH_TYPE_TRUNK) {
  14915 
  14916          trunk_id = mpls_info->match_key[vp].trunk_id;
  14917          mpls_port->criteria = BCM_MPLS_PORT_MATCH_PORT;
  14918          BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id);
  14919     } else if ((mpls_info->match_key[vp].flags & 
  14920                 _BCM_MPLS_PORT_MATCH_TYPE_LABEL) ||
  14921                 (mpls_info->match_key[vp].flags == 
  14922                  _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT)) {
  14923         mpls_entry_entry_t ment, ret_ment;
  14924 
  14925         sal_memset(&ment, 0, sizeof(mpls_entry_entry_t));
  14926         sal_memset(&ret_ment, 0, sizeof(mpls_entry_entry_t));
  14927 
  14928          if (mpls_info->match_key[vp].flags & 
  14929              _BCM_MPLS_PORT_MATCH_TYPE_LABEL) {
  14930               mpls_port->criteria = BCM_MPLS_PORT_MATCH_LABEL;
  14931          } else if (mpls_info->match_key[vp].flags & 
  14932                     _BCM_MPLS_PORT_MATCH_TYPE_LABEL_PORT) {
  14933               mpls_port->criteria = BCM_MPLS_PORT_MATCH_LABEL_PORT; 
  14934          }
  14935          mpls_port->match_label = mpls_info->match_key[vp].match_label;
  14936 
  14937          if (match_trunk_id != -1) {
  14938               trunk_id = match_trunk_id;
  14939               soc_MPLS_ENTRYm_field32_set(unit, &ment, Tf, 1);
  14940               soc_MPLS_ENTRYm_field32_set(unit, &ment, TGIDf, trunk_id);
  14941               BCM_GPORT_TRUNK_SET(mpls_port->port, trunk_id);
  14942          } else {
  14943               mod_in = match_modid;
  14944               port_in = match_port;
  14945               soc_MPLS_ENTRYm_field32_set(unit, &ment, MODULE_IDf, mod_in);
  14946               soc_MPLS_ENTRYm_field32_set(unit, &ment, PORT_NUMf, port_in);
  14947 
  14948               BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit, 
  14949                           BCM_STK_MODMAP_GET, mod_in, port_in, 
  14950                           &mod_out, &port_out));
  14951               BCM_GPORT_MODPORT_SET(mpls_port->port, mod_out, port_out);
  14952          }
  14953          soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_LABELf, 
  14954                                      mpls_info->match_key[vp].match_label);
  14955  
  14956          rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &src_trk_idx,
  14957                              &ment, &ret_ment, 0);
  14958  
  14959          if (rv == SOC_E_NONE) {
  14960               if (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 
  14961                                             CW_CHECK_CTRLf) == 0x3) {
  14962                    
  14963                    /* Control word is present, and check sequence number */
  14964                    mpls_port->flags |= BCM_MPLS_PORT_SEQUENCED;
  14965               } else if (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 
  14966                                             CW_CHECK_CTRLf) == 0x1) {
  14967                    mpls_port->flags |= BCM_MPLS_PORT_CONTROL_WORD;
  14968               }
  14969 
  14970               if (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, PW_TERM_NUM_VALIDf)) {
  14971                    mpls_port->flags |= BCM_MPLS_PORT_COUNTED;
  14972               }
  14973 
  14974 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  14975               else if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, CLASS_IDf)) {
  14976                   mpls_port->class_id = soc_MPLS_ENTRYm_field32_get(unit, &ret_ment,
  14977                     CLASS_IDf);
  14978               }
  14979 #endif
  14980 
  14981 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)
  14982               if (soc_feature(unit, soc_feature_mpls_entropy)) {
  14983                    if (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, ENTROPY_LABEL_PRESENTf)) {
  14984                         mpls_port->flags2 |= BCM_MPLS_PORT2_INGRESS_ENTROPY_ENABLE;
  14985                    }
  14986               }
  14987               /* VCCV defines 3 control-channels */
  14988               if (soc_mem_field_valid(unit, MPLS_ENTRYm, PW_CC_TYPEf)) {
  14989                   mpls_port->vccv_type = soc_MPLS_ENTRYm_field32_get(unit, 
  14990                                        &ret_ment, PW_CC_TYPEf);
  14991               }
  14992 #endif /* defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT_SUPPORT) */
  14993               if (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 
  14994                                         DECAP_USE_EXP_FOR_PRIf) == 0x1) {
  14995                    /* MAP_PRI_AND_CNG */
  14996                    /* Use specified EXP-map to determine internal prio/color */
  14997                    mpls_port->exp_map = 
  14998                         soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, EXP_MAPPING_PTRf);
  14999                    mpls_port->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS;
  15000                    mpls_port->flags |= BCM_MPLS_PORT_INT_PRI_MAP;
  15001               } else if (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 
  15002                                                DECAP_USE_EXP_FOR_PRIf) == 0x2) {
  15003                    /* NEW_PRI_MAP_CNG */
  15004                    /* Use the specified internal priority value */
  15005                    mpls_port->int_pri = 
  15006                         soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, NEW_PRIf);
  15007                    mpls_port->flags |= BCM_MPLS_PORT_INT_PRI_SET;
  15008 
  15009                    /* Use specified EXP-map to determine internal color */
  15010                    mpls_port->exp_map = 
  15011                         soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, EXP_MAPPING_PTRf);
  15012                    mpls_port->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS;
  15013                    mpls_port->flags |= BCM_MPLS_PORT_COLOR_MAP;
  15014               } else {
  15015                    if (soc_mem_field_valid(unit, MPLS_ENTRYm,
  15016                                         TRUST_OUTER_DOT1P_PTRf)) {
  15017                         if (soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 
  15018                                                TRUST_OUTER_DOT1P_PTRf) == 
  15019                                                _BCM_TR_MPLS_PRI_CNG_MAP_NONE) {
  15020                           /*
  15021                            * Don't trust the encapsulated packet's 802.1p pri/cfi.
  15022                            * Use a fixed value for internal priority.
  15023                           */
  15024                            mpls_port->int_pri = 
  15025                                 soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, NEW_PRIf);
  15026                            mpls_port->flags |= BCM_MPLS_PORT_INT_PRI_SET;
  15027                         }
  15028                    }
  15029               }
  15030          }
  15031 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
  15032         if (soc_feature(unit, soc_feature_mpls_ecn)) {
  15033             int ecn_map_id;
  15034             int ecn_map_hw_idx;
  15035             int ret;
  15036 #if defined(BCM_TRIDENT3_SUPPORT)
  15037             if(soc_feature(unit, soc_feature_td3_style_mpls)) {
  15038                 ecn_map_hw_idx = soc_MPLS_ENTRYm_field32_get(unit, &ret_ment,
  15039                         EXP_TO_ECN_MAPPING_PTRf);
  15040             } else
  15041 #endif
  15042             {
  15043             ecn_map_hw_idx = soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, 
  15044                                                          EXP_TO_IP_ECN_MAPPING_PTRf);
  15045             }
  15046             ret = bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_idx, 
  15047                                          _BCM_XGS5_MPLS_ECN_MAP_TYPE_EXP2ECN, 
  15048                                          &ecn_map_id);
  15049             if (BCM_SUCCESS(ret)) {
  15050                 mpls_port->flags2 |= BCM_MPLS_PORT2_INGRESS_ECN_MAP;
  15051                 mpls_port->ecn_map_id = ecn_map_id;
  15052             }
  15053         }
  15054 #endif 
  15055     } else if (mpls_info->match_key[vp].flags & _BCM_MPLS_PORT_MATCH_TYPE_SHARE) {
  15056         mpls_port->criteria = BCM_MPLS_PORT_MATCH_SHARE;
  15057     } else {
  15058         mpls_port->criteria = BCM_MPLS_PORT_MATCH_NONE;
  15059     }
  15060     return rv;
  15061 }
  15062 
  15063 /*
  15064  * Function:
  15065  *      _bcm_tr_mpls_nh_drop
  15066  * Purpose:
  15067  *      Set MPLS Next-Hop based Drop setting
  15068  * Parameters:
  15069  *      unit    - (IN) Device Number
  15070  *      drop   - (IN) Drop setting
  15071  * Returns:
  15072  *      BCM_E_XXX
  15073  */
  15074 int
  15075 _bcm_tr_mpls_nh_drop(int unit, int vp, int drop) 
  15076 {
  15077     int nh_index;
  15078     ing_dvp_table_entry_t dvp;
  15079 
  15080     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
  15081     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
  15082     return soc_mem_field32_modify(unit, ING_L3_NEXT_HOPm, nh_index, DROPf, drop);
  15083 }
  15084 
  15085 /*
  15086  * Function:
  15087  *      _bcm_tr_mpls_l2vpn_source_port_set
  15088  * Purpose:
  15089  *      Set L2 VPN source Modid/port 
  15090  * Parameters:
  15091  *      unit    - (IN) Device Number
  15092  *      mpls_port     - (IN) MPLS port
  15093  * Returns:
  15094  *      BCM_E_XXX
  15095  */
  15096 STATIC int
  15097 _bcm_tr_mpls_l2vpn_source_port_set(int unit, bcm_mpls_port_t *mpls_port, source_vp_entry_t *svp)
  15098 {
  15099     int rv = BCM_E_NONE, gport_id;
  15100     bcm_module_t mod_in;
  15101     bcm_port_t port_in;
  15102     bcm_trunk_t trunk_id;
  15103 
  15104          rv = _bcm_esw_gport_resolve(unit, mpls_port->mpls_port_id, &mod_in, 
  15105                                 &port_in, &trunk_id, &gport_id);
  15106          BCM_IF_ERROR_RETURN(rv);
  15107          if (mod_in != -1) {
  15108              soc_SOURCE_VPm_field32_set(unit, svp, SRC_MODIDf, mod_in);
  15109          }
  15110          if (port_in != -1) {
  15111              soc_SOURCE_VPm_field32_set(unit, svp, SRC_PORTf, port_in);
  15112          }
  15113          return rv;
  15114 }
  15115 
  15116 /*
  15117  * Function:
  15118  *      bcmi_mpls_clear_mpls_entry_for_vp
  15119  * Purpose:
  15120  *      This function checks whether to clear MPLS entry for 
  15121  *      this vpws vp. THis could be a backup port so
  15122  *      we may not need to clean the entry as entry should be cleaned
  15123  *      only when primary port is removed.
  15124  * Parameters:
  15125  *      unit    - (IN) Device Number
  15126  *      vpn     - (IN) vpn
  15127  *      vp      - (IN) virtual port
  15128  * Returns:
  15129  *      TRUE/FALSE
  15130  */
  15131 int
  15132 bcmi_mpls_clear_mpls_entry_for_vp(int unit, bcm_vpn_t vpn, int vp)
  15133 {
  15134 
  15135     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  15136     int max_vpws_vpn, num_vp;
  15137 
  15138     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  15139     max_vpws_vpn = num_vp / 2;
  15140 
  15141     if (vpn <= max_vpws_vpn) {
  15142         /* if vp3 port is not valid then vp2 could be a primary port */
  15143         if (mpls_info->vpws_vp_map[vpn].vp3 == -1) {
  15144             /* if vp3 in invalid and vp2 is valid then vp2 is
  15145                first backup port to be created so we should
  15146                remove the mpls entry.
  15147                For all others we should not remove the mpls
  15148                label entry.
  15149              */
  15150             if (mpls_info->vpws_vp_map[vpn].vp2 == vp) {
  15151                 return 0;
  15152             } else {
  15153                 return 1;
  15154             }
  15155          } else {
  15156              if ((mpls_info->vpws_vp_map[vpn].vp2 == vp) &&
  15157                  (sal_memcmp(&mpls_info->match_key[vp],
  15158                           &mpls_info->match_key[mpls_info->vpws_vp_map[vpn].vp3],
  15159                           sizeof(_bcm_tr_mpls_match_port_info_t)))) {
  15160                  return 0;
  15161              } else {
  15162                  return 1;
  15163              }
  15164          }
  15165     }
  15166     return 0;
  15167 }
  15168 
  15169 /*
  15170  * Function:
  15171  *      _bcm_tr_mpls_vpws_vp_map_backup_port_clear
  15172  * Purpose:
  15173  *      Clear VPWS VPN member Virtual backup ports
  15174  * Parameters:
  15175  *      unit    - (IN) Device Number
  15176  *      vpn     - (IN) VPN instance ID
  15177  *      vp     - (IN) Network Virtual Port
  15178  * Returns:
  15179  *      void
  15180  */
  15181 STATIC void
  15182 _bcm_tr_mpls_vpws_vp_map_backup_port_clear(int unit, bcm_vpn_t vpn, int vp)
  15183 {
  15184     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  15185     int max_vpws_vpn, num_vp;
  15186 
  15187     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  15188     max_vpws_vpn = num_vp / 2;
  15189 
  15190     if (vpn <= max_vpws_vpn) {
  15191 
  15192         if (mpls_info->vpws_vp_map[vpn].vp_b_1 == vp) {
  15193             (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1,
  15194                         mpls_info->vpws_vp_map[vpn].vp_b_1 );
  15195             mpls_info->vpws_vp_map[vpn].vp_b_1 = -1;
  15196         } else if ( mpls_info->vpws_vp_map[vpn].vp_b_2 == vp) {
  15197             (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1,
  15198                         mpls_info->vpws_vp_map[vpn].vp_b_2 );
  15199             mpls_info->vpws_vp_map[vpn].vp_b_2 = -1;
  15200         } else if ( mpls_info->vpws_vp_map[vpn].vp_b_3 == vp) {
  15201             (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1,
  15202                         mpls_info->vpws_vp_map[vpn].vp_b_3 );
  15203             mpls_info->vpws_vp_map[vpn].vp_b_3 = -1;
  15204         } else if(mpls_info->vpws_vp_map[vpn].vp2 == vp) {
  15205             (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1,
  15206                         mpls_info->vpws_vp_map[vpn].vp2);
  15207             mpls_info->vpws_vp_map[vpn].vp2 = -1;
  15208         }
  15209     }
  15210 }
  15211 
  15212 /*
  15213  * Function:
  15214  *      bcmi_mpls_port_failover_update_is_required
  15215  * Purpose:
  15216  *      Check if update to failover entry is required at this nh index.
  15217  * Parameters:
  15218  *      unit              - (IN) Device Number
  15219  *      mpls_port         - (IN) Mpls Port Id
  15220  *      primary_nh_index  - (IN) primary next hop index
  15221  *      nh_index          - (IN) next hop index
  15222  * Returns:
  15223  *      TRUE/FALSE
  15224  */
  15225 int
  15226 bcmi_mpls_port_failover_update_is_required(int unit, bcm_mpls_port_t *mpls_port,
  15227                                  bcm_if_t primary_nh_index, bcm_if_t nh_index)
  15228 {
  15229 
  15230     if (_BCM_FAILOVER_IS_MULTI_LEVEL(mpls_port->failover_id)) {
  15231         /* in case of multicast group, we need to create entry */
  15232         if (mpls_port->failover_mc_group > 1) {
  15233             return 1;
  15234         }
  15235         /*
  15236          * if backup nh index is next to primary then create entry.
  15237          * Also make sure that primary nh is start of nh chain.
  15238          */
  15239         if (((primary_nh_index+1) == nh_index) &&
  15240             (bcmi_l3_nh_multi_count_get(unit, primary_nh_index) == 4)) {
  15241             return 1;
  15242         }
  15243         /*
  15244          *  if we are adding a backup port where primary is not in same chain
  15245          *  then backup will have chain of 4. this is case where we have
  15246          *  one separate primary and 4 other backup ports.
  15247          *  In this case, primary nh will point to double wide prot entry
  15248          *  and should have a chain of 2 nhs.
  15249          */
  15250         if ((bcmi_l3_nh_multi_count_get(unit, nh_index) == 4) &&
  15251            ((bcmi_l3_nh_multi_count_get(unit, primary_nh_index) == 2))) {
  15252             return 1;
  15253         } else {
  15254             return 0;
  15255         }
  15256     }
  15257     return 1;
  15258 }
  15259 
  15260 /*
  15261  * Function:
  15262  *      _bcm_tr_mpls_vpws_vp_map_set
  15263  * Purpose:
  15264  *      Set VPWS VPN member Virtual ports
  15265  * Parameters:
  15266  *      unit    - (IN) Device Number
  15267  *      vpn     - (IN) VPN instance ID
  15268  *      vp1     - (IN) Access Virtual Port
  15269  *      vp2     - (IN) Network Virtual Port
  15270  *      vp3     - (IN) Primary Network VPort
  15271  * Returns:
  15272  *      BCM_E_XXX
  15273  */
  15274 STATIC void
  15275 _bcm_tr_mpls_vpws_vp_map_set (int unit, bcm_vpn_t vpn, int vp1, int vp2, 
  15276                               int vp3) 
  15277 {
  15278     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  15279     int max_vpws_vpn, num_vp;
  15280 
  15281     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  15282     max_vpws_vpn = num_vp / 2;
  15283 
  15284     if ( vpn <= max_vpws_vpn ) {
  15285             mpls_info->vpws_vp_map[vpn].vp1 = vp1;
  15286             mpls_info->vpws_vp_map[vpn].vp2 = vp2;
  15287             mpls_info->vpws_vp_map[vpn].vp3 = vp3;
  15288         }
  15289 }
  15290 
  15291 /*
  15292  * Function:
  15293  *      bcmi_mpls_vpws_vp_map_backup_port_set
  15294  * Purpose:
  15295  *      Set VPWS VPN member Virtual backup ports
  15296  * Parameters:
  15297  *      unit    - (IN) Device Number
  15298  *      vpn     - (IN) VPN instance ID
  15299  *      vp     - (IN) Network Virtual Port
  15300  * Returns:
  15301  *      BCM_E_XXX
  15302  */
  15303 STATIC int
  15304 bcmi_mpls_vpws_vp_map_backup_port_set(int unit, bcm_vpn_t vpn, int vp)
  15305 {
  15306     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  15307     int max_vpws_vpn, num_vp;
  15308     if (!(soc_feature(unit, soc_feature_hierarchical_protection))) {
  15309         return BCM_E_NONE;
  15310     }
  15311 
  15312     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  15313     max_vpws_vpn = num_vp / 2;
  15314 
  15315     if (vpn <= max_vpws_vpn) {
  15316         if (mpls_info->vpws_vp_map[vpn].vp_b_1 == -1) {
  15317             mpls_info->vpws_vp_map[vpn].vp_b_1 = vp;
  15318         } else if ( mpls_info->vpws_vp_map[vpn].vp_b_2 == -1) {
  15319             mpls_info->vpws_vp_map[vpn].vp_b_2 = vp;
  15320         } else if ( mpls_info->vpws_vp_map[vpn].vp_b_3 == -1) {
  15321             mpls_info->vpws_vp_map[vpn].vp_b_3 = vp;
  15322         } else {
  15323             return BCM_E_CONFIG;
  15324         }
  15325     }
  15326     return BCM_E_NONE;
  15327 }
  15328 
  15329 /*
  15330  * Function:
  15331  *      bcmi_mpls_match_backup_ports
  15332  * Purpose:
  15333  *      Match a virtual port in VPWS VPN member Virtual backup ports
  15334  * Parameters:
  15335  *      unit    - (IN) Device Number
  15336  *      vpn     - (IN) VPN instance ID
  15337  *      vp     - (IN) Network Virtual Port
  15338  * Returns:
  15339  *      BCM_E_XXX
  15340  */
  15341 STATIC int
  15342 bcmi_mpls_match_backup_ports(int unit, bcm_vpn_t vpn, int vp)
  15343 {
  15344     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  15345     int max_vpws_vpn, num_vp;
  15346 
  15347     if (!(soc_feature(unit, soc_feature_hierarchical_protection))) {
  15348         return 0;
  15349     }
  15350 
  15351     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  15352     max_vpws_vpn = num_vp / 2;
  15353 
  15354     if (vpn <= max_vpws_vpn) {
  15355         if ((mpls_info->vpws_vp_map[vpn].vp_b_1 == vp) ||
  15356             (mpls_info->vpws_vp_map[vpn].vp_b_2 == vp) ||
  15357                 ( mpls_info->vpws_vp_map[vpn].vp_b_3 == vp)) {
  15358             return 1;
  15359         }
  15360     }
  15361     return 0;
  15362 }
  15363 
  15364 /*
  15365  * Function:
  15366  *      bcmi_mpls_update_backup_svp
  15367  * Purpose:
  15368  *      Update source vp for a backup port.
  15369  * Parameters:
  15370  *      unit    - (IN) Device Number
  15371  *      vp      - (IN) source virtual port
  15372  *      dvp     - (IN) Destination Virtual Port
  15373  * Returns:
  15374  *      BCM_E_XXX
  15375  */
  15376 STATIC int
  15377 bcmi_mpls_update_backup_svp(int unit, int vp, int dvp)
  15378 {
  15379     source_vp_entry_t svp;
  15380 
  15381     BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
  15382     if (soc_feature(unit, soc_feature_generic_dest)) {
  15383         soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp,
  15384                 DESTINATIONf, SOC_MEM_FIF_DEST_DVP, dvp);
  15385     } else {
  15386     soc_SOURCE_VPm_field32_set(unit, &svp, DVPf, dvp);
  15387     }
  15388     BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp));
  15389 
  15390     return BCM_E_NONE;
  15391 }
  15392 
  15393 /*
  15394  * Function:
  15395  *      bcmi_mpls_update_dvp_in_backup_ports
  15396  * Purpose:
  15397  *      Update destination vp for a matching backup port.
  15398  * Parameters:
  15399  *      unit     - (IN) Device Number
  15400  *      vpn      - (IN) VPN instance ID
  15401  *      dvp      - (IN) Destination Virtual Port
  15402  * Returns:
  15403  *      BCM_E_XXX
  15404  */
  15405 STATIC int
  15406 bcmi_mpls_update_dvp_in_backup_ports(int unit, bcm_vpn_t vpn, int uni_vp)
  15407 {
  15408    _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  15409     int max_vpws_vpn, num_vp;
  15410 
  15411     if (!(soc_feature(unit, soc_feature_hierarchical_protection))) {
  15412         return BCM_E_NONE;
  15413     }
  15414 
  15415     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  15416     max_vpws_vpn = num_vp / 2;
  15417 
  15418     if (uni_vp == -1) {
  15419         /* clearing the dvp from entry */
  15420         uni_vp = 0;
  15421     }
  15422 
  15423     if (vpn <= max_vpws_vpn) {
  15424         if (mpls_info->vpws_vp_map[vpn].vp_b_1 != -1) {
  15425             BCM_IF_ERROR_RETURN(bcmi_mpls_update_backup_svp(unit,
  15426                 mpls_info->vpws_vp_map[vpn].vp_b_1, uni_vp));
  15427         }
  15428 
  15429         if (mpls_info->vpws_vp_map[vpn].vp_b_2 != -1) {
  15430             BCM_IF_ERROR_RETURN(bcmi_mpls_update_backup_svp(unit,
  15431                 mpls_info->vpws_vp_map[vpn].vp_b_2, uni_vp));
  15432         }
  15433 
  15434         if (mpls_info->vpws_vp_map[vpn].vp_b_3 != -1) {
  15435             BCM_IF_ERROR_RETURN(bcmi_mpls_update_backup_svp(unit,
  15436                 mpls_info->vpws_vp_map[vpn].vp_b_3, uni_vp));
  15437         }
  15438 
  15439     }
  15440     return BCM_E_NONE;
  15441 }
  15442 
  15443 STATIC int
  15444 bcmi_mpls_failover_nhi_cleanup_check(int unit, bcm_vpn_t vpn, int incoming_vp,
  15445                               bcm_failover_t failover_id,
  15446                               bcm_if_t failover_nh_index,
  15447                               bcm_if_t primary_nh_index,
  15448                               bcm_if_t nh_index, int *cleanup)
  15449 {
  15450 
  15451     uint32 vfi, vp;
  15452     source_vp_entry_t svp;
  15453     egr_l3_next_hop_entry_t egr_nh;
  15454     int i, base_nh_index;
  15455 
  15456     if (_BCM_FAILOVER_IS_MULTI_LEVEL(failover_id)) {
  15457         /* if the primary index is the base index of multi level group,
  15458          * then its failover port should should have next nh index.
  15459          */
  15460         if ((primary_nh_index + 1) == failover_nh_index) {
  15461             base_nh_index = primary_nh_index;
  15462         } else {
  15463             base_nh_index = failover_nh_index;
  15464         }
  15465 
  15466         /*
  15467          * in case of multi level failover, all the backup links
  15468          * have to be in consecutive order.
  15469          * therefore we can check if this incoming NH is part of
  15470          * that group and vp on it is valid.
  15471          */
  15472         for (i=0 ; i<4; i++) {
  15473              BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm,
  15474                          MEM_BLOCK_ANY, base_nh_index + i, &egr_nh));
  15475              /*
  15476               * Reading dvp here and reading svp. we keep
  15477               * svp and dvp same for a particular flow.
  15478               */
  15479              if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  15480                  vp = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
  15481                          &egr_nh, MPLS__DVPf);
  15482              } else {
  15483                  vp = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
  15484                          &egr_nh, DVPf);
  15485              }
  15486 
  15487             /* Check for the validity of the VP */
  15488             if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  15489                  continue;
  15490             }
  15491 
  15492             /*
  15493              * we should have some other port than incoming to see
  15494              * if we want to delete the failover entry.
  15495              */
  15496             if (vp == incoming_vp) {
  15497                 continue;
  15498             }
  15499             _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vpn);
  15500             BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
  15501             if ((soc_SOURCE_VPm_field32_get
  15502                 (unit, &svp, ENTRY_TYPEf) != 0x1) ||
  15503                 (vfi != soc_SOURCE_VPm_field32_get(unit, &svp, VFIf))) {
  15504 
  15505                 continue;
  15506             }
  15507             /* if the incoming NH is in the range of multi
  15508              * level failover NH group then cleanup is not required.
  15509              */
  15510             if ((nh_index > base_nh_index) &&
  15511                 (nh_index < (base_nh_index + 4))) {
  15512                 *cleanup = 0;
  15513             }
  15514         }
  15515     } else {
  15516         if (failover_nh_index == nh_index) {
  15517             *cleanup = 1;
  15518         } else {
  15519             *cleanup = 0;
  15520         }
  15521     }
  15522     return BCM_E_NONE;
  15523 }
  15524 
  15525 /*
  15526  * Function:
  15527  *      _bcm_tr_mpls_vpws_vp_map_get
  15528  * Purpose:
  15529  *      Get VPWS VPN member Virtual ports
  15530  * Parameters:
  15531  *      unit    - (IN) Device Number
  15532  *      vpn     - (IN) VPN instance ID
  15533  *      vp1     - (OUT) Access Virtual Port
  15534  *      vp2     - (OUT) Network Virtual Port
  15535  *      vp3     - (OUT) Primary Network VPort.
  15536  * Returns:
  15537  *      BCM_E_XXX
  15538  */
  15539 
  15540 STATIC void
  15541 _bcm_tr_mpls_vpws_vp_map_get (int unit, bcm_vpn_t vpn, int *vp1, int *vp2,
  15542                               int *vp3) 
  15543 {
  15544     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  15545     int max_vpws_vpn, num_vp;
  15546 
  15547     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  15548     max_vpws_vpn = num_vp / 2;
  15549 
  15550     if ( vpn <= max_vpws_vpn ) {
  15551          *vp1 = mpls_info->vpws_vp_map[vpn].vp1;
  15552          *vp2 = mpls_info->vpws_vp_map[vpn].vp2;
  15553          *vp3 = mpls_info->vpws_vp_map[vpn].vp3;
  15554       }
  15555 }
  15556 
  15557 /*
  15558  * Function:
  15559  *      _bcm_tr_mpls_vpws_vp_map_get
  15560  * Purpose:
  15561  *      Clear VPWS VPN member Virtual ports
  15562  * Parameters:
  15563  *      unit    - (IN) Device Number
  15564  *      vpn     - (IN) VPN instance ID
  15565  * Returns:
  15566  *      BCM_E_XXX
  15567  */
  15568 
  15569 STATIC void
  15570 _bcm_tr_mpls_vpws_vp_map_clear (int unit, bcm_vpn_t vpn) 
  15571 {
  15572     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  15573     int max_vpws_vpn, num_vp;
  15574 
  15575     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  15576     max_vpws_vpn = num_vp / 2;
  15577 
  15578     if ( vpn <= max_vpws_vpn ) {
  15579         if (mpls_info->vpws_vp_map[vpn].vp1 != -1) {
  15580             (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, mpls_info->vpws_vp_map[vpn].vp1 );
  15581             mpls_info->vpws_vp_map[vpn].vp1 = -1;
  15582         }
  15583         if (mpls_info->vpws_vp_map[vpn].vp2 != -1) {
  15584             (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, mpls_info->vpws_vp_map[vpn].vp2 );
  15585              mpls_info->vpws_vp_map[vpn].vp2 = -1;
  15586         }
  15587         if (mpls_info->vpws_vp_map[vpn].vp3 != -1) {
  15588              mpls_info->vpws_vp_map[vpn].vp3 = -1;
  15589         }
  15590     }
  15591 }
  15592 
  15593 #if defined(BCM_TRIUMPH2_SUPPORT)
  15594 STATIC int
  15595 _bcm_mpls_source_vp_set(int unit, bcm_mpls_port_t* mpls_port, int active_vp)
  15596 {
  15597     source_vp_entry_t svp;
  15598     bcm_port_t local_port;
  15599     int value;
  15600     int rv = BCM_E_NONE;
  15601     int dscp_map_chunk = 0, ing_pri_cng_chunk = 0;
  15602     soc_mem_t port_tbl;
  15603 
  15604 #if defined(BCM_TRIDENT3_SUPPORT)
  15605     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  15606         ing_pri_cng_chunk = 64;
  15607         dscp_map_chunk = 64;
  15608     } else
  15609 #endif
  15610     {
  15611         ing_pri_cng_chunk = 16;
  15612         dscp_map_chunk = 64;
  15613     }
  15614 
  15615 
  15616     /* Sanity Checking */
  15617     if (mpls_port == NULL || active_vp < 0) {
  15618         return BCM_E_PARAM;
  15619     }
  15620 
  15621     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  15622         port_tbl = LPORT_TABm;
  15623     } else {
  15624         port_tbl = PORT_TABm;
  15625     }
  15626 
  15627     /* For Katana for each SVP set TRUST_DSCP_PTR in SOURCE_VP with
  15628      * the TRUST_DSCP_PTR of the physical port
  15629      */
  15630     if (!(mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL)) {
  15631         /* Deal with physical ports */
  15632         if (BCM_GPORT_IS_SET(mpls_port->port) && !BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  15633             if (bcm_esw_port_local_get(unit, mpls_port->port, &local_port) < 0) {
  15634                 return BCM_E_PARAM;
  15635             }
  15636         } else {
  15637             return BCM_E_PARAM;
  15638         }
  15639 
  15640         if (!SOC_PORT_VALID(unit, local_port)) {
  15641             return BCM_E_PARAM;
  15642         }
  15643 
  15644         switch(mpls_port->criteria) {
  15645         case BCM_MPLS_PORT_MATCH_PORT:
  15646         case BCM_MPLS_PORT_MATCH_PORT_VLAN:
  15647         case BCM_MPLS_PORT_MATCH_PORT_INNER_VLAN:
  15648         case BCM_MPLS_PORT_MATCH_PORT_VLAN_STACKED:
  15649         case BCM_MPLS_PORT_MATCH_VLAN:
  15650             /*  Read PORT Table */
  15651             if (!soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DSCP_PTRf) ||
  15652                 !soc_mem_field_valid(unit, port_tbl, TRUST_DOT1P_PTRf) ||
  15653                 !soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DOT1P_PTRf))  {
  15654                 return BCM_E_NONE;
  15655             }
  15656 
  15657             rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, active_vp, &svp);
  15658             if (rv < 0) {
  15659                 return rv;
  15660             }
  15661 
  15662             if (soc_feature(unit, soc_feature_dscp_map_per_port)) {
  15663                 int index_min = 0;
  15664                 /* Delete the old profile first */
  15665                 if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  15666                     value = soc_SOURCE_VPm_field32_get(unit, 
  15667                                                        &svp, 
  15668                                                        TRUST_DSCP_PTRf);
  15669                     BCM_IF_ERROR_RETURN(
  15670                         _bcm_dscp_table_entry_delete(unit, 
  15671                                                      value * dscp_map_chunk));
  15672                     
  15673                     value = soc_SOURCE_VPm_field32_get(unit, 
  15674                                                        &svp, 
  15675                                                        TRUST_DOT1P_PTRf);
  15676                     BCM_IF_ERROR_RETURN(
  15677                         _bcm_ing_pri_cng_map_entry_delete(
  15678                             unit, value * ing_pri_cng_chunk));
  15679                 }
  15680 
  15681                 /* Get dscp table profile min index */
  15682                 BCM_IF_ERROR_RETURN(
  15683                     _bcm_dscp_table_entry_range(unit, &index_min, NULL));
  15684 
  15685                 /*
  15686                  * Increase the profile ref_count 
  15687                  * If index_min is zero, means there is no reserved dscp profile
  15688                  * Otherwise need to handle specially
  15689                  */
  15690                 if (index_min == 0) {
  15691 
  15692                     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  15693                         rv = _bcm_esw_port_tab_get(unit, local_port,
  15694                                 TRUST_DSCP_PTRf,
  15695                                 &value);
  15696                     } else {
  15697                     rv = _bcm_tr2_port_tab_get(unit, local_port, 
  15698                                                TRUST_DSCP_PTRf, 
  15699                                                &value);
  15700                     }
  15701                     if (rv == BCM_E_NONE) {
  15702                         BCM_IF_ERROR_RETURN(
  15703                             _bcm_dscp_table_entry_reference(
  15704                                 unit, (value * dscp_map_chunk), 
  15705                                 dscp_map_chunk));
  15706                         soc_SOURCE_VPm_field32_set(unit, &svp, 
  15707                                                    TRUST_DSCP_PTRf, value);
  15708                     }
  15709                 } else {
  15710                     /* Create a dscp profile, copy content from phy_port */
  15711                     void    *dscp_table;
  15712                     int     alloc_size;
  15713                     void    *entries[2]; 
  15714 
  15715                     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  15716                         alloc_size = dscp_map_chunk *
  15717                                      sizeof(phb_mapping_tbl_2_entry_t);
  15718                     } else {
  15719                     alloc_size = dscp_map_chunk *
  15720                                  sizeof(dscp_table_entry_t);
  15721                     }
  15722 
  15723                     dscp_table = soc_cm_salloc(unit, alloc_size,
  15724                                                "TR2 dscp table");
  15725                     if (NULL == dscp_table) {
  15726                         return BCM_E_MEMORY;
  15727                     }
  15728                     entries[0] = dscp_table;
  15729 
  15730                     /* Read the port chunk */
  15731                     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  15732                         rv = soc_mem_read_range(unit, PHB_MAPPING_TBL_2m, MEM_BLOCK_ANY, 
  15733                                                 local_port * dscp_map_chunk,
  15734                                                 (local_port + 1) * dscp_map_chunk - 1, 
  15735                                                 dscp_table); 
  15736                     } else {
  15737                     rv = soc_mem_read_range(unit, DSCP_TABLEm, MEM_BLOCK_ANY, 
  15738                                             local_port * dscp_map_chunk,
  15739                                             (local_port + 1) * dscp_map_chunk - 1, 
  15740                                             dscp_table); 
  15741                     }
  15742 
  15743                     if (BCM_FAILURE(rv)) {
  15744                         soc_cm_sfree(unit, dscp_table);
  15745                         return rv;
  15746                     }
  15747                     /* Write the profile chunk */
  15748                     rv = _bcm_dscp_table_entry_add(unit, entries, 
  15749                                                    dscp_map_chunk, 
  15750                                                    (uint32 *)&value);
  15751                     if (BCM_FAILURE(rv)) {
  15752                         soc_cm_sfree(unit, dscp_table);
  15753                         return rv;
  15754                     }
  15755 
  15756                     soc_cm_sfree(unit, dscp_table);
  15757                     soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_DSCP_PTRf, 
  15758                                                (value / dscp_map_chunk));
  15759                 }
  15760             }
  15761 			
  15762             if (soc_feature(unit, soc_feature_color_prio_map_profile)) {
  15763                 /* Increase profile ref_count */
  15764                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  15765                     rv = _bcm_esw_port_tab_get(unit, local_port, TRUST_DOT1P_PTRf,
  15766                             &value);
  15767                 } else {
  15768                 rv = _bcm_tr2_port_tab_get(unit, local_port, TRUST_DOT1P_PTRf, 
  15769                                            &value);
  15770                 }
  15771                 if (rv == BCM_E_NONE) {
  15772                     BCM_IF_ERROR_RETURN(
  15773                         _bcm_ing_pri_cng_map_entry_reference(
  15774                             unit, (value * ing_pri_cng_chunk), 
  15775                             ing_pri_cng_chunk));
  15776                     soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_DOT1P_PTRf, 
  15777                                                value);
  15778                 }
  15779             }
  15780 
  15781             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  15782                 rv = _bcm_esw_port_tab_get(unit, local_port, TRUST_DSCP_V4f,
  15783                         &value);
  15784             } else {
  15785             rv = _bcm_tr2_port_tab_get(unit, local_port, TRUST_DSCP_V4f, 
  15786                                        &value);
  15787             }
  15788             if (rv == BCM_E_NONE) {
  15789                 soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_DSCP_V4f, value);
  15790             }
  15791             
  15792             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  15793                 rv = _bcm_esw_port_tab_get(unit, local_port, TRUST_DSCP_V6f,
  15794                         &value);
  15795             } else {
  15796             rv = _bcm_tr2_port_tab_get(unit, local_port, TRUST_DSCP_V6f, 
  15797                                        &value);
  15798             }
  15799             if (rv == BCM_E_NONE) {
  15800                 soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_DSCP_V6f, value);
  15801             }
  15802             
  15803             rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, &svp);
  15804             if (rv == BCM_E_NONE) {
  15805                 _BCM_MPLS_SVP_PROFILE_SET_USED_SET(unit, active_vp);
  15806             }
  15807             break;
  15808         default:
  15809             break;
  15810         }
  15811     }
  15812     return rv;
  15813 }
  15814 
  15815 STATIC int
  15816 _bcm_mpls_source_vp_clear(int unit, int criteria, int vp, bcm_vpn_t vpn)
  15817 {
  15818     source_vp_entry_t svp;
  15819     bcm_mpls_port_t mpls_port;
  15820     int rv = BCM_E_NONE;
  15821     int value = 0;
  15822     int dscp_map_chunk = 0, ing_pri_cng_chunk = 0;
  15823     soc_mem_t port_tbl;
  15824 #if defined(BCM_TRIDENT3_SUPPORT)
  15825     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  15826         ing_pri_cng_chunk = 64;
  15827         dscp_map_chunk = 64;
  15828     } else
  15829 #endif
  15830     {
  15831         ing_pri_cng_chunk = 16;
  15832         dscp_map_chunk = 64;
  15833     }
  15834 
  15835     if (!_BCM_MPLS_SVP_PROFILE_SET_USED_GET(unit, vp)) {
  15836         return rv;
  15837     }
  15838 
  15839     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  15840         port_tbl = LPORT_TABm;
  15841     } else {
  15842         port_tbl = PORT_TABm;
  15843     }
  15844 
  15845     /* Decrease svp DSCP&DOT1P profiles ref_count */
  15846     if ((criteria == _BCM_MPLS_PORT_MATCH_TYPE_PORT) ||
  15847         (criteria == _BCM_MPLS_PORT_MATCH_TYPE_VLAN) ||
  15848         (criteria == _BCM_MPLS_PORT_MATCH_TYPE_INNER_VLAN) ||
  15849         (criteria == _BCM_MPLS_PORT_MATCH_TYPE_VLAN_STACKED) ||
  15850         (criteria == _BCM_MPLS_PORT_MATCH_TYPE_TRUNK)) {
  15851 
  15852         /*  Read PORT Table */
  15853         if (!soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DSCP_PTRf) ||
  15854             !soc_mem_field_valid(unit, port_tbl, TRUST_DOT1P_PTRf) ||
  15855             !soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DOT1P_PTRf))  {
  15856             return BCM_E_NONE;
  15857         }
  15858 
  15859         rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp); 
  15860         if (rv < 0) {
  15861             return rv;
  15862         }
  15863         /* avoid using wrong index to delete DSCP entry
  15864          * and get error return code,  0 is not always min index for DSCP
  15865          * in some chips.
  15866          */ 
  15867         rv = _bcm_tr_mpls_port_get(unit, vpn, vp, &mpls_port);
  15868         if (rv < 0) {
  15869             return rv;
  15870         }
  15871         if (mpls_port.flags & BCM_MPLS_PORT_EGRESS_TUNNEL) {
  15872             return BCM_E_NONE;
  15873         }
  15874         if (soc_feature(unit, soc_feature_dscp_map_per_port)) {
  15875             if (soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DSCP_PTRf)) {
  15876                 value = soc_SOURCE_VPm_field32_get(unit, 
  15877                                                    &svp, 
  15878                                                    TRUST_DSCP_PTRf);
  15879                 rv = _bcm_dscp_table_entry_delete(unit, value * dscp_map_chunk);
  15880                 if (rv != BCM_E_NONE) {
  15881                     return rv;
  15882                 } else {
  15883                     rv = BCM_E_NONE;
  15884                 }
  15885             }
  15886         }
  15887         if (soc_feature(unit, soc_feature_color_prio_map_profile)) {
  15888             if (soc_mem_field_valid(unit, SOURCE_VPm, TRUST_DOT1P_PTRf)) {
  15889                 value = soc_SOURCE_VPm_field32_get(unit, 
  15890                                                    &svp, 
  15891                                                    TRUST_DOT1P_PTRf);
  15892                 rv = _bcm_ing_pri_cng_map_entry_delete(unit, 
  15893                                                        value * ing_pri_cng_chunk);
  15894                 if (rv != BCM_E_NONE) {
  15895                     return rv;
  15896                 } else {
  15897                     rv = BCM_E_NONE;
  15898                 }
  15899             } 
  15900         }
  15901         _BCM_MPLS_SVP_PROFILE_SET_USED_CLR(unit, vp);
  15902     }
  15903     return rv;
  15904 }
  15905 
  15906 /*
  15907  * Function:
  15908  *      bcm_tr_mpls_share_vp_bitmap_get
  15909  * Purpose:
  15910  *      Get shared VPs info per VPN
  15911  * Parameters:
  15912  *      unit       - (IN) Device Number
  15913  *      vpn        - (IN) VPN that shared vp belong to
  15914  *      vp_bitmap  - (OUT) shared vp bitmap
  15915  * Returns:
  15916  *      BCM_E_XXX
  15917  */
  15918 int
  15919 bcm_tr_mpls_share_vp_bitmap_get(int unit, bcm_vpn_t vpn, SHR_BITDCL *vp_bitmap)
  15920 {
  15921     vlan_xlate_entry_t *vent;
  15922     soc_mem_t mem;
  15923     int index_min = 0;
  15924     int index_max = 0;
  15925     uint8 *xlate_buf = NULL;
  15926     int buf_size = 0;
  15927     int i = 0;
  15928     int rv = BCM_E_NONE;
  15929     int vfi = -1;
  15930     int vp = -1;
  15931 
  15932     if (vpn != BCM_MPLS_VPLS_VPN_INVALID) {
  15933          _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vpn);
  15934          if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
  15935              return BCM_E_NOT_FOUND;
  15936          }
  15937     }
  15938 
  15939 #if defined(BCM_TRIDENT3_SUPPORT)
  15940     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  15941         mem = VLAN_XLATE_1_DOUBLEm;
  15942     } else
  15943 #endif
  15944     {
  15945     mem = VLAN_XLATEm;
  15946     }
  15947     index_min = soc_mem_index_min(unit, mem);
  15948     index_max = soc_mem_index_max(unit, mem);
  15949 
  15950     buf_size = SOC_MEM_TABLE_BYTES(unit, mem);
  15951     xlate_buf = soc_cm_salloc(unit, buf_size, "VLAN_XLATE buffer");
  15952     if (NULL == xlate_buf) {
  15953         return BCM_E_MEMORY;
  15954     }
  15955     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, xlate_buf);
  15956     if (rv < 0) {
  15957         soc_cm_sfree(unit, xlate_buf);
  15958         return rv;
  15959     }
  15960 
  15961     for (i = index_min; i <= index_max; i++) {
  15962         vent = soc_mem_table_idx_to_pointer(unit,
  15963             mem, vlan_xlate_entry_t *, xlate_buf, i);
  15964 
  15965         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  15966             if ((soc_mem_field32_get(unit, mem, vent, BASE_VALID_0f) == 0) ||
  15967                     (soc_mem_field32_get(unit, mem, vent, BASE_VALID_1f) == 0)) {
  15968                 continue;
  15969             }
  15970         } else {
  15971         if (soc_mem_field32_get(unit, mem, vent, VALIDf) == 0) {
  15972             continue;
  15973         }
  15974         }
  15975 
  15976         if (soc_mem_field32_get(unit, mem, vent, XLATE__MPLS_ACTIONf) != 0x1) {
  15977             continue;
  15978         }
  15979 
  15980         if (vfi != -1 && soc_mem_field32_get(unit, mem, vent, XLATE__VFIf) != vfi) {
  15981             continue;
  15982         }
  15983 
  15984         vp = soc_mem_field32_get(unit, mem, vent, XLATE__SOURCE_VPf);
  15985         SHR_BITSET(vp_bitmap, vp);
  15986     }
  15987 
  15988     (void)soc_cm_sfree(unit, xlate_buf);
  15989 
  15990     return BCM_E_NONE;
  15991 }
  15992 #endif
  15993 
  15994 /*
  15995  * Function:
  15996  *      _bcm_tr_mpls_vpws_port_add
  15997  * Purpose:
  15998  *      Add VPWS port to a VPN
  15999  * Parameters:
  16000  *      unit    - (IN) Device Number
  16001  *      vpn     - (IN) VPN instance ID
  16002  *      mpls_port - (IN/OUT) mpls port information (OUT : mpls_port_id)
  16003  * Returns:
  16004  *      BCM_E_XXX
  16005  */
  16006 
  16007 STATIC int
  16008 _bcm_tr_mpls_vpws_port_add(int unit, bcm_vpn_t vpn, bcm_mpls_port_t *mpls_port)
  16009 {
  16010     int active_vp = -1;
  16011     source_vp_entry_t svp1, svp2;
  16012     ing_dvp_table_entry_t dvp1, dvp2;
  16013     egr_l3_next_hop_entry_t egr_nh;
  16014     uint8 vp_valid_flag = 0;
  16015     bcm_port_t local_port;
  16016     int tpid_enable = 0, tpid_index;
  16017     int customer_drop=0, is_local = 0, rv = BCM_E_PARAM, nh_index = 0;
  16018     int     vp3= -1, num_vp, match_vp=0, vp3_read = -1;
  16019     source_vp_entry_t  svp3;
  16020     ing_dvp_table_entry_t     dvp3;
  16021     bcm_vpn_t  vpn_id;
  16022     int vp1=-1, vp2=-1, backup_vp2 = -1;
  16023     _bcm_mpls_old_nh_info_t old_nh_info;
  16024     int  prot_index = -1;
  16025 #ifdef BCM_ENDURO_SUPPORT
  16026     svp_disable_vlan_checks_tab_entry_t svp_disable_check;
  16027 #endif /* BCM_ENDURO_SUPPORT */
  16028     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  16029     int match_add = TRUE;
  16030     bcm_mpls_label_t vp3_match_label;
  16031     _bcm_vp_info_t vp_info;
  16032     bcm_switch_network_group_t network_group;
  16033     uint32 dest_type, dest_val;
  16034     soc_field_t dest_field = 0;
  16035     egr_dvp_attribute_entry_t  egr_dvp_attribute;
  16036 
  16037     if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm,DESTINATIONf)) {
  16038         dest_field = DESTINATIONf;
  16039     }
  16040 
  16041         network_group = mpls_port->network_group_id;
  16042         rv = _bcm_validate_splithorizon_network_group(unit,
  16043             mpls_port->flags & BCM_MPLS_PORT_NETWORK, &network_group);
  16044         BCM_IF_ERROR_RETURN(rv);
  16045         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  16046         _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn);
  16047         _bcm_vp_info_init(&vp_info);
  16048         vp_info.vp_type = _bcmVpTypeMpls;
  16049 
  16050         sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
  16051         sal_memset(&svp1, 0, sizeof(source_vp_entry_t));
  16052         sal_memset(&egr_dvp_attribute, 0,
  16053                 sizeof(egr_dvp_attribute_entry_t));
  16054         if ( vpn != BCM_MPLS_VPWS_VPN_INVALID) {
  16055 
  16056              (void) _bcm_tr_mpls_vpws_vp_map_get (unit, vpn_id,  &vp1,  &vp2, &vp3_read);
  16057              if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  16058                  if (BCM_SUCCESS(_bcm_esw_failover_mpls_check(unit,
  16059                                                               mpls_port))) {
  16060                      if (vp2 == -1 && vp1 != -1 && vp3_read != -1) {
  16061                          /* Add new primary port: failover port should be set into vp2  */
  16062                          vp2 = vp3_read;
  16063                          vp3_read = -1;
  16064                          _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1,
  16065                                                       vp2, vp3_read);
  16066                      }
  16067                  }
  16068              }
  16069              backup_vp2 = vp2;
  16070             /* ---- Read in current table values for VP1 and VP2 ----- */
  16071             if (vp1 != -1) {
  16072                 BCM_IF_ERROR_RETURN (
  16073                    READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp1, &svp1));
  16074                 if (soc_SOURCE_VPm_field32_get(unit, &svp1, ENTRY_TYPEf) != 0) {
  16075                     vp_valid_flag |= 0x1;  /* -- VP1 Valid ----- */
  16076                 }
  16077                 BCM_IF_ERROR_RETURN (
  16078                    READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp1, &dvp1));
  16079             }
  16080 
  16081             if (vp2 != -1) {
  16082                 BCM_IF_ERROR_RETURN (
  16083                    READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp2, &svp2));
  16084                 if (soc_SOURCE_VPm_field32_get(unit, &svp2, ENTRY_TYPEf) != 0) {
  16085                     vp_valid_flag |= 0x2;        /* -- VP2 Valid ----- */
  16086                 }
  16087                 BCM_IF_ERROR_RETURN (
  16088                    READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp2, &dvp2));
  16089             }
  16090 
  16091             /* ---- Read in current table values for VP3 ----- */
  16092             if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  16093                 active_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id);
  16094                 if (active_vp == -1) {
  16095                    return BCM_E_PARAM;
  16096                 }
  16097                 if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(active_vp)) {
  16098                     active_vp =
  16099                         _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(active_vp);
  16100                 }
  16101                 if (!_bcm_vp_used_get(unit, active_vp, _bcmVpTypeMpls)) {
  16102                      return BCM_E_NOT_FOUND;
  16103                 }
  16104                 /* IN case of multi level failover, we can have backup
  16105                  * ports which are not vp2, but to resue the same code,
  16106                  * we will try to use them through vp2 variables.
  16107                  */
  16108                 if ((active_vp != vp1) && (active_vp != vp2)) {
  16109                     if (bcmi_mpls_match_backup_ports(unit, vpn_id, active_vp)) {
  16110 
  16111                     vp2 = active_vp;
  16112                     BCM_IF_ERROR_RETURN (
  16113                         READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp2, &svp2));
  16114 
  16115                     if (soc_SOURCE_VPm_field32_get(unit, &svp2, ENTRY_TYPEf) != 0) {
  16116                         vp_valid_flag |= 0x2;        /* -- VP2 Valid ----- */
  16117                     }
  16118                     BCM_IF_ERROR_RETURN (
  16119                        READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp2, &dvp2));
  16120                     } else {
  16121                         /* Read in current table values for VP3 */
  16122                         vp3 = active_vp;
  16123                         BCM_IF_ERROR_RETURN (
  16124                             READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp3, &dvp3));
  16125                         BCM_IF_ERROR_RETURN (
  16126                             READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp3, &svp3));
  16127                     }
  16128                 }
  16129 
  16130                 if (soc_SOURCE_VPm_field32_get(unit, &svp1, ENTRY_TYPEf) == 0) {
  16131                    vp_valid_flag |= 0x10;
  16132                 } 
  16133                 if (soc_SOURCE_VPm_field32_get(unit, &svp2, ENTRY_TYPEf) == 0) {
  16134                    vp_valid_flag |= 0x20;
  16135                 }
  16136             }
  16137         } else if (vpn == BCM_MPLS_VPWS_VPN_INVALID) {
  16138 
  16139               if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  16140                    active_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id);
  16141                    if (active_vp == -1) {
  16142                        return BCM_E_PARAM;
  16143                    }
  16144 
  16145                    if (!_bcm_vp_used_get(unit, active_vp, _bcmVpTypeMpls)) {
  16146                         return BCM_E_NOT_FOUND;
  16147                    }
  16148 
  16149                    BCM_IF_ERROR_RETURN (
  16150                              READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, active_vp, &svp2));
  16151 
  16152                    if (soc_feature(unit, soc_feature_generic_dest)) {
  16153                        dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm,
  16154                                &svp2, DESTINATIONf, &dest_type);
  16155                        if (dest_type == SOC_MEM_FIF_DEST_DVP) {
  16156                            match_vp = dest_val;
  16157                        }
  16158                    } else {
  16159                    match_vp = soc_SOURCE_VPm_field32_get(unit, &svp2, DVPf);
  16160                    }
  16161 
  16162                    soc_SOURCE_VPm_field32_set(unit, &svp2, 
  16163                                   ENTRY_TYPEf, 0x0);
  16164                    rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, &svp2);
  16165                    if (BCM_SUCCESS(rv)) {
  16166                         BCM_IF_ERROR_RETURN (
  16167                                   READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, match_vp, &svp1));
  16168                         soc_SOURCE_VPm_field32_set(unit, &svp1, 
  16169                                        ENTRY_TYPEf, 0x0);
  16170                         rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, match_vp, &svp1);
  16171                    }
  16172                    return rv;
  16173               } else {
  16174                    /* VP3 Add */
  16175                    vp_valid_flag = 0x4;
  16176               }
  16177          }
  16178 
  16179 
  16180         switch (vp_valid_flag) {
  16181 
  16182               case 0x0: /* No VP is valid */
  16183                              if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  16184                                   return BCM_E_NOT_FOUND;
  16185                              }
  16186 
  16187                              if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) {
  16188                                  if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) {
  16189                                      vp2 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id);
  16190                                      if (vp2 == -1) {
  16191                                          return BCM_E_PARAM;
  16192                                      }
  16193 
  16194                                      if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeMpls)) {
  16195                                          return BCM_E_EXISTS;
  16196                                      }
  16197                                      if (vp2 >= num_vp) {
  16198                                          return (BCM_E_BADID);
  16199                                      }
  16200                                      vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16201                                      BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp2, vp_info));
  16202                                  }
  16203                                  else {
  16204                                      vp1 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id);
  16205                                      if (vp1 == -1) {
  16206                                          return BCM_E_PARAM;
  16207                                      }
  16208 
  16209                                      if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeMpls)) {
  16210                                          return BCM_E_EXISTS;
  16211                                      }
  16212                                      if (vp1 >= num_vp) {
  16213                                          return (BCM_E_BADID);
  16214                                      }
  16215                                      vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
  16216                                      BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp1, vp_info));
  16217                                  }
  16218 
  16219                              } else {
  16220                                  /* No entries are used, allocate a new VP index for VP1 */
  16221                                  if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) {
  16222                                      /* Allocate a new VP index for VP2 */
  16223                                      vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16224                                      rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp2);
  16225                                      if (rv < 0) {
  16226                                          (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp1);
  16227                                          return rv;
  16228                                      }
  16229                                      _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp2);
  16230                                  } else {
  16231                                      vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
  16232                                      rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp1);
  16233                                      if (rv < 0) {
  16234                                          return rv;
  16235                                      }
  16236                                  }
  16237                              }
  16238 
  16239                              /*
  16240                               * This is the first port being added. If it's a network side port, it should go
  16241                               * into VP2. If it's a customer side port, it should go into VP1.
  16242                               */
  16243                              if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) {
  16244                                  active_vp = vp2;
  16245                                  vp_valid_flag = 0x2;
  16246                                  if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) {
  16247                                      BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit,
  16248                                                  MEM_BLOCK_ALL, vp2, &egr_dvp_attribute));
  16249                                  }
  16250                              } else {
  16251                                  active_vp = vp1;
  16252                                  vp_valid_flag = 1;
  16253                                  if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) {
  16254                                      BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit,
  16255                                                  MEM_BLOCK_ALL, vp1, &egr_dvp_attribute));
  16256                                  }
  16257                              }
  16258 
  16259                              sal_memset(&svp1, 0, sizeof(source_vp_entry_t));
  16260                              sal_memset(&dvp1, 0, sizeof(ing_dvp_table_entry_t));
  16261                              sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
  16262                              sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t));
  16263 
  16264                              (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3_read);
  16265                              break;
  16266 
  16267 
  16268          case 0x1:    /* Only VP1 is valid */	
  16269                              if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  16270                                   if (active_vp != vp1) {
  16271                                        return BCM_E_NOT_FOUND;
  16272                                   }
  16273                                   nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp1, 
  16274                                                                          NEXT_HOP_INDEXf);
  16275                              } else if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) {
  16276                                 vp2 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id);
  16277                                 if (vp2 == -1) {
  16278                                      return BCM_E_PARAM;
  16279                                 }
  16280 
  16281                                 if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeMpls)) {
  16282                                      return BCM_E_EXISTS;
  16283                                 }
  16284                                 if (vp2 >= num_vp) {
  16285                                      return (BCM_E_BADID);
  16286                                 }
  16287                                 if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) {
  16288                                     vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16289                                 }
  16290                                 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp2, vp_info));
  16291                                (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1,  vp2, vp3_read);
  16292 
  16293                                  active_vp = vp2;
  16294                                  vp_valid_flag = 3;
  16295                                  sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
  16296                                  sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t));
  16297 
  16298                              } else {
  16299                                  if(vp2 == -1) {
  16300 
  16301                                      if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) {
  16302                                          vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16303                                      }
  16304                                      /* Allocate a new VP index for VP2 */
  16305                                      rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp2);
  16306                                      if (rv < 0) {
  16307                                          return rv;
  16308                                      }
  16309                                      if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) {
  16310                                          _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp2);
  16311                                      }
  16312                                  }
  16313 
  16314                                  active_vp = vp2;
  16315                                  vp_valid_flag = 3;
  16316                                  sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
  16317                                  sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t));
  16318                                  (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3_read);
  16319                              }
  16320                              if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) {
  16321                                  BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit,
  16322                                              MEM_BLOCK_ALL, active_vp, &egr_dvp_attribute));
  16323                              }
  16324                              break;
  16325 
  16326 
  16327 
  16328          case 0x2: /* Only VP2 is valid */
  16329                              if (!(mpls_port->flags & BCM_MPLS_PORT_NETWORK)) {
  16330                                  /* 
  16331                                   * Since only VP2 is valid and the port being added is not a network port,
  16332                                   * it's customer side port i.e. VP1
  16333                                   */
  16334                                  if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) {
  16335                                      vp1 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id);
  16336                                      if (vp1 == -1) {
  16337                                          return BCM_E_PARAM;
  16338                                      }
  16339 
  16340                                      if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeMpls)) {
  16341                                          return BCM_E_EXISTS;
  16342                                      }
  16343                                      if (vp1 >= num_vp) {
  16344                                          return (BCM_E_BADID);
  16345                                      }
  16346                                      vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
  16347                                      BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp1, vp_info));
  16348                                      (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3_read);
  16349 
  16350                                      active_vp = vp1;
  16351                                      vp_valid_flag = 3;
  16352                                      sal_memset(&svp1, 0, sizeof(source_vp_entry_t));
  16353                                      sal_memset(&dvp1, 0, sizeof(ing_dvp_table_entry_t));
  16354                                  } else {
  16355                                      if (vp1 == -1) {
  16356                                          /* Allocate a new VP index for VP1 */
  16357                                          vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
  16358                                          rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp1);
  16359                                          if (rv < 0) {
  16360                                              return rv;
  16361                                          }
  16362                                      }
  16363 
  16364                                      active_vp = vp1;
  16365                                      vp_valid_flag = 3;
  16366                                      sal_memset(&svp1, 0, sizeof(source_vp_entry_t));
  16367                                      sal_memset(&dvp1, 0, sizeof(ing_dvp_table_entry_t));
  16368                                      (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3_read);
  16369                                  }
  16370                                  if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) {
  16371                                      BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit,
  16372                                                  MEM_BLOCK_ALL, active_vp, &egr_dvp_attribute));
  16373                                  }
  16374                              } else {
  16375                                  /* 
  16376                                   * Since only VP2 is valid and the port being
  16377                                   * added is a network port, its either existing 
  16378                                   * network port (VP2) being replaced or a 
  16379                                   * primary network port (VP3) being added.
  16380                                   */
  16381                                  if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  16382                                      /* in case of multi level protection, 
  16383                                       * we have already changed the vp2 above for 
  16384                                       * matching backup port. 
  16385                                       */
  16386                                      if (active_vp != vp2) {
  16387                                          return BCM_E_NOT_FOUND;
  16388                                      }
  16389                                      nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp2,
  16390                                              NEXT_HOP_INDEXf);
  16391                                      break;
  16392                                  }
  16393 #if defined(BCM_TRIUMPH2_SUPPORT)
  16394                                  if (soc_feature(unit, soc_feature_mpls_failover)) {
  16395                                      if (BCM_SUCCESS(_bcm_esw_failover_mpls_check(unit, mpls_port))) {
  16396 
  16397                                          if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) {
  16398                                              vp3 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id);
  16399                                              if (vp3 == -1) {
  16400                                                  return BCM_E_PARAM;
  16401                                              }
  16402 
  16403                                              if (_bcm_vp_used_get(unit, vp3, _bcmVpTypeMpls)) {
  16404                                                  return BCM_E_EXISTS;
  16405                                              }
  16406                                              if (vp3 >= num_vp) {
  16407                                                  return (BCM_E_BADID);
  16408                                              }
  16409 
  16410                                              sal_memset(&svp3, 0, sizeof(source_vp_entry_t));
  16411                                              sal_memset(&dvp3, 0, sizeof(ing_dvp_table_entry_t));
  16412                                              active_vp = vp3;
  16413 
  16414                                              /*
  16415                                               * Book keep the Primary Network VP (vp3). It's required to link to
  16416                                               * the SVP of customer side when it's created
  16417                                               */
  16418                                              (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3);
  16419                                              vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16420                                              BCM_IF_ERROR_RETURN(
  16421                                                      _bcm_vp_used_set(unit, active_vp, vp_info));
  16422                                          } else {
  16423                                              if (mpls_port->flags & BCM_MPLS_PORT_FAILOVER) {
  16424                                                  /* VP conservation */
  16425                                                  vp3 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id);
  16426                                                  if (vp3 == -1) {
  16427                                                      return BCM_E_PARAM;
  16428                                                  }
  16429                                              } else {
  16430                                                  /* allocate a new VP index */
  16431                                                  vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16432                                                  rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp3);
  16433                                                  if (vp3 == -1) {
  16434                                                      return BCM_E_PARAM;
  16435                                                  }
  16436                                                  if (rv < 0) {
  16437                                                      return rv;
  16438                                                  }
  16439                                                  _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp3);
  16440                                              }
  16441                                              sal_memset(&svp3, 0, sizeof(source_vp_entry_t));
  16442                                              sal_memset(&dvp3, 0, sizeof(ing_dvp_table_entry_t));
  16443                                              active_vp = vp3;
  16444                                              /*
  16445                                               * Book keep the Primary Network VP (vp3). It's required to link to
  16446                                               * the SVP of customer side when it's created
  16447                                               */
  16448                                              (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3);
  16449                                              vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16450                                              BCM_IF_ERROR_RETURN(
  16451                                                      _bcm_vp_used_set(unit, active_vp, vp_info));
  16452                                          }
  16453                                          if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) {
  16454                                              BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit,
  16455                                                          MEM_BLOCK_ALL, active_vp, &egr_dvp_attribute));
  16456                                          }
  16457                                      } else if (_BCM_FAILOVER_IS_MULTI_LEVEL(mpls_port->failover_id)) {
  16458                                          /* We can get another backup port here in case this is multi level failover */
  16459                                          if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) {
  16460                                              vp2 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id);
  16461                                              if (vp2 == -1) {
  16462                                                  return BCM_E_PARAM;
  16463                                              }
  16464                                              if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeMpls)) {
  16465                                                  return BCM_E_EXISTS;
  16466                                              }
  16467                                              if (vp2 >= num_vp) {
  16468                                                  return (BCM_E_BADID);
  16469                                              }
  16470                                              sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
  16471                                              sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t));
  16472                                              active_vp = vp2;
  16473                                              /* We need to update backup ports */
  16474                                              BCM_IF_ERROR_RETURN(
  16475                                                  bcmi_mpls_vpws_vp_map_backup_port_set(
  16476                                                  unit, vpn_id, vp2));
  16477                                          } else {
  16478                                              /* allocate a new VP index */
  16479                                              vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16480                                              rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp2);
  16481                                              if (vp2 == -1) {
  16482                                                  return BCM_E_PARAM;
  16483                                              }
  16484                                              if (rv < 0) {
  16485                                                  return rv;
  16486                                              }
  16487                                              _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp2);
  16488                                              sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
  16489                                              sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t));
  16490                                              active_vp = vp2;
  16491                                              vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16492                                              BCM_IF_ERROR_RETURN(
  16493                                                      _bcm_vp_used_set(unit, active_vp, vp_info));
  16494                                              BCM_IF_ERROR_RETURN(
  16495                                                  bcmi_mpls_vpws_vp_map_backup_port_set(
  16496                                                  unit, vpn_id, vp2));
  16497                                          }
  16498                                      }
  16499                                  } else 
  16500 #endif /* BCM_TRIUMPH2_SUPPORT  */
  16501                                  {
  16502                                      if (soc_feature(unit, soc_feature_mpls_software_failover) &&
  16503                                              (mpls_port->flags & BCM_MPLS_PORT_FAILOVER)) {
  16504                                          active_vp = BCM_GPORT_MPLS_PORT_ID_GET(
  16505                                                  mpls_port->failover_port_id);
  16506                                      } else {
  16507                                          if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  16508                                              return BCM_E_FULL;
  16509                                          }
  16510                                      }
  16511                                  }
  16512 
  16513                                  if (active_vp == vp1) {
  16514                                      /* Replacing VP1 */
  16515                                      nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp1,
  16516                                              NEXT_HOP_INDEXf);
  16517                                  } else if (active_vp == vp2) {
  16518                                      /* Replacing VP2 */
  16519                                      nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp2,
  16520                                              NEXT_HOP_INDEXf);
  16521                                  } else if (active_vp == vp3) {
  16522                                      nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp3,
  16523                                              NEXT_HOP_INDEXf);
  16524                                  }
  16525                              }
  16526                              break;
  16527 
  16528 
  16529               
  16530          case 0x3: /* VP1 and VP2 are valid */
  16531 #if defined(BCM_TRIUMPH2_SUPPORT)
  16532                              if (soc_feature(unit, soc_feature_mpls_failover)) {
  16533                                 if ((mpls_port->flags & BCM_MPLS_PORT_FAILOVER) &&
  16534                                     (mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  16535                                     int failover_nh_index = -1;
  16536                                     int failover_id = -1;
  16537                                     int failover_mc_group = -1;
  16538                                     if (active_vp != vp2) {
  16539                                         return BCM_E_NOT_FOUND;
  16540                                     }
  16541                                     nh_index = 
  16542                                         soc_ING_DVP_TABLEm_field32_get(
  16543                                             unit, &dvp2, NEXT_HOP_INDEXf);
  16544                                     rv = _bcm_esw_failover_prot_nhi_get(
  16545                                               unit, nh_index, &failover_id,
  16546                                               &failover_nh_index, &failover_mc_group);
  16547                                     if (BCM_SUCCESS(rv) && (failover_mc_group > 0)) {
  16548                                         rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit, vp2,
  16549                                                            nh_index, &failover_nh_index);
  16550                                         if (BCM_SUCCESS(rv) && (failover_nh_index > 0)) {
  16551                                             nh_index =  failover_nh_index;
  16552                                         }
  16553                                     } else if (BCM_SUCCESS(rv) && (failover_nh_index > 0)) {
  16554                                         nh_index = failover_nh_index;
  16555                                     }
  16556                                     break;
  16557                                 } else if (BCM_SUCCESS(_bcm_esw_failover_mpls_check(unit, mpls_port))) {
  16558                                   if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  16559                                        if (active_vp != vp3) {
  16560                                            return BCM_E_NOT_FOUND;
  16561                                        }
  16562                                        nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp3,
  16563                                                                           NEXT_HOP_INDEXf);
  16564                                   }  else if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) {
  16565                                             vp3 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id);
  16566                                             if (vp3 == -1) {
  16567                                                  return BCM_E_PARAM;
  16568                                             }
  16569 
  16570                                             if (_bcm_vp_used_get(unit, vp3, _bcmVpTypeMpls)) {
  16571                                                  return BCM_E_EXISTS;
  16572                                             }
  16573                                             if (vp3 >= num_vp) {
  16574                                                  return (BCM_E_BADID);
  16575                                             }
  16576                                             vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16577                                             BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp3, vp_info));
  16578                                             sal_memset(&svp3, 0, sizeof(source_vp_entry_t));
  16579                                             sal_memset(&dvp3, 0, sizeof(ing_dvp_table_entry_t));
  16580                                             active_vp = vp3;
  16581                                             (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3);
  16582                                             BCM_IF_ERROR_RETURN(
  16583                                                  _bcm_vp_used_set(unit, active_vp, vp_info));
  16584                                             if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) {
  16585                                                 BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit,
  16586                                                             MEM_BLOCK_ALL, active_vp, &egr_dvp_attribute));
  16587                                             }
  16588                                     } else {
  16589                                         if (mpls_port->flags & BCM_MPLS_PORT_FAILOVER) {
  16590                                             /* VP conservation */
  16591                                             vp3 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id);
  16592                                             if (vp3 == -1) {
  16593                                                 return BCM_E_PARAM;
  16594                                             }
  16595                                         } else {
  16596                                             /* allocate a new VP index */
  16597                                             vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16598                                             rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp3);
  16599                                             if (vp3 == -1) {
  16600                                                 return BCM_E_PARAM;
  16601                                             }
  16602                                             if (rv < 0) {
  16603                                                 return rv;
  16604                                             }
  16605                                             _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp3);
  16606                                         }
  16607                                         sal_memset(&svp3, 0, sizeof(source_vp_entry_t));
  16608                                         sal_memset(&dvp3, 0, sizeof(ing_dvp_table_entry_t));
  16609                                         active_vp = vp3;
  16610                                         if (!(mpls_port->flags & BCM_MPLS_PORT_FAILOVER)) {
  16611                                             (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, vp3);
  16612                                             vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16613                                             BCM_IF_ERROR_RETURN(
  16614                                                  _bcm_vp_used_set(unit, active_vp, vp_info));
  16615                                             if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) {
  16616                                                 BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit,
  16617                                                             MEM_BLOCK_ALL, active_vp, &egr_dvp_attribute));
  16618                                             }
  16619                                         }
  16620                                   }
  16621                               } else if (_BCM_FAILOVER_IS_MULTI_LEVEL(mpls_port->failover_id)) {
  16622                                   if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  16623                                        if (active_vp != vp2) {
  16624                                            return BCM_E_NOT_FOUND;
  16625                                        }
  16626                                    nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp2,
  16627                                                                       NEXT_HOP_INDEXf);
  16628                                   }  else if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) {
  16629                                         vp2 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id);
  16630                                         if (vp2 == -1) {
  16631                                              return BCM_E_PARAM;
  16632                                         }
  16633 
  16634                                         if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeMpls)) {
  16635                                              return BCM_E_EXISTS;
  16636                                         }
  16637                                         if (vp2 >= num_vp) {
  16638                                              return (BCM_E_BADID);
  16639                                         }
  16640                                         vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16641                                         BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp2, vp_info));
  16642                                         sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
  16643                                         sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t));
  16644                                         active_vp = vp2;
  16645                                         BCM_IF_ERROR_RETURN(
  16646                                              _bcm_vp_used_set(unit, active_vp, vp_info));
  16647                                         BCM_IF_ERROR_RETURN(
  16648                                             bcmi_mpls_vpws_vp_map_backup_port_set(
  16649                                             unit, vpn_id, vp2));
  16650                                   } else {
  16651                                        if (mpls_port->flags & BCM_MPLS_PORT_FAILOVER) {
  16652                                            /* VP conservation */
  16653                                            vp2 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id);
  16654                                            if (vp2 == -1) {
  16655                                                return BCM_E_PARAM;
  16656                                            }
  16657                                        } else {
  16658                                            /* allocate a new VP index */
  16659                                            vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16660                                            rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp2);
  16661                                            if (vp2 == -1) {
  16662                                                 return BCM_E_PARAM;
  16663                                            }
  16664                                            if (rv < 0) {
  16665                                                 return rv;
  16666                                            }
  16667                                            _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp2);
  16668                                        }
  16669                                        sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
  16670                                        sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t));
  16671                                        active_vp = vp2;
  16672 
  16673                                        if (!(mpls_port->flags & BCM_MPLS_PORT_FAILOVER)) {
  16674                                            vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16675                                            BCM_IF_ERROR_RETURN(
  16676                                                 _bcm_vp_used_set(unit, active_vp, vp_info));
  16677                                            BCM_IF_ERROR_RETURN(
  16678                                                 bcmi_mpls_vpws_vp_map_backup_port_set(
  16679                                                 unit, vpn_id, vp2));
  16680                                         }
  16681                                      }
  16682                                  }
  16683                              } else 
  16684 #endif /* BCM_TRIUMPH2_SUPPORT  */
  16685                              {
  16686                                  if (soc_feature(unit, soc_feature_mpls_software_failover) &&
  16687                                      (mpls_port->flags & BCM_MPLS_PORT_FAILOVER)) {
  16688                                       active_vp = BCM_GPORT_MPLS_PORT_ID_GET(
  16689                                                           mpls_port->failover_port_id);
  16690                                  } else {
  16691                                      if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  16692                                          return BCM_E_FULL;
  16693                                      }
  16694                                  }
  16695                              }
  16696 
  16697                              if (active_vp == vp1) {
  16698                                   /* Replacing VP1 */
  16699                                        nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp1,
  16700                                                                                          NEXT_HOP_INDEXf);
  16701                              }
  16702 
  16703                              else if (active_vp == vp2) {
  16704                                   /* Replacing VP2 */
  16705                                   nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp2,
  16706                                                                                          NEXT_HOP_INDEXf);
  16707                              }
  16708 
  16709                              else if (active_vp == vp3) {
  16710                                   nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp3,
  16711                                                                                          NEXT_HOP_INDEXf);
  16712                              }
  16713                              break;
  16714 
  16715 
  16716               
  16717               case 0x4: /* Only VP3 is valid - For Software based Failover purposes */
  16718                             if (soc_feature(unit, soc_feature_mpls_software_failover)) {
  16719                                  if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID) {
  16720                                       vp3 = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id);
  16721                                        if (vp3 == -1) {
  16722                                            return BCM_E_PARAM;
  16723                                        }
  16724 
  16725                                       if (_bcm_vp_used_get(unit, vp3, _bcmVpTypeMpls)) {
  16726                                            return BCM_E_EXISTS;
  16727                                       }
  16728                                       if (vp3 >= num_vp) {
  16729                                            return (BCM_E_BADID);
  16730                                       }
  16731                                       vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16732                                       BCM_IF_ERROR_RETURN(
  16733                                            _bcm_vp_used_set(unit, vp3, vp_info));
  16734                                  } else {
  16735                                            /* allocate a new VP index */
  16736                                            vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16737                                            rv = _bcm_vp_alloc(unit, 0, (num_vp - 1),
  16738                                                          1, SOURCE_VPm, vp_info, &vp3);
  16739                                            if (rv < 0) {
  16740                                                 return rv;
  16741                                            }
  16742                                            _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp3);
  16743                                  }
  16744                                  sal_memset(&svp3, 0, sizeof(source_vp_entry_t));
  16745                                  sal_memset(&dvp3, 0, sizeof(ing_dvp_table_entry_t));
  16746                                  active_vp = vp3;
  16747                                  vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  16748                                  BCM_IF_ERROR_RETURN(
  16749                                        _bcm_vp_used_set(unit, active_vp, vp_info));
  16750                              }
  16751                              break;
  16752 
  16753               case 0x12:
  16754                              if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  16755                                  if (active_vp == vp2) {
  16756                                      nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp2, 
  16757                                              NEXT_HOP_INDEXf);
  16758                                  } else if (active_vp == vp3_read) {
  16759                                      nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp3, 
  16760                                              NEXT_HOP_INDEXf);
  16761                                  } else {
  16762                                      return BCM_E_NOT_FOUND;
  16763                                  }
  16764                              }
  16765                              break;
  16766 
  16767               case 0x21:
  16768                              if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  16769                                  if (active_vp == vp1) {
  16770                                      nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp1, 
  16771                                              NEXT_HOP_INDEXf);
  16772                                  } else if (active_vp == vp3_read) {
  16773                                      nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp3, 
  16774                                              NEXT_HOP_INDEXf);
  16775                                  } else {
  16776                                      return BCM_E_NOT_FOUND;
  16777                                  }
  16778                              }
  16779                              break;
  16780 
  16781               case 0x30:
  16782                              if (soc_feature(unit, soc_feature_mpls_software_failover)) {
  16783                                   if ( vpn != BCM_MPLS_VPWS_VPN_INVALID) {
  16784                                        if (active_vp == vp2) {
  16785                                             soc_SOURCE_VPm_field32_set(unit, &svp2, 
  16786                                                            ENTRY_TYPEf, 0x2);
  16787                                             rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp2, &svp2);
  16788                                             if (BCM_SUCCESS(rv) && (vp1 != -1)) {
  16789                                                  soc_SOURCE_VPm_field32_set(unit, &svp1, 
  16790                                                                 ENTRY_TYPEf, 0x2);
  16791                                                  if (soc_feature(unit, soc_feature_generic_dest)) {
  16792                                                      soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1,
  16793                                                              DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp2);
  16794                                                  } else {
  16795                                                  soc_SOURCE_VPm_field32_set(unit, &svp1, 
  16796                                                                 DVPf, vp2);
  16797                                                  }
  16798                                                  rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp1, &svp1);
  16799                                             }
  16800                                        } else if (active_vp == vp3) {
  16801                                             soc_SOURCE_VPm_field32_set(unit, &svp3, 
  16802                                                       ENTRY_TYPEf, 0x2);
  16803 
  16804                                             if (vp1 != -1) {
  16805                                                 if (soc_feature(unit, soc_feature_generic_dest)) {
  16806                                                     soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp3,
  16807                                                             DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp1);
  16808                                                 } else {
  16809                                                 soc_SOURCE_VPm_field32_set(unit, &svp3, 
  16810                                                           DVPf, vp1);
  16811                                                 }
  16812                                             }
  16813                                             rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp3, &svp3);
  16814                                             if (BCM_SUCCESS(rv) && (vp1 != -1)) {
  16815                                                  soc_SOURCE_VPm_field32_set(unit, &svp1, 
  16816                                                        ENTRY_TYPEf, 0x2);
  16817 
  16818                                                  if (soc_feature(unit, soc_feature_generic_dest)) {
  16819                                                      soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1,
  16820                                                              DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp3);
  16821                                                  } else {
  16822                                                  soc_SOURCE_VPm_field32_set(unit, &svp1, 
  16823                                                        DVPf, vp3);
  16824                                                  }
  16825                                                  rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp1, &svp1);
  16826                                             }
  16827                                             if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  16828                                                 (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, active_vp, -1);
  16829                                             }
  16830                                        }
  16831                                   }
  16832                                   return rv;
  16833                              }
  16834                              break;
  16835 
  16836               default:
  16837                              return BCM_E_CONFIG;
  16838        }
  16839 
  16840         if (active_vp == -1) {
  16841            return BCM_E_CONFIG;
  16842         }
  16843 
  16844         if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  16845             /* Set the MPLS port ID */
  16846             BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->mpls_port_id, active_vp);
  16847         } 
  16848         if (mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) {
  16849             /* Input parameters check. */
  16850             if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, mpls_port->encap_id) &&
  16851                 !BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, mpls_port->encap_id)) {
  16852                 return (BCM_E_PARAM);
  16853             }
  16854 
  16855             /* Calculate next hop index. */
  16856             if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, mpls_port->encap_id)) {
  16857                 nh_index = mpls_port->encap_id - BCM_XGS3_EGRESS_IDX_MIN(unit);
  16858             } else {
  16859                 nh_index = mpls_port->encap_id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
  16860             }
  16861         } else {
  16862             mpls_port->encap_id = 0;
  16863         }
  16864 
  16865         switch (vp_valid_flag) {
  16866 
  16867               case 0x30:
  16868                             if (soc_feature(unit, soc_feature_vlan_xlate)) {
  16869                                 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, nh_index, &egr_nh);
  16870                                 if (rv < 0) {
  16871                                     goto vpws_cleanup;
  16872                                 }
  16873 
  16874                                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, MPLS__USE_DVP_IN_EVXLT_KEYf, 0x1);
  16875                                 rv = soc_mem_write (unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, nh_index, &egr_nh);
  16876 
  16877                                 if (rv < 0) {
  16878                                     goto vpws_cleanup;
  16879                                 }
  16880                             }
  16881                             break;
  16882 
  16883               default:
  16884                             customer_drop = (mpls_port->flags & BCM_MPLS_PORT_DROP) ? 1:0;
  16885                             rv = _bcm_tr_mpls_l2_nh_info_add(unit, mpls_port, active_vp, customer_drop, 1,
  16886                                          &nh_index, &local_port, &is_local, &old_nh_info);
  16887                             if (rv < 0) {
  16888                                 return rv;
  16889                             }
  16890 
  16891                             if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TAGGED) {
  16892                                     rv = _bcm_fb2_outer_tpid_lkup(unit, mpls_port->service_tpid, 
  16893                                                                    &tpid_index);
  16894                                     if (rv < 0) {
  16895                                         goto vpws_cleanup;
  16896                                     }
  16897                                     tpid_enable = (1 << tpid_index);
  16898                             }
  16899                             break;
  16900         }
  16901 
  16902        if (mpls_port->flags & BCM_MPLS_PORT_FAILOVER) {
  16903            rv = _bcm_esw_mpls_match_add(unit, mpls_port, 
  16904                       _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(active_vp), vpn, TRUE);
  16905            mpls_port->mpls_port_id =
  16906                 _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(mpls_port->mpls_port_id); 
  16907            mpls_port->encap_id = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_index;
  16908            if (soc_feature(unit, soc_feature_mpls_software_failover)) {
  16909                if (mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) {
  16910                    rv = soc_mem_field32_modify(unit, ING_DVP_TABLEm,
  16911                                                 active_vp, NEXT_HOP_INDEXf, nh_index);
  16912                    if (rv < 0) {
  16913                        goto vpws_cleanup;
  16914                    }
  16915 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  16916                    if (SOC_IS_TRIDENT2PLUS(unit)) {
  16917                        rv = soc_mem_field32_modify(unit, ING_DVP_2_TABLEm,
  16918                                active_vp, NEXT_HOP_INDEXf, nh_index);
  16919                    }
  16920                    if (rv < 0) {
  16921                        goto vpws_cleanup;
  16922                    }
  16923 #endif
  16924                }
  16925            }
  16926            if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  16927                (void)_bcm_tr_mpls_l2_old_nh_info_delete(
  16928                     unit, mpls_port, nh_index, &old_nh_info);
  16929            }
  16930            goto vpws_cleanup;
  16931         }
  16932 
  16933               if (active_vp == vp1) {
  16934 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
  16935                                                 defined(BCM_APACHE_SUPPORT)
  16936                   if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) ||
  16937                                                         SOC_IS_APACHE(unit)) {
  16938                       rv = _bcm_esw_add_policer_to_table(unit, 
  16939                                                mpls_port->policer_id,
  16940                                                SOURCE_VPm, 0, &svp1);
  16941                       BCM_IF_ERROR_RETURN(rv);
  16942                   }
  16943 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_APACHE_SUPPORT */
  16944                         /* Set SOURCE_VP */
  16945                         soc_SOURCE_VPm_field32_set(unit, &svp1, CLASS_IDf,
  16946                             mpls_port->if_class);
  16947                         if (soc_feature(unit,
  16948                             soc_feature_multiple_split_horizon_group)) {
  16949                             soc_SOURCE_VPm_field32_set(
  16950                                 unit, &svp1, NETWORK_GROUPf, network_group);
  16951                         } else {
  16952                             soc_SOURCE_VPm_field32_set(
  16953                                 unit, &svp1, NETWORK_PORTf,
  16954                                 (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ?
  16955                                 1 : 0);
  16956                         }
  16957                         if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TAGGED) {
  16958                              soc_SOURCE_VPm_field32_set(unit, &svp1, SD_TAG_MODEf, 1);
  16959 
  16960                              if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TPID_ENABLEf)) {
  16961                              soc_SOURCE_VPm_field32_set(unit, &svp1, TPID_ENABLEf, tpid_enable);
  16962                              }
  16963                              if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TRUST_OUTER_DOT1Pf)) {
  16964                                   soc_SOURCE_VPm_field32_set(unit, &svp1, TRUST_OUTER_DOT1Pf, 1);
  16965                              }
  16966                         } else {
  16967                              soc_SOURCE_VPm_field32_set(unit, &svp1, SD_TAG_MODEf, 0);
  16968                         }
  16969 
  16970                         if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  16971                              rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp1, &svp1);
  16972                              if (rv < 0) {
  16973                                   goto vpws_cleanup;
  16974                              }
  16975 
  16976                              if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  16977                                  uint32 svp_attrs_1[SOC_MAX_MEM_WORDS];
  16978 
  16979                                  sal_memset(svp_attrs_1, 0,
  16980                                          sizeof(uint32) * SOC_MAX_MEM_WORDS);
  16981                                  soc_SVP_ATTRS_1m_field_set(unit,
  16982                                          &svp_attrs_1, TPID_ENABLEf,
  16983                                          (uint32 *)&tpid_enable);
  16984                                  BCM_IF_ERROR_RETURN(
  16985                                          WRITE_SVP_ATTRS_1m(unit,
  16986                                              MEM_BLOCK_ALL, vp1,
  16987                                              &svp_attrs_1));
  16988                              }
  16989                              /* Link in the newly allocated next-hop entry */
  16990                             soc_ING_DVP_TABLEm_field32_set(unit, &dvp1, NEXT_HOP_INDEXf,
  16991                                                                                          nh_index);
  16992                             /* Enable DVP as Network_port */
  16993                             if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) {
  16994                                   soc_ING_DVP_TABLEm_field32_set(unit, &dvp1, NETWORK_PORTf,
  16995                                        ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) &&
  16996                                         (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ) ? 1 : 0);
  16997                             }
  16998                             if (soc_feature(unit,
  16999                                 soc_feature_multiple_split_horizon_group)) {
  17000                                 if (soc_mem_field_valid(
  17001                                     unit, ING_DVP_TABLEm, NETWORK_GROUPf)) {
  17002                                     soc_ING_DVP_TABLEm_field32_set(
  17003                                             unit, &dvp1, NETWORK_GROUPf,
  17004                                             network_group);
  17005                                 }
  17006 
  17007                                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  17008                                     rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm,
  17009                                             active_vp,
  17010                                             COMMON__DVP_NETWORK_GROUPf,
  17011                                             network_group);
  17012                                     if (rv < 0) {
  17013                                         goto vpws_cleanup;
  17014                                     }
  17015                                 }
  17016                             }
  17017 
  17018                             rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, active_vp, &dvp1);
  17019                             if (rv < 0) {
  17020                                goto vpws_cleanup;
  17021                             }
  17022                             rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp1, active_vp);
  17023                             if (rv < 0) {
  17024                                goto vpws_cleanup;
  17025                             }
  17026                          } else {
  17027 
  17028                              /* Link in the newly allocated next-hop entry to DVP */
  17029                              soc_ING_DVP_TABLEm_field32_set(unit, &dvp1, NEXT_HOP_INDEXf,
  17030                                                                                          nh_index);
  17031                             /* Enable DVP as Network_port */
  17032                             if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) {
  17033                                   soc_ING_DVP_TABLEm_field32_set(unit, &dvp1, NETWORK_PORTf,
  17034                                        ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) &&
  17035                                         (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ) ? 1 : 0);
  17036                             }
  17037 
  17038                             if (soc_feature(unit,
  17039                                 soc_feature_multiple_split_horizon_group)) {
  17040                                 if (soc_mem_field_valid(
  17041                                     unit, ING_DVP_TABLEm, NETWORK_GROUPf)) {
  17042                                     soc_ING_DVP_TABLEm_field32_set(
  17043                                             unit, &dvp1, NETWORK_GROUPf,
  17044                                             network_group);
  17045 
  17046                                 }
  17047 
  17048                                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  17049                                     rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm,
  17050                                             active_vp,
  17051                                             COMMON__DVP_NETWORK_GROUPf,
  17052                                             network_group);
  17053                                     if (rv < 0) {
  17054                                         goto vpws_cleanup;
  17055                                     }
  17056                                 }
  17057                             }
  17058 
  17059                              rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, active_vp, &dvp1);
  17060                              if (rv < 0) {
  17061                                   goto vpws_cleanup;
  17062                              }
  17063                              rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp1, active_vp);
  17064                              if (rv < 0) {
  17065                                   goto vpws_cleanup;
  17066                              }
  17067 
  17068                              /* Tie the SVP to DVP. */
  17069                              soc_SOURCE_VPm_field32_set(unit, &svp1, 
  17070                                                                                ENTRY_TYPEf, 0x2); /* VPWS */
  17071                              switch (vp_valid_flag) {
  17072                                   case 1:
  17073                                       if (soc_feature(unit, soc_feature_generic_dest)) {
  17074                                           soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1,
  17075                                                   DESTINATIONf, SOC_MEM_FIF_DEST_DVP, 0);
  17076                                       } else {
  17077                                        soc_SOURCE_VPm_field32_set(unit, &svp1, DVPf, 0);
  17078                                       }
  17079                                        break;
  17080                                   case 3:
  17081                                        if (vp3_read != -1) {
  17082                                            if (soc_feature(unit, soc_feature_generic_dest)) {
  17083                                                soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1,
  17084                                                        DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp3_read);
  17085                                            } else {
  17086                                            soc_SOURCE_VPm_field32_set(unit, &svp1, DVPf, vp3_read);
  17087                                            }
  17088                                        } else if (vp2 != -1) {
  17089                                            if (soc_feature(unit, soc_feature_generic_dest)) {
  17090                                                soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1,
  17091                                                        DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp2);
  17092                                            } else {
  17093                                            soc_SOURCE_VPm_field32_set(unit, &svp1, DVPf, vp2);
  17094                                        }
  17095                                        }
  17096                                        break;
  17097                                   default:
  17098                                        if (soc_feature(unit, soc_feature_generic_dest)) {
  17099                                            soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1,
  17100                                                    DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp1);
  17101                                        } else {
  17102                                        soc_SOURCE_VPm_field32_set(unit, &svp1, DVPf, vp1);
  17103                                        }
  17104                                        break;
  17105                              }
  17106                              if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) {
  17107                                   soc_SOURCE_VPm_field32_set(unit, &svp1, DISABLE_VLAN_CHECKSf, 1);
  17108                              }
  17109                              if (soc_mem_field_valid(unit, SOURCE_VPm, SRC_PORTf) && 
  17110                                  soc_mem_field_valid(unit, SOURCE_VPm, SRC_MODIDf)) {
  17111                                  rv = _bcm_tr_mpls_l2vpn_source_port_set(unit, mpls_port, &svp1);
  17112                              }
  17113                              if (rv < 0) {
  17114                                   goto vpws_cleanup;
  17115                              }
  17116 
  17117                              if (soc_mem_field_valid(unit, SOURCE_VPm, SVP_PROFILE_INDEXf)) {
  17118                                  if(mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) {
  17119                                      soc_SOURCE_VPm_field32_set(unit, &svp1, SVP_PROFILE_INDEXf, 3);
  17120                                  } else {
  17121                                      soc_SOURCE_VPm_field32_set(unit, &svp1, SVP_PROFILE_INDEXf, 2);
  17122                                  }
  17123                              }
  17124 
  17125                              rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp1, &svp1);
  17126                              if ((rv >= 0) && (vp_valid_flag == 3)) {
  17127                                  if (soc_feature(unit, soc_feature_generic_dest)) {
  17128                                      soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp2,
  17129                                              DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp1);
  17130                                  } else {
  17131                                   soc_SOURCE_VPm_field32_set(unit, &svp2, DVPf, vp1);
  17132                                  }
  17133                                   rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp2, &svp2);
  17134                              } else if ((rv >= 0) && (vp_valid_flag == 1)) {
  17135                                   if (vp2 != -1) {
  17136                                       rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp2, &svp2);
  17137                                   }
  17138                              }
  17139                              if ((rv >= 0) && (vp3_read != -1)) {
  17140                                  source_vp_entry_t  svp3_read;
  17141                                  sal_memset(&svp3_read, 0, sizeof(source_vp_entry_t));
  17142                                  BCM_IF_ERROR_RETURN (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp3_read, &svp3_read));
  17143                                  if (soc_feature(unit, soc_feature_generic_dest)) {
  17144                                      dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm,
  17145                                              &svp2, DESTINATIONf, &dest_type);
  17146                                      if (dest_type == SOC_MEM_FIF_DEST_DVP) {
  17147                                          if (vp1 != dest_val) {
  17148                                              rv = bcmi_td3_soc_mem_fields32_modify(unit,
  17149                                                      SOURCE_VPm, vp3_read, dest_field, vp1);
  17150                                          }
  17151                                      }
  17152                                  } else {
  17153                                  if (vp1 != soc_SOURCE_VPm_field32_get(unit, &svp3_read, DVPf)) {
  17154                                      rv = soc_mem_field32_modify(unit, SOURCE_VPm, vp3_read, DVPf, vp1);
  17155                                   }
  17156                              }
  17157                              }
  17158 
  17159                              if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  17160                                  uint32 svp_attrs_1[SOC_MAX_MEM_WORDS];
  17161 
  17162                                  sal_memset(svp_attrs_1, 0,
  17163                                          sizeof(uint32) * SOC_MAX_MEM_WORDS);
  17164                                  soc_SVP_ATTRS_1m_field_set(unit,
  17165                                          &svp_attrs_1, TPID_ENABLEf,
  17166                                          (uint32 *)&tpid_enable);
  17167                                  BCM_IF_ERROR_RETURN(
  17168                                          WRITE_SVP_ATTRS_1m(unit,
  17169                                              MEM_BLOCK_ALL, vp1,
  17170                                              &svp_attrs_1));
  17171                              }
  17172                              /* update other backup ports also here */
  17173                              bcmi_mpls_update_dvp_in_backup_ports(unit, vpn_id, vp1);
  17174 #ifdef BCM_ENDURO_SUPPORT
  17175                              if (SOC_IS_ENDURO(unit)) {
  17176                                  BCM_IF_ERROR_RETURN (
  17177                                     READ_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ANY, vp1, &svp_disable_check));
  17178                                  soc_SVP_DISABLE_VLAN_CHECKS_TABm_field32_set(unit, &svp_disable_check, DISABLE_VLAN_CHECKSf, 1); 
  17179                                  BCM_IF_ERROR_RETURN ( 
  17180                                     WRITE_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ALL, vp1, &svp_disable_check)); 
  17181                              }
  17182 #endif /* BCM_ENDURO_SUPPORT */
  17183                         }
  17184                          if (rv < 0) {
  17185                               goto vpws_cleanup;
  17186                          }
  17187               }
  17188 
  17189 
  17190 
  17191               else if (active_vp == vp2) {
  17192 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_APACHE_SUPPORT)
  17193                   if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit)) {
  17194                       rv = _bcm_esw_add_policer_to_table(unit,
  17195                                                mpls_port->policer_id,
  17196                                                SOURCE_VPm, 0, &svp2);
  17197                       BCM_IF_ERROR_RETURN(rv);
  17198                   }
  17199 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_APACHE_SUPPORT */
  17200                         /* Set SOURCE_VP */
  17201                         soc_SOURCE_VPm_field32_set(unit, &svp2, CLASS_IDf,
  17202                              mpls_port->if_class);
  17203                         if (soc_feature(unit,
  17204                             soc_feature_multiple_split_horizon_group)) {
  17205                             soc_SOURCE_VPm_field32_set(
  17206                                     unit, &svp2, NETWORK_GROUPf, network_group);
  17207                         } else {
  17208                             soc_SOURCE_VPm_field32_set(
  17209                                 unit, &svp2, NETWORK_PORTf,
  17210                                 (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ?
  17211                                 1 : 0);
  17212                         }
  17213                         if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TAGGED) {
  17214                              soc_SOURCE_VPm_field32_set(unit, &svp2, SD_TAG_MODEf, 1);
  17215 
  17216 #if defined(BCM_TRIDENT3_SUPPORT)
  17217                              if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  17218                                  uint32 svp_attrs_1[SOC_MAX_MEM_WORDS];
  17219 
  17220                                  sal_memset(svp_attrs_1, 0,
  17221                                          sizeof(uint32) * SOC_MAX_MEM_WORDS);
  17222                                  soc_SVP_ATTRS_1m_field_set(unit,
  17223                                          &svp_attrs_1, TPID_ENABLEf,
  17224                                          (uint32 *)&tpid_enable);
  17225                                  BCM_IF_ERROR_RETURN(
  17226                                          WRITE_SVP_ATTRS_1m(unit,
  17227                                              MEM_BLOCK_ALL, active_vp,
  17228                                              &svp_attrs_1));
  17229                              } else
  17230 #endif
  17231                              {
  17232                               soc_SOURCE_VPm_field32_set(unit, &svp2, TPID_ENABLEf, tpid_enable);
  17233                              }
  17234                              if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TRUST_OUTER_DOT1Pf)) {
  17235                                   soc_SOURCE_VPm_field32_set(unit, &svp2, TRUST_OUTER_DOT1Pf, 1);
  17236                              }
  17237                         } else {
  17238                              soc_SOURCE_VPm_field32_set(unit, &svp2, SD_TAG_MODEf, 0);
  17239                         }
  17240 
  17241                         if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  17242                              rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp2, &svp2);
  17243                              if (rv < 0) {
  17244                                   goto vpws_cleanup;
  17245                              }
  17246                              /* Link in the newly allocated next-hop entry */
  17247                              soc_ING_DVP_TABLEm_field32_set(unit, &dvp2, NEXT_HOP_INDEXf,
  17248                                                                                         nh_index);
  17249                             /* Enable DVP as Network_port */
  17250                             if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) {
  17251                                   soc_ING_DVP_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf,
  17252                                        ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) &&
  17253                                         (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ) ? 1 : 0);
  17254                             }
  17255                             if (soc_feature(unit,
  17256                                 soc_feature_multiple_split_horizon_group)) {
  17257                                 if (soc_mem_field_valid(
  17258                                     unit, ING_DVP_TABLEm, NETWORK_GROUPf)) {
  17259                                     soc_ING_DVP_TABLEm_field32_set(
  17260                                             unit, &dvp2, NETWORK_GROUPf,
  17261                                             network_group);
  17262 
  17263                                 }
  17264 
  17265                                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  17266                                     rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm,
  17267                                             active_vp,
  17268                                             COMMON__DVP_NETWORK_GROUPf,
  17269                                             network_group);
  17270                                     if (rv < 0) {
  17271                                         goto vpws_cleanup;
  17272                                     }
  17273                                 }
  17274                             }
  17275 
  17276                              rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, active_vp, &dvp2);
  17277                              if (rv < 0) {
  17278                                   goto vpws_cleanup;
  17279                              }
  17280                              rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp2, active_vp);
  17281                              if (rv < 0) {
  17282                                   goto vpws_cleanup;
  17283                              }
  17284                           
  17285                              if (vp3_read != -1) {
  17286                                  /*
  17287                                   * A primary network port already exists.
  17288                                   * vp2 is backup network port.
  17289                                   */
  17290                                  vp3_match_label = mpls_info->match_key[vp3_read].match_label;
  17291                                  if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL) {
  17292                                      if (vp3_match_label == mpls_port->match_label) {
  17293                                        /*
  17294                                         * If same label is used for match on primary and backup,
  17295                                         * no need to add another MPLS_ENTRY for backup
  17296                                         */
  17297                                         match_add = FALSE;
  17298                                         if(!((mpls_info->match_key[vp2].match_label == -1) ||
  17299                                             (vp3_match_label == mpls_info->match_key[vp2].match_label))){
  17300                                             /* Delete old MPLS_ENTRY, update software record*/
  17301                                             (void)_bcm_esw_mpls_match_delete(unit, vp2, TRUE);
  17302                                             mpls_info->match_key[vp2].flags =
  17303                                                 _BCM_MPLS_PORT_MATCH_TYPE_LABEL;
  17304                                             mpls_info->match_key[vp2].match_label =
  17305                                                 mpls_port->match_label;
  17306                                             mpls_info->match_key[vp2].modid = 0;
  17307                                             mpls_info->match_key[vp2].port = 0;
  17308                                         }
  17309                                     }
  17310                                  }
  17311                              }
  17312                         } else {
  17313                             /* we may have other backup ports coming up with 
  17314                              * the same label as vp2 label, So we might have 
  17315                              * to make sure that we dont update the match entry.
  17316                              */
  17317                             if ((backup_vp2 != -1) && (backup_vp2 != vp2)) {
  17318                                 if ((mpls_port->criteria == 
  17319                                     BCM_MPLS_PORT_MATCH_LABEL) &&
  17320                                      (mpls_info->match_key[backup_vp2].match_label == 
  17321                                          mpls_port->match_label)) {
  17322                                          /*
  17323                                           * If same label is used for match on other backup,
  17324                                           * no need to add another MPLS_ENTRY for backup
  17325                                           */
  17326                                          match_add = FALSE;
  17327                                      }
  17328                                  }
  17329 
  17330                              /* Link in the newly allocated next-hop entry to DVP */
  17331                              soc_ING_DVP_TABLEm_field32_set(unit, &dvp2, NEXT_HOP_INDEXf,
  17332                                                                                            nh_index);
  17333                             /* Enable DVP as Network_port */
  17334                             if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) {
  17335                                   soc_ING_DVP_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf,
  17336                                        ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) &&
  17337                                         (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ) ? 1 : 0);
  17338                             }
  17339 
  17340                             if (soc_feature(unit,
  17341                                 soc_feature_multiple_split_horizon_group)) {
  17342                                 if (soc_mem_field_valid(
  17343                                     unit, ING_DVP_TABLEm, NETWORK_GROUPf)) {
  17344                                     soc_ING_DVP_TABLEm_field32_set(
  17345                                             unit, &dvp2, NETWORK_GROUPf,
  17346                                             network_group);
  17347 
  17348                                 }
  17349 
  17350                                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  17351                                     rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm,
  17352                                             active_vp,
  17353                                             COMMON__DVP_NETWORK_GROUPf,
  17354                                             network_group);
  17355                                     if (rv < 0) {
  17356                                         goto vpws_cleanup;
  17357                                     }
  17358                                 }
  17359                             }
  17360 
  17361                              rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, active_vp, &dvp2);
  17362                              if (rv < 0) {
  17363                                   goto vpws_cleanup;
  17364                              }
  17365                              rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp2, active_vp);
  17366                              if (rv < 0) {
  17367                                   goto vpws_cleanup;
  17368                              }
  17369 
  17370                              /* Tie the SVP to DVP. If only one port is valid, point to itself */
  17371                              soc_SOURCE_VPm_field32_set(unit, &svp2, 
  17372                                             ENTRY_TYPEf, 0x2); /* VPWS */
  17373 
  17374                              if (soc_feature(unit, soc_feature_generic_dest)) {
  17375                                  soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp2,
  17376                                          DESTINATIONf, SOC_MEM_FIF_DEST_DVP,
  17377                                          (vp_valid_flag == 0x3) ? vp1 : vp2);
  17378                              } else {
  17379                              soc_SOURCE_VPm_field32_set(unit, &svp2, DVPf,
  17380                                             (vp_valid_flag == 0x3) ? vp1 : vp2);
  17381                              }
  17382                              if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) {
  17383                                   soc_SOURCE_VPm_field32_set(unit, &svp2, DISABLE_VLAN_CHECKSf, 1);
  17384                              }
  17385                              if (soc_mem_field_valid(unit, SOURCE_VPm, SRC_PORTf) && 
  17386                                  soc_mem_field_valid(unit, SOURCE_VPm, SRC_MODIDf)) {
  17387                                  rv = _bcm_tr_mpls_l2vpn_source_port_set(unit, mpls_port, &svp2);
  17388                              }
  17389                              if (rv < 0) {
  17390                                   goto vpws_cleanup;
  17391                              }
  17392 
  17393                              if (soc_mem_field_valid(unit, SOURCE_VPm, SVP_PROFILE_INDEXf)) {
  17394                                  if(mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) {
  17395                                      soc_SOURCE_VPm_field32_set(unit, &svp2, SVP_PROFILE_INDEXf, 3);
  17396                                  } else {
  17397                                      soc_SOURCE_VPm_field32_set(unit, &svp2, SVP_PROFILE_INDEXf, 2);
  17398                                  }
  17399 
  17400 
  17401                              }
  17402                              rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, &svp2);
  17403                              /* we write source_vp entry only when we create the first port or it is primary port.
  17404                                 usually primary port will be vp3, as failover needs to be created first */
  17405                              if (rv >= 0) {
  17406                                  int vp3_valid = 0;
  17407                                  if (vp_valid_flag == 0x3) {
  17408                                      if (soc_feature(unit, soc_feature_generic_dest)) {
  17409                                          dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm,
  17410                                                  &svp1, DESTINATIONf, &dest_type);
  17411                                          if (dest_type == SOC_MEM_FIF_DEST_DVP) {
  17412                                              vp3 = dest_val;
  17413                                          }
  17414                                      } else {
  17415                                  vp3 = soc_SOURCE_VPm_field32_get(unit, &svp1, DVPf);
  17416                                  }
  17417                                  }
  17418                                  else if (vp3_read != -1) {
  17419                                      vp3 = vp3_read;
  17420                                  }
  17421                                  if ((vp3 != -1) && (_bcm_vp_used_get(unit, vp3, _bcmVpTypeMpls))) {
  17422                                      vp3_valid = 1;
  17423                                  }
  17424                                  if (!vp3_valid || (vp3_valid &&
  17425                                      BCM_SUCCESS(_bcm_esw_failover_mpls_check(unit, mpls_port)))) {
  17426                                      if (vp_valid_flag == 0x3) {
  17427                                          if (soc_feature(unit, soc_feature_generic_dest)) {
  17428                                              soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1,
  17429                                                      DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp2);
  17430                                          } else {
  17431                                     soc_SOURCE_VPm_field32_set(unit, &svp1, DVPf, vp2);
  17432                                          }
  17433                                     if (vp1 != -1) {
  17434                                         rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp1, &svp1);
  17435                                         }
  17436                                      }
  17437                                  } else {
  17438                                      rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp3, &dvp3);
  17439                                      prot_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp3,
  17440                                                                                      NEXT_HOP_INDEXf);
  17441 
  17442                                      if (bcmi_mpls_port_failover_update_is_required
  17443                                          (unit, mpls_port, prot_index, nh_index)) {
  17444                                          /* if user does not send any if id then he might
  17445                                           * want to use the same NH as prot NH.
  17446                                           * that way next 3 NHs are used as backup NHs.
  17447                                           * other option is that he might be sending mc group,
  17448                                           * but in that case we will not even use failover_if_id.
  17449                                           */
  17450 
  17451                                      rv = _bcm_esw_failover_prot_nhi_create
  17452                                          (unit, 0, (uint32)prot_index,
  17453                                          nh_index, mpls_port->failover_mc_group,
  17454                                           mpls_port->failover_id);
  17455 
  17456                                     }
  17457                                  }
  17458 
  17459                              }
  17460                              if (rv < 0) {
  17461                                   goto vpws_cleanup;
  17462                              }
  17463 #ifdef BCM_ENDURO_SUPPORT
  17464                              if (SOC_IS_ENDURO(unit)) {
  17465                                  BCM_IF_ERROR_RETURN ( 
  17466                                     READ_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ANY, active_vp, &svp_disable_check)); 
  17467                                  soc_SVP_DISABLE_VLAN_CHECKS_TABm_field32_set(unit, &svp_disable_check, DISABLE_VLAN_CHECKSf, 1); 
  17468                                  BCM_IF_ERROR_RETURN ( 
  17469                                      WRITE_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ALL, active_vp, &svp_disable_check)); 
  17470                              }
  17471 #endif /* BCM_ENDURO_SUPPORT */
  17472                         }
  17473               }
  17474 
  17475 
  17476 
  17477               else if (active_vp == vp3) {
  17478 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_APACHE_SUPPORT)
  17479                   if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit)) {
  17480                       rv = _bcm_esw_add_policer_to_table(unit,
  17481                                                mpls_port->policer_id,
  17482                                                SOURCE_VPm, 0, &svp3);
  17483                       BCM_IF_ERROR_RETURN(rv);
  17484                   }
  17485 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_APACHE_SUPPORT */
  17486                         /* Set SOURCE_VP */
  17487                         soc_SOURCE_VPm_field32_set(unit, &svp3, CLASS_IDf,
  17488                                             mpls_port->if_class);
  17489                         if (soc_feature(unit,
  17490                             soc_feature_multiple_split_horizon_group)) {
  17491                             soc_SOURCE_VPm_field32_set(
  17492                                     unit, &svp3, NETWORK_GROUPf, network_group);
  17493                         } else {
  17494                             soc_SOURCE_VPm_field32_set(
  17495                                 unit, &svp3, NETWORK_PORTf,
  17496                                 (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ?
  17497                                 1 : 0);
  17498                         }
  17499                         if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TAGGED) {
  17500                              soc_SOURCE_VPm_field32_set(unit, &svp3, 
  17501                                             SD_TAG_MODEf, 1);
  17502 
  17503 #if defined(BCM_TRIDENT3_SUPPORT)
  17504                              if (SOC_IS_TRIDENT3X(unit)) {
  17505                                  uint32 svp_attrs_1[SOC_MAX_MEM_WORDS];
  17506 
  17507                                  sal_memset(svp_attrs_1, 0,
  17508                                          sizeof(uint32) * SOC_MAX_MEM_WORDS);
  17509                                  soc_SVP_ATTRS_1m_field_set(unit,
  17510                                          &svp_attrs_1, TPID_ENABLEf,
  17511                                          (uint32 *)&tpid_enable);
  17512                                  BCM_IF_ERROR_RETURN(
  17513                                          WRITE_SVP_ATTRS_1m(unit,
  17514                                              MEM_BLOCK_ALL, active_vp,
  17515                                              &svp_attrs_1));
  17516                              } else
  17517 #endif
  17518                              {
  17519                              soc_SOURCE_VPm_field32_set(unit, &svp3, 
  17520                                             TPID_ENABLEf, tpid_enable);
  17521                              }
  17522                              if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TRUST_OUTER_DOT1Pf)) {
  17523                                   soc_SOURCE_VPm_field32_set(unit, &svp3, TRUST_OUTER_DOT1Pf, 1);
  17524                              }
  17525                         } else {
  17526                              soc_SOURCE_VPm_field32_set(unit, &svp3, 
  17527                                             SD_TAG_MODEf, 0);
  17528                         }
  17529                         if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  17530                              rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp3, &svp3);
  17531                              if (rv < 0) {
  17532                                   goto vpws_cleanup;
  17533                              }
  17534                              /* Link in the newly allocated next-hop entry */
  17535                              soc_ING_DVP_TABLEm_field32_set(unit, &dvp3, 
  17536                                        NEXT_HOP_INDEXf, nh_index);
  17537                             /* Enable DVP as Network_port */
  17538                             if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) {
  17539                                   soc_ING_DVP_TABLEm_field32_set(unit, &dvp3, NETWORK_PORTf,
  17540                                        ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) &&
  17541                                         (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ) ? 1 : 0);
  17542                             }
  17543 
  17544                             if (soc_feature(unit,
  17545                                 soc_feature_multiple_split_horizon_group)) {
  17546                                 if (soc_mem_field_valid(
  17547                                     unit, ING_DVP_TABLEm, NETWORK_GROUPf)) {
  17548                                     soc_ING_DVP_TABLEm_field32_set(
  17549                                         unit, &dvp3, NETWORK_GROUPf, network_group);
  17550                                }
  17551 
  17552                                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  17553                                     rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm,
  17554                                             active_vp,
  17555                                             COMMON__DVP_NETWORK_GROUPf,
  17556                                             network_group);
  17557                                     if (rv < 0) {
  17558                                         goto vpws_cleanup;
  17559                                     }
  17560                                 }
  17561                             }
  17562 
  17563                              rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, 
  17564                                        active_vp, &dvp3);
  17565                              if (rv < 0) {
  17566                                   goto vpws_cleanup;
  17567                              }
  17568                              rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp3, active_vp);
  17569                              if (rv < 0) {
  17570                                  goto vpws_cleanup;
  17571                              }
  17572 
  17573                         } else {
  17574                              /* Link in the newly allocated next-hop entry to DVP */
  17575                              soc_ING_DVP_TABLEm_field32_set(unit, &dvp3, 
  17576                                             NEXT_HOP_INDEXf, nh_index);
  17577                             /* Enable DVP as Network_port */
  17578                             if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) {
  17579                                   soc_ING_DVP_TABLEm_field32_set(unit, &dvp3, NETWORK_PORTf,
  17580                                        ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) &&
  17581                                         (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ) ? 1 : 0);
  17582                             }
  17583 
  17584                             if (soc_feature(unit,
  17585                                 soc_feature_multiple_split_horizon_group)) {
  17586                                 if (soc_mem_field_valid(
  17587                                     unit, ING_DVP_TABLEm, NETWORK_GROUPf)) {
  17588                                     soc_ING_DVP_TABLEm_field32_set(
  17589                                         unit, &dvp3, NETWORK_GROUPf, network_group);
  17590                                 }
  17591 
  17592                                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  17593                                     rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm,
  17594                                             active_vp,
  17595                                             COMMON__DVP_NETWORK_GROUPf,
  17596                                             network_group);
  17597                                     if (rv < 0) {
  17598                                         goto vpws_cleanup;
  17599                                     }
  17600                                 }
  17601                             }
  17602 
  17603                              rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, 
  17604                                             active_vp, &dvp3);
  17605                              if (rv < 0) {
  17606                                   goto vpws_cleanup;
  17607                              }
  17608                              rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp3, active_vp);
  17609                              if (rv < 0) {
  17610                                  goto vpws_cleanup;
  17611                              }
  17612 
  17613                              if (vpn == BCM_MPLS_VPWS_VPN_INVALID) {
  17614                                   /* Set SVP Invalid */
  17615                                   soc_SOURCE_VPm_field32_set(unit, &svp3, 
  17616                                                       ENTRY_TYPEf, 0x0);
  17617                              } else {
  17618                                   /* Set SVP Valid */
  17619                                   soc_SOURCE_VPm_field32_set(unit, &svp3, 
  17620                                                       ENTRY_TYPEf, 0x2);
  17621                                   /* Tie SVP to DVP. */
  17622                                   if (vp1 != -1) {
  17623                                       if (soc_feature(unit, soc_feature_generic_dest)) {
  17624                                           soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp3,
  17625                                               DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp1);
  17626                                       } else {
  17627                                       soc_SOURCE_VPm_field32_set(unit, &svp3, DVPf, vp1);
  17628                                   }
  17629                              }
  17630                              }
  17631                              if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) {
  17632                                   soc_SOURCE_VPm_field32_set(unit, &svp3, DISABLE_VLAN_CHECKSf, 1);
  17633                              }
  17634                              if (soc_mem_field_valid(unit, SOURCE_VPm, SRC_PORTf) && 
  17635                                  soc_mem_field_valid(unit, SOURCE_VPm, SRC_MODIDf)) {
  17636                                  rv = _bcm_tr_mpls_l2vpn_source_port_set(unit, mpls_port, &svp3);
  17637                              }
  17638                              if (rv < 0) {
  17639                                   goto vpws_cleanup;
  17640                              }
  17641 
  17642                              if (soc_mem_field_valid(unit, SOURCE_VPm, SVP_PROFILE_INDEXf)) {
  17643                                  if(mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) {
  17644                                      soc_SOURCE_VPm_field32_set(unit, &svp3, SVP_PROFILE_INDEXf, 3);
  17645                                  } else {
  17646                                      soc_SOURCE_VPm_field32_set(unit, &svp3, SVP_PROFILE_INDEXf, 2);
  17647                                  }
  17648 
  17649                              }
  17650                              rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, 
  17651                                             active_vp, &svp3);
  17652                              if ((rv >= 0) && (vp_valid_flag == 0x3)) {
  17653                                  if (soc_feature(unit, soc_feature_generic_dest)) {
  17654                                      soc_mem_field32_dest_set(unit, SOURCE_VPm, &svp1,
  17655                                              DESTINATIONf, SOC_MEM_FIF_DEST_DVP, vp3);
  17656                                  } else {
  17657                                   soc_SOURCE_VPm_field32_set(unit, &svp1, DVPf, vp3);
  17658                                  }
  17659                                   rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp1, &svp1);
  17660                              }
  17661                              if (rv < 0) {
  17662                                   goto vpws_cleanup;
  17663                              }
  17664 #ifdef BCM_ENDURO_SUPPORT
  17665                              if (SOC_IS_ENDURO(unit)) {
  17666                                  BCM_IF_ERROR_RETURN ( 
  17667                                     READ_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ANY, active_vp, &svp_disable_check)); 
  17668                                  soc_SVP_DISABLE_VLAN_CHECKS_TABm_field32_set(unit, &svp_disable_check, DISABLE_VLAN_CHECKSf, 1); 
  17669                                  BCM_IF_ERROR_RETURN ( 
  17670                                     WRITE_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ALL, active_vp, &svp_disable_check)); 
  17671                             }
  17672 #endif /* BCM_ENDURO_SUPPORT */
  17673                         }
  17674 
  17675               }
  17676 
  17677 #if defined(BCM_TRIUMPH2_SUPPORT)
  17678             if (soc_feature(unit, soc_feature_mpls_failover)) {
  17679                 int failover_vp = 0;
  17680                 bcm_mpls_port_t   failover_mpls_port;
  17681 
  17682                 if (BCM_SUCCESS(_bcm_esw_failover_mpls_check(unit, mpls_port))) {
  17683 
  17684                     failover_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id);
  17685 
  17686                     if (failover_vp >= 0) {
  17687                         if (!_bcm_vp_used_get(unit, failover_vp, _bcmVpTypeMpls)) {
  17688                             rv = BCM_E_NOT_FOUND;
  17689                             goto vpws_cleanup;
  17690                         }
  17691                         rv = _bcm_esw_mpls_match_get(unit,  &failover_mpls_port, failover_vp);
  17692                         if ( rv < 0 ) {
  17693                             if (rv != BCM_E_NOT_FOUND) {
  17694                                 goto vpws_cleanup;
  17695                             }
  17696                         }
  17697                         if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL_PORT) {
  17698                             if ((mpls_port->match_label == failover_mpls_port.match_label) &&
  17699                                 (mpls_port->port == failover_mpls_port.port)) {
  17700 
  17701                                 /*
  17702                                  * Replace failover_vp with Primary vp, keep software record
  17703                                  * for get operation.
  17704                                  */
  17705                                 rv = _bcm_esw_mpls_match_delete(unit, failover_vp, FALSE);
  17706                             }
  17707                         } else if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL) {
  17708                             if (mpls_port->match_label == failover_mpls_port.match_label) {
  17709                                 /*
  17710                                  * Replace failover_vp with Primary vp, keep software record
  17711                                  * for get operation.
  17712                                  */
  17713                                 rv = _bcm_esw_mpls_match_delete(unit, failover_vp, FALSE);
  17714                             }
  17715                         }
  17716                     }
  17717                 }
  17718             }
  17719 #endif /* BCM_TRIUMPH2_SUPPORT  */
  17720 
  17721          if (soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, MTU_VALUEf) ||
  17722                          soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, COMMON__MTU_VALUEf)) {
  17723             rv = _bcm_tr_mpls_port_mtu_set(unit, active_vp, mpls_port->mtu);
  17724              if (rv < 0) {
  17725                   goto vpws_cleanup;
  17726              }
  17727          }
  17728 
  17729          /*CMH SVP ATTRIBUTES*/
  17730          if (soc_feature(unit,soc_feature_td3_style_mpls)) {
  17731              int entry_type = 2;
  17732              rv = bcmi_cmh_svp_attributes_set(unit, entry_type, active_vp,
  17733                      TRUE, mpls_port->flags);
  17734              if (rv < 0) {
  17735                  goto vpws_cleanup;
  17736              }
  17737          }
  17738 
  17739          if (TRUE == match_add) {
  17740             rv = _bcm_esw_mpls_match_add(unit, mpls_port, active_vp, vpn, TRUE);
  17741          }
  17742 
  17743             /* Set the MPLS port ID */
  17744             if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  17745                 BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->mpls_port_id, active_vp);
  17746                 mpls_port->encap_id = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_index;
  17747             }
  17748 #if defined(BCM_TRIUMPH2_SUPPORT)
  17749             if (!BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  17750                 if (!(mpls_port->flags2 & BCM_MPLS_PORT2_QOS_NONE)) {
  17751                 _bcm_mpls_source_vp_set(unit, mpls_port, active_vp);
  17752             }
  17753             }
  17754 #endif
  17755 
  17756         /* Free the old next-hop entry. */
  17757         if (vp_valid_flag != 0x30) {
  17758             (void)_bcm_tr_mpls_l2_old_nh_info_delete(unit, mpls_port, nh_index,
  17759                                                      &old_nh_info);
  17760         }
  17761 
  17762 vpws_cleanup:
  17763         if (rv < 0) {
  17764 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
  17765                                                     defined(BCM_APACHE_SUPPORT)
  17766             if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) ||
  17767                                             SOC_IS_APACHE(unit)) {
  17768                 _bcm_esw_reset_policer_from_table(unit, 
  17769                                               mpls_port->policer_id, 
  17770                                               SOURCE_VPm, active_vp, &svp1); 
  17771             }
  17772 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_APACHE_SUPPORT */
  17773             if (tpid_enable) {
  17774                 (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
  17775             }
  17776 
  17777             if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  17778                 (void) _bcm_tr_mpls_l2_nh_info_delete(unit, nh_index);
  17779             
  17780                 /* Free the VP's */
  17781                 if (vp_valid_flag) {
  17782                     if (vp1 == active_vp) {
  17783                         (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp1);
  17784                         if (vpn != BCM_MPLS_VPWS_VPN_INVALID) {
  17785                             (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, -1, vp2, vp3_read);
  17786                     }
  17787                     }
  17788                     if (vp2 == active_vp) {
  17789                         (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp2);
  17790                         _BCM_MPLS_NETWORK_VP_USED_CLR(unit, vp2);
  17791                         if (vpn != BCM_MPLS_VPWS_VPN_INVALID) {
  17792                             (void) _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, -1, vp3_read);
  17793                     }                 
  17794                 }
  17795             }
  17796             }
  17797 
  17798             return rv;
  17799         }
  17800 
  17801         return rv;
  17802 }
  17803 
  17804 /*
  17805  * Function:
  17806  *     _bcm_tr_mpls_vpls_port_add
  17807  * Purpose:
  17808  *      Add VPLS port to a VPN
  17809  * Parameters:
  17810  *   unit - (IN) Device Number
  17811  *   vpn - (IN) VPN instance ID
  17812  *   mpls_port - (IN/OUT) mpls port information (OUT : mpls_port_id)
  17813  * Returns:
  17814  *     BCM_E_XXX
  17815  */
  17816 
  17817 STATIC int
  17818 _bcm_tr_mpls_vpls_port_add(int unit, bcm_vpn_t vpn, bcm_mpls_port_t *mpls_port)
  17819 {
  17820     int vp, num_vp, vfi = 0;
  17821     source_vp_entry_t svp;
  17822     ing_dvp_table_entry_t dvp;
  17823 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \
  17824     || defined(BCM_TRIDENT_SUPPORT)
  17825     ing_dvp_2_table_entry_t dvp2;
  17826 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */
  17827     ing_l3_next_hop_entry_t ing_nh;
  17828     int modid_local=0, module_id, is_trunk=0;
  17829     bcm_port_t local_port;
  17830     bcm_trunk_t trunk_id = -1;
  17831     int tpid_enable = 0, tpid_index;
  17832     int drop, is_local = 0, rv = BCM_E_PARAM, nh_index = 0;
  17833     int cml_default_enable=0, cml_default_new=0, cml_default_move=0;
  17834     _bcm_mpls_old_nh_info_t old_nh_info;
  17835 #ifdef BCM_ENDURO_SUPPORT
  17836     svp_disable_vlan_checks_tab_entry_t svp_disable_check;
  17837 #endif /* BCM_ENDURO_SUPPORT */
  17838     int entry_update = TRUE;
  17839     _bcm_vp_info_t vp_info;
  17840     bcm_switch_network_group_t network_group;
  17841     uint32 dest_type, dest_val;
  17842     int port_in = 0;
  17843     egr_dvp_attribute_entry_t  egr_dvp_attribute;
  17844 
  17845 #ifdef BCM_TRIUMPH2_SUPPORT
  17846     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  17847     uint32 old_failover_vp = 0;
  17848 #endif
  17849     _bcm_vp_info_init(&vp_info);
  17850     vp_info.vp_type = _bcmVpTypeMpls;
  17851 
  17852     if (mpls_port->criteria != BCM_MPLS_PORT_MATCH_SHARE) {
  17853         if ( vpn != BCM_MPLS_VPLS_VPN_INVALID) {
  17854             _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vpn);
  17855             if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
  17856                 return BCM_E_NOT_FOUND;
  17857             }
  17858         } else {
  17859             vfi = 0x3FF;
  17860         }
  17861     }
  17862 
  17863     sal_memset(&egr_dvp_attribute, 0,
  17864             sizeof(egr_dvp_attribute_entry_t));
  17865     if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  17866         vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id);
  17867 
  17868         if (vp == -1) {
  17869             return BCM_E_PARAM;
  17870         }
  17871 
  17872         if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) {
  17873             vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp);
  17874         }
  17875 
  17876         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  17877             return BCM_E_NOT_FOUND;
  17878         }
  17879         rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
  17880         if (rv < 0) {
  17881             return rv;
  17882         }
  17883         rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp);
  17884         if (rv < 0) {
  17885             return rv;
  17886         }
  17887         nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 
  17888                                                   NEXT_HOP_INDEXf);
  17889         if (soc_feature(unit, soc_feature_mpls_software_failover)) {        
  17890            /* VP Detach */
  17891            if ((soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0x1) && 
  17892                                         (vpn == BCM_MPLS_VPLS_VPN_INVALID)){
  17893              soc_SOURCE_VPm_field32_set(unit, &svp, ENTRY_TYPEf, 0x0);
  17894              BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 
  17895                                                MEM_BLOCK_ANY, nh_index, &ing_nh));             
  17896              /* Set Drop */
  17897              soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, 0x1); 
  17898              BCM_IF_ERROR_RETURN(soc_mem_write (unit, ING_L3_NEXT_HOPm, 
  17899                                         MEM_BLOCK_ALL, nh_index, &ing_nh));
  17900              rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
  17901              return rv;
  17902            }
  17903      
  17904            /* VP Attach */
  17905            if ((soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0x0) && 
  17906                                         (vpn != BCM_MPLS_VPLS_VPN_INVALID)){
  17907              soc_SOURCE_VPm_field32_set(unit, &svp, ENTRY_TYPEf, 0x1);
  17908              BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 
  17909                                                MEM_BLOCK_ANY, nh_index, &ing_nh));             
  17910              /* Reset Drop */
  17911              soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, 0x0); 
  17912              BCM_IF_ERROR_RETURN(soc_mem_write (unit, ING_L3_NEXT_HOPm, 
  17913                                         MEM_BLOCK_ALL, nh_index, &ing_nh));
  17914              if (mpls_port->criteria != BCM_MPLS_PORT_MATCH_SHARE) {
  17915                 soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, vfi);
  17916                 _bcm_vp_vfi_set(unit, vp, vpn);
  17917              } 
  17918              rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
  17919              return rv;
  17920            }
  17921         }
  17922 
  17923     } else if (mpls_port->flags & BCM_MPLS_PORT_WITH_ID ) {
  17924         int vpless_port = FALSE;
  17925         if (!BCM_GPORT_IS_MPLS_PORT(mpls_port->mpls_port_id)) {
  17926             return (BCM_E_BADID);
  17927         }
  17928 
  17929         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  17930         vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id);
  17931         if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) {
  17932             vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp);
  17933             vpless_port = TRUE;
  17934         }
  17935 
  17936         if (vp == -1) {
  17937             return BCM_E_PARAM;
  17938         }
  17939 
  17940         if (vp >= num_vp) {
  17941             return (BCM_E_BADID);
  17942         }
  17943 
  17944         if ((vpn != BCM_MPLS_VPLS_VPN_INVALID) && (!vpless_port)) {
  17945             if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  17946                 return BCM_E_EXISTS;
  17947             }
  17948         }
  17949 
  17950         if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) {
  17951             vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  17952         } else {
  17953             vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
  17954         }
  17955 
  17956         BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info));
  17957 
  17958         /* ------------  SW Failover - Applicable for TRIUMPH/VL only ---- */
  17959         if (soc_feature(unit, soc_feature_mpls_software_failover)) {
  17960 
  17961             if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  17962                 return BCM_E_NOT_FOUND;
  17963             }
  17964             rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
  17965             if (rv < 0) {
  17966                 return rv;
  17967             }
  17968             rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp);
  17969             if (rv < 0) {
  17970                 return rv;
  17971             }
  17972             nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
  17973             if ((nh_index != 0)  &&  (nh_index < soc_mem_index_count(unit, ING_L3_NEXT_HOPm))) {
  17974                BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 
  17975                                                            MEM_BLOCK_ANY, nh_index, &ing_nh));
  17976 
  17977 
  17978                if (soc_feature(unit, soc_feature_generic_dest)) {
  17979                    dest_val = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm,
  17980                            &ing_nh, DESTINATIONf, &dest_type);
  17981                    if (dest_type == SOC_MEM_FIF_DEST_LAG) {
  17982                        /* Trunk group */
  17983                        trunk_id = dest_val & SOC_MEM_FIF_DGPP_TGID_MASK;
  17984                        is_trunk = 1;
  17985 
  17986                    } else {
  17987                        port_in   = dest_val & SOC_MEM_FIF_DGPP_PORT_MASK;
  17988                        module_id = (dest_val & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
  17989                            SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
  17990                    }
  17991 
  17992                    if (!is_trunk) {
  17993                        BCM_IF_ERROR_RETURN
  17994                            ( _bcm_esw_modid_is_local(unit, module_id, &modid_local));
  17995                    }
  17996                    if (modid_local) {
  17997                        local_port = port_in;
  17998                    } else if (is_trunk) {
  17999                        BCM_GPORT_TRUNK_SET(local_port, trunk_id);
  18000                    }
  18001                } else {
  18002                module_id = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 
  18003                                                            &ing_nh, MODULE_IDf);
  18004                is_trunk = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, 
  18005                                                            &ing_nh, Tf);
  18006                if (!is_trunk) {
  18007                    BCM_IF_ERROR_RETURN
  18008                    ( _bcm_esw_modid_is_local(unit, module_id, &modid_local));
  18009                }
  18010                if (modid_local) {
  18011                   local_port = 
  18012                      soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, PORT_NUMf);
  18013                } else if (is_trunk) {
  18014                      trunk_id = 
  18015                        soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, TGIDf); 
  18016                      BCM_GPORT_TRUNK_SET(local_port, trunk_id);
  18017                }
  18018                }
  18019                /* VP Detach */
  18020                if ((soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0x1) && 
  18021                                             (vpn == BCM_MPLS_VPLS_VPN_INVALID)){
  18022                  soc_SOURCE_VPm_field32_set(unit, &svp, ENTRY_TYPEf, 0x0);
  18023                  /* Set Drop */
  18024                  soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, 0x1); 
  18025                  BCM_IF_ERROR_RETURN(soc_mem_write (unit, ING_L3_NEXT_HOPm, 
  18026                                             MEM_BLOCK_ALL, nh_index, &ing_nh));
  18027                  rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
  18028                  return rv;
  18029                }
  18030          
  18031                /* VP Attach */
  18032                if ((soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0x0) && 
  18033                                             (vpn != BCM_MPLS_VPLS_VPN_INVALID)){
  18034                  soc_SOURCE_VPm_field32_set(unit, &svp, ENTRY_TYPEf, 0x1);
  18035                  /* Reset Drop */
  18036                  soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, 0x0); 
  18037                  BCM_IF_ERROR_RETURN(soc_mem_write (unit, ING_L3_NEXT_HOPm, 
  18038                                             MEM_BLOCK_ALL, nh_index, &ing_nh));
  18039                  rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
  18040                  return rv;
  18041                }
  18042             }
  18043         }
  18044 
  18045         sal_memset(&svp, 0, sizeof(source_vp_entry_t));
  18046         sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t));
  18047 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \
  18048     || defined(BCM_TRIDENT_SUPPORT)
  18049         if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit) 
  18050             || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT3X(unit) ||
  18051             SOC_IS_TOMAHAWKX(unit)) {
  18052             sal_memset(&dvp2, 0, sizeof(ing_dvp_2_table_entry_t));
  18053         }
  18054 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */
  18055         /*Set EGR_DVP_ATTRIBUTE indexed by vp to zero*/
  18056         if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) {
  18057             BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit,
  18058                         MEM_BLOCK_ALL, vp, &egr_dvp_attribute));
  18059         }
  18060     } else {
  18061         if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) {
  18062             vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  18063         } else {
  18064             vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
  18065         }
  18066 
  18067         if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_SHARE) {
  18068             vp_info.flags |= _BCM_VP_INFO_SHARED_PORT;
  18069         }
  18070 
  18071         if (mpls_port->flags & BCM_MPLS_PORT_FAILOVER) {
  18072              /* VP conservation */
  18073              vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id);
  18074              if (vp == -1) {
  18075                  return BCM_E_PARAM;
  18076              }
  18077         } else {
  18078            /* allocate a new VP index */
  18079            num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  18080            rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp);
  18081            if (rv < 0) {
  18082                return rv;
  18083            }
  18084         }
  18085         sal_memset(&svp, 0, sizeof(source_vp_entry_t));
  18086         sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t));
  18087 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \
  18088     || defined(BCM_TRIDENT_SUPPORT)
  18089         if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit) 
  18090             || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT3X(unit) ||
  18091             SOC_IS_TOMAHAWKX(unit)) {
  18092             sal_memset(&dvp2, 0, sizeof(ing_dvp_2_table_entry_t));
  18093         }
  18094 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */
  18095         BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info));
  18096 
  18097         /*Set EGR_DVP_ATTRIBUTE indexed by vp to zero*/
  18098         if (SOC_MEM_IS_VALID(unit, EGR_DVP_ATTRIBUTEm)) {
  18099             BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit,
  18100                         MEM_BLOCK_ALL, vp, &egr_dvp_attribute));
  18101         }
  18102     }
  18103 #ifdef BCM_TRIUMPH2_SUPPORT 
  18104     if (soc_feature(unit, soc_feature_mpls_failover)) {
  18105         old_failover_vp = mpls_info->failover_vp[vp];
  18106     }
  18107 #endif
  18108 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
  18109                                         defined(BCM_APACHE_SUPPORT)
  18110     if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit)) {
  18111         rv = _bcm_esw_add_policer_to_table(unit, mpls_port->policer_id, 
  18112                                            SOURCE_VPm, 0, &svp);
  18113         BCM_IF_ERROR_RETURN(rv);
  18114     }
  18115 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT BCM_APACHE_SUPPORT */
  18116 
  18117     if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  18118         /* Set the MPLS port ID */
  18119         BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->mpls_port_id, vp);
  18120     }
  18121 
  18122     if (mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) {
  18123         /* Input parameters check. */
  18124         if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, mpls_port->encap_id) &&
  18125             !BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, mpls_port->encap_id)) {
  18126             return (BCM_E_PARAM);
  18127         }
  18128 
  18129         /* Calculate next hop index. */
  18130         if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, mpls_port->encap_id)) {
  18131             nh_index = mpls_port->encap_id - BCM_XGS3_EGRESS_IDX_MIN(unit);
  18132         } else {
  18133             nh_index = mpls_port->encap_id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
  18134         }
  18135     }
  18136 
  18137     if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
  18138         network_group = mpls_port->network_group_id;
  18139         rv = _bcm_validate_splithorizon_network_group(unit,
  18140                 mpls_port->flags & BCM_MPLS_PORT_NETWORK, &network_group);
  18141          BCM_IF_ERROR_RETURN(rv);
  18142     }
  18143 
  18144     drop = (mpls_port->flags & BCM_MPLS_PORT_DROP) ? 1 : 0;
  18145     rv = _bcm_tr_mpls_l2_nh_info_add(unit, mpls_port, vp, drop, 0,
  18146                                      &nh_index, &local_port, &is_local,
  18147                                      &old_nh_info);
  18148     if (rv < 0) {
  18149         if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  18150             (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp);
  18151             _BCM_MPLS_NETWORK_VP_USED_CLR(unit, vp);
  18152         }
  18153         return rv;
  18154     }
  18155 
  18156     if (mpls_port->flags & BCM_MPLS_PORT_FAILOVER) {
  18157          rv = _bcm_esw_mpls_match_add(unit, mpls_port, 
  18158                  _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(vp), vpn, TRUE);
  18159          mpls_port->mpls_port_id = 
  18160               _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(mpls_port->mpls_port_id);
  18161          mpls_port->encap_id = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_index;
  18162          if (soc_feature(unit, soc_feature_mpls_software_failover)) {
  18163              if (mpls_port->flags & BCM_MPLS_PORT_ENCAP_WITH_ID) {
  18164                  rv = soc_mem_field32_modify(unit, ING_DVP_TABLEm,
  18165                                                 vp, NEXT_HOP_INDEXf, nh_index);
  18166 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \
  18167     || defined(BCM_TRIDENT_SUPPORT)
  18168                  if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit) 
  18169                      || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT3X(unit)) {
  18170                  rv = soc_mem_field32_modify(unit, ING_DVP_2_TABLEm,
  18171                                                 vp, NEXT_HOP_INDEXf, nh_index);
  18172                  }
  18173 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */ 
  18174              }
  18175          }
  18176          goto vpls_cleanup;
  18177     }
  18178 
  18179     if (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TAGGED) {
  18180         rv = _bcm_fb2_outer_tpid_lkup(unit, mpls_port->service_tpid,
  18181                                            &tpid_index);
  18182         if (rv < 0) {
  18183             goto vpls_cleanup;
  18184         }
  18185         tpid_enable = (1 << tpid_index);
  18186         soc_SOURCE_VPm_field32_set(unit, &svp, SD_TAG_MODEf, 1);
  18187 
  18188 #if defined(BCM_TRIDENT3_SUPPORT)
  18189         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  18190             uint32 svp_attrs_1[SOC_MAX_MEM_WORDS];
  18191 
  18192             sal_memset(svp_attrs_1, 0,
  18193                     sizeof(uint32) * SOC_MAX_MEM_WORDS);
  18194             BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit,
  18195                         MEM_BLOCK_ANY, vp, svp_attrs_1));
  18196             soc_SVP_ATTRS_1m_field_set(unit,
  18197                     &svp_attrs_1, TPID_ENABLEf,
  18198                     (uint32 *)&tpid_enable);
  18199             BCM_IF_ERROR_RETURN(
  18200                     WRITE_SVP_ATTRS_1m(unit,
  18201                         MEM_BLOCK_ALL, vp,
  18202                         &svp_attrs_1));
  18203         } else
  18204 #endif
  18205         {
  18206         soc_SOURCE_VPm_field32_set(unit, &svp, TPID_ENABLEf, tpid_enable);
  18207         }
  18208         if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, TRUST_OUTER_DOT1Pf)) {
  18209               soc_SOURCE_VPm_field32_set(unit, &svp, TRUST_OUTER_DOT1Pf, 1);
  18210         }
  18211     } else {
  18212         soc_SOURCE_VPm_field32_set(unit, &svp, SD_TAG_MODEf, 0);
  18213     }
  18214     soc_SOURCE_VPm_field32_set(unit, &svp, CLASS_IDf, 
  18215                                mpls_port->if_class);
  18216     if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
  18217         soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf, network_group);
  18218     } else {
  18219         soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf,
  18220                             (mpls_port->flags & BCM_MPLS_PORT_NETWORK) ? 1 : 0);
  18221     }
  18222     if (mpls_port->flags & BCM_MPLS_PORT_NETWORK) {
  18223         _BCM_MPLS_NETWORK_VP_USED_SET(unit, vp);
  18224     }
  18225 
  18226     if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  18227         rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
  18228 
  18229         /* Link in the newly allocated next-hop entry in ING_DVP_TABLE */
  18230         soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NEXT_HOP_INDEXf,
  18231                                        nh_index);
  18232 
  18233         if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) {
  18234             if ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) &&
  18235                 (mpls_port->flags & BCM_MPLS_PORT_NETWORK)) { /* Network */
  18236 #ifdef BCM_RIOT_SUPPORT
  18237                 if (BCMI_RIOT_IS_ENABLED(unit)) {
  18238                     soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 0);
  18239                 } else
  18240 #endif
  18241                 {
  18242                     soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 1);
  18243                 }
  18244             } else { /* Access */
  18245                 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 0);
  18246             }
  18247         }
  18248 
  18249         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
  18250             if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_GROUPf)) {
  18251 #ifdef BCM_RIOT_SUPPORT
  18252                 if (BCMI_RIOT_IS_ENABLED(unit)) {
  18253                     soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf, 0);
  18254                 } else
  18255 #endif
  18256                 {
  18257                     soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf, network_group);
  18258                 }
  18259             }
  18260             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  18261                 rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm,
  18262                         vp,COMMON__DVP_NETWORK_GROUPf,
  18263                         network_group);
  18264                 if (rv < 0) {
  18265                     goto vpls_cleanup;
  18266                 }
  18267             }
  18268         }
  18269 
  18270         rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp);
  18271         if (rv < 0) {
  18272             goto vpls_cleanup;
  18273         }
  18274 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \
  18275     || defined(BCM_TRIDENT_SUPPORT)
  18276         if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit) 
  18277             || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT3X(unit) ||
  18278             SOC_IS_TOMAHAWKX(unit)) {
  18279            /* Link in the newly allocated next-hop entry in ING_DVP_2_TABLE
  18280             * Since Field module uses DVP_2_TABLE for REDIRECT_TO_DVP Action
  18281             * for devices TD/TD2/TR3
  18282             */
  18283            sal_memset(&dvp2, 0, sizeof(ing_dvp_2_table_entry_t));
  18284            BCM_IF_ERROR_RETURN(READ_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ANY,
  18285                                                      vp, &dvp2));
  18286            soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NEXT_HOP_INDEXf,
  18287                                           nh_index);
  18288 
  18289            if (soc_mem_field_valid(unit, ING_DVP_2_TABLEm, NETWORK_PORTf)) {
  18290                if ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) &&
  18291                    (mpls_port->flags & BCM_MPLS_PORT_NETWORK)) { /* Network */
  18292 #ifdef BCM_RIOT_SUPPORT
  18293                    if (BCMI_RIOT_IS_ENABLED(unit)) {
  18294                        soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf, 0);
  18295                    } else
  18296 #endif
  18297                    {
  18298                        soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf, 1);
  18299                    }
  18300                } else { /* Access */
  18301                    soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf, 0);
  18302                }
  18303            }
  18304            
  18305            if ((soc_feature(unit, soc_feature_multiple_split_horizon_group)) &&
  18306               (soc_mem_field_valid(unit, ING_DVP_2_TABLEm, NETWORK_GROUPf))) {
  18307 #ifdef BCM_RIOT_SUPPORT
  18308                if (BCMI_RIOT_IS_ENABLED(unit)) {
  18309                    soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_GROUPf, 0);
  18310                } else
  18311 #endif
  18312                {
  18313                    soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_GROUPf, network_group);
  18314                }
  18315            }
  18316 
  18317            rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp2);
  18318            if (rv < 0) {
  18319                goto vpls_cleanup;
  18320            }
  18321         }
  18322 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */
  18323     } else {
  18324         /* Link in the newly allocated next-hop entry in ING_DVP_TABLE */
  18325         soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NEXT_HOP_INDEXf,
  18326                                        nh_index);
  18327 
  18328         if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf)) {
  18329             if ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) &&
  18330                 (mpls_port->flags & BCM_MPLS_PORT_NETWORK)) { /* Network */
  18331 #ifdef BCM_RIOT_SUPPORT
  18332                 if (BCMI_RIOT_IS_ENABLED(unit)) {
  18333                     soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 0);
  18334                 } else
  18335 #endif
  18336                 {
  18337                     soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 1);
  18338                 }
  18339             } else { /* Access */
  18340                 soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 0);
  18341             }
  18342         }
  18343 
  18344         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
  18345             if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_GROUPf)) {
  18346 #ifdef BCM_RIOT_SUPPORT
  18347                 if (BCMI_RIOT_IS_ENABLED(unit)) {
  18348                     soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf, 0);
  18349                 } else
  18350 #endif
  18351                 {
  18352                     soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf, network_group);
  18353                 }
  18354             }
  18355 
  18356             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  18357                 rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm,
  18358                         vp, COMMON__DVP_NETWORK_GROUPf,
  18359                         network_group);
  18360                 if (rv < 0) {
  18361                     goto vpls_cleanup;
  18362                 }
  18363             }
  18364         }
  18365 
  18366         rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp);
  18367         if (rv < 0) {
  18368             goto vpls_cleanup;
  18369         }
  18370 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \
  18371     || defined(BCM_TRIDENT_SUPPORT)
  18372         if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit)
  18373             || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT3X(unit) ||
  18374             SOC_IS_TOMAHAWKX(unit)) {
  18375            /* Link in the newly allocated next-hop entry in ING_DVP_2_TABLE
  18376             * Since Field module uses DVP_2_TABLE for REDIRECT_TO_DVP Action
  18377             * for devices TD/TD2/TR3
  18378             */
  18379            soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NEXT_HOP_INDEXf,
  18380                                           nh_index);
  18381 
  18382            if (soc_mem_field_valid(unit, ING_DVP_2_TABLEm, NETWORK_PORTf)) {
  18383                if ((mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) &&
  18384                    (mpls_port->flags & BCM_MPLS_PORT_NETWORK)) { /* Network */
  18385 #ifdef BCM_RIOT_SUPPORT
  18386                    if (BCMI_RIOT_IS_ENABLED(unit)) {
  18387                        soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf, 0);
  18388                    } else
  18389 #endif
  18390                    {
  18391                        soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf, 1);
  18392                    }
  18393                } else { /* Access */
  18394                    soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_PORTf, 0);
  18395                }
  18396            }
  18397 
  18398            if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
  18399                if (soc_mem_field_valid(unit, ING_DVP_2_TABLEm, NETWORK_GROUPf)) {
  18400 #ifdef BCM_RIOT_SUPPORT
  18401                    if (BCMI_RIOT_IS_ENABLED(unit)) {
  18402                        soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_GROUPf, 0);
  18403                    } else
  18404 #endif
  18405                    {
  18406                        soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp2, NETWORK_GROUPf, network_group);
  18407                    }
  18408                }
  18409            }
  18410 
  18411            rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp2);
  18412            if (rv < 0) {
  18413                goto vpls_cleanup;
  18414            }
  18415         }
  18416 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */
  18417 
  18418         if (vpn == BCM_MPLS_VPLS_VPN_INVALID) {
  18419             soc_SOURCE_VPm_field32_set(unit, &svp, 
  18420                                        ENTRY_TYPEf, 0x0); /* INVALID */
  18421             rv = soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, nh_index, &ing_nh);
  18422             if (rv < 0) {
  18423                 goto vpls_cleanup;
  18424             }
  18425             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, 0x1); /* Set Drop */
  18426             rv = soc_mem_write (unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ALL, nh_index, &ing_nh);	   
  18427             if (rv < 0) {
  18428                 goto vpls_cleanup;
  18429             }
  18430         } else {
  18431             /* Initialize the SVP parameters */
  18432             soc_SOURCE_VPm_field32_set(unit, &svp, 
  18433                                        ENTRY_TYPEf, 0x1); /* VPLS */
  18434         }
  18435 
  18436         if (mpls_port->criteria != BCM_MPLS_PORT_MATCH_SHARE) {
  18437             soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, vfi);
  18438             _bcm_vp_vfi_set(unit, vp, vpn);
  18439         }
  18440 
  18441         rv = _bcm_vp_default_cml_mode_get (unit, 
  18442                            &cml_default_enable, &cml_default_new, 
  18443                            &cml_default_move);
  18444          if (rv < 0) {
  18445              goto vpls_cleanup;
  18446          }
  18447 
  18448         if (cml_default_enable) {
  18449             /* Set the CML to default values */
  18450             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml_default_new);
  18451             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml_default_move);
  18452         } else {
  18453             /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */
  18454             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, 0x8);
  18455             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, 0x8);
  18456         }
  18457         if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) {
  18458             if (!soc_feature(unit, soc_feature_vlan_vfi_membership)) {
  18459                 soc_SOURCE_VPm_field32_set(unit, &svp, DISABLE_VLAN_CHECKSf, 1);
  18460             }
  18461         }
  18462         if (soc_mem_field_valid(unit, SOURCE_VPm, SRC_PORTf) && 
  18463              soc_mem_field_valid(unit, SOURCE_VPm, SRC_MODIDf)) {
  18464              rv = _bcm_tr_mpls_l2vpn_source_port_set(unit, mpls_port, &svp);
  18465         }
  18466         if (rv < 0) {
  18467             goto vpls_cleanup;
  18468         }
  18469 
  18470         /*CMH SVP ATTRS*/
  18471         if (soc_feature(unit,soc_feature_td3_style_mpls)) {
  18472             int entry_type = 1;
  18473             rv = bcmi_cmh_svp_attributes_set(unit, entry_type, vp, TRUE,
  18474                     mpls_port->flags);
  18475             if (rv < 0) {
  18476                 goto vpls_cleanup;
  18477             }
  18478 
  18479             if (soc_mem_field_valid(unit, SOURCE_VPm, SVP_PROFILE_INDEXf)) {
  18480                 if (mpls_port->flags & BCM_MPLS_PORT_EGRESS_TUNNEL) {
  18481                     soc_SOURCE_VPm_field32_set(unit, &svp,
  18482                             SVP_PROFILE_INDEXf, 1);
  18483                 }
  18484             }
  18485         }
  18486 
  18487         rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
  18488         if (rv < 0) {
  18489             goto vpls_cleanup;
  18490         }
  18491 #ifdef BCM_ENDURO_SUPPORT
  18492         if (SOC_IS_ENDURO(unit)) {
  18493             BCM_IF_ERROR_RETURN ( 
  18494                 READ_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ANY, vp, &svp_disable_check)); 
  18495             soc_SVP_DISABLE_VLAN_CHECKS_TABm_field32_set(unit, &svp_disable_check, DISABLE_VLAN_CHECKSf, 1); 
  18496             BCM_IF_ERROR_RETURN ( 
  18497                 WRITE_SVP_DISABLE_VLAN_CHECKS_TABm(unit, MEM_BLOCK_ALL, vp, &svp_disable_check)); 
  18498         }
  18499 #endif /* BCM_ENDURO_SUPPORT */
  18500     }
  18501 
  18502 #if defined(BCM_TRIUMPH2_SUPPORT)
  18503         if (soc_feature(unit, soc_feature_mpls_failover)) {
  18504             int failover_vp = 0;
  18505             bcm_mpls_port_t  failover_mpls_port;
  18506 
  18507             if (BCM_SUCCESS(_bcm_esw_failover_mpls_check(unit, mpls_port))) {
  18508                 failover_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id);
  18509                 if (failover_vp >=0 ) {
  18510                     if (!_bcm_vp_used_get(unit, failover_vp, _bcmVpTypeMpls)) {
  18511                         rv = BCM_E_NOT_FOUND;
  18512                         goto vpls_cleanup;
  18513                     }
  18514                     rv = _bcm_esw_mpls_match_get(unit,  &failover_mpls_port, failover_vp);
  18515                     if ( rv < 0 ) {
  18516                         if (rv != BCM_E_NOT_FOUND) {
  18517                              goto vpls_cleanup;
  18518                         }
  18519                     }
  18520                     if (mpls_port->match_label == failover_mpls_port.match_label) {
  18521                         /* Replace failover_vp with Primary vp
  18522                          * As part of doing this, we should only remove the
  18523                          * h/w entry for backup port and not the software state.
  18524                          */
  18525                         rv = _bcm_esw_mpls_match_delete(unit, failover_vp, FALSE);
  18526                         if (BCM_FAILURE(rv)) {
  18527                             if (rv != BCM_E_NOT_FOUND) {
  18528                                 return rv;
  18529                             }
  18530                         }
  18531                     }
  18532                     mpls_info->failover_vp[vp] = failover_vp;
  18533                 }
  18534             } else if (mpls_port->failover_id) {
  18535                 /*
  18536                  * If this is not a primary port but user
  18537                  * is providing failover id then this is a failover
  18538                  * port and we need to make sure we dont overwrite
  18539                  * primary matching entry,if present.
  18540                  */
  18541                 mpls_entry_entry_t return_ment;
  18542                 int primary_port = 0, primary_nh_index = 0;
  18543 
  18544                 rv = _bcm_esw_mpls_failover_nw_port_match_get(unit, mpls_port, -1,
  18545                         &return_ment);
  18546 
  18547                 if (rv == BCM_E_NONE) {
  18548                     /* entry exists. dont update h/w entry as this is failover port */
  18549                     entry_update = FALSE;
  18550                     primary_port = soc_MPLS_ENTRYm_field32_get(unit,
  18551                         &return_ment, MPLS__SOURCE_VPf);
  18552 
  18553                     if (primary_port > 0) {
  18554                         ing_dvp_table_entry_t p_dvp;
  18555 
  18556                         BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit,
  18557                             MEM_BLOCK_ANY, primary_port, &p_dvp));
  18558                         primary_nh_index = soc_ING_DVP_TABLEm_field32_get(unit,
  18559                              &p_dvp, NEXT_HOP_INDEXf);
  18560                     }
  18561                     /*
  18562                      * if we are adding a failover port to existing primary
  18563                      * port then create protection table entry also.
  18564                      */
  18565                     if (bcmi_mpls_port_failover_update_is_required(
  18566                         unit, mpls_port, primary_nh_index, nh_index)) {
  18567                         rv = _bcm_esw_failover_prot_nhi_create(unit, 0,
  18568                              (uint32) primary_nh_index, nh_index,
  18569                              mpls_port->failover_mc_group,
  18570                              mpls_port->failover_id);
  18571 
  18572                         if (BCM_FAILURE(rv)) {
  18573                             goto vpls_cleanup;
  18574                         }
  18575                     }
  18576                 } else if (rv != BCM_E_NOT_FOUND) {
  18577                     return rv;
  18578             }
  18579         }
  18580     }
  18581 #endif /* BCM_TRIUMPH2_SUPPORT  */
  18582 
  18583          if (soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, MTU_VALUEf) ||
  18584                          soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, COMMON__MTU_VALUEf)) {
  18585             rv = _bcm_tr_mpls_port_mtu_set(unit, vp, mpls_port->mtu); 
  18586              if (rv < 0) {
  18587                   goto vpls_cleanup;
  18588              }
  18589          }
  18590         /*
  18591          * Add the matching entry in s/w and h/w tables.
  18592          * If this is a failover port, you may not want to write this
  18593          * entry in h/w tables as that would overwrite primary entry.
  18594          * entry_update is made false above to achieve that behavior.
  18595          */
  18596         rv = _bcm_esw_mpls_match_add(unit, mpls_port, vp, vpn, entry_update);
  18597         if (rv == BCM_E_NONE) {
  18598             /* Set the MPLS port ID */
  18599             BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->mpls_port_id, vp);
  18600             mpls_port->encap_id = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_index;
  18601         }
  18602 
  18603 #if defined(BCM_TRIUMPH2_SUPPORT)
  18604         if (!BCM_GPORT_IS_TRUNK(mpls_port->port)) {
  18605             if (!(mpls_port->flags2 & BCM_MPLS_PORT2_QOS_NONE)) {
  18606             _bcm_mpls_source_vp_set(unit, mpls_port, vp);
  18607         }
  18608         }
  18609 #endif
  18610         /* Free the old next-hop entry. */
  18611 
  18612         (void)_bcm_tr_mpls_l2_old_nh_info_delete(unit, mpls_port, nh_index,
  18613                                                  &old_nh_info);
  18614 #if defined(BCM_TRIDENT2_SUPPORT)
  18615         if (soc_feature(unit, soc_feature_vp_lag)) {
  18616             if (mpls_port->flags & BCM_MPLS_PORT_REPLACE) {
  18617                 if (rv == BCM_E_NONE) {
  18618                     rv = _bcm_td2_mpls_vplag_vp_update(unit, mpls_port->mpls_port_id);
  18619                 }
  18620             }
  18621         }
  18622 #endif
  18623 
  18624   vpls_cleanup:
  18625     if (rv < 0) {
  18626 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
  18627                                                     defined(BCM_APACHE_SUPPORT)
  18628         if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit)) {
  18629             _bcm_esw_reset_policer_from_table(unit, mpls_port->policer_id, 
  18630                                                     SOURCE_VPm, vp, &svp); 
  18631         }
  18632 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_APACHE_SUPPORT */
  18633         if (tpid_enable) {
  18634             (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
  18635         }
  18636         if (!(mpls_port->flags & BCM_MPLS_PORT_REPLACE)) {
  18637             (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp);
  18638             _BCM_MPLS_NETWORK_VP_USED_CLR(unit, vp);
  18639             (void) _bcm_tr_mpls_l2_nh_info_delete(unit, nh_index);
  18640         }
  18641 #ifdef BCM_TRIUMPH2_SUPPORT 
  18642         if (soc_feature(unit, soc_feature_mpls_failover)) {
  18643             mpls_info->failover_vp[vp] = old_failover_vp;
  18644         }
  18645 #endif
  18646 
  18647         return rv;
  18648     }
  18649 
  18650     return rv;
  18651 }
  18652 
  18653 /*
  18654  * Function:
  18655  *      bcm_mpls_port_add
  18656  * Purpose:
  18657  *      Add an mpls port to a VPN
  18658  * Parameters:
  18659  *      unit    - (IN) Device Number
  18660  *      vpn     - (IN) VPN instance ID
  18661  *      mpls_port - (IN/OUT) mpls port information (OUT : mpls_port_id)
  18662  * Returns:
  18663  *      BCM_E_XXX
  18664  */
  18665 int 
  18666 bcm_tr_mpls_port_add(int unit, bcm_vpn_t vpn, bcm_mpls_port_t *mpls_port)
  18667 {
  18668     int mode, rv = BCM_E_PARAM, bit_num = 0; 
  18669 
  18670     BCM_IF_ERROR_RETURN(bcm_xgs3_l3_egress_mode_get(unit, &mode));
  18671     if (!mode) {
  18672         LOG_INFO(BSL_LS_BCM_L3,
  18673                  (BSL_META_U(unit,
  18674                              "L3 egress mode must be set first\n")));
  18675         return BCM_E_DISABLED;
  18676     }
  18677 
  18678     if (mpls_port->criteria == BCM_MPLS_PORT_MATCH_SHARE) {
  18679         if (!soc_feature(unit, soc_feature_vp_sharing)) {
  18680             return BCM_E_UNAVAIL;
  18681         }
  18682     }
  18683 
  18684     if (!_BCM_MPLS_VPN_IS_VPLS(vpn) && 
  18685          !_BCM_MPLS_VPN_IS_VPWS(vpn)) {
  18686 
  18687         if ((vpn != BCM_MPLS_VPWS_VPN_INVALID) && (vpn != BCM_MPLS_VPLS_VPN_INVALID)) {
  18688             return BCM_E_PARAM;
  18689         }
  18690     }
  18691 
  18692     if (mpls_port->if_class) {
  18693         bit_num = soc_mem_field_length(unit, SOURCE_VPm, CLASS_IDf);
  18694         if (mpls_port->if_class > (( 1 << bit_num ) - 1)) {
  18695             return BCM_E_PARAM;
  18696         }
  18697     }
  18698 
  18699     /* BCM_MPLS_PORT_INT_PRI_MAP or BCM_MPLS_PORT_INT_PRI_SET indicates 
  18700      * how to generate the internal Priority and Color values, and they don't coexist.
  18701      */
  18702     if ((mpls_port->flags & BCM_MPLS_PORT_INT_PRI_MAP) && 
  18703         (mpls_port->flags & BCM_MPLS_PORT_INT_PRI_SET)) {
  18704         return BCM_E_PARAM;
  18705     }
  18706 
  18707     if ((mpls_port->criteria == BCM_MPLS_PORT_MATCH_LABEL_VLAN) ||
  18708         (mpls_port->criteria == BCM_MPLS_PORT_MATCH_INVALID)) {
  18709         return BCM_E_PARAM;
  18710     }
  18711 
  18712     if ((mpls_port->flags & BCM_MPLS_PORT_CONTROL_WORD) &&
  18713         (mpls_port->flags & BCM_MPLS_PORT_SEQUENCED)) {
  18714         return BCM_E_PARAM;
  18715     }
  18716 
  18717     if (soc_mem_field_valid(unit, MPLS_ENTRYm, PW_CC_TYPEf)) {
  18718         if (mpls_port->vccv_type >=
  18719             (1 << soc_mem_field_length(unit, MPLS_ENTRYm, PW_CC_TYPEf))) {
  18720             return BCM_E_PARAM;
  18721         }
  18722     }
  18723 
  18724 #if defined(BCM_TRIUMPH3_SUPPORT)
  18725     if (SOC_IS_TRIUMPH3(unit)) {
  18726         if (soc_mem_field_valid(unit, MPLS_ENTRY_1m, MPLS__PW_CC_TYPEf)) {
  18727             if (mpls_port->vccv_type >=
  18728                 (1 << soc_mem_field_length(unit, MPLS_ENTRY_1m,
  18729                  MPLS__PW_CC_TYPEf))) {
  18730                 return BCM_E_PARAM;
  18731             }
  18732         }
  18733     }
  18734 #endif
  18735 
  18736     if (_BCM_MPLS_VPN_IS_VPWS(vpn) || (vpn == BCM_MPLS_VPWS_VPN_INVALID) ) {
  18737         rv = _bcm_tr_mpls_vpws_port_add(unit, vpn, mpls_port);
  18738     } else if (_BCM_MPLS_VPN_IS_VPLS(vpn) || (vpn == BCM_MPLS_VPLS_VPN_INVALID)) {
  18739         rv = _bcm_tr_mpls_vpls_port_add(unit, vpn, mpls_port);
  18740     }
  18741 
  18742 #ifdef BCM_WARM_BOOT_SUPPORT
  18743     SOC_CONTROL_LOCK(unit);
  18744     SOC_CONTROL(unit)->scache_dirty = 1;
  18745     SOC_CONTROL_UNLOCK(unit);
  18746 #endif
  18747 
  18748     return rv;
  18749 }
  18750 
  18751 /*
  18752  * Function:
  18753  *      _bcm_share_mpls_vp_delete
  18754  * Purpose:
  18755  *      Delete match criteria of shared VPs
  18756  * Parameters:
  18757  *      unit    - (IN) Device Number
  18758  *      vpn     - (IN) VPN that shared vp belong to
  18759  *      vp      - (IN) Source Virtual Port
  18760  * Returns:
  18761  *      BCM_E_XXX
  18762  */
  18763 int
  18764 _bcm_share_mpls_vp_delete(int unit, bcm_vpn_t vpn, int vp)
  18765 {
  18766     vlan_xlate_entry_t *vent;
  18767     soc_mem_t mem;
  18768     int index_min = 0;
  18769     int index_max = 0;
  18770     uint8 *xlate_buf = NULL;
  18771     int buf_size = 0;
  18772     int i = 0;
  18773     int rv = BCM_E_NONE;
  18774     int vfi = -1;
  18775     int source_vp = -1;
  18776 
  18777     _BCM_MPLS_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
  18778 
  18779 #if defined(BCM_TRIDENT3_SUPPORT)
  18780     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  18781         mem = VLAN_XLATE_1_DOUBLEm;
  18782     } else
  18783 #endif
  18784     {
  18785     mem = VLAN_XLATEm;
  18786     }
  18787     index_min = soc_mem_index_min(unit, mem);
  18788     index_max = soc_mem_index_max(unit, mem);
  18789 
  18790     buf_size = SOC_MEM_TABLE_BYTES(unit, mem);
  18791     xlate_buf = soc_cm_salloc(unit, buf_size, "VLAN_XLATE buffer");
  18792     if (NULL == xlate_buf) {
  18793         return BCM_E_MEMORY;
  18794     }
  18795     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, xlate_buf);
  18796     if (rv < 0) {
  18797         soc_cm_sfree(unit, xlate_buf);
  18798         return rv;
  18799     }
  18800 
  18801     for (i = index_min; i <= index_max; i++) {
  18802         vent = soc_mem_table_idx_to_pointer(unit,
  18803             mem, vlan_xlate_entry_t *, xlate_buf, i);
  18804 
  18805         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  18806             if ((soc_mem_field32_get(unit, mem, vent, BASE_VALID_0f) == 0) ||
  18807                     (soc_mem_field32_get(unit, mem, vent, BASE_VALID_1f) == 0)) {
  18808                 continue;
  18809             }
  18810         } else {
  18811         if (soc_mem_field32_get(unit, mem, vent, VALIDf) == 0) {
  18812             continue;
  18813         }
  18814         }
  18815 
  18816         if (soc_mem_field32_get(unit, mem, vent, XLATE__MPLS_ACTIONf) != 0x1) {
  18817             continue;
  18818         }
  18819 
  18820         if (vfi != -1 && soc_mem_field32_get(unit, mem, vent, XLATE__VFIf) != vfi) {
  18821             continue;
  18822         }
  18823 
  18824         source_vp = soc_mem_field32_get(unit, mem, vent, XLATE__SOURCE_VPf);
  18825         if (vp != source_vp) {
  18826             continue;
  18827         }
  18828         rv = soc_mem_delete_index(unit, mem, MEM_BLOCK_ALL, i);
  18829         if (rv < BCM_E_NONE) {
  18830             (void)soc_cm_sfree(unit, xlate_buf);
  18831             return rv;
  18832         }
  18833         bcm_tr_mpls_port_match_count_adjust(unit, source_vp, -1);
  18834     }
  18835 
  18836     (void)soc_cm_sfree(unit, xlate_buf);
  18837 
  18838     return BCM_E_NONE;
  18839 }
  18840 
  18841 
  18842 STATIC int
  18843 _bcm_tr_mpls_port_delete(int unit, bcm_vpn_t vpn, int vp)
  18844 {
  18845     int rv = BCM_E_NONE;
  18846     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  18847     int failover_nh_index=-1;
  18848     int failover_id =-1;
  18849     int failover_mc_group=-1;
  18850 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  18851     bcm_policer_t policer = 0;
  18852 #endif
  18853     int vpless_failover_port = FALSE; /* the failover port without a dedicated vp */
  18854     int failover_port = FALSE;
  18855     int prot_index;
  18856     int dvp = 0;
  18857     _bcm_vp_info_t vp_info;
  18858 #if defined(BCM_TRIUMPH2_SUPPORT)
  18859     int criteria, is_trunk = 0;
  18860     int failover_dvp;
  18861     egr_l3_next_hop_entry_t egr_nh;
  18862     int nh_index = 0;
  18863     ing_l3_next_hop_entry_t ing_nh;
  18864 #endif
  18865     uint32 dest_type, dest_val;
  18866     int temp_vp3 = 0;
  18867     soc_field_t dest_field = 0;
  18868 
  18869     if(SOC_MEM_FIELD_VALID(unit, SOURCE_VPm,DESTINATIONf)) {
  18870         dest_field = DESTINATIONf;
  18871     }
  18872 
  18873     if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) {
  18874         vpless_failover_port = TRUE;
  18875         vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp);
  18876     }
  18877 
  18878     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  18879     if ((vp_info.flags & _BCM_VP_INFO_SHARED_PORT)) {
  18880         if (mpls_info->match_key[vp].match_count >= 1) {
  18881             BCM_IF_ERROR_RETURN(_bcm_share_mpls_vp_delete(unit, vpn, vp));
  18882         }
  18883         if (mpls_info->match_key[vp].match_count > 0) {
  18884             return BCM_E_NONE;
  18885         } else if (mpls_info->match_key[vp].match_count == 0) {
  18886             bcm_tr_mpls_match_clear (unit, vp);
  18887         }
  18888     } else if (mpls_info->match_key[vp].match_count > 1) {
  18889          return BCM_E_BUSY;
  18890     }
  18891 
  18892 #if defined(BCM_TRIUMPH2_SUPPORT)
  18893     criteria = mpls_info->match_key[vp].flags;
  18894     if ((vp_info.flags & _BCM_VP_INFO_SHARED_PORT)) {
  18895         rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp);
  18896         if (rv < 0) {
  18897             return rv;
  18898         }
  18899         nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
  18900                                                   NEXT_HOP_INDEXf);
  18901         BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm,
  18902                                 MEM_BLOCK_ANY, nh_index, &ing_nh));
  18903 
  18904         if (soc_feature(unit, soc_feature_generic_dest)) {
  18905             dest_val = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm,
  18906                     &ing_nh, DESTINATIONf, &dest_type);
  18907             if (dest_type == SOC_MEM_FIF_DEST_LAG) {
  18908                 /* Trunk group */
  18909                 is_trunk = 1;
  18910             }
  18911         } else {
  18912         is_trunk = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, Tf);
  18913         }
  18914     } else {
  18915         is_trunk = (mpls_info->match_key[vp].trunk_id != -1) ? TRUE : FALSE;
  18916     }
  18917 #endif
  18918     if ((vpn == BCM_MPLS_VPWS_VPN_INVALID) || (vpn == BCM_MPLS_VPLS_VPN_INVALID)) {
  18919         source_vp_entry_t svp;
  18920         if (!soc_feature(unit, soc_feature_mpls_software_failover)) {
  18921             return BCM_E_UNAVAIL;
  18922         }        
  18923         BCM_IF_ERROR_RETURN (
  18924             READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
  18925         if (soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0) {
  18926             ing_dvp_table_entry_t dvp;
  18927             int nh_index = 0;
  18928             BCM_IF_ERROR_RETURN (
  18929                 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
  18930             nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 
  18931                                                       NEXT_HOP_INDEXf);
  18932             BCM_IF_ERROR_RETURN(_bcm_esw_mpls_match_delete(unit, vp, TRUE));
  18933             sal_memset(&svp, 0, sizeof(source_vp_entry_t));
  18934             rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
  18935             if (BCM_FAILURE(rv)) {
  18936                 return rv;
  18937             }
  18938             sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t));
  18939             rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp);
  18940             if (rv < 0) {
  18941                 return rv;
  18942             }
  18943             rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp, vp);
  18944             if (rv < 0) {
  18945                 return rv;
  18946             }
  18947             rv = _bcm_tr_mpls_l2_nh_info_delete(unit, nh_index);
  18948             if (BCM_FAILURE(rv)) {
  18949                 return rv;;
  18950             }
  18951             (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp);
  18952             _BCM_MPLS_NETWORK_VP_USED_CLR(unit, vp);
  18953         } else {
  18954             return BCM_E_PARAM;
  18955         }
  18956     } else if (_BCM_MPLS_VPN_IS_VPWS(vpn)) {
  18957         int nh_index = 0, vp3=0;
  18958         source_vp_entry_t svp1, svp2, svp3;
  18959         ing_dvp_table_entry_t dvp1, dvp2, dvp3;
  18960         uint8 valid = 0;
  18961         bcm_vpn_t   vpn_id;
  18962         int vp1=-1, vp2=-1, vp3_read = -1;
  18963 
  18964         sal_memset(&svp1, 0, sizeof(source_vp_entry_t));
  18965         sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
  18966         sal_memset(&svp3, 0, sizeof(source_vp_entry_t));
  18967 
  18968         sal_memset(&dvp1, 0, sizeof(ing_dvp_table_entry_t));
  18969         sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t));
  18970         sal_memset(&dvp3, 0, sizeof(ing_dvp_table_entry_t));
  18971 
  18972 
  18973        _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn);
  18974 
  18975         (void) _bcm_tr_mpls_vpws_vp_map_get (unit, vpn_id,  &vp1,  &vp2, &vp3_read);
  18976 
  18977         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  18978             return BCM_E_NOT_FOUND;
  18979         }
  18980 
  18981         if (vp1 != -1) {
  18982               BCM_IF_ERROR_RETURN (
  18983                   READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp1, &svp1));
  18984               if (soc_SOURCE_VPm_field32_get(unit, &svp1, ENTRY_TYPEf) != 0) {
  18985                    valid |= 1;
  18986                    BCM_IF_ERROR_RETURN (
  18987                         READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp1, &dvp1));
  18988               }
  18989          }
  18990 
  18991          if ((vp2 != -1) || (bcmi_mpls_match_backup_ports(unit, vpn_id, vp))) {
  18992               if ((vp != vp2) && (bcmi_mpls_match_backup_ports(unit, vpn_id, vp))) {
  18993                   vp2 = vp;
  18994               }
  18995               if (vp2 != -1) {
  18996               BCM_IF_ERROR_RETURN (
  18997                    READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp2, &svp2));
  18998               if (soc_SOURCE_VPm_field32_get(unit, &svp2, ENTRY_TYPEf) != 0) {
  18999                    valid |= 2;
  19000                    BCM_IF_ERROR_RETURN (
  19001                         READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp2, &dvp2));
  19002               }
  19003          }
  19004          }
  19005 
  19006          if (vp == vp1) {
  19007             if (!(valid & 1)) {
  19008                  return BCM_E_NOT_FOUND;
  19009             }
  19010             if (soc_feature(unit, soc_feature_generic_dest)) {
  19011                 dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm,
  19012                         &svp1, DESTINATIONf, &dest_type);
  19013                 if (dest_type == SOC_MEM_FIF_DEST_DVP) {
  19014                     dvp = dest_val;
  19015                 }
  19016             } else {
  19017             dvp = soc_SOURCE_VPm_field32_get(unit, &svp1, DVPf);
  19018             }
  19019             nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp1, 
  19020                                                       NEXT_HOP_INDEXf);
  19021          } else if (vp == vp2)  {
  19022             if (!(valid & 2)) {
  19023                  return BCM_E_NOT_FOUND;
  19024             }
  19025 
  19026             if (soc_feature(unit, soc_feature_generic_dest)) {
  19027                 dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm,
  19028                         &svp2, DESTINATIONf, &dest_type);
  19029                 if (dest_type == SOC_MEM_FIF_DEST_DVP) {
  19030                     dvp = dest_val;
  19031                 }
  19032             } else {
  19033             dvp = soc_SOURCE_VPm_field32_get(unit, &svp2, DVPf);
  19034             }
  19035             nh_index = soc_ING_DVP_TABLEm_field32_get(unit, 
  19036                                        &dvp2, NEXT_HOP_INDEXf);
  19037          } else {
  19038             /* Read in current table values for VP3 */
  19039             vp3 = vp;
  19040             BCM_IF_ERROR_RETURN (
  19041                  READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp3, &dvp3));
  19042             BCM_IF_ERROR_RETURN (
  19043                  READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp3, &svp3));
  19044             nh_index = soc_ING_DVP_TABLEm_field32_get(unit, 
  19045                                        &dvp3, NEXT_HOP_INDEXf);
  19046          }
  19047 
  19048          if ((soc_feature(unit, soc_feature_td3_style_mpls)) &&
  19049                  (soc_feature(unit,
  19050                      soc_feature_multiple_split_horizon_group))) {
  19051              rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm,
  19052                      vp, COMMON__DVP_NETWORK_GROUPf, 0);
  19053              if (rv < 0) {
  19054                  return rv;
  19055              }
  19056          }
  19057          if (soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, MTU_VALUEf) ||
  19058                          soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, COMMON__MTU_VALUEf)) {
  19059             rv = _bcm_tr_mpls_port_mtu_clear(unit, vp);
  19060              if (rv < 0) {
  19061                   return rv;
  19062              }
  19063          }
  19064 
  19065         if (vpless_failover_port) {
  19066             failover_port = TRUE;
  19067         } else {
  19068             source_vp_entry_t svp_uni;
  19069             ing_dvp_table_entry_t dvp_nni;
  19070             int dvp_num_nni = 0; /* network side dvp number*/
  19071 
  19072             /* check if vp is a failover port. Both failover port and
  19073              * primary port should point to the same DVP customer(uni) side.
  19074              */
  19075             if (vp3_read != -1) {
  19076                 int del_fo_nh = 0;
  19077                 sal_memset(&svp_uni, 0, sizeof(source_vp_entry_t));
  19078                 sal_memset(&dvp_nni, 0, sizeof(ing_dvp_table_entry_t));
  19079                 if (dvp == 0) {
  19080                     del_fo_nh = 1;
  19081                 } else {
  19082                 BCM_IF_ERROR_RETURN (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, 
  19083                                      dvp, &svp_uni));
  19084 
  19085                 if (soc_feature(unit, soc_feature_generic_dest)) {
  19086                     dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm,
  19087                             &svp_uni, DESTINATIONf, &dest_type);
  19088                     if (dest_type == SOC_MEM_FIF_DEST_DVP) {
  19089                         dvp_num_nni = dest_val;
  19090                     }
  19091                 } else {
  19092                 dvp_num_nni = soc_SOURCE_VPm_field32_get(unit, &svp_uni, DVPf);
  19093                 }
  19094                 if (dvp_num_nni && (dvp_num_nni != vp)) {
  19095                         /* we need to check if this is the prime multi level backup port
  19096                          get the nh index */
  19097                         del_fo_nh = 1; 
  19098                     }                                      
  19099                 }
  19100                 if (del_fo_nh) {
  19101                     /* possbile failover port case */
  19102                     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, 
  19103                              MEM_BLOCK_ANY, vp3_read, &dvp_nni));
  19104                     prot_index = soc_ING_DVP_TABLEm_field32_get(unit, 
  19105                                        &dvp_nni, NEXT_HOP_INDEXf);
  19106                     rv = _bcm_esw_failover_prot_nhi_get (unit, prot_index,
  19107                           &failover_id, &failover_nh_index, &failover_mc_group);
  19108                     /* For 1+1 protection NHI use failover multicast group index */
  19109                     /* Do this only if this is not a multi level level protection.
  19110                      * For multi level protection, we wil have mc group pointing to
  19111                      * backup links
  19112                      */
  19113                     if (BCM_SUCCESS(rv) && (failover_mc_group > 0) && 
  19114                         (!(_BCM_FAILOVER_IS_MULTI_LEVEL(failover_id)))) {
  19115 
  19116                         rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit, vp,
  19117                             prot_index, &failover_nh_index);
  19118                     }
  19119                     if (BCM_SUCCESS(rv)) {
  19120                         if (failover_nh_index == nh_index) {
  19121                             /* confirm the failover port */
  19122                             failover_port = TRUE; 
  19123                             BCM_IF_ERROR_RETURN(_bcm_esw_failover_prot_nhi_cleanup(unit,
  19124                                    prot_index));
  19125                         }
  19126                     }
  19127                 }
  19128             }
  19129             if (bcmi_mpls_match_backup_ports(unit, vpn_id, vp)) {
  19130                 failover_port = TRUE;
  19131             } 
  19132         }
  19133 
  19134         /* If the other port is valid, point it to itself */
  19135         if (vp == vp1) {
  19136             rv = _bcm_esw_mpls_match_delete(unit, 
  19137                      vpless_failover_port == FALSE?
  19138                              vp:
  19139                             _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(vp), TRUE);
  19140             if ( rv < 0 ) {
  19141                 if (rv != BCM_E_NOT_FOUND) {
  19142                      return rv;
  19143                 } else {
  19144                     rv = BCM_E_NONE;
  19145                 }
  19146             }
  19147 
  19148 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  19149             if (soc_feature(unit, soc_feature_global_meter)) {
  19150                 rv = _bcm_esw_get_policer_from_table(unit, SOURCE_VPm, vp1, &svp1, 
  19151                                                           &policer, 1); 
  19152                 if(BCM_SUCCESS(rv)) {
  19153                      _bcm_esw_policer_decrement_ref_count(unit, policer);
  19154                 } else {
  19155                     return rv;
  19156                 }
  19157             }
  19158 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT */
  19159 
  19160             if (soc_feature(unit, soc_feature_generic_dest)) {
  19161                 dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm,
  19162                         &svp2, DESTINATIONf, &dest_type);
  19163                 if (dest_type == SOC_MEM_FIF_DEST_DVP) {
  19164                     temp_vp3 = dest_val;
  19165                 }
  19166 
  19167             } else {
  19168                 temp_vp3 = soc_SOURCE_VPm_field32_get(unit, &svp2, DVPf);
  19169             }
  19170                 if ((rv >= 0) && (failover_port == FALSE)) {
  19171                if ((vp2 != -1) && 
  19172                    (vp1 == temp_vp3)) {
  19173                    if (soc_feature(unit, soc_feature_generic_dest)) {
  19174                        dest_val = 0;
  19175                        rv = bcmi_td3_soc_mem_fields32_modify(unit,
  19176                                SOURCE_VPm, vp2, dest_field, dest_val);
  19177                    } else {
  19178                     rv = soc_mem_field32_modify(unit, SOURCE_VPm, 
  19179                                                 vp2, DVPf, 0);
  19180                    }
  19181                    /* Please update other backup ports here */
  19182                    bcmi_mpls_update_dvp_in_backup_ports(unit, vpn_id, -1);
  19183                }
  19184 
  19185                if ((rv >= 0) && (vp3_read != -1)) {
  19186                    BCM_IF_ERROR_RETURN (
  19187                    READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp3_read, &svp3));
  19188                    if (vp1 == temp_vp3) {
  19189                        if (soc_feature(unit, soc_feature_generic_dest)) {
  19190                            dest_val = 0;
  19191                            rv = bcmi_td3_soc_mem_fields32_modify(unit,
  19192                                    SOURCE_VPm, vp3_read, dest_field, dest_val);
  19193                        } else {
  19194                        rv = soc_mem_field32_modify(unit, SOURCE_VPm,
  19195                                                    vp3_read, DVPf, 0);                      
  19196                    }
  19197                 }
  19198                 }
  19199                 }
  19200         } else if (vp == vp2) {
  19201             if (bcmi_mpls_clear_mpls_entry_for_vp(unit, vpn_id, vp)) {
  19202                 (void) bcm_tr_mpls_match_clear (unit, vp);
  19203             } else {
  19204                 rv = _bcm_esw_mpls_match_delete(unit,
  19205                         vpless_failover_port == FALSE?
  19206                         vp:
  19207                         _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(vp), TRUE);
  19208 
  19209                 if ( rv < 0 ) {
  19210                     if (rv != BCM_E_NOT_FOUND) {
  19211                         return rv;
  19212                     } else {
  19213                         rv = BCM_E_NONE;
  19214                     }
  19215                 }
  19216             }
  19217 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  19218             if (soc_feature(unit, soc_feature_global_meter)) {
  19219                 rv = _bcm_esw_get_policer_from_table(unit, SOURCE_VPm, vp2, &svp2, 
  19220                                                           &policer, 1); 
  19221                 if(BCM_SUCCESS(rv)) {
  19222                      _bcm_esw_policer_decrement_ref_count(unit, policer);
  19223                 } else {
  19224                     return rv;
  19225                 }
  19226             }
  19227 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT */
  19228 
  19229                 if (rv >= 0 && (failover_port == FALSE)) {
  19230                     if (vp1 != -1) {
  19231                         if (soc_feature(unit, soc_feature_generic_dest)) {
  19232                             dest_val = 0;
  19233                             rv = bcmi_td3_soc_mem_fields32_modify(unit,
  19234                                     SOURCE_VPm, vp1, dest_field, dest_val);
  19235                         } else {
  19236                     rv = soc_mem_field32_modify(unit, SOURCE_VPm, 
  19237                                                 vp1, DVPf, 0);
  19238                 }                    
  19239                 }                                          
  19240                 }                                          
  19241         } else if (vp == vp3) {
  19242             /* vp1: customer side mpls port
  19243              * vp2: failover port
  19244              * vp3: service side primary mpls port
  19245              */ 
  19246             int match_label_delete = TRUE;
  19247             int fo_vp = -1;
  19248             if (soc_feature(unit, soc_feature_generic_dest)) {
  19249                 dest_val = soc_mem_field32_dest_get(unit, SOURCE_VPm,
  19250                         &svp3, DESTINATIONf, &dest_type);
  19251                 if (dest_type == SOC_MEM_FIF_DEST_DVP) {
  19252                     dvp = dest_val;
  19253                 }
  19254             } else {
  19255             dvp = soc_SOURCE_VPm_field32_get(unit, &svp3, DVPf);
  19256             }
  19257 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  19258             if (soc_feature(unit, soc_feature_global_meter)) {
  19259                 rv = _bcm_esw_get_policer_from_table(unit, SOURCE_VPm, vp3, &svp3, 
  19260                                                           &policer, 1); 
  19261                 if(BCM_SUCCESS(rv)) {
  19262                      _bcm_esw_policer_decrement_ref_count(unit, policer);
  19263                 } else {
  19264                     return rv;
  19265                 }
  19266             }
  19267 #endif /* BCM_KATANA_SUPPORT or BCM_TRIUMPH3_SUPPORT */
  19268             if (rv >= 0) {
  19269                 if (soc_feature(unit, soc_feature_generic_dest)) {
  19270                     dest_val = 0;
  19271                     rv = bcmi_td3_soc_mem_fields32_modify(unit,
  19272                             SOURCE_VPm, vp3, dest_field, dest_val);
  19273                 } else {
  19274                 rv = soc_mem_field32_modify(unit, SOURCE_VPm, 
  19275                                                 vp3, DVPf, 0);
  19276             }
  19277             }
  19278             failover_nh_index = -1;
  19279             failover_mc_group = -1;
  19280             if (BCM_SUCCESS(rv)) {
  19281                 rv = _bcm_esw_failover_prot_nhi_get (unit, nh_index,
  19282                         &failover_id, &failover_nh_index, &failover_mc_group);
  19283             }
  19284             if (BCM_SUCCESS(rv) &&
  19285                 ((failover_nh_index > 0) || (failover_mc_group > 0))) {
  19286 
  19287                 if (failover_nh_index > 0) {
  19288                     /* a failover port exists, vc_term label is shared with failover
  19289                      * port. let the failover port delete it.
  19290                      */
  19291                     fo_vp = dvp==vp1?vp2:vp1;
  19292                     if ((dvp > 0) && (fo_vp != -1)) {
  19293                         if (soc_feature(unit, soc_feature_generic_dest)) {
  19294                             rv = bcmi_td3_soc_mem_fields32_modify(unit,
  19295                                    SOURCE_VPm, dvp, dest_field, fo_vp);
  19296                         } else {
  19297                     rv = soc_mem_field32_modify(unit, SOURCE_VPm, 
  19298                                                 dvp, DVPf, fo_vp);
  19299                     }
  19300                     }
  19301                     if ((fo_vp != -1) && 
  19302                         (mpls_info->match_key[vp3].flags ==
  19303                                 _BCM_MPLS_PORT_MATCH_TYPE_LABEL)) {
  19304                         mpls_info->match_key[fo_vp].match_label = 
  19305                                    mpls_info->match_key[vp3].match_label;
  19306                         mpls_info->match_key[fo_vp].flags |= 
  19307                                          _BCM_MPLS_PORT_MATCH_TYPE_LABEL;
  19308                         mpls_info->match_key[fo_vp].modid = 0;
  19309                         mpls_info->match_key[fo_vp].port  = 0;
  19310                         match_label_delete = FALSE;
  19311                     }
  19312                 }
  19313                 if (BCM_SUCCESS(rv)) {
  19314                    rv = _bcm_esw_failover_prot_nhi_cleanup(unit,nh_index);
  19315                 }
  19316             }
  19317             if (rv < 0 ) {
  19318                 if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_UNAVAIL)) {
  19319                     rv = 0;
  19320                 } else {
  19321                    return rv;
  19322                 }
  19323             }
  19324             if (match_label_delete) {
  19325                 rv = _bcm_esw_mpls_match_delete(unit, vp, TRUE);
  19326                 if ( rv < 0 ) {
  19327                     if (rv != BCM_E_NOT_FOUND) {
  19328                          return rv;
  19329                     } else {
  19330                         rv = BCM_E_NONE;
  19331                     }
  19332                 }
  19333             } else {
  19334                 /* Update source vp in mpls entry on primary vp deletion */
  19335                 if (fo_vp != -1) {
  19336                     (void) _bcm_esw_mpls_match_failover_update(unit, vp, fo_vp);
  19337                 }
  19338                 (void) bcm_tr_mpls_match_clear (unit, vp);
  19339             }
  19340         }
  19341 
  19342         if (rv >= 0) {
  19343             /* Invalidate the VP being deleted */
  19344             if ((vp == vp1) && (vpless_failover_port == FALSE)) {
  19345 #if defined(BCM_TRIUMPH2_SUPPORT)
  19346                 if (!is_trunk) {
  19347                     rv = _bcm_mpls_source_vp_clear(unit, criteria, vp, vpn);
  19348                     if (BCM_FAILURE(rv)) {
  19349                         return rv;
  19350                     }
  19351                 }
  19352 #endif
  19353                 sal_memset(&svp1, 0, sizeof(source_vp_entry_t));
  19354                 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp1, &svp1);
  19355                 if (rv >= 0) {
  19356                     ing_dvp_table_entry_t dvp_tmp;
  19357                     sal_memset(&dvp_tmp, 0, sizeof(ing_dvp_table_entry_t));
  19358                     rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp1, &dvp_tmp);
  19359                 }
  19360 
  19361                 /*Reset CMH SVP ATTRIBUTES*/
  19362                 if (soc_feature(unit,soc_feature_td3_style_mpls)) {
  19363                     rv = bcmi_cmh_svp_attributes_set(unit, 2, vp1,
  19364                             FALSE, 0);
  19365                     if (rv < 0) {
  19366                         return rv;
  19367                     }
  19368                 }
  19369 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  19370                 if (rv >= 0 &&
  19371                         soc_feature(unit, soc_feature_ifp_redirect_to_dvp)) {
  19372                     ing_dvp_2_table_entry_t dvp_tmp;
  19373                     sal_memset(&dvp_tmp, 0, sizeof(ing_dvp_2_table_entry_t));
  19374                     rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp1, &dvp_tmp);
  19375                 }
  19376 #endif
  19377             } else if ((vp == vp2) && (vpless_failover_port == FALSE)) {
  19378 #if defined(BCM_TRIUMPH2_SUPPORT)
  19379                 if (!is_trunk) {
  19380                     rv = _bcm_mpls_source_vp_clear(unit, criteria, vp, vpn);
  19381                     if (BCM_FAILURE(rv)) {
  19382                         return rv;
  19383                     }
  19384                 }
  19385 #endif
  19386                 sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
  19387                 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp2, &svp2);
  19388                 if (rv >= 0) {
  19389                     ing_dvp_table_entry_t dvp_tmp;
  19390                     sal_memset(&dvp_tmp, 0, sizeof(ing_dvp_table_entry_t));
  19391                     rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp2, &dvp_tmp);
  19392                 }
  19393 
  19394                 /*Reset CMH SVP ATTRIBUTES*/
  19395                 if (soc_feature(unit,soc_feature_td3_style_mpls)) {
  19396                     rv = bcmi_cmh_svp_attributes_set(unit, 2, vp2,
  19397                             FALSE, 0);
  19398                     if (rv < 0) {
  19399                         return rv;
  19400                     }
  19401                 }
  19402 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  19403                 if (rv >= 0 &&
  19404                         soc_feature(unit, soc_feature_ifp_redirect_to_dvp)) {
  19405                     ing_dvp_2_table_entry_t dvp_tmp;
  19406                     sal_memset(&dvp_tmp, 0, sizeof(ing_dvp_2_table_entry_t));
  19407                     rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp2, &dvp_tmp);
  19408                 }
  19409 #endif
  19410             } else if (vp == vp3) {
  19411                 sal_memset(&svp3, 0, sizeof(source_vp_entry_t));
  19412                 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp3, &svp3);
  19413                 if (rv >= 0) {
  19414                     ing_dvp_table_entry_t dvp_tmp;
  19415                     sal_memset(&dvp_tmp, 0, sizeof(ing_dvp_table_entry_t));
  19416                     rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp3, &dvp_tmp);
  19417                 }
  19418 
  19419                 /*Reset CMH SVP ATTRIBUTES*/
  19420                 if (soc_feature(unit,soc_feature_td3_style_mpls)) {
  19421                     rv = bcmi_cmh_svp_attributes_set(unit, 2, vp3,
  19422                             FALSE, 0);
  19423                     if (rv < 0) {
  19424                         return rv;
  19425                     }
  19426                 }
  19427 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  19428                 if (rv >= 0 &&
  19429                         soc_feature(unit, soc_feature_ifp_redirect_to_dvp)) {
  19430                     ing_dvp_2_table_entry_t dvp_tmp;
  19431                     sal_memset(&dvp_tmp, 0, sizeof(ing_dvp_2_table_entry_t));
  19432                     rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp3, &dvp_tmp);
  19433                 }
  19434 #endif
  19435                 if (vp1 != -1) {
  19436                     if (vp2 != -1) {
  19437                         if (soc_feature(unit, soc_feature_generic_dest)) {
  19438                             rv = bcmi_td3_soc_mem_fields32_modify(unit,
  19439                                     SOURCE_VPm, vp1, dest_field, vp2);
  19440                         } else {
  19441                         rv = soc_mem_field32_modify(unit, SOURCE_VPm, vp1, DVPf, vp2);
  19442                         }
  19443                     } else {
  19444                         if (soc_feature(unit, soc_feature_generic_dest)) {
  19445                             dest_val = 0;
  19446                             rv = bcmi_td3_soc_mem_fields32_modify(unit, SOURCE_VPm,
  19447                                     vp1, dest_field, dest_val);
  19448                     } else {
  19449                         rv = soc_mem_field32_modify(unit, SOURCE_VPm, vp1, DVPf, 0);
  19450                     }
  19451                 }
  19452             }
  19453             }
  19454 
  19455             if (vp != vp3) {  
  19456                 /* Free vp-less failover port resource when deleting
  19457                  * either vp-less failover port or its primary port.
  19458                  */
  19459                 failover_nh_index = -1;
  19460                 failover_mc_group = -1;
  19461                 rv = _bcm_esw_failover_prot_nhi_get (unit, nh_index,
  19462                         &failover_id, &failover_nh_index, &failover_mc_group);
  19463                 if (BCM_SUCCESS(rv)) {
  19464                     if (failover_mc_group > 0) {
  19465                         rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit,vp,nh_index,
  19466                                                    &failover_nh_index);
  19467                     }
  19468                     if (failover_nh_index > 0) {
  19469                         rv = _bcm_tr_mpls_l2_nh_info_delete(unit, 
  19470                                                        failover_nh_index);
  19471                         if (BCM_SUCCESS(rv)) {
  19472                             rv = _bcm_esw_failover_prot_nhi_cleanup(unit,nh_index);
  19473                         }
  19474                     }
  19475                 } else if (rv == BCM_E_UNAVAIL) {
  19476                     if (soc_feature(unit, soc_feature_mpls_software_failover) &&
  19477                         (vpless_failover_port == TRUE) ) {
  19478                         rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit,vp,nh_index,
  19479                                                    &failover_nh_index);
  19480                         if (BCM_SUCCESS(rv)) {
  19481                             rv = _bcm_tr_mpls_l2_nh_info_delete(unit, failover_nh_index);
  19482                         }
  19483                     }
  19484                 }
  19485 
  19486                 if (rv < 0 ) {
  19487                     if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_UNAVAIL)) {
  19488                         rv = 0;
  19489                     } else {
  19490                         return rv;
  19491                     }
  19492                 }
  19493             }
  19494 
  19495             /* Delete the next-hop info */
  19496             if ((rv >= 0) && (vpless_failover_port == FALSE)) {
  19497                 rv = _bcm_tr_mpls_l2_nh_info_delete(unit, nh_index);
  19498             }
  19499             if ( rv < 0 ) {
  19500                 if (rv != BCM_E_NOT_FOUND) {
  19501                     return rv;
  19502                 } else {
  19503                         rv = 0;
  19504                 }
  19505             }
  19506             /* Free the VP */
  19507             if (vpless_failover_port == FALSE) {
  19508                 (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp);
  19509                 _BCM_MPLS_NETWORK_VP_USED_CLR(unit, vp);
  19510                 if (vp == vp1) {
  19511                     _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, -1, vp2, vp3_read);
  19512                 } else if (vp == vp2) {
  19513                     _bcm_tr_mpls_vpws_vp_map_backup_port_clear(unit, vpn_id, vp2);
  19514                 } else if (vp == vp3) {
  19515                     _bcm_tr_mpls_vpws_vp_map_set(unit, vpn_id, vp1, vp2, -1);
  19516                 }
  19517             }
  19518         }
  19519     } else if (_BCM_MPLS_VPN_IS_VPLS(vpn)) {
  19520         int nh_index = 0, vfi;
  19521         source_vp_entry_t svp;
  19522         ing_dvp_table_entry_t dvp;
  19523 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \
  19524     || defined(BCM_TRIDENT_SUPPORT)
  19525         ing_dvp_2_table_entry_t dvp2;
  19526 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */
  19527 
  19528         sal_memset(&svp, 0, sizeof(source_vp_entry_t));
  19529         sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t));
  19530 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \
  19531     || defined(BCM_TRIDENT_SUPPORT)
  19532         if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit)
  19533             || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT3X(unit) ||
  19534             SOC_IS_TOMAHAWKX(unit)) {
  19535             sal_memset(&dvp2, 0, sizeof(ing_dvp_2_table_entry_t));
  19536         }
  19537 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */
  19538 
  19539         _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vpn);
  19540         if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
  19541             return BCM_E_NOT_FOUND;
  19542         }
  19543         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  19544             return BCM_E_NOT_FOUND;
  19545         }
  19546 
  19547         BCM_IF_ERROR_RETURN (
  19548             READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
  19549         if (soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0) {
  19550             return BCM_E_NOT_FOUND;
  19551         }
  19552 
  19553         rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp);
  19554         if (rv < 0) {
  19555             return rv;
  19556         }
  19557         nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
  19558         if (soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, MTU_VALUEf) ||
  19559                          soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, COMMON__MTU_VALUEf)) {
  19560             rv = _bcm_tr_mpls_port_mtu_clear(unit, vp);
  19561              if (rv < 0) {
  19562                   return rv;
  19563              }
  19564         }
  19565 
  19566         /*
  19567          * In case we are removing the failover port,
  19568          * we should clean protection tables also.
  19569          * check for primary matching entry and then
  19570          * make sure that this is failover port for that entry.
  19571          */
  19572         if (soc_feature(unit, soc_feature_mpls_failover)) {
  19573         mpls_entry_entry_t ret_ment;
  19574         int primary_port=0, primary_nh_index=0;
  19575         int cleanup = 1;
  19576 
  19577         rv = _bcm_esw_mpls_failover_nw_port_match_get(unit, NULL, vp, &ret_ment);
  19578 
  19579             if (rv == BCM_E_NONE) {
  19580                 ing_dvp_table_entry_t p_dvp;
  19581 
  19582                 primary_port =
  19583                    soc_MPLS_ENTRYm_field32_get(unit, &ret_ment, MPLS__SOURCE_VPf);
  19584 
  19585                 if (primary_port > 0) {
  19586                     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit,
  19587                         MEM_BLOCK_ANY, primary_port, &p_dvp));
  19588                     primary_nh_index = soc_ING_DVP_TABLEm_field32_get(unit,
  19589                         &p_dvp, NEXT_HOP_INDEXf);
  19590 
  19591 
  19592                     rv = _bcm_esw_failover_prot_nhi_get (unit,
  19593                         primary_nh_index, &failover_id,
  19594                         &failover_nh_index, &failover_mc_group);
  19595 
  19596                      if (failover_nh_index > 0) {
  19597                          /* check if we can cleanup the failover entry if failover port
  19598                           * is getting deleted
  19599                           */
  19600                          rv = bcmi_mpls_failover_nhi_cleanup_check(
  19601                               unit, vpn, vp, failover_id,
  19602                               failover_nh_index, primary_nh_index, nh_index, &cleanup);
  19603                          if (rv) {
  19604                              return(rv);
  19605                          }
  19606 
  19607                          if (cleanup) {
  19608                              /* Clean failover protection entry.*/
  19609                              rv = _bcm_esw_failover_prot_nhi_cleanup(unit, primary_nh_index);
  19610                              if (rv) {
  19611                                  return(rv);
  19612                              }
  19613                          }
  19614                          if (primary_port != vp) {
  19615                              /* clean s/w state so that match delete does not
  19616                               * find this port to delete matching entry.
  19617                               * else, match_delete routing can remove
  19618                               * primary port entry as that is with same label */
  19619                              (void) bcm_tr_mpls_match_clear (unit, vp);
  19620                           }
  19621                      }
  19622                 }
  19623             } else if (rv != BCM_E_NOT_FOUND) {
  19624                 return rv;
  19625             }
  19626         }
  19627 
  19628         BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  19629         if (!(vp_info.flags & _BCM_VP_INFO_SHARED_PORT)) {
  19630             rv = _bcm_esw_mpls_match_delete(unit,
  19631                    vpless_failover_port == FALSE? vp:
  19632                    _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(vp), TRUE);
  19633             if ( rv < 0 ) {
  19634                 if (rv != BCM_E_NOT_FOUND) {
  19635                     return rv;
  19636                 }
  19637             }
  19638         } else {
  19639             if (mpls_info->match_key[vp].match_count == 0) {
  19640                 bcm_tr_mpls_match_clear (unit, vp);
  19641             }
  19642         }
  19643 
  19644 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  19645         if (soc_feature(unit, soc_feature_global_meter)) {
  19646             rv = _bcm_esw_get_policer_from_table(unit, SOURCE_VPm, vp, &svp, 
  19647                                                       &policer, 0); 
  19648             if(BCM_SUCCESS(rv)) {
  19649                  _bcm_esw_policer_decrement_ref_count(unit, policer);
  19650             } else {
  19651                 return rv;
  19652             }
  19653         }
  19654 #endif /* BCM_KATANA_SUPPORT  or BCM_TRIUMPH3_SUPPORT*/
  19655 
  19656         if (vpless_failover_port == FALSE) {
  19657 #if defined(BCM_TRIUMPH2_SUPPORT)
  19658             if (!is_trunk) {
  19659                rv = _bcm_mpls_source_vp_clear(unit, criteria, vp, vpn);
  19660                if (BCM_FAILURE(rv)) {
  19661                    return rv;
  19662                }
  19663             }
  19664 #endif
  19665             /* Clear the SVP and DVP table entries */
  19666             sal_memset(&svp, 0, sizeof(source_vp_entry_t));
  19667             rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
  19668             if (rv < 0) {
  19669                 return rv;
  19670             }
  19671 
  19672             _bcm_vp_vfi_set(unit, vp, 0);
  19673 
  19674             /*Reset CMH SVP ATTRIBUTES*/
  19675             if (soc_feature(unit,soc_feature_td3_style_mpls)) {
  19676                 rv = bcmi_cmh_svp_attributes_set(unit, 1, vp,
  19677                         FALSE, 0);
  19678                 if (rv < 0) {
  19679                     return rv;
  19680                 }
  19681             }
  19682 
  19683             sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t));
  19684             rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp);
  19685             if (rv < 0) {
  19686                 return rv;
  19687             }
  19688             rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp, vp);
  19689             if (rv < 0) {
  19690                 return rv;
  19691             }
  19692 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) \
  19693     || defined(BCM_TRIDENT_SUPPORT)
  19694             if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit)
  19695                 || SOC_IS_TRIDENT(unit) || SOC_IS_TRIDENT3X(unit) ||
  19696                 SOC_IS_TOMAHAWKX(unit)) {
  19697                 sal_memset(&dvp2, 0, sizeof(ing_dvp_2_table_entry_t));
  19698                 rv = WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp2);
  19699                 if (rv < 0) {
  19700                     return rv;
  19701                 }
  19702             }
  19703 #endif /* BCM_TRIDENT2_SUPPORT or BCM_TRIUMPH3_SUPPORT or BCM_TRIDENT_SUPPORT */
  19704 
  19705             if ((soc_feature(unit, soc_feature_td3_style_mpls)) &&
  19706                     (soc_feature(unit,
  19707                          soc_feature_multiple_split_horizon_group))) {
  19708                 rv = soc_mem_field32_modify(unit, EGR_DVP_ATTRIBUTEm,
  19709                         vp, COMMON__DVP_NETWORK_GROUPf, 0);
  19710                 if (rv < 0) {
  19711                     return rv;
  19712                 }
  19713             }
  19714         }
  19715 
  19716 #if defined(BCM_TRIUMPH2_SUPPORT)
  19717         if (soc_feature(unit, soc_feature_mpls_failover)) {
  19718              rv = _bcm_esw_failover_prot_nhi_get (unit, nh_index,
  19719                            &failover_id, &failover_nh_index, &failover_mc_group);
  19720              /*For 1+1 vpless failover get failover nhi using multicast group index*/
  19721              if(failover_mc_group > 0){
  19722                  rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit,vp,nh_index,
  19723                          &failover_nh_index);
  19724              }
  19725              if ((failover_nh_index > 0) && (!(_BCM_FAILOVER_IS_MULTI_LEVEL(failover_id)))) {
  19726                  BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm,
  19727                              MEM_BLOCK_ANY, failover_nh_index, &egr_nh));
  19728                  if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  19729                      failover_dvp = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
  19730                              &egr_nh, MPLS__DVPf);
  19731                  } else {
  19732                      failover_dvp = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
  19733                              &egr_nh, DVPf);
  19734                  }
  19735                  /*
  19736                   * If vpless failover, delete failover nh index also.
  19737                   * If non-vpless failover, do not delete failover nh index.
  19738                   * .If this is the VPLESS primary port being deleted, then the
  19739                   *  VPLESS backup port's nh index is also removed.
  19740                   * .If this is the VPLESS backup port being deleted,
  19741                   *  failover_nh_index is its own nh index, so backup port's
  19742                   *  nh index will be removed.
  19743                   */
  19744                  if (failover_dvp == vp) {
  19745                      rv = _bcm_tr_mpls_l2_nh_info_delete(unit, failover_nh_index);
  19746                  } else {
  19747                      int rv1;
  19748                      bcm_mpls_port_t failover_mpls_port;
  19749                      bcm_mpls_port_t_init(&failover_mpls_port);
  19750                      rv1 = _bcm_esw_mpls_match_get(unit, &failover_mpls_port, failover_dvp);
  19751                      if (rv1 == BCM_E_NOT_FOUND) {
  19752                          BCM_IF_ERROR_RETURN(_bcm_esw_mpls_match_add(unit, &failover_mpls_port, 
  19753                                                                     failover_dvp, vpn, TRUE));
  19754                      }
  19755                  }
  19756              }
  19757              if (BCM_SUCCESS(rv)) {
  19758                  rv = _bcm_esw_failover_prot_nhi_cleanup(unit,nh_index);
  19759              }
  19760 
  19761              if ( rv < 0 ) {
  19762                if (rv != BCM_E_NOT_FOUND) {
  19763                   return rv;
  19764                } else {
  19765                    rv = 0;
  19766                }
  19767              }
  19768         } else 
  19769 #endif /* BCM_TRIUMPH2_SUPPORT */
  19770         if (soc_feature(unit, soc_feature_mpls_software_failover) &&
  19771             (vpless_failover_port == TRUE) ) {
  19772             rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit,vp,nh_index,
  19773                                                    &failover_nh_index);
  19774             if (BCM_SUCCESS(rv)) {
  19775                 rv = _bcm_tr_mpls_l2_nh_info_delete(unit, failover_nh_index);
  19776             }
  19777             if (rv < 0 ) {
  19778                 if (rv != BCM_E_NOT_FOUND) {
  19779                     return rv;
  19780                 } else {
  19781                     rv = 0;
  19782                 }
  19783             }
  19784         }
  19785 
  19786         if (vpless_failover_port == FALSE) {
  19787             /* Delete the next-hop info */
  19788             if (rv >= 0) {
  19789                 rv = _bcm_tr_mpls_l2_nh_info_delete(unit, nh_index);
  19790             }
  19791             if ( rv < 0 ) {
  19792                 if (rv != BCM_E_NOT_FOUND) {
  19793                     return rv;
  19794                 } else {
  19795                         rv = 0;
  19796                 }
  19797             }
  19798 
  19799             /* Free the VP */
  19800             (void) _bcm_vp_free(unit, _bcmVpTypeMpls, 1, vp);
  19801             _BCM_MPLS_NETWORK_VP_USED_CLR(unit, vp);
  19802 #ifdef BCM_TRIUMPH2_SUPPORT 
  19803             if (soc_feature(unit, soc_feature_mpls_failover)) {           
  19804                 int i;
  19805                 int num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  19806                 for (i = 0; i < num_vp; i++) {
  19807                     if (mpls_info->failover_vp[i] == vp) {
  19808                         mpls_info->failover_vp[i] = 0;
  19809                     }
  19810                 }    
  19811                 mpls_info->failover_vp[vp] = 0;
  19812                 
  19813             }
  19814 #endif  
  19815         }
  19816     }
  19817 
  19818 #ifdef BCM_TRIUMPH2_SUPPORT
  19819     if (soc_feature(unit, soc_feature_gport_service_counters)) {
  19820         bcm_gport_t gport;
  19821 
  19822         /* Release Service counter, if any */
  19823         BCM_GPORT_MPLS_PORT_ID_SET(gport, vp);
  19824         _bcm_esw_flex_stat_handle_free(unit, _bcmFlexStatTypeGport, gport);
  19825     }
  19826 #endif
  19827 
  19828 #ifdef BCM_WARM_BOOT_SUPPORT
  19829     SOC_CONTROL_LOCK(unit);
  19830     SOC_CONTROL(unit)->scache_dirty = 1;
  19831     SOC_CONTROL_UNLOCK(unit);
  19832 #endif
  19833 
  19834     return rv;
  19835 }
  19836 
  19837 /*
  19838  * Function:
  19839  *      bcm_mpls_port_delete
  19840  * Purpose:
  19841  *      Delete an mpls port from a VPN
  19842  * Parameters:
  19843  *      unit       - (IN) Device Number
  19844  *      vpn        - (IN) VPN instance ID
  19845  *      mpls_port_id - (IN) mpls port information
  19846  * Returns:
  19847  *      BCM_E_XXX
  19848  */
  19849 int
  19850 bcm_tr_mpls_port_delete(int unit, bcm_vpn_t vpn, bcm_gport_t mpls_port_id)
  19851 {
  19852     int vp;
  19853 
  19854     if (((vpn == BCM_MPLS_VPWS_VPN_INVALID) ||
  19855          (vpn == BCM_MPLS_VPLS_VPN_INVALID)) && 
  19856          !soc_feature(unit, soc_feature_mpls_software_failover)) {
  19857         return BCM_E_PARAM; 
  19858     }
  19859     if (!_BCM_MPLS_VPN_IS_VPLS(vpn) && 
  19860          !_BCM_MPLS_VPN_IS_VPWS(vpn) ) {
  19861         return BCM_E_PARAM;
  19862     }
  19863 
  19864     vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port_id);
  19865     if (vp == -1) {
  19866         return BCM_E_PARAM;
  19867     }
  19868 
  19869     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  19870         return BCM_E_NOT_FOUND;
  19871     }
  19872     if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(mpls_port_id)) {
  19873         vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(vp);
  19874     }
  19875     return (_bcm_tr_mpls_port_delete(unit, vpn, vp));
  19876 }
  19877 /*
  19878  * Function:
  19879  *      bcmi_mpls_delete_backup_ports
  19880  * Purpose:
  19881  *      Delete an mpls backup port
  19882  * Parameters:
  19883  *      unit       - (IN) Device Number
  19884  *      vpn        - (IN) VPN instance ID
  19885  *      vp         - (IN) mpls backup port 
  19886  * Returns:
  19887  *      BCM_E_XXX
  19888  */
  19889 int
  19890 bcmi_mpls_delete_backup_ports(int unit, int vpn, int vp)
  19891 {
  19892 
  19893     int rv;
  19894     source_vp_entry_t svp;
  19895     ing_dvp_table_entry_t dvp;
  19896 
  19897     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
  19898     if (rv < 0) {
  19899         return rv;
  19900     }
  19901 
  19902     rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp);
  19903     if (rv < 0) {
  19904         return rv;
  19905     }
  19906     if (soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) != 0) {
  19907         rv = _bcm_tr_mpls_port_delete(unit, vpn, vp);
  19908         if (rv < 0) {
  19909             return rv;
  19910         }
  19911     }
  19912     return BCM_E_NONE;
  19913 }
  19914 /*
  19915  * Function:
  19916  *      bcmi_mpls_delete_all_backup_ports
  19917  * Purpose:
  19918  *      Delete all mpls backup ports in that vpn
  19919  * Parameters:
  19920  *      unit       - (IN) Device Number
  19921  *      vpn        - (IN) VPN instance ID
  19922  * Returns:
  19923  *      BCM_E_XXX
  19924  */
  19925 int
  19926 bcmi_mpls_delete_all_backup_ports(int unit, bcm_vpn_t vpn)
  19927 {
  19928 
  19929     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  19930     int max_vpws_vpn, num_vp;
  19931     bcm_vpn_t vpn_id;
  19932 
  19933     if (!_BCM_MPLS_VPN_IS_VPWS(vpn)) {
  19934         return BCM_E_PARAM;
  19935     }
  19936 
  19937     _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn);
  19938 
  19939     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  19940     max_vpws_vpn = num_vp / 2;
  19941 
  19942     if (vpn_id <= max_vpws_vpn) {
  19943         if (mpls_info->vpws_vp_map[vpn_id].vp_b_1 != -1) {
  19944             BCM_IF_ERROR_RETURN(bcmi_mpls_delete_backup_ports(unit, vpn,
  19945                 mpls_info->vpws_vp_map[vpn_id].vp_b_1));
  19946         }
  19947 
  19948         if (mpls_info->vpws_vp_map[vpn_id].vp_b_2 != -1) {
  19949             BCM_IF_ERROR_RETURN(bcmi_mpls_delete_backup_ports(unit, vpn,
  19950                 mpls_info->vpws_vp_map[vpn_id].vp_b_2));
  19951         }
  19952 
  19953         if (mpls_info->vpws_vp_map[vpn_id].vp_b_3 != -1) {
  19954              BCM_IF_ERROR_RETURN(bcmi_mpls_delete_backup_ports(unit, vpn,
  19955                 mpls_info->vpws_vp_map[vpn_id].vp_b_3));
  19956         }
  19957     }
  19958     return BCM_E_NONE;
  19959 }
  19960 
  19961 /*
  19962  * Function:
  19963  *      bcm_mpls_port_delete_all
  19964  * Purpose:
  19965  *      Delete all mpls ports from a VPN
  19966  * Parameters:
  19967  *      unit - Device Number
  19968  *      vpn - VPN instance ID
  19969  * Returns:
  19970  *      BCM_E_XXX
  19971  */
  19972 int
  19973 bcm_tr_mpls_port_delete_all(int unit, bcm_vpn_t vpn)
  19974 {
  19975     int rv = BCM_E_NONE;
  19976 
  19977     if (!_BCM_MPLS_VPN_IS_VPLS(vpn) && 
  19978          !_BCM_MPLS_VPN_IS_VPWS(vpn)) {
  19979         return BCM_E_PARAM;
  19980     }
  19981 
  19982     if (_BCM_MPLS_VPN_IS_VPWS(vpn)) {
  19983         int vp1=-1, vp2=-1, vp3_read = -1;
  19984         source_vp_entry_t svp1, svp2, svp3;
  19985         ing_dvp_table_entry_t dvp1, dvp2, dvp3;
  19986         bcm_vpn_t   vpn_id;
  19987 
  19988         sal_memset(&svp1, 0, sizeof(source_vp_entry_t));
  19989         sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
  19990         sal_memset(&svp3, 0, sizeof(source_vp_entry_t));
  19991         sal_memset(&dvp1, 0, sizeof(ing_dvp_table_entry_t));
  19992         sal_memset(&dvp2, 0, sizeof(ing_dvp_table_entry_t));
  19993         sal_memset(&dvp3, 0, sizeof(ing_dvp_table_entry_t));
  19994 
  19995        _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn);
  19996 
  19997         (void) _bcm_tr_mpls_vpws_vp_map_get (unit, vpn_id, &vp1, &vp2, &vp3_read);
  19998 
  19999         if (vp1 != -1) {
  20000             rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp1, &svp1);
  20001             if (rv < 0) {
  20002                 goto done;
  20003             }
  20004             rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp1, &dvp1);
  20005             if (rv < 0) {
  20006                 goto done;
  20007             }
  20008             /* See if the entry already exists */
  20009             if (soc_SOURCE_VPm_field32_get(unit, &svp1, ENTRY_TYPEf) != 0) {
  20010                 rv = _bcm_tr_mpls_port_delete(unit, vpn, vp1);
  20011                 if (rv < 0) {
  20012                     goto done;
  20013                 }
  20014             }
  20015         }
  20016 
  20017         if (vp2 != -1) {
  20018             rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp2, &svp2);
  20019             if (rv < 0) {
  20020                 goto done;
  20021             }
  20022             rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp2, &dvp2);
  20023             if (rv < 0) {
  20024                 goto done;
  20025             }
  20026             if (soc_SOURCE_VPm_field32_get(unit, &svp2, ENTRY_TYPEf) != 0) {
  20027                 rv = _bcm_tr_mpls_port_delete(unit, vpn, vp2);
  20028                 if (rv < 0) {
  20029                     goto done;
  20030                 }
  20031             }
  20032         }
  20033 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT
  20034         if (soc_feature(unit, soc_feature_hierarchical_protection)) {
  20035 		rv = bcmi_mpls_delete_all_backup_ports(unit, vpn);
  20036         if (rv < 0) {
  20037             goto done;
  20038         }
  20039         }
  20040 #endif
  20041         /* need to delete vp3 for there may be a dedicated vp for failover port. */
  20042         if (vp3_read != -1) {
  20043             rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp3_read, &svp3);
  20044             if (rv < 0) {
  20045                 goto done;
  20046             }
  20047             rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp3_read, &dvp3);
  20048             if (rv < 0) {
  20049                 goto done;
  20050             }
  20051             if (soc_SOURCE_VPm_field32_get(unit, &svp3, ENTRY_TYPEf) != 0) {
  20052                 rv = _bcm_tr_mpls_port_delete(unit, vpn, vp3_read);
  20053                 if (rv < 0) {
  20054                     goto done;
  20055                 }
  20056             }
  20057         }
  20058     } else if (_BCM_MPLS_VPN_IS_VPLS(vpn)) {
  20059         uint32 vfi, vp, num_vp;
  20060         source_vp_entry_t svp;
  20061 
  20062         sal_memset(&svp, 0, sizeof(source_vp_entry_t));
  20063 
  20064         _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vpn);
  20065 
  20066         if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
  20067             rv =  BCM_E_NOT_FOUND;
  20068             goto done;
  20069         }
  20070         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  20071         for (vp = 0; vp < num_vp; vp++) {
  20072             /* Check for the validity of the VP */
  20073             if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {	
  20074                 continue;
  20075             }
  20076             rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
  20077             if (rv < 0) {
  20078                 goto done;
  20079             }
  20080             if ((soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0x1) &&
  20081                     (vfi == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf))) {
  20082                 rv = _bcm_tr_mpls_port_delete(unit, vpn, vp);
  20083                 if (rv < 0) {
  20084                     goto done;
  20085                 }
  20086             } else if ((soc_feature(unit, soc_feature_vp_sharing) ||
  20087                     soc_feature(unit, soc_feature_nexthop_share_dvp)) && 
  20088                     (_bcm_virtual_bk_info[unit].vp_shared_vp_bitmap)) {
  20089 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  20090                 if (SHR_BITGET((&_bcm_virtual_bk_info[unit])->vp_shared_vp_bitmap, vp) &&
  20091                         MPLS_INFO(unit)->match_key[vp].match_count > 0) {
  20092                     rv = _bcm_tr_mpls_port_delete(unit, vpn, vp);
  20093                     if (rv < 0) {
  20094                         goto done;
  20095                     }
  20096                 }
  20097 #endif
  20098             }
  20099         }
  20100     }
  20101 
  20102   done:
  20103     return rv;
  20104 }
  20105 
  20106 STATIC int
  20107 _bcm_tr_mpls_port_get(int unit, bcm_vpn_t vpn, int vp,
  20108                       bcm_mpls_port_t *mpls_port)
  20109 {
  20110 #if defined(BCM_TRIDENT3_SUPPORT)
  20111     int nw_group = 0;
  20112 #endif
  20113     int i, nh_index, tpid_enable = 0, rv = BCM_E_NONE;
  20114     ing_dvp_table_entry_t dvp;
  20115     source_vp_entry_t svp;
  20116     int split_horizon_port_flag=0;
  20117     int vpless_failover_port = FALSE; /* the failover port without a dedicated vp */
  20118     _bcm_vp_info_t vp_info;
  20119 #if defined(BCM_TRIUMPH2_SUPPORT)
  20120     int vp1, vp2, vp3;
  20121     vp1 = vp2 = vp3 = -1;
  20122 #endif
  20123 
  20124     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  20125         return BCM_E_UNAVAIL;
  20126     }
  20127 
  20128     /* Initialize the structure */
  20129     bcm_mpls_port_t_init(mpls_port);
  20130     BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->mpls_port_id, vp);
  20131 
  20132     if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(vp)) {
  20133         vpless_failover_port = TRUE;
  20134         mpls_port->mpls_port_id =
  20135               _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(mpls_port->mpls_port_id);
  20136         vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(vp);
  20137 
  20138         mpls_port->flags |= BCM_MPLS_PORT_FAILOVER;
  20139     }
  20140 
  20141     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
  20142     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
  20143 
  20144 #if defined(BCM_TRIUMPH2_SUPPORT)
  20145     if (soc_feature(unit, soc_feature_mpls_failover)) {  
  20146         int prot_nh_index =-1;
  20147         int prot_mc_group=-1;
  20148         int failover_id;
  20149         int dvp = -1;
  20150         egr_l3_next_hop_entry_t egr_nh;
  20151 
  20152         BCM_IF_ERROR_RETURN(_bcm_esw_failover_prot_nhi_get(unit, nh_index,
  20153                             &failover_id, &prot_nh_index, &prot_mc_group));
  20154         if (vpless_failover_port == TRUE) {
  20155             if (prot_mc_group > 0) {
  20156                 rv = _bcm_tr_mpls_vpless_failover_nh_index_find(unit, vp,
  20157                             nh_index, &prot_nh_index);
  20158                 if (BCM_SUCCESS(rv) && (prot_nh_index > 0)) {
  20159                     nh_index = prot_nh_index;
  20160                 }
  20161             } else if (prot_nh_index > 0) {
  20162                 nh_index = prot_nh_index;
  20163             }
  20164         }
  20165         
  20166         if (failover_id != 0) {
  20167             if (prot_mc_group > 0) {
  20168                 if ((_BCM_MPLS_VPN_IS_VPWS(vpn)) && 
  20169                     (!_BCM_FAILOVER_IS_MULTI_LEVEL(failover_id))){
  20170                     bcm_vpn_t   vpn_id;
  20171 
  20172                     _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn);
  20173                     (void) _bcm_tr_mpls_vpws_vp_map_get (unit, vpn_id, &vp1,
  20174                                                          &vp2, &vp3);
  20175                     if (((FALSE == vpless_failover_port) && (vp3 == vp)) ||
  20176                         (TRUE == vpless_failover_port)) {                        
  20177                         BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->failover_port_id,
  20178                                                    vp2);
  20179                         mpls_port->failover_id = failover_id;
  20180                         mpls_port->failover_mc_group = prot_mc_group;
  20181                     }
  20182                 } else {
  20183                     mpls_port->failover_id = failover_id;
  20184                     mpls_port->failover_mc_group = prot_mc_group;
  20185 #ifdef BCM_TRIUMPH2_SUPPORT 
  20186                     if (soc_feature(unit, soc_feature_mpls_failover)) {
  20187                         if ((_BCM_MPLS_VPN_IS_VPLS(vpn)) && 
  20188                         (!_BCM_FAILOVER_IS_MULTI_LEVEL(failover_id))) {
  20189                             if (vpless_failover_port == FALSE) {
  20190                                 _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  20191                                 BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->failover_port_id,
  20192                                                            mpls_info->failover_vp[vp]);
  20193                             } else {
  20194                                 BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->failover_port_id,
  20195                                                            vp);
  20196                             }
  20197                         }
  20198                     }
  20199 #endif                                        
  20200                 }
  20201             } else {
  20202                 /* Retrieve EGR L3 NHOP Entry */
  20203                 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm,
  20204                             MEM_BLOCK_ANY, prot_nh_index, &egr_nh));
  20205                 if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  20206                     dvp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, MPLS__DVPf);
  20207                 } else {
  20208                     dvp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DVPf);
  20209                 }
  20210                 if (vpless_failover_port == TRUE) {
  20211                     mpls_port->failover_id = failover_id;
  20212                     BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->failover_port_id, dvp);
  20213                 } else {
  20214                     int primary_dvp = -1;
  20215                     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm,
  20216                                                       MEM_BLOCK_ANY, nh_index, &egr_nh));
  20217                     if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  20218                         primary_dvp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, MPLS__DVPf);
  20219                     } else {
  20220                         primary_dvp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DVPf);
  20221                     }
  20222                     if (primary_dvp != dvp) {
  20223                         mpls_port->failover_id = failover_id;
  20224                         BCM_GPORT_MPLS_PORT_ID_SET(mpls_port->failover_port_id, dvp);
  20225                     }
  20226                 }
  20227             }
  20228         }
  20229     }
  20230 #endif /* BCM_TRIUMPH2_SUPPORT  */
  20231 
  20232     if (soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, MTU_VALUEf) ||
  20233                          soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, COMMON__MTU_VALUEf)) {
  20234         rv = _bcm_tr_mpls_port_mtu_get(unit, vp, &mpls_port->mtu);
  20235         BCM_IF_ERROR_RETURN(rv);
  20236     }
  20237 
  20238     /* Get the match parameters */
  20239     rv = _bcm_esw_mpls_match_get(unit, mpls_port,
  20240           vpless_failover_port == FALSE? vp: 
  20241           _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(vp));
  20242     BCM_IF_ERROR_RETURN(rv);
  20243 
  20244     /* Check for Network-Port */
  20245     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  20246     if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
  20247         split_horizon_port_flag = TRUE;
  20248     }
  20249 
  20250     /* Get the next-hop parameters */
  20251     rv = _bcm_tr_mpls_l2_nh_info_get(unit, vp, mpls_port, nh_index);
  20252     BCM_IF_ERROR_RETURN(rv);
  20253 
  20254     if ((mpls_port->egress_label.flags & BCM_MPLS_EGRESS_LABEL_ENTROPY_ENABLE) &&
  20255         (mpls_port->flags2 & BCM_MPLS_PORT2_INGRESS_ENTROPY_ENABLE)) {
  20256         mpls_port->flags |= BCM_MPLS_PORT_ENTROPY_ENABLE;
  20257     }
  20258 
  20259     if(nh_index>0)
  20260         mpls_port->encap_id = nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
  20261     /* Fill in SVP parameters */
  20262     BCM_IF_ERROR_RETURN (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
  20263     mpls_port->if_class = soc_SOURCE_VPm_field32_get(unit, &svp, CLASS_IDf);
  20264     if (split_horizon_port_flag) {
  20265         mpls_port->flags |= BCM_MPLS_PORT_NETWORK;
  20266     }
  20267 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  20268     if (soc_feature(unit, soc_feature_global_meter)) {
  20269         _bcm_esw_get_policer_from_table(unit, SOURCE_VPm, vp, &svp, 
  20270                                                     &mpls_port->policer_id, 1); 
  20271     }
  20272 #endif
  20273     if (soc_SOURCE_VPm_field32_get(unit, &svp, SD_TAG_MODEf)) {
  20274 #if defined(BCM_TRIDENT3_SUPPORT)
  20275         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  20276             uint32 svp_attrs_1[SOC_MAX_MEM_WORDS];
  20277 
  20278             BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit,
  20279                         MEM_BLOCK_ANY, vp, svp_attrs_1));
  20280             soc_SVP_ATTRS_1m_field_get(unit,
  20281                     &svp_attrs_1, TPID_ENABLEf, (uint32 *)&tpid_enable);
  20282         } else
  20283 #endif
  20284         {
  20285         tpid_enable = soc_SOURCE_VPm_field32_get(unit, &svp, TPID_ENABLEf);
  20286         }
  20287         if (tpid_enable) {
  20288             mpls_port->flags |= BCM_MPLS_PORT_SERVICE_TAGGED;
  20289             if (!((mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_ADD) ||
  20290                   (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_TPID_REPLACE) ||
  20291                   (mpls_port->flags & BCM_MPLS_PORT_SERVICE_TPID_REPLACE) ||
  20292                   (mpls_port->flags & BCM_MPLS_PORT_SERVICE_VLAN_PRI_TPID_REPLACE))) {
  20293                 for (i = 0; i < 4; i++) {
  20294                     if (tpid_enable & (1 << i)) {
  20295                         _bcm_fb2_outer_tpid_entry_get(unit, &mpls_port->service_tpid, i);
  20296                     }
  20297                 }
  20298             }
  20299         }
  20300     }
  20301 
  20302 #if defined(BCM_TRIDENT3_SUPPORT)
  20303     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  20304         rv = bcmi_egr_dvp_attribute_nwgroup_get(unit, vp, &nw_group);
  20305         if (rv == BCM_E_NONE) {
  20306             mpls_port->network_group_id = nw_group;
  20307         }
  20308     }
  20309 #endif
  20310 
  20311     return rv;
  20312 }
  20313 
  20314 /*
  20315  * Function:
  20316  *      bcm_mpls_port_get
  20317  * Purpose:
  20318  *      Get an mpls port from a VPN
  20319  * Parameters:
  20320  *      unit       - (IN) Device Number
  20321  *      vpn        - (IN) VPN instance ID
  20322  *      mpls_port  - (IN/OUT) mpls port information
  20323  */
  20324 int
  20325 bcm_tr_mpls_port_get(int unit, bcm_vpn_t vpn, bcm_mpls_port_t *mpls_port)
  20326 {
  20327     int vp;
  20328 
  20329     if (!_BCM_MPLS_VPN_IS_VPLS(vpn) && 
  20330          !_BCM_MPLS_VPN_IS_VPWS(vpn)) {
  20331         if ((vpn != BCM_MPLS_VPWS_VPN_INVALID) && 
  20332             (vpn != BCM_MPLS_VPLS_VPN_INVALID)) {
  20333             return BCM_E_PARAM;
  20334         }
  20335     }
  20336 
  20337     vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->mpls_port_id);
  20338     if (vp == -1) {
  20339         return BCM_E_PARAM;
  20340     }
  20341 
  20342     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  20343         return BCM_E_NOT_FOUND;
  20344     }
  20345     if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(mpls_port->mpls_port_id)) {
  20346         vp = _BCM_MPLS_GPORT_FAILOVER_VPLESS_SET(vp);
  20347     }
  20348     return _bcm_tr_mpls_port_get(unit, vpn, vp, mpls_port);
  20349 }
  20350 
  20351 /*
  20352  * Function:
  20353  *      bcm_mpls_port_get_all
  20354  * Purpose:
  20355  *      Get all mpls ports from a VPN
  20356  * Parameters:
  20357  *      unit     - (IN) Device Number
  20358  *      vpn      - (IN) VPN instance ID
  20359  *      port_max   - (IN) Maximum number of interfaces in array
  20360  *      port_array - (OUT) Array of mpls ports
  20361  *      port_count - (OUT) Number of interfaces returned in array
  20362  */
  20363 int
  20364 bcm_tr_mpls_port_get_all(int unit, bcm_vpn_t vpn, int port_max,
  20365                          bcm_mpls_port_t *port_array, int *port_count)
  20366 {
  20367     int vp, rv = BCM_E_NONE;
  20368     int vp1=-1, vp2=-1, vp3_read = -1;
  20369 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  20370     SHR_BITDCL *share_vp_bitmap = NULL;
  20371 #endif
  20372 
  20373     if (!_BCM_MPLS_VPN_IS_VPLS(vpn) && 
  20374          !_BCM_MPLS_VPN_IS_VPWS(vpn)) {
  20375         return BCM_E_PARAM;
  20376     }
  20377 
  20378     *port_count = 0;
  20379 
  20380     if (_BCM_MPLS_VPN_IS_VPWS(vpn)) {
  20381         bcm_vpn_t   vpn_id;
  20382 
  20383         _BCM_MPLS_VPN_GET(vpn_id, _BCM_MPLS_VPN_TYPE_VPWS, vpn);
  20384 
  20385         (void) _bcm_tr_mpls_vpws_vp_map_get (unit, vpn_id, &vp1, &vp2, &vp3_read);
  20386 
  20387         vp = vp1;
  20388         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  20389             if (*port_count < port_max) {
  20390                 rv = _bcm_tr_mpls_port_get(unit, vpn, vp, 
  20391                                            &port_array[*port_count]);
  20392                 if (rv < 0) {
  20393                     goto done;
  20394                 }
  20395                 (*port_count)++;
  20396             }
  20397         }
  20398 
  20399         vp = vp2;
  20400         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  20401             if (*port_count < port_max) {
  20402                 rv = _bcm_tr_mpls_port_get(unit, vpn, vp, 
  20403                                            &port_array[*port_count]);
  20404                 if (rv < 0) {
  20405                     goto done;
  20406                 }
  20407                 (*port_count)++;
  20408             }
  20409         }
  20410 
  20411         vp = vp3_read;
  20412         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  20413             if (*port_count < port_max) {
  20414                 rv = _bcm_tr_mpls_port_get(unit, vpn, vp, 
  20415                                            &port_array[*port_count]);
  20416                 if (rv < 0) {
  20417                     goto done;
  20418                 }
  20419                 (*port_count)++;
  20420             }
  20421         }
  20422     } else if (_BCM_MPLS_VPN_IS_VPLS(vpn)) {
  20423         uint32 vfi, entry_type;
  20424         int num_vp;
  20425         source_vp_entry_t svp;
  20426         int vpls_vpn_min = 0;
  20427         int vpls_vpn_max = 0;
  20428 
  20429         _BCM_MPLS_VPN_SET(vpls_vpn_min, _BCM_MPLS_VPN_TYPE_VPLS, 0);
  20430         vpls_vpn_max = soc_mem_index_count(unit, VFIm) + vpls_vpn_min - 1;
  20431         if (vpn < vpls_vpn_min || vpn > vpls_vpn_max) {
  20432             return BCM_E_PARAM;
  20433         }
  20434 
  20435         _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vpn);
  20436 
  20437         if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
  20438             rv = BCM_E_NOT_FOUND;
  20439             goto done;
  20440         }
  20441         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  20442 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  20443         /*get sharing VP bitmap*/
  20444         share_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "sharr_vp_bitmap");
  20445         if (share_vp_bitmap == NULL) {
  20446             return BCM_E_MEMORY;
  20447         }
  20448         sal_memset(share_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
  20449 
  20450         if (soc_feature(unit, soc_feature_vp_sharing)) {
  20451             rv = bcm_tr_mpls_share_vp_bitmap_get(unit, vpn, share_vp_bitmap);
  20452             if (rv < 0) {
  20453                 goto cleanup;
  20454             }
  20455         }
  20456 #endif
  20457         for (vp = 0; vp < num_vp; vp++) {
  20458             if (*port_count == port_max) {
  20459                 break;
  20460             }
  20461 
  20462             if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  20463                 continue;
  20464             }
  20465 
  20466             rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
  20467             if (rv < 0) {
  20468                 goto cleanup;
  20469             }
  20470             entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf);
  20471 
  20472             if ((vfi == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf) && entry_type == 0x1)
  20473 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  20474                      || SHR_BITGET(share_vp_bitmap, vp)
  20475 #endif
  20476             ) {
  20477                 rv = _bcm_tr_mpls_port_get(unit, vpn, vp, 
  20478                                            &port_array[*port_count]);
  20479                 if (rv < 0) {
  20480                     goto cleanup;
  20481                 }
  20482                 (*port_count)++;
  20483             }
  20484         }
  20485         cleanup:;
  20486 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  20487           sal_free(share_vp_bitmap);
  20488 #endif
  20489     }
  20490   done:
  20491     return rv;
  20492 }
  20493 
  20494 /*
  20495  * Function:
  20496  *      _bcm_tr_mpls_port_resolve
  20497  * Purpose:
  20498  *      Get the modid, port, trunk values for a MPLS port
  20499  * Returns:
  20500  *      BCM_E_XXX
  20501  */
  20502 int
  20503 _bcm_tr_mpls_port_resolve(int unit, bcm_gport_t mpls_port_id, 
  20504                           bcm_module_t *modid, bcm_port_t *port,
  20505                           bcm_trunk_t *trunk_id, int *id)
  20506 
  20507 {
  20508     int rv = BCM_E_NONE, nh_index, vp;
  20509     ing_l3_next_hop_entry_t ing_nh;
  20510     ing_dvp_table_entry_t dvp;
  20511     uint32 dest_type, dest_val;
  20512 
  20513     if(!SOC_WARM_BOOT(unit)) {
  20514         /* Warmboot re-init is in progress. So skip init check */
  20515         rv = _bcm_tr_mpls_check_init (unit);
  20516         if (rv < 0) {
  20517             return rv;
  20518         }
  20519     }
  20520 
  20521     if (!BCM_GPORT_IS_MPLS_PORT(mpls_port_id)) {
  20522         return (BCM_E_BADID);
  20523     }
  20524 
  20525     vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port_id);
  20526     if (vp == -1) {
  20527        return BCM_E_PARAM;
  20528     }
  20529 
  20530     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  20531         return BCM_E_NOT_FOUND;
  20532     }
  20533     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
  20534     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 
  20535                                               NEXT_HOP_INDEXf);
  20536     BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY,
  20537                                       nh_index, &ing_nh));
  20538 
  20539     if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf) != 0x2) {
  20540         /* Entry type is not L2 DVP */
  20541         return BCM_E_NOT_FOUND;
  20542     }
  20543 
  20544     if (soc_feature(unit, soc_feature_generic_dest)) {
  20545         dest_val = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm,
  20546                 &ing_nh, DESTINATIONf, &dest_type);
  20547         if (dest_type == SOC_MEM_FIF_DEST_LAG) {
  20548             /* Trunk group */
  20549             *trunk_id = dest_val & SOC_MEM_FIF_DGPP_TGID_MASK;
  20550 
  20551         } else {
  20552             *port  = dest_val & SOC_MEM_FIF_DGPP_PORT_MASK;
  20553             *modid = (dest_val & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
  20554                 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
  20555         }
  20556     } else {
  20557     if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
  20558         *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf);
  20559     } else {
  20560         /* Only add this to replication set if destination is local */
  20561         *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
  20562         *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf);
  20563     }
  20564     }
  20565     *id = vp;
  20566     return rv;
  20567 }
  20568 
  20569 void 
  20570 bcm_tr_mpls_port_match_count_adjust(int unit, int vp, int step)
  20571 {
  20572     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  20573  
  20574     mpls_info->match_key[vp].match_count += step;
  20575 }
  20576 
  20577 static soc_field_t _tnl_label_f[] =
  20578 { MPLS_LABEL_0f, MPLS_LABEL_1f, MPLS_LABEL_2f, MPLS_LABEL_3f,
  20579   MPLS_LABEL_4f, MPLS_LABEL_5f, MPLS_LABEL_6f, MPLS_LABEL_7f };
  20580 static soc_field_t _tnl_exp_select_f[] =
  20581 { MPLS_EXP_SELECT_0f, MPLS_EXP_SELECT_1f, 
  20582   MPLS_EXP_SELECT_2f, MPLS_EXP_SELECT_3f,
  20583   MPLS_EXP_SELECT_4f, MPLS_EXP_SELECT_5f,
  20584   MPLS_EXP_SELECT_6f, MPLS_EXP_SELECT_7f };
  20585 static soc_field_t _tnl_exp_ptr_f[] =   
  20586 { MPLS_EXP_MAPPING_PTR_0f, MPLS_EXP_MAPPING_PTR_1f, 
  20587   MPLS_EXP_MAPPING_PTR_2f, MPLS_EXP_MAPPING_PTR_3f,
  20588   MPLS_EXP_MAPPING_PTR_4f, MPLS_EXP_MAPPING_PTR_5f,
  20589   MPLS_EXP_MAPPING_PTR_6f, MPLS_EXP_MAPPING_PTR_7f };
  20590 static soc_field_t _tnl_exp_f[] =    
  20591 { MPLS_EXP_0f, MPLS_EXP_1f, MPLS_EXP_2f, MPLS_EXP_3f,
  20592   MPLS_EXP_4f, MPLS_EXP_5f, MPLS_EXP_6f, MPLS_EXP_7f};
  20593 static soc_field_t _tnl_ttl_f[] =
  20594 { MPLS_TTL_0f, MPLS_TTL_1f, MPLS_TTL_2f, MPLS_TTL_3f,
  20595   MPLS_TTL_4f, MPLS_TTL_5f, MPLS_TTL_6f, MPLS_TTL_7f};
  20596 static soc_field_t _tnl_pri_f[] = 
  20597 { NEW_PRI_0f, NEW_PRI_1f, NEW_PRI_2f, NEW_PRI_3f,
  20598   NEW_PRI_4f, NEW_PRI_5f, NEW_PRI_6f, NEW_PRI_7f};
  20599 static soc_field_t _tnl_cfi_f[] = 
  20600 { NEW_CFI_0f, NEW_CFI_1f, NEW_CFI_2f, NEW_CFI_3f,
  20601   NEW_CFI_4f, NEW_CFI_5f, NEW_CFI_6f, NEW_CFI_7f};
  20602 
  20603 /*  
  20604  * Function:
  20605  *      bcm_tr_mpls_tunnel_intf_valid
  20606  * Purpose:
  20607  *      Set MPLS Tunnel
  20608  * Parameters:
  20609  *      unit - Device Number
  20610  *      nh_index - Next Hop Index
  20611  * Returns:
  20612  *      BCM_E_XXX
  20613  */
  20614 
  20615 int
  20616 bcm_tr_mpls_tunnel_intf_valid (int unit, int nh_index)
  20617 {
  20618     egr_ip_tunnel_mpls_entry_t tnl_entry;
  20619     egr_l3_intf_entry_t if_entry;
  20620     egr_l3_next_hop_entry_t egr_nh;
  20621 #ifdef BCM_TOMAHAWK3_SUPPORT
  20622     egr_l3_next_hop_2_entry_t egr_nh_2;
  20623 #endif
  20624     bcm_if_t   l3_intf = 0;
  20625     int  tnl_index = 0, mpls_index = 0;
  20626 #ifdef BCM_TRIDENT3_SUPPORT
  20627     egr_ip_tunnel_mpls_double_wide_entry_t tnl_entry_double;
  20628 #endif
  20629 
  20630     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  20631                                       nh_index, &egr_nh));
  20632     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  20633         l3_intf = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  20634                 L3__INTF_NUMf);
  20635     } else
  20636 #ifdef BCM_TOMAHAWK3_SUPPORT
  20637     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  20638          BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOP_2m, MEM_BLOCK_ANY,
  20639                                       nh_index, &egr_nh_2));
  20640          l3_intf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOP_2m, &egr_nh_2,
  20641                 INTF_NUMf);
  20642     } else
  20643 #endif
  20644     {
  20645     l3_intf = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, 
  20646                                              INTF_NUMf);
  20647     }
  20648 
  20649     if (!BCM_L3_INTF_USED_GET(unit, l3_intf)) {
  20650         return BCM_E_NOT_FOUND;
  20651     }
  20652 
  20653     BCM_IF_ERROR_RETURN ( READ_EGR_L3_INTFm(unit, 
  20654                                  MEM_BLOCK_ANY, l3_intf, &if_entry));
  20655     mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry, 
  20656                                               MPLS_TUNNEL_INDEXf);
  20657     tnl_index = mpls_index / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit);
  20658 
  20659     if ((mpls_index != 0) && (_BCM_MPLS_TNL_USED_GET(unit, mpls_index))) {
  20660 #if defined(BCM_TRIDENT3_SUPPORT)
  20661         if (SOC_MEM_IS_VALID(unit, EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm)) {
  20662             BCM_IF_ERROR_RETURN(
  20663                     READ_EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm(unit,
  20664                         MEM_BLOCK_ANY,
  20665                         tnl_index, &tnl_entry_double));
  20666             if (soc_mem_field32_get(unit,
  20667                         EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm,
  20668                         &tnl_entry_double,
  20669                         DATA_TYPEf) == 0x14) {
  20670                 return BCM_E_NONE;
  20671             }
  20672         } else
  20673 #endif
  20674         {
  20675          BCM_IF_ERROR_RETURN (READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 
  20676                                       tnl_index, &tnl_entry));
  20677          if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  20678                                 ENTRY_TYPEf) == 3) {
  20679               return BCM_E_NONE;
  20680          }
  20681     }
  20682     }
  20683     return BCM_E_NOT_FOUND;
  20684 }
  20685 
  20686 /*
  20687  * Function:
  20688  *      _bcm_tr_mpls_egr_tunnel_ref_count_adjust
  20689  * Purpose:
  20690  *      Increment / Decrement Reference Count for Egress Tunnel
  20691  * Parameters:
  20692  *      unit              Unit number
  20693  *      index            (IN) Entry Index
  20694  *      step              (IN) usage reference
  20695  */
  20696 
  20697 STATIC void 
  20698 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (int unit, int index, int step)
  20699 {
  20700     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  20701  
  20702     if (( mpls_info->egr_tunnel_ref_count[index] == 0 ) && (step < 0)) {
  20703          mpls_info->egr_tunnel_ref_count[index] = 0;
  20704     } else {
  20705          mpls_info->egr_tunnel_ref_count[index] += step;
  20706     }
  20707 
  20708 }
  20709 
  20710 /*
  20711  * Function:
  20712  *      _bcm_tr_mpls_egr_tunnel_ref_count_reset
  20713  * Purpose:
  20714  *      reset the reference Count 
  20715  * Parameters:
  20716  *      unit              Unit number
  20717  *      index            (IN) Entry Index
  20718  */
  20719 
  20720 STATIC void
  20721 _bcm_tr_mpls_egr_tunnel_ref_count_reset (int unit, int index)
  20722 {
  20723     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  20724 
  20725     mpls_info->egr_tunnel_ref_count[index] = 0;
  20726 }
  20727 
  20728 /*
  20729  * Function:
  20730  *      _bcm_tr_mpls_egr_tunnel_ref_count_get
  20731  * Purpose:
  20732  *      get the current reference Count
  20733  * Parameters:
  20734  *      unit              Unit number
  20735  *      index            (IN) Entry Index
  20736  */
  20737 
  20738 STATIC void
  20739 _bcm_tr_mpls_egr_tunnel_ref_count_get (int unit, int index, int *cnt_value)
  20740 {
  20741     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  20742 
  20743     *cnt_value = mpls_info->egr_tunnel_ref_count[index];
  20744 }
  20745 
  20746 /*
  20747  * Function:
  20748  *           _bcm_tr_mpls_get_vc_and_swap_table_index
  20749  * Purpose:
  20750  *           Obtain Index into  EGR_IP_TUNNEL_MPLS
  20751  * Parameters:
  20752  *           IN :  Unit
  20753  *           IN :  push_action
  20754  *           IN :  label_array
  20755  *           OUT : match_mpls_tunnel_index
  20756  * Returns:
  20757  *      BCM_E_XXX
  20758  */
  20759 
  20760 STATIC int
  20761 _bcm_tr_mpls_egr_tunnel_lookup (int unit, int push_action, 
  20762                                           bcm_mpls_egress_label_t *label_array,
  20763                                           int *match_mpls_tunnel_index)
  20764 {
  20765     uint32 label_value[8];
  20766     uint32 entry_ttl, entry_exp, entry_push_action;
  20767     int num_ip_tnl;
  20768     int i = 0, tnl_index = -1, mpls_index = -1;
  20769     egr_ip_tunnel_mpls_entry_t tnl_entry;
  20770 
  20771     num_ip_tnl = soc_mem_index_count(unit, EGR_IP_TUNNEL_MPLSm);
  20772 
  20773     /* parameter checking */
  20774     if (push_action != 0 && label_array == NULL) {
  20775         return BCM_E_PARAM;
  20776     }
  20777 
  20778     for (tnl_index = 0; tnl_index < num_ip_tnl; tnl_index++) {
  20779          BCM_IF_ERROR_RETURN(
  20780               READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 
  20781                              tnl_index, &tnl_entry));
  20782               if (!_BCM_MPLS_IP_TNL_USED_GET(unit, tnl_index)) {
  20783                 continue;
  20784               }
  20785               if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  20786                                 ENTRY_TYPEf) != 3) {
  20787                     return BCM_E_INTERNAL;
  20788               }
  20789          mpls_index = tnl_index * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit);
  20790          for (i = 0; i <  _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); i++) {
  20791               if (!(_BCM_MPLS_TNL_USED_GET(unit, mpls_index))) {
  20792                     mpls_index++;
  20793                     continue;
  20794               }
  20795               label_value[i] = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 
  20796                             &tnl_entry, _tnl_label_f[i]);
  20797               entry_ttl = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 
  20798                             &tnl_entry, _tnl_ttl_f[i]);
  20799               entry_exp = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 
  20800                             &tnl_entry, _tnl_exp_f[i]);
  20801               entry_push_action = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm,
  20802                             &tnl_entry, _tnl_push_action_f[i]);
  20803 
  20804               if ((push_action == 0x2) &&
  20805                   (i < (_BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit) - 1)) &&
  20806                   (_BCM_MPLS_TNL_USED_GET(unit, mpls_index+1))){
  20807                    /* Match 2 consecutive label entries. */
  20808                   label_value[i+1] = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, 
  20809                             &tnl_entry, _tnl_label_f[i+1]);
  20810                   if ( (label_array[0].label == label_value[i]) && 
  20811                         (label_array[1].label == label_value[i+1]) &&
  20812                         (push_action == entry_push_action)) {
  20813                        *match_mpls_tunnel_index = (tnl_index * 
  20814                                _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)) + i;
  20815                        return BCM_E_NONE;
  20816                    }
  20817               } else if (push_action == 0x1) {
  20818                    if ((label_array[0].label == label_value[i]) &&
  20819                        (label_array[0].ttl == entry_ttl) &&
  20820                        (label_array[0].exp == entry_exp) &&
  20821                        (push_action == entry_push_action)) {
  20822                        *match_mpls_tunnel_index = (tnl_index * 
  20823                                _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)) + i;
  20824                        return BCM_E_NONE;
  20825                    }
  20826               } else if (push_action == 0x0) {
  20827                    /* Case of Dummy entry */
  20828                    if ((0 == label_value[i]) &&
  20829                        (0 == entry_ttl) &&
  20830                        (0 == entry_exp) &&
  20831                        (0 == entry_push_action)) {
  20832                        *match_mpls_tunnel_index = (tnl_index * 
  20833                                _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)) + i;
  20834                        return BCM_E_NONE;
  20835                    }
  20836               }
  20837               mpls_index++;
  20838          }
  20839     }
  20840     return BCM_E_NONE;
  20841 }
  20842 
  20843 /*
  20844  * Function:
  20845  *           _tr_mpls_tunnel_entry_copy
  20846  * Purpose:
  20847  *           Copy a source EGR_IP_TUNNEL_MPLS table entry to the
  20848              destination. 
  20849  * Parameters:
  20850  *           IN :  Unit
  20851  *           IN :  dst_mpls_inx - destination tunnel mpls index
  20852  *           OUT : dst_entry    - destination tunnel entry
  20853  *           IN :  src_mpls_inx - source tunnel mpls index
  20854  *           IN :  src_entry    - source tunnel entry
  20855  * Returns:
  20856  *      BCM_E_XXX
  20857  */
  20858 
  20859 STATIC int
  20860 _tr_mpls_tunnel_entry_copy (int unit, int dst_mpls_inx,
  20861                          egr_ip_tunnel_mpls_entry_t *dst_entry,
  20862                          int src_mpls_inx,
  20863                          egr_ip_tunnel_mpls_entry_t *src_entry)
  20864 {
  20865     int dst_offset;
  20866     int src_offset;
  20867     int src_value;
  20868 
  20869     dst_offset = dst_mpls_inx &
  20870         _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit);
  20871     src_offset = src_mpls_inx &
  20872         _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit);
  20873 
  20874     src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry,
  20875                   _tnl_push_action_f[src_offset]);
  20876     soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry,
  20877                   _tnl_push_action_f[dst_offset], src_value);
  20878     src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry,
  20879                   _tnl_label_f[src_offset]);
  20880     soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 
  20881                   _tnl_label_f[dst_offset], src_value);
  20882     src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry,
  20883                   _tnl_exp_select_f[src_offset]);
  20884     soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 
  20885                   _tnl_exp_select_f[dst_offset], src_value);
  20886     src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry,
  20887                   _tnl_exp_f[src_offset]);
  20888     soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 
  20889                   _tnl_exp_f[dst_offset], src_value);
  20890     src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry,
  20891                   _tnl_pri_f[src_offset]);
  20892     soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 
  20893                   _tnl_pri_f[dst_offset], src_value);
  20894     src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry,
  20895                   _tnl_cfi_f[src_offset]);
  20896     soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 
  20897                   _tnl_cfi_f[dst_offset], src_value);
  20898     src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry,
  20899                   _tnl_exp_ptr_f[src_offset]);
  20900     soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 
  20901                   _tnl_exp_ptr_f[dst_offset], src_value);
  20902     src_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, src_entry,
  20903                   _tnl_ttl_f[src_offset]);
  20904     soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, dst_entry, 
  20905                   _tnl_ttl_f[dst_offset], src_value);
  20906     return BCM_E_NONE;
  20907 }
  20908 
  20909 /*
  20910  * Function:
  20911  *           _tr_egr_l3_intf_tunnel_index_replace
  20912  * Purpose:
  20913  *           Traverse the EGR_L3_INTF table to replace the old tunnel 
  20914  *           index with the new index. 
  20915  * Parameters:
  20916  *           IN :  Unit
  20917  *           IN :  old_mpls_inx - old tunnel mpls index
  20918  *           IN :  new_mpls_inx - new tunnel mpls index
  20919  * Returns:
  20920  *      BCM_E_XXX
  20921  */
  20922 STATIC int
  20923 _tr_egr_l3_intf_tunnel_index_replace (int unit, int old_mpls_inx, 
  20924                             int new_mpls_inx)
  20925 {
  20926     /* Indexes to iterate over memories, chunks and entries */
  20927     int             chnk_idx, ent_idx, chnk_idx_max, mem_idx_max;
  20928     int             buf_size, chunksize, chnk_end;
  20929     uint32          *tbl_chnk;
  20930     uint32          *el3inf_entry;
  20931     int             rv = BCM_E_NONE;
  20932     soc_mem_t mem;
  20933     int mpls_inx;
  20934 
  20935     mem = EGR_L3_INTFm;
  20936 
  20937     chunksize = 0x400; /* 1k */
  20938     buf_size = sizeof(egr_l3_intf_entry_t) * chunksize;
  20939     tbl_chnk = soc_cm_salloc(unit, buf_size, "egr_l3_intf traverse");
  20940     if (NULL == tbl_chnk) {
  20941         return BCM_E_MEMORY;
  20942     }
  20943 
  20944     mem_idx_max = soc_mem_index_max(unit, mem);
  20945     for (chnk_idx = soc_mem_index_min(unit, mem);
  20946          chnk_idx <= mem_idx_max;
  20947          chnk_idx += chunksize) {
  20948         sal_memset((void *)tbl_chnk, 0, buf_size);
  20949 
  20950         chnk_idx_max =
  20951             ((chnk_idx + chunksize) <= mem_idx_max) ?
  20952             chnk_idx + chunksize - 1: mem_idx_max;
  20953 
  20954         soc_mem_lock(unit, mem);
  20955         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
  20956                                 chnk_idx, chnk_idx_max, tbl_chnk);
  20957         if (SOC_FAILURE(rv)) {
  20958             soc_mem_unlock(unit, mem);
  20959             break;
  20960         }
  20961         chnk_end = (chnk_idx_max - chnk_idx);
  20962         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
  20963             el3inf_entry =
  20964                 soc_mem_table_idx_to_pointer(unit, mem, uint32 *,
  20965                                              tbl_chnk, ent_idx);
  20966 
  20967             mpls_inx = soc_mem_field32_get(unit, mem, el3inf_entry, 
  20968                                             MPLS_TUNNEL_INDEXf);
  20969 
  20970             if (mpls_inx != old_mpls_inx) {
  20971                 continue;
  20972             }
  20973             /* replace with new tunnel index */
  20974             soc_mem_field32_set(unit, mem,el3inf_entry, 
  20975                                 MPLS_TUNNEL_INDEXf, new_mpls_inx);
  20976             rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, chnk_idx+ent_idx, 
  20977                                 el3inf_entry);
  20978             if (BCM_FAILURE(rv)) {
  20979                 break;
  20980             }
  20981         }
  20982         soc_mem_unlock(unit, mem);
  20983         if (BCM_FAILURE(rv)) {
  20984             break;
  20985         }
  20986     }
  20987     soc_cm_sfree(unit, tbl_chnk);
  20988     return rv;
  20989 }
  20990 
  20991 /*
  20992  * Function:
  20993  *           _tr_egr_tunnel_mpls_free_slots_reorder
  20994  * Purpose:
  20995  *           Re-arrange two non-consecutive free slots in EGR_TUNNEL_MPLS table
  20996  *           to make it consective for the purpose of pushing two labels. 
  20997  *           This involves to move a occupied slot ajacent to the first free slot
  20998  *           to the second free slot and traverse the EGR_L3_INTF table to 
  20999  *           replace the tunnel index accordingly.
  21000  * Parameters:
  21001  *           IN :  Unit
  21002  *           IN :  free_slot1 - first free slot 
  21003  *           IN :  free_slot2 - second free slot
  21004  *           IN :  src_tnl_entry - tunnel entry with first free MPLS slot
  21005  * Returns:
  21006  *      BCM_E_XXX
  21007  */
  21008 STATIC int
  21009 _tr_egr_tunnel_mpls_free_slots_reorder (int unit, int free_slot1, int free_slot2,
  21010                     egr_ip_tunnel_mpls_entry_t *src_tnl_entry)
  21011 {
  21012     int src_tnl_mpls_inx;
  21013     int dst_tnl_mpls_inx;
  21014     int ref_count;
  21015     int rv;
  21016     egr_ip_tunnel_mpls_entry_t dst_tnl_entry;
  21017 
  21018     if (free_slot1 & 0x1) { /* need to free even entry above */
  21019         src_tnl_mpls_inx = free_slot1 - 1;
  21020     } else { /* free odd entry below */
  21021         src_tnl_mpls_inx = free_slot1 + 1;
  21022     }
  21023     dst_tnl_mpls_inx = free_slot2;
  21024 
  21025     /* read destination  tunnel entry */
  21026     rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY,
  21027             (dst_tnl_mpls_inx / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)),
  21028             &dst_tnl_entry);
  21029     BCM_IF_ERROR_RETURN(rv);
  21030 
  21031     /* copy the source mpls entry to the destination */
  21032     rv = _tr_mpls_tunnel_entry_copy(unit,dst_tnl_mpls_inx,&dst_tnl_entry,
  21033                                  src_tnl_mpls_inx,src_tnl_entry);
  21034     BCM_IF_ERROR_RETURN(rv);
  21035 
  21036     /* write the destination entry to HW */
  21037     rv = WRITE_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY,
  21038             (dst_tnl_mpls_inx / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)),
  21039              &dst_tnl_entry);
  21040     BCM_IF_ERROR_RETURN(rv);
  21041 
  21042     /* now search the egr_l3_intf table to update the new tunnel index */
  21043     rv = _tr_egr_l3_intf_tunnel_index_replace(unit,
  21044                           src_tnl_mpls_inx,dst_tnl_mpls_inx);
  21045     BCM_IF_ERROR_RETURN(rv);
  21046 
  21047     /* get the moved entry's original ref counter number */
  21048     _bcm_tr_mpls_egr_tunnel_ref_count_get (unit, 
  21049                             src_tnl_mpls_inx,&ref_count);
  21050     _bcm_tr_mpls_egr_tunnel_ref_count_reset (unit, src_tnl_mpls_inx);
  21051     _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 
  21052                             dst_tnl_mpls_inx, ref_count);
  21053     _BCM_MPLS_TNL_USED_SET(unit, dst_tnl_mpls_inx);
  21054     _BCM_MPLS_TNL_USED_CLR(unit, src_tnl_mpls_inx);
  21055     return rv;
  21056 }
  21057 
  21058 /*  
  21059  * Function:
  21060  *      bcm_mpls_tunnel_initiator_set
  21061  * Purpose:
  21062  *      Set MPLS Tunnel initiator
  21063  * Parameters:
  21064  *      unit - Device Number
  21065  *      intf - The egress L3 interface
  21066  *      num_labels  - Number of labels in the array
  21067  *      label_array - Array of MPLS label and header information
  21068  * Returns:
  21069  *      BCM_E_XXX
  21070  */
  21071 int
  21072 bcm_tr_mpls_tunnel_initiator_set(int unit, bcm_if_t intf, int num_labels,
  21073                                  bcm_mpls_egress_label_t *label_array)
  21074 {
  21075     egr_ip_tunnel_mpls_entry_t tnl_entry;
  21076     egr_l3_intf_entry_t if_entry;
  21077     int rv, i, num_mpls_map, num_ip_tnl, push_action=0, offset;
  21078     int found = 0, tnl_index = 0, mpls_index = 0;
  21079     int hw_map_idx;
  21080     bcm_tunnel_initiator_t tnl_init;
  21081     uint32 tnl_flags;
  21082     int old_push_act_value;
  21083     int match_mpls_tunnel_index=-1;
  21084     int free_slot1;
  21085     int free_slot2;
  21086 
  21087     if ((num_labels < 0) || (num_labels > 2)  ||
  21088         (intf < 0) || (intf >= L3_INFO(unit)->l3_intf_table_size)) {
  21089         return BCM_E_PARAM;
  21090     }
  21091 
  21092     if (num_labels == 2) {
  21093         push_action = 0x2; /* push 2 labels */
  21094     } else if (num_labels == 1) {
  21095         push_action = 0x1; /* push 1 label */
  21096     } 
  21097 
  21098     /* Param checking */
  21099     num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
  21100     for (i = 0; i < num_labels; i++) {
  21101         if (label_array[i].qos_map_id == 0) { /* treat it as using default */
  21102             hw_map_idx = 0;
  21103         } else {
  21104             BCM_IF_ERROR_RETURN(_egr_qos_id2hw_idx(unit,
  21105                             label_array[i].qos_map_id,&hw_map_idx)); 
  21106         }
  21107         if ((label_array[i].label > 0xfffff) ||
  21108             (hw_map_idx < 0) ||
  21109             (hw_map_idx >= num_mpls_map) ||
  21110             (label_array[i].exp > 7) || (label_array[i].pkt_pri > 7) ||
  21111             (label_array[i].pkt_cfi > 1)) {
  21112             return BCM_E_PARAM;
  21113         }
  21114     }
  21115 
  21116     if (!BCM_L3_INTF_USED_GET(unit, intf)) {
  21117         LOG_INFO(BSL_LS_BCM_L3,
  21118                  (BSL_META_U(unit,
  21119                              "L3 interface not created\n")));
  21120         return BCM_E_NOT_FOUND;
  21121     }
  21122 
  21123     /* L3 interface info */
  21124     rv = READ_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf, &if_entry);
  21125     if (rv < 0) {
  21126         return rv;
  21127     }
  21128 
  21129    /* init the allocated entry */
  21130    sal_memset(&tnl_entry, 0, sizeof(egr_ip_tunnel_mpls_entry_t));
  21131 
  21132    /* Case of Dummy Tunnel entry sharing by multiple L3_INTF */
  21133    if (num_labels == 0) {
  21134            /* Lookup if Tunnel Entry with Tunnel Label exists? */
  21135            rv = _bcm_tr_mpls_egr_tunnel_lookup (unit, push_action,
  21136                                    NULL, &match_mpls_tunnel_index);
  21137            if (rv < 0) {
  21138               return rv;
  21139            }
  21140 
  21141            if (match_mpls_tunnel_index != -1) {
  21142                /* L3_Interface to point to mpls_tunnel */
  21143                soc_EGR_L3_INTFm_field32_set(unit, &if_entry,
  21144                                      MPLS_TUNNEL_INDEXf, match_mpls_tunnel_index);
  21145                /* Increment Ref count */
  21146                _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 
  21147                                                    match_mpls_tunnel_index, 1);
  21148                rv = WRITE_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf, &if_entry);
  21149                return rv;
  21150            }
  21151    }
  21152 
  21153    for (i = 0; i < num_labels; i++) {
  21154        /* Check for Port_independent Label mapping */
  21155        rv = bcm_tr_mpls_port_independent_range (unit, label_array[i].label, 
  21156                                                       BCM_GPORT_INVALID);
  21157        /* Either Port-scope-label or Explicit-Null-label */
  21158        if ((rv == BCM_E_CONFIG) || (label_array[i].label == 0)) {
  21159            /* Tunnel-label is Port-based */
  21160            /* Lookup if Tunnel Entry with Tunnel Label exists? */
  21161            rv = _bcm_tr_mpls_egr_tunnel_lookup (unit, push_action,
  21162                                    label_array, &match_mpls_tunnel_index);
  21163            if (rv < 0) {
  21164               return rv;
  21165            }
  21166 
  21167            if (match_mpls_tunnel_index != -1) {
  21168                /* L3_Interface to point to mpls_tunnel */
  21169                soc_EGR_L3_INTFm_field32_set(unit, &if_entry,
  21170                                      MPLS_TUNNEL_INDEXf, match_mpls_tunnel_index);
  21171                /* Increment Ref count */
  21172                _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 
  21173                                                    match_mpls_tunnel_index, 1);
  21174                if (push_action == 2) {
  21175                    _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit,
  21176                                                        match_mpls_tunnel_index+1, 1);
  21177                }
  21178                rv = WRITE_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf, &if_entry);
  21179                return rv;
  21180            }
  21181        }
  21182     }
  21183 
  21184     mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry, 
  21185                                               MPLS_TUNNEL_INDEXf);
  21186     tnl_index = mpls_index / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit);
  21187 
  21188     if ((mpls_index != 0) && (_BCM_MPLS_TNL_USED_GET(unit, mpls_index))) {
  21189        /* Obtain referenced Tunnel entry */ 
  21190         rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 
  21191                                       tnl_index, &tnl_entry);
  21192         if (rv < 0) {
  21193             return rv;
  21194         }
  21195         if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21196                                 ENTRY_TYPEf) != 3) {
  21197             return BCM_E_INTERNAL;
  21198         }
  21199         offset = mpls_index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit);
  21200         old_push_act_value = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm,
  21201                                                  &tnl_entry, _tnl_push_action_f[offset]);
  21202         if (old_push_act_value != push_action) {
  21203             /* Changing push action is not permitted, need to clear/set */
  21204             return BCM_E_PARAM;
  21205         }
  21206     } else {
  21207         /* allocate an unused EGR_IP_TUNNEL_MPLS_ENTRY */
  21208        num_ip_tnl = soc_mem_index_count(unit, EGR_IP_TUNNEL_MPLSm);
  21209 
  21210         /*
  21211          * First try finding an allocated tunnel entry with 
  21212          * unused MPLS entries.
  21213          */
  21214         free_slot1 = -1;
  21215         free_slot2 = -1;
  21216         for (tnl_index = 0; tnl_index < num_ip_tnl; tnl_index++) {
  21217             if (!_BCM_MPLS_IP_TNL_USED_GET(unit, tnl_index)) {
  21218                 continue;
  21219             }
  21220             mpls_index = tnl_index * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit);
  21221             for (i = 0; i < _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); i++) {
  21222                 if (!(_BCM_MPLS_TNL_USED_GET(unit, mpls_index))) {
  21223                     if (free_slot1 == -1) {
  21224                         free_slot1 = mpls_index;
  21225                     } else if (free_slot2 == -1) {
  21226                         free_slot2 = mpls_index;
  21227                     }
  21228                 }
  21229                 if ((push_action == 0x2) &&
  21230                         (i == (_BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit) - 1))) {
  21231                     /* Pushing 2 labels, need 2 consecutive entries. */
  21232                     break;
  21233                 }
  21234                 if (!(_BCM_MPLS_TNL_USED_GET(unit, mpls_index))) {
  21235                     if (push_action == 0x2) {
  21236                         /* Pushing 2 labels, need 2 consecutive entries with even base */
  21237                         if (!(_BCM_MPLS_TNL_USED_GET(unit, mpls_index + 1))) {
  21238                             if(mpls_index % 2 == 0) {
  21239                                 found = 1;
  21240                                 break;
  21241                             }
  21242                         }
  21243                     } else {
  21244                         found = 1;
  21245                         break;
  21246                     }
  21247                 }
  21248                 mpls_index++;
  21249             }
  21250             if (found) {
  21251                 break;
  21252             }
  21253         }
  21254         if (found) {
  21255             /* Mark entry as used */
  21256             _BCM_MPLS_TNL_USED_SET(unit, mpls_index);
  21257             _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 
  21258                                                    mpls_index, 1);
  21259             if (push_action == 0x2) {
  21260                 _BCM_MPLS_TNL_USED_SET(unit, mpls_index+1);
  21261                 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 
  21262                                                    mpls_index+1, 1);
  21263             }
  21264 
  21265             /* Read existing entry */
  21266             rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 
  21267                                           tnl_index, &tnl_entry);
  21268             if (rv < 0) {
  21269                 goto cleanup;
  21270             }
  21271         } else {
  21272             /*
  21273              * Alloc an egr_ip_tunnel entry. By calling bcm_xgs3_tnl_init_add
  21274              * with _BCM_L3_SHR_WRITE_DISABLE flag, a tunnel index is
  21275              * allocated but nothing is written to hardware. The "tnl_init"
  21276              * information is not used, set to all zero.
  21277              */
  21278             bcm_tunnel_initiator_t_init(&tnl_init);
  21279             tnl_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE |
  21280                 _BCM_L3_SHR_SKIP_INDEX_ZERO;
  21281             rv = bcm_xgs3_tnl_init_add(unit, tnl_flags, &tnl_init, &tnl_index);
  21282             if (rv == BCM_E_FULL) {
  21283                 if (free_slot2 == -1 || push_action != 2) {
  21284                     return rv; /* table truely full */
  21285                 }
  21286                 /* process the case of table fragmentation fo two labels.
  21287                  * push_action==2 
  21288                  */
  21289 
  21290                 tnl_index = (free_slot1 /
  21291                         _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit));
  21292                 rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 
  21293                                           tnl_index, &tnl_entry);
  21294                 BCM_IF_ERROR_RETURN(rv);
  21295                 rv = _tr_egr_tunnel_mpls_free_slots_reorder(unit, free_slot1,
  21296                      free_slot2, &tnl_entry);
  21297                 BCM_IF_ERROR_RETURN(rv);
  21298 
  21299                 /*sync up after update if both free slots in same entry*/
  21300                 if ((free_slot1 / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit)) ==
  21301                         (free_slot2 / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit))) {
  21302                     rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 
  21303                                           tnl_index, &tnl_entry);
  21304                     BCM_IF_ERROR_RETURN(rv);  
  21305                 }
  21306 
  21307                 mpls_index = free_slot1 & (~1);
  21308                 /* Mark entries as used */
  21309                 _BCM_MPLS_TNL_USED_SET(unit, mpls_index);
  21310                 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit,
  21311                                                    mpls_index, 1);
  21312                 _BCM_MPLS_TNL_USED_SET(unit, mpls_index + 1);
  21313                 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit,
  21314                                                    mpls_index+1, 1);
  21315                 found = 1;  /* for cleanup */
  21316             } else if (rv < 0) {
  21317                 return rv;
  21318             } else {
  21319                 mpls_index = tnl_index * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit);
  21320 
  21321                 /* Mark entries as used */
  21322                 _BCM_MPLS_IP_TNL_USED_SET(unit, tnl_index);
  21323                 _BCM_MPLS_TNL_USED_SET(unit, mpls_index);
  21324                 _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 
  21325                                                    mpls_index, 1);
  21326                 if (push_action == 0x2) {
  21327                     _BCM_MPLS_TNL_USED_SET(unit, mpls_index + 1);
  21328                     _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 
  21329                                                    mpls_index+1, 1);
  21330                 }
  21331                 /* Clear and set ENTRY_TYPE */
  21332                 sal_memset(&tnl_entry, 0, sizeof(egr_ip_tunnel_mpls_entry_t));
  21333                 soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 
  21334                                 ENTRY_TYPEf, 0x3);
  21335             }
  21336         } 
  21337     }
  21338 
  21339     offset = mpls_index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit);
  21340     for (i = 0; i < num_labels; i++) {
  21341         if (label_array[i].qos_map_id == 0) { /* treat it as using default */
  21342             hw_map_idx = 0;
  21343         } else {
  21344             rv = _egr_qos_id2hw_idx(unit,
  21345                             label_array[i].qos_map_id,&hw_map_idx);
  21346             if (rv < 0) {
  21347                 goto cleanup;
  21348             }
  21349         }
  21350 
  21351         soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21352                             _tnl_push_action_f[offset], push_action);
  21353         if (push_action > 0) {
  21354             soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 
  21355                                 _tnl_label_f[offset], label_array[i].label);
  21356         }
  21357         /*For Two Label push set Second label push action as 1*/
  21358         if ((push_action == 0x2) && (i == 1)) {
  21359             soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21360                     _tnl_push_action_f[offset], 1);
  21361 
  21362         }
  21363 
  21364         if ((label_array[i].flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) ||
  21365             (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) {
  21366 
  21367             /* Use the specified EXP, PRI and CFI */
  21368             if ((label_array[i].flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) ||
  21369                 (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ||
  21370                 (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_PRI_REMARK)) {
  21371                 rv = BCM_E_PARAM;
  21372                 goto cleanup;
  21373             }
  21374             soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 
  21375                                 _tnl_exp_select_f[offset], 0x0); /* USE_FIXED */
  21376             soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 
  21377                                 _tnl_exp_f[offset], label_array[i].exp);
  21378             soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 
  21379                                 _tnl_pri_f[offset], label_array[i].pkt_pri);
  21380             soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 
  21381                                 _tnl_cfi_f[offset], label_array[i].pkt_cfi);
  21382         } else if (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) {
  21383             if (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_PRI_SET) {
  21384                 rv = BCM_E_PARAM;
  21385                 goto cleanup;
  21386             }
  21387             /* Use EXP-map for EXP, PRI and CFI */
  21388             soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21389                                 _tnl_exp_select_f[offset], 0x1); /* USE_MAPPING */
  21390             soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 
  21391                                 _tnl_exp_ptr_f[offset], hw_map_idx);
  21392         } else { /* BCM_MPLS_EGRESS_LABEL_EXP_COPY */
  21393             /* Use EXP from inner label. If there is no inner label,
  21394              * use the specified EXP value. Use EXP-map for PRI/CFI.
  21395              */
  21396             soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21397                                 _tnl_exp_select_f[offset], 0x2); /* USE_INNER */
  21398     
  21399             soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 
  21400                                 _tnl_exp_f[offset], label_array[i].exp);
  21401     
  21402             /* Use EXP-map for PRI/CFI */
  21403             soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 
  21404                                 _tnl_exp_ptr_f[offset], hw_map_idx);
  21405         }
  21406     
  21407         if (label_array[i].flags & BCM_MPLS_EGRESS_LABEL_TTL_SET) {
  21408             /* Use specified TTL */
  21409             soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 
  21410                                 _tnl_ttl_f[offset], label_array[i].ttl);
  21411         } else {
  21412             soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry, 
  21413                                 _tnl_ttl_f[offset], 0);
  21414         }
  21415         offset++;
  21416     }
  21417 
  21418     /* Commit the values to HW */
  21419     rv = WRITE_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 
  21420                                    tnl_index, &tnl_entry);
  21421     if (rv < 0) {
  21422         goto cleanup;
  21423     }
  21424 
  21425     /* Update the EGR_L3_INTF to point to the MPLS tunnel entry */
  21426     rv = soc_mem_field32_modify(unit, EGR_L3_INTFm, intf, 
  21427                                 MPLS_TUNNEL_INDEXf, mpls_index);
  21428 
  21429 #ifdef BCM_WARM_BOOT_SUPPORT
  21430     SOC_CONTROL_LOCK(unit);
  21431     SOC_CONTROL(unit)->scache_dirty = 1;
  21432     SOC_CONTROL_UNLOCK(unit);
  21433 #endif
  21434 
  21435     return rv;
  21436 
  21437   cleanup:
  21438     if (!found) {
  21439         /* Free the tunnel entry */
  21440         tnl_flags = _BCM_L3_SHR_WRITE_DISABLE;
  21441         (void) bcm_xgs3_tnl_init_del(unit, tnl_flags, tnl_index);
  21442 
  21443         /* Clear "in-use" for the IP tunnel entry */
  21444         _BCM_MPLS_IP_TNL_USED_CLR(unit, tnl_index);
  21445     }
  21446     /* Clear "in-use" for the MPLS tunnel entry(s) */
  21447     _BCM_MPLS_TNL_USED_CLR(unit, mpls_index);
  21448     if (push_action == 0x2) {
  21449         _BCM_MPLS_TNL_USED_CLR(unit, mpls_index + 1);
  21450     }
  21451     return rv;
  21452 }
  21453 
  21454 /*  
  21455  * Function:
  21456  *      _bcm_tr_mpls_tunnel_initiator_clear
  21457  * Purpose:
  21458  *      Clear MPLS Tunnel initiator
  21459  * Parameters:
  21460  *      unit - Device Number
  21461  *      intf - The egress L3 interface
  21462  *      num_labels  - Number of labels in the array
  21463  *      label_array - Array of MPLS label and header information
  21464  * Returns:
  21465  *      BCM_E_XXX
  21466  */
  21467 
  21468 STATIC int
  21469 _bcm_tr_mpls_tunnel_initiator_clear(int unit, int intf_id)
  21470 {
  21471     egr_ip_tunnel_mpls_entry_t tnl_entry;
  21472     egr_l3_intf_entry_t if_entry;
  21473     int rv, offset, push_action, mpls_entry_used;
  21474     int tnl_index = 0, mpls_index = 0;
  21475     uint32 tnl_flags;
  21476     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  21477 
  21478 
  21479     /* L3 interface info */
  21480     rv = READ_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf_id, &if_entry);
  21481     if (rv < 0) {
  21482         return rv;
  21483     }
  21484     mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry,
  21485                                               MPLS_TUNNEL_INDEXf);
  21486     tnl_index = mpls_index / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit);
  21487 
  21488     if (!_BCM_MPLS_TNL_USED_GET(unit, mpls_index)) {
  21489         return BCM_E_NOT_FOUND;
  21490     }
  21491     rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY,
  21492                                   tnl_index, &tnl_entry);
  21493     if (rv < 0) {
  21494         return rv;
  21495     }
  21496     if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21497                             ENTRY_TYPEf) != 3) {
  21498         return BCM_E_NOT_FOUND;
  21499     }
  21500     offset = mpls_index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit);
  21501     push_action = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21502                                       _tnl_push_action_f[offset]);
  21503 
  21504     /* Decrement Reference Count */
  21505     _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 
  21506                                                   mpls_index, -1);
  21507     if (push_action == 0x2) {
  21508         _bcm_tr_mpls_egr_tunnel_ref_count_adjust (unit, 
  21509                                                    mpls_index+1, -1);
  21510     }
  21511 
  21512     /* Update the EGR_L3_INTF to no longer point to the MPLS tunnel entry */
  21513     soc_mem_field32_set(unit, EGR_L3_INTFm, &if_entry,
  21514                                 MPLS_TUNNEL_INDEXf, 0);
  21515     rv = WRITE_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf_id, &if_entry);
  21516     if (rv < 0) {
  21517         return rv;
  21518     }
  21519 
  21520     if ( mpls_info->egr_tunnel_ref_count[mpls_index] != 0x0 ) {
  21521          return BCM_E_NONE;
  21522     }
  21523 
  21524     /* Clear the MPLS tunnel entry(s) */
  21525     soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21526                         _tnl_label_f[offset], 0);
  21527     soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21528                         _tnl_push_action_f[offset], 0);
  21529     soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21530                         _tnl_exp_select_f[offset], 0);
  21531     soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21532                         _tnl_exp_ptr_f[offset], 0);
  21533     soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21534                         _tnl_exp_f[offset], 0);
  21535     soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21536                         _tnl_ttl_f[offset], 0);
  21537     if (push_action == 0x2) {
  21538         offset++;
  21539         soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21540                             _tnl_label_f[offset], 0);
  21541         soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21542                             _tnl_push_action_f[offset], 0);
  21543         soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21544                             _tnl_exp_select_f[offset], 0);
  21545         soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21546                             _tnl_exp_ptr_f[offset], 0);
  21547         soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21548                             _tnl_exp_f[offset], 0);
  21549         soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21550                             _tnl_ttl_f[offset], 0);
  21551     }
  21552 
  21553     /* Clear "in-use" for the MPLS tunnel entry(s) */
  21554     _BCM_MPLS_TNL_USED_CLR(unit, mpls_index);
  21555     if (push_action == 0x2) {
  21556         _BCM_MPLS_TNL_USED_CLR(unit, mpls_index + 1);
  21557     }
  21558 
  21559     mpls_index = tnl_index * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit);
  21560 
  21561     /* See if we can free the IP tunnel base entry */
  21562     _BCM_MPLS_TNL_USED_RANGE_GET(unit, mpls_index,
  21563             _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit), mpls_entry_used);
  21564 
  21565     if (!mpls_entry_used) {
  21566         /* None of the 4 or 8 entries are used, free base entry */
  21567         tnl_flags = _BCM_L3_SHR_WRITE_DISABLE;
  21568         (void) bcm_xgs3_tnl_init_del(unit, tnl_flags, tnl_index);
  21569 
  21570         /* Clear "in-use" for the IP tunnel entry */
  21571         _BCM_MPLS_IP_TNL_USED_CLR(unit, tnl_index);
  21572 
  21573         /* Clear HW Entry-Type */
  21574         soc_mem_field32_set(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21575                 ENTRY_TYPEf, 0);
  21576     }
  21577 
  21578     rv = WRITE_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 
  21579                                    tnl_index, &tnl_entry);
  21580     if (rv < 0) {
  21581         return rv;
  21582     }
  21583 
  21584 #ifdef BCM_WARM_BOOT_SUPPORT
  21585     SOC_CONTROL_LOCK(unit);
  21586     SOC_CONTROL(unit)->scache_dirty = 1;
  21587     SOC_CONTROL_UNLOCK(unit);
  21588 #endif
  21589 
  21590     return BCM_E_NONE;
  21591 }
  21592 
  21593 /*
  21594  * Function:
  21595  *      bcm_mpls_tunnel_initiator_clear
  21596  * Purpose:
  21597  *      Clear MPLS Tunnel Initiator
  21598  * Parameters:
  21599  *      unit - Device Number
  21600  *      intf - The egress L3 interface
  21601  * Returns:
  21602  *      BCM_E_XXX
  21603  */
  21604 int
  21605 bcm_tr_mpls_tunnel_initiator_clear(int unit, bcm_if_t intf)
  21606 {
  21607     if ((intf < 0) || (intf >= L3_INFO(unit)->l3_intf_table_size)) {
  21608         return BCM_E_PARAM;
  21609     }
  21610 
  21611     if (!BCM_L3_INTF_USED_GET(unit, intf)) {
  21612         LOG_INFO(BSL_LS_BCM_L3,
  21613                  (BSL_META_U(unit,
  21614                              "L3 interface not created\n")));
  21615         return BCM_E_NOT_FOUND;
  21616     }
  21617     return _bcm_tr_mpls_tunnel_initiator_clear(unit, intf);
  21618 }
  21619 
  21620 /*
  21621  * Function:
  21622  *      bcm_mpls_tunnel_initiator_get
  21623  * Purpose:
  21624  *      Get MPLS Tunnel Initiator info
  21625  * Parameters:
  21626  *      unit        - (IN) Device Number
  21627  *      intf        - (IN) The egress L3 interface
  21628  *      label_max   - (IN) Number of entries in label_array
  21629  *      label_array - (OUT) MPLS header information
  21630  *      label_count - (OUT) Actual number of labels returned
  21631  * Returns:
  21632  *      BCM_E_XXX
  21633  */
  21634 int
  21635 bcm_tr_mpls_tunnel_initiator_get(int unit, bcm_if_t intf, int label_max,
  21636                                  bcm_mpls_egress_label_t *label_array,
  21637                                  int *label_count)
  21638 {
  21639     egr_ip_tunnel_mpls_entry_t tnl_entry;
  21640     egr_l3_intf_entry_t if_entry;
  21641     int rv, i, ix, push_action, offset;
  21642     int tnl_index = 0, mpls_index = 0;
  21643 
  21644     if ((label_array == NULL) ||
  21645         (intf < 0) || (intf >= L3_INFO(unit)->l3_intf_table_size)) {
  21646         return BCM_E_PARAM;
  21647     }
  21648 
  21649     if (!BCM_L3_INTF_USED_GET(unit, intf)) {
  21650         LOG_INFO(BSL_LS_BCM_L3,
  21651                  (BSL_META_U(unit,
  21652                              "L3 interface not created\n")));
  21653         return BCM_E_NOT_FOUND;
  21654     }
  21655 
  21656     /* L3 interface info */
  21657     rv = READ_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, intf, &if_entry);
  21658     if (rv < 0) {
  21659         return rv;
  21660     }
  21661     mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry, 
  21662                                               MPLS_TUNNEL_INDEXf);
  21663     tnl_index = mpls_index / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit);
  21664 
  21665     if (!_BCM_MPLS_TNL_USED_GET(unit, mpls_index)) {
  21666         return BCM_E_NOT_FOUND;
  21667     }
  21668     rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY, 
  21669                                   tnl_index, &tnl_entry);
  21670     if (rv < 0) {
  21671         return rv;
  21672     }
  21673     if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21674                             ENTRY_TYPEf) != 3) {
  21675         return BCM_E_NOT_FOUND;
  21676     }
  21677 
  21678     *label_count = 0;
  21679     sal_memset(label_array, 0, sizeof(bcm_mpls_egress_label_t) * label_max);
  21680     offset = mpls_index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit);
  21681     push_action = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21682                                       _tnl_push_action_f[offset]);
  21683     if (push_action == 0x1) {
  21684         *label_count = 1;
  21685     } else if (push_action == 0x2) {
  21686         *label_count = 2;
  21687     }
  21688     if (label_max < *label_count) {
  21689         *label_count = label_max;
  21690     }
  21691     for (i = 0; i < *label_count; i++) {
  21692         label_array[i].label =
  21693             soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm,
  21694                                 &tnl_entry, _tnl_label_f[offset]);
  21695         if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21696                                 _tnl_exp_select_f[offset]) == 0x0) {
  21697             /* Use the specified EXP, PRI and CFI */
  21698             label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_EXP_SET;
  21699             label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_PRI_SET;
  21700             label_array[i].exp = 
  21701                 soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm,
  21702                                     &tnl_entry, _tnl_exp_f[offset]);
  21703             label_array[i].pkt_pri = 
  21704                 soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm,
  21705                                     &tnl_entry, _tnl_pri_f[offset]);
  21706             label_array[i].pkt_cfi = 
  21707                 soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm,
  21708                                     &tnl_entry, _tnl_cfi_f[offset]);
  21709         } else if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21710                                        _tnl_exp_select_f[offset]) == 0x1) {
  21711             /* Use EXP-map for EXP, PRI and CFI */
  21712             label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_EXP_REMARK;
  21713             label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK;
  21714 
  21715             ix = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm,
  21716                                      &tnl_entry, _tnl_exp_ptr_f[offset]);
  21717 
  21718             BCM_IF_ERROR_RETURN(
  21719                     _egr_qos_hw_idx2id(unit, ix, &label_array[i].qos_map_id));
  21720         } else {
  21721             /* Use EXP from incoming label. If there is no incoming label,
  21722              * use the specified EXP value.
  21723              */
  21724             label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_EXP_COPY;
  21725             label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK;
  21726             label_array[i].exp = 
  21727                 soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm,
  21728                                     &tnl_entry, _tnl_exp_f[offset]);
  21729 
  21730             /* Use EXP-map for PRI/CFI */
  21731             ix = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm,
  21732                                      &tnl_entry, _tnl_exp_ptr_f[offset]);
  21733             BCM_IF_ERROR_RETURN(
  21734                     _egr_qos_hw_idx2id(unit, ix, &label_array[i].qos_map_id));
  21735         }
  21736         if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21737                                 _tnl_ttl_f[offset])) {
  21738             /* Use specified TTL value */
  21739             label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET;
  21740             label_array[i].ttl = 
  21741                 soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm,
  21742                                     &tnl_entry, _tnl_ttl_f[offset]);
  21743         } else {
  21744             label_array[i].flags |= BCM_MPLS_EGRESS_LABEL_TTL_DECREMENT;
  21745         }
  21746         offset++;
  21747     }
  21748     return BCM_E_NONE;
  21749 }
  21750 
  21751 /*
  21752  * Function:
  21753  *      _bcm_tr_mpls_tunnel_chain_label_count_get
  21754  * Purpose:
  21755  *      Get number of labels in a single chain
  21756  * Parameters:
  21757  *      unit        - (IN) Device Number
  21758  *      index       - (IN) Mpls index
  21759  *      label_count - (OUT) Actual number of labels returned
  21760  * Returns:
  21761  *      BCM_E_XXX
  21762  */
  21763 int
  21764 _bcm_tr_mpls_tunnel_chain_label_count_get(int unit, uint32 index,
  21765                                           int *label_count)
  21766 {
  21767     egr_ip_tunnel_mpls_entry_t tnl_entry;
  21768     int rv, i, push_action, offset;
  21769     int tnl_index = 0;
  21770     rv = BCM_E_NONE;
  21771 
  21772     tnl_index = index / _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit);
  21773     if (!_BCM_MPLS_TNL_USED_GET(unit, index)) {
  21774         return BCM_E_NOT_FOUND;
  21775     }
  21776 
  21777     rv = READ_EGR_IP_TUNNEL_MPLSm(unit, MEM_BLOCK_ANY,
  21778             tnl_index, &tnl_entry);
  21779 
  21780     if (rv < 0) {
  21781         return rv;
  21782     }
  21783     if (soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21784                 ENTRY_TYPEf) != 3) {
  21785         return BCM_E_NOT_FOUND;
  21786     }
  21787     *label_count = 0;
  21788     offset = index & _BCM_MPLS_EGR_L3_INTF_MPLS_INDEX_OFFSET_MASK(unit);
  21789 
  21790     for(i = 0; i < _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit) ; i++) {
  21791         push_action = soc_mem_field32_get(unit, EGR_IP_TUNNEL_MPLSm, &tnl_entry,
  21792                 _tnl_push_action_f[offset+i]);
  21793         if (push_action == 0x1) {
  21794             break;
  21795         }
  21796     }
  21797     *label_count = i+1;
  21798     return rv;
  21799 }
  21800 
  21801 /*
  21802  * Function:
  21803  *      bcm_mpls_tunnel_initiator_clear_all
  21804  * Purpose:
  21805  *      Clear all MPLS Tunnel Initiators
  21806  * Parameters:
  21807  *      unit - Device Number
  21808  * Returns:
  21809  *      BCM_E_XXX
  21810  */
  21811 int
  21812 bcm_tr_mpls_tunnel_initiator_clear_all(int unit)
  21813 {
  21814     egr_l3_intf_entry_t if_entry;
  21815     int mpls_index, i;
  21816     int rv=BCM_E_NONE;
  21817 
  21818     for (i = 0; i < L3_INFO(unit)->l3_intf_table_size; i++) {
  21819         if (!BCM_L3_INTF_USED_GET(unit, i)) {
  21820             continue;
  21821         }
  21822         rv = READ_EGR_L3_INTFm(unit, MEM_BLOCK_ANY, i, &if_entry);
  21823         if (rv < 0) {
  21824             return rv;
  21825         }
  21826         mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry,
  21827                                                   MPLS_TUNNEL_INDEXf);
  21828         if (!_BCM_MPLS_TNL_USED_GET(unit, mpls_index)) {
  21829             continue;
  21830         }
  21831         rv = _bcm_tr_mpls_tunnel_initiator_clear(unit, i);
  21832         if (rv < 0) {
  21833             return rv;
  21834         }
  21835     }
  21836     return rv;
  21837 }
  21838 
  21839 /*
  21840  * Function:
  21841  *       bcm_tr_mpls_get_entry_type
  21842  * Purpose:
  21843  *       To get Entry_type of  EGR_L3_NEXT_HOP Entry  for a specific EGR_NH Index
  21844  * Parameters:
  21845  *       IN :  Unit
  21846  *       IN :  nh_index
  21847  *      OUT: entry_type
  21848  * Returns:
  21849  *       BCM_E_XXX
  21850  */
  21851 
  21852 int
  21853 bcm_tr_mpls_get_entry_type (int unit, int nh_index, uint32 *entry_type )
  21854 {
  21855     egr_l3_next_hop_entry_t egr_nh;
  21856     int rv=BCM_E_NONE;
  21857 
  21858     /* Retrieve EGR L3 NHOP Entry */
  21859     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  21860                                       nh_index, &egr_nh));
  21861     *entry_type = 
  21862         soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]);
  21863 
  21864     return rv;
  21865 }
  21866 
  21867 /*
  21868  * Function:
  21869  *       bcm_tr_mpls_get_label_action
  21870  * Purpose:
  21871  *       To get MPLS Label action for a specific next_hop_index
  21872  * Parameters:
  21873  *       IN :  Unit
  21874  *       IN :  nh_index
  21875  *     OUT : label_action
  21876  * Returns:
  21877  *       BCM_E_XXX
  21878  */
  21879 
  21880 int
  21881 bcm_tr_mpls_get_label_action (int unit, int nh_index, uint32 *label_action )
  21882 {
  21883 
  21884     egr_l3_next_hop_entry_t egr_nh;
  21885     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
  21886     int vc_swap_idx;
  21887     uint32 label_select = 0;
  21888 
  21889     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  21890                                       nh_index, &egr_nh));
  21891 
  21892     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  21893         *label_action =  soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
  21894                 &egr_nh, MPLS__MPLS_LABEL_ACTIONf);
  21895         return BCM_E_NONE;
  21896     } else if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  21897          vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  21898                                                        MPLS__VC_AND_SWAP_INDEXf);
  21899     } else {
  21900          vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  21901                                                        VC_AND_SWAP_INDEXf);
  21902     }
  21903 
  21904     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
  21905                                       MEM_BLOCK_ANY, vc_swap_idx, &vc_entry));
  21906 
  21907 #if defined(BCM_TRIDENT3_SUPPORT)
  21908     /*SWAP Action is similar to PUSH in TD3*/
  21909     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  21910         if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) {
  21911             *label_action =
  21912                 MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_idx];
  21913         }
  21914     } else
  21915 #endif
  21916     {
  21917     *label_action =  soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  21918                                         &vc_entry, MPLS_LABEL_ACTIONf);
  21919     }
  21920 #if defined(BCM_TRIDENT3_SUPPORT)
  21921     if(soc_feature(unit, soc_feature_td3_style_mpls)) {
  21922         label_select = soc_mem_field32_get(unit,
  21923                 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  21924                 &vc_entry, LABEL_SELECTf);
  21925     }
  21926 #endif
  21927     if (label_select) {
  21928         *label_action = _BCM_MPLS_ACTION_PRESERVED;
  21929     }
  21930     return BCM_E_NONE;
  21931 
  21932 }
  21933 
  21934 /*
  21935  * Function:
  21936  *       bcm_tr_mpls_egress_entry_mac_replace
  21937  * Purpose:
  21938  *       Replace  MAC_DA within MAC_DA_PROFILE
  21939  * Parameters:
  21940  *       IN :  Unit
  21941  *       IN :  nh_index
  21942  *       IN :  Egress forwarding destination.
  21943  * Returns:
  21944  *       BCM_E_XXX
  21945  */
  21946 
  21947 int
  21948 bcm_tr_mpls_egress_entry_mac_replace(int unit, int nh_index, bcm_l3_egress_t *egr)
  21949 {
  21950     egr_l3_next_hop_entry_t egr_nh;
  21951     uint32 new_macda_index=-1, old_macda_index=-1;
  21952     void *entries[1];
  21953     int rv = BCM_E_NONE;
  21954     int entry_type;
  21955     egr_mac_da_profile_entry_t macda;
  21956 
  21957     BCM_IF_ERROR_RETURN
  21958         (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, nh_index, &egr_nh));
  21959 
  21960     entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, nh_entry_type_field[unit]);
  21961 
  21962      /*
  21963      * If entry_type is 0, then the MAC address is in EGR_L3_NEXT_HOPm
  21964      */
  21965      if (entry_type == 1) {
  21966          sal_memset(&macda, 0, sizeof(egr_mac_da_profile_entry_t));
  21967          soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, &macda, MAC_ADDRESSf, egr->mac_addr);
  21968          entries[0] = &macda;
  21969          BCM_IF_ERROR_RETURN
  21970              (_bcm_mac_da_profile_entry_add(unit, entries, 1, (uint32 *) &new_macda_index));
  21971  
  21972          if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  21973              old_macda_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
  21974                          &egr_nh, MPLS__MAC_DA_PROFILE_INDEXf);
  21975              soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  21976                          &egr_nh, MPLS__MAC_DA_PROFILE_INDEXf, new_macda_index);
  21977          } else {
  21978              old_macda_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
  21979                           &egr_nh, MAC_DA_PROFILE_INDEXf);
  21980              soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  21981                           &egr_nh, MAC_DA_PROFILE_INDEXf, new_macda_index);
  21982          }
  21983  
  21984          rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, nh_index, &egr_nh);
  21985          if (BCM_SUCCESS(rv)) { 
  21986              if (old_macda_index != -1) {
  21987                  _bcm_mac_da_profile_entry_delete(unit, old_macda_index);
  21988              }
  21989          } else {
  21990                  _bcm_mac_da_profile_entry_delete(unit, new_macda_index);
  21991          }
  21992      } else if (soc_feature(unit, soc_feature_egress_object_mac_da_replace) && (entry_type == 0)) {
  21993          if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, MAC_ADDRESSf)) {
  21994              /* Set next hop mac address. */
  21995              soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, MAC_ADDRESSf, egr->mac_addr);
  21996              rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, nh_index, &egr_nh);
  21997          }
  21998      }
  21999      return rv;
  22000 }
  22001 
  22002 /*
  22003  * Function:
  22004  *       bcm_tr_mpls_l3_label_add
  22005  * Purpose:
  22006  *       Updates  Inner_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index
  22007  * Parameters:
  22008  *       IN :  Unit
  22009  *       IN :  mpls_label
  22010  *       IN :  nh_index
  22011  * Returns:
  22012  *       BCM_E_XXX
  22013  */
  22014 
  22015 int
  22016 bcm_tr_mpls_l3_label_add (int unit, bcm_l3_egress_t *egr, int nh_index, uint32 flags)
  22017 {
  22018     int  rv=BCM_E_NONE;
  22019     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
  22020     int      vc_swap_index=-1;
  22021     egr_l3_next_hop_entry_t egr_nh;
  22022     uint32    entry_type;
  22023     int       hw_map_idx, num_mpls_map;
  22024     int bkt_idx;
  22025     bcm_tr_mpls_vc_swap_table_hash_t *hash_input;
  22026     int ref_count = 0;
  22027 
  22028 
  22029     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  22030         /* NOT supported in TH3 */
  22031         return BCM_E_CONFIG;
  22032     }
  22033 
  22034     /* Retrieve EGR L3 NHOP Entry */
  22035     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  22036                                       nh_index, &egr_nh));
  22037 
  22038     sal_memset(&vc_entry, 0,
  22039             sizeof(egr_mpls_vc_and_swap_label_table_entry_t));
  22040 
  22041     BCM_IF_ERROR_RETURN(bcm_tr_mpls_get_entry_type(unit, nh_index, &entry_type));
  22042     if ((entry_type == 1) && (egr->mpls_label != BCM_MPLS_LABEL_INVALID) && (flags & BCM_L3_REPLACE)) {
  22043         /* Be sure that the existing entry is already setup to
  22044          * egress into an MPLS tunnel. If not, return BCM_E_PARAM.
  22045          */
  22046         entry_type = 
  22047             soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]);
  22048 
  22049         if (entry_type != 0x1) { /* != MPLS_MACDA_PROFILE */
  22050             return BCM_E_PARAM;
  22051         }
  22052 
  22053         /* Retrieve VC_AND_SWAP_INDEX */
  22054         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  22055              vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  22056                                                        MPLS__VC_AND_SWAP_INDEXf);
  22057         } else {
  22058              vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  22059                                                        VC_AND_SWAP_INDEXf);
  22060         }
  22061 
  22062         if (vc_swap_index == 0) {
  22063  
  22064             BCM_IF_ERROR_RETURN(
  22065                 _bcm_tr_mpls_get_vc_and_swap_table_index(unit, 0, 
  22066                     NULL, NULL, egr, NULL, _BCM_MPLS_ACTION_PUSH, 
  22067                     &vc_swap_index));
  22068         } else {
  22069             /* Retrieve VC_AND_SWAP_TABLE entry */
  22070             BCM_IF_ERROR_RETURN(
  22071                 soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  22072                      MEM_BLOCK_ALL, vc_swap_index, &vc_entry));
  22073 #if defined(BCM_TRIUMPH3_SUPPORT)
  22074             if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) {
  22075                 BCM_IF_ERROR_RETURN(
  22076                     _bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit,
  22077                                                               vc_swap_index,
  22078                                                               nh_index));
  22079             }
  22080 #endif
  22081             /* Check if any VC_AND_SWAP_LABEL related info has changed */
  22082             if (BCM_FAILURE(_bcm_tr_mpls_vc_swap_compare
  22083                 (unit, NULL, NULL, egr, NULL,_BCM_MPLS_ACTION_PUSH, &vc_entry))) {
  22084 
  22085                 _bcm_tr_mpls_vc_and_swap_ref_count_get(unit, vc_swap_index, &ref_count);
  22086 
  22087                 /* Check if any other Egress objects shares the same vc_swap_index */
  22088                 if (ref_count > 1) {
  22089                     _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, vc_swap_index, -1);
  22090 
  22091                     /* Entry sharing can't be possible, create a new index */
  22092                     BCM_IF_ERROR_RETURN(
  22093                         _bcm_tr_mpls_get_vc_and_swap_table_index(unit, 0,
  22094                             NULL, NULL, egr, NULL, _BCM_MPLS_ACTION_PUSH,
  22095                             &vc_swap_index));
  22096                 } else {
  22097                     int tmp_action  = 0;
  22098 
  22099 #ifdef BCM_TRIDENT3_SUPPORT
  22100                     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  22101                        tmp_action = MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index];
  22102                     }
  22103 #endif
  22104                     /* delete the sw state for old entry */
  22105                     BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_index_get(
  22106                         unit, NULL, tmp_action, NULL, NULL, &vc_entry, &bkt_idx));
  22107 
  22108                     hash_input = &(bcmi_vc_swap_label_hash[unit][bkt_idx]);
  22109                     BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_delete(
  22110                         unit, hash_input, vc_swap_index));
  22111 
  22112                     /* Create the sw state for new entry */
  22113                     BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_index_get(
  22114                         unit, NULL, _BCM_MPLS_ACTION_PUSH, NULL, egr, NULL, &bkt_idx));
  22115 
  22116                     hash_input = &(bcmi_vc_swap_label_hash[unit][bkt_idx]);
  22117                     BCM_IF_ERROR_RETURN(bcmi_tr_mpls_vc_swap_hash_insert(unit, hash_input,
  22118                         vc_swap_index, NULL, NULL, egr, NULL, _BCM_MPLS_ACTION_PUSH,
  22119                             &vc_swap_index, FALSE));
  22120                 }
  22121             }
  22122         }
  22123     }else if ((entry_type == 1) && (egr->mpls_label == BCM_MPLS_LABEL_INVALID) && (flags & BCM_L3_REPLACE)) {
  22124         rv = bcm_tr_mpls_l3_label_delete (unit, nh_index);
  22125         return rv;
  22126     } else {
  22127 
  22128         BCM_IF_ERROR_RETURN(
  22129             _bcm_tr_mpls_get_vc_and_swap_table_index(unit, 0,
  22130                 NULL, NULL, egr, NULL, _BCM_MPLS_ACTION_PUSH, &vc_swap_index));
  22131     }
  22132     /* Retrieve hardware index for mapping pointer */
  22133     if ((egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) ||
  22134         (egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) {
  22135         /* Mapping pointer not used */
  22136         hw_map_idx = -1;
  22137     } else {
  22138         num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
  22139         rv = _egr_qos_id2hw_idx(unit,egr->mpls_qos_map_id,&hw_map_idx);
  22140         if ((rv != BCM_E_NONE) || hw_map_idx < 0 || hw_map_idx >= num_mpls_map) {
  22141             if (egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) {
  22142                 rv = BCM_E_PARAM;
  22143                 goto cleanup;
  22144             } else {
  22145                 hw_map_idx = 0; /* use default */
  22146             }
  22147         }
  22148     }
  22149 
  22150     /* Program the MPLS_VC_AND_SWAP table entry */
  22151     rv = _bcm_tr_mpls_vc_and_swap_table_entry_set(unit, NULL, NULL, egr,
  22152                                              _BCM_MPLS_ACTION_PUSH, &vc_entry, hw_map_idx,
  22153                                              vc_swap_index);
  22154     if (rv < 0){
  22155        goto cleanup;
  22156     }
  22157 #if defined(BCM_TRIUMPH2_SUPPORT) \
  22158     ||  defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
  22159     if (SOC_IS_TRIUMPH2(unit)
  22160         || SOC_IS_ENDURO(unit) || SOC_IS_TRIDENT(unit)) {
  22161         /* workaround a hardware issue which is corrected on newer chips
  22162          * that the EGR_SD_TAG_CONTROL register influnces L3 MPLS tunnel's
  22163          * TPID selection. This shouldn't happen since L3 MPLS 
  22164          * isn't using SD_TAG.
  22165          */
  22166         soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  22167                                 &vc_entry, SD_TAG_ACTION_IF_NOT_PRESENTf,
  22168                                 3);
  22169     }
  22170 #endif
  22171     rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  22172                    MEM_BLOCK_ALL, vc_swap_index,
  22173                    &vc_entry);
  22174     if (rv < 0){
  22175        goto cleanup;
  22176     }
  22177     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, 
  22178                         &egr_nh, nh_entry_type_field[unit],
  22179                         entry_type);
  22180 
  22181     if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  22182           soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22183                           &egr_nh, MPLS__VC_AND_SWAP_INDEXf,
  22184                           vc_swap_index);
  22185           /* Enable HG.L3_bit */
  22186           soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22187                     &egr_nh, MPLS__HG_L3_OVERRIDEf, 0x1);
  22188            soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22189                      &egr_nh, MPLS__HG_MODIFY_ENABLEf, 0x1);
  22190 #if defined(INCLUDE_XFLOW_MACSEC)
  22191         if (soc_feature(unit, soc_feature_xflow_macsec) &&
  22192             ((egr->flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_ENCRYPT) ||
  22193             (egr->flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_DECRYPT))) {
  22194             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22195                     &egr_nh, MPLS__MACSEC_ENCRYPTf, 0);
  22196             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22197                     &egr_nh, MPLS__MACSEC_DECRYPTf, 0);
  22198             if (egr->flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_ENCRYPT) {
  22199                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22200                         &egr_nh, MPLS__MACSEC_ENCRYPTf, 0x1);
  22201             } else {
  22202                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22203                         &egr_nh, MPLS__MACSEC_DECRYPTf, 0x1);
  22204             }
  22205             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22206                     &egr_nh, MPLS__HG_MC_DST_MODIDf, egr->module);
  22207             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22208                     &egr_nh, MPLS__HG_MC_DST_PORT_NUMf, egr->port);
  22209         }
  22210 #endif
  22211     } else {
  22212           soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22213                           &egr_nh, VC_AND_SWAP_INDEXf,
  22214                           vc_swap_index);
  22215           /* Enable HG.L3_bit */
  22216           soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22217                     &egr_nh, HG_L3_OVERRIDEf, 0x1);
  22218            soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22219                      &egr_nh, HG_MODIFY_ENABLEf, 0x1);
  22220     }
  22221  #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  22222     if (soc_feature(unit, soc_feature_mpls_nh_ttl_control)) {
  22223         if (egr->flags & BCM_L3_KEEP_TTL) {
  22224             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  22225                                 MPLS__DISABLE_TTL_DECREMENTf, 1);
  22226         } else {
  22227             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  22228                                 MPLS__DISABLE_TTL_DECREMENTf, 0);
  22229         }
  22230     }
  22231 #endif
  22232     rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm,
  22233                        MEM_BLOCK_ALL, nh_index, &egr_nh);
  22234 
  22235     if (rv < 0) {
  22236        goto cleanup;
  22237     }
  22238 #if defined(BCM_TRIUMPH3_SUPPORT)
  22239     if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) {
  22240         rv = _bcm_tr_mpls_vc_and_swap_hash_nhop_add(unit,
  22241                                                     vc_swap_index,
  22242                                                     nh_index);
  22243         if (rv < 0) {
  22244             goto cleanup;
  22245         }
  22246     }
  22247 #endif
  22248 #ifdef BCM_WARM_BOOT_SUPPORT
  22249     SOC_CONTROL_LOCK(unit);
  22250     SOC_CONTROL(unit)->scache_dirty = 1;
  22251     SOC_CONTROL_UNLOCK(unit);
  22252 #endif
  22253 
  22254     return rv;
  22255 
  22256 cleanup:
  22257     if (vc_swap_index >= 0) {
  22258         if (!(flags & BCM_L3_REPLACE)) {
  22259          _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, vc_swap_index, -1);
  22260         /* Free VC_AND_SWAP_LABEL entry */
  22261         (void)_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, vc_swap_index);
  22262     }
  22263     }
  22264     return rv; 
  22265 }
  22266 
  22267 /*
  22268  * Function:
  22269  *		bcm_tr_mpls_l3_label_get
  22270  * Purpose:
  22271  *		Retrieves the  Inner_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index
  22272  * Parameters:
  22273  *		IN :  Unit
  22274  *           IN :  mpls_label
  22275  *           IN :  nh_index
  22276  * Returns:
  22277  *		BCM_E_XXX
  22278  */
  22279 
  22280 int
  22281 bcm_tr_mpls_l3_label_get (int unit, int index, bcm_l3_egress_t *egr)
  22282 {
  22283     int rv=BCM_E_NONE;
  22284     int  vc_swap_index=-1;
  22285     egr_l3_next_hop_entry_t egr_nh;
  22286     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
  22287     uint32	entry_type;
  22288     uint32  label_action = 0;
  22289 
  22290     /* Retrieve EGR L3 NHOP Entry */
  22291     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  22292                                       index, &egr_nh));
  22293 
  22294     entry_type = 
  22295         soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]);
  22296 
  22297     if (entry_type != 0x1) { /* != MPLS_MACDA_PROFILE */
  22298         egr->mpls_label = BCM_MPLS_LABEL_INVALID;
  22299         return rv;
  22300     }
  22301 
  22302 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  22303     if (soc_feature(unit, soc_feature_mpls_nh_ttl_control)) {
  22304         if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  22305                                 MPLS__DISABLE_TTL_DECREMENTf)) {
  22306             egr->flags |= BCM_L3_KEEP_TTL;
  22307         }
  22308     }
  22309 #endif
  22310 
  22311 #ifdef BCM_TOMAHAWK3_SUPPORT
  22312     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  22313         label_action =
  22314             soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
  22315                     &egr_nh, MPLS__MPLS_LABEL_ACTIONf);
  22316 
  22317         if (label_action == _BCM_MPLS_ACTION_PUSH) {
  22318             egr->flags |= BCM_L3_ROUTE_LABEL;
  22319             egr->mpls_label =
  22320                 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
  22321                                     &egr_nh, MPLS__MPLS_LABELf);
  22322             egr->mpls_ttl =
  22323                 soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
  22324                                     &egr_nh, MPLS__MPLS_TTLf);
  22325             if (egr->mpls_ttl) {
  22326                 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET;
  22327             }
  22328             if (soc_feature(unit, soc_feature_mpls_ecn)) {
  22329                 int ecn_map_id;
  22330                 int ecn_map_pri;
  22331                 int ecn_map_hw_idx;
  22332                 int ret;
  22333                 ecn_map_hw_idx = soc_mem_field32_get(unit,
  22334                                                      EGR_L3_NEXT_HOPm,
  22335                                                      &egr_nh,
  22336                                                      MPLS__IP_ECN_TO_EXP_MAPPING_PTRf);
  22337                 ecn_map_pri = soc_mem_field32_get(unit,
  22338                                                   EGR_L3_NEXT_HOPm,
  22339                                                   &egr_nh,
  22340                                                   MPLS__IP_ECN_TO_EXP_PRIORITYf);
  22341                 ret =  bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_idx,
  22342                                               _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP,
  22343                                               &ecn_map_id);
  22344                 if (BCM_SUCCESS(ret)) {
  22345                     egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP;
  22346                     egr->mpls_ecn_map_id = ecn_map_id;
  22347                     if (ecn_map_pri) {
  22348                         egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST;
  22349                     }
  22350                 }
  22351             }
  22352         } else {
  22353             egr->mpls_label = BCM_MPLS_LABEL_INVALID;
  22354         }
  22355         return rv;
  22356     }
  22357 #endif
  22358 
  22359     /* Retrieve VC_AND_SWAP_INDEX */
  22360     if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  22361          vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  22362                                                        MPLS__VC_AND_SWAP_INDEXf);
  22363     } else {
  22364          vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  22365                                                        VC_AND_SWAP_INDEXf);
  22366     }
  22367     if (vc_swap_index != -1) {
  22368         /* Retrieve VC_AND_SWAP_TABLE entry */
  22369         BCM_IF_ERROR_RETURN( 
  22370             soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  22371                          MEM_BLOCK_ALL, vc_swap_index, &vc_entry));
  22372 
  22373 #if defined(BCM_TRIDENT3_SUPPORT)
  22374         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  22375             if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) {
  22376                 label_action = MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index];
  22377             } 
  22378         } else 
  22379 #endif
  22380         {
  22381         label_action = 
  22382             soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  22383                                 &vc_entry, MPLS_LABEL_ACTIONf);
  22384         }
  22385 #if defined(BCM_SWAP_TO_SELF_SUPPORT)
  22386         if (soc_feature(unit, soc_feature_mpls_swap_label_preserve) && 
  22387             (label_action == _BCM_MPLS_ACTION_NOOP)) {
  22388             return rv;
  22389         }
  22390 #endif
  22391         if (label_action == _BCM_MPLS_ACTION_PUSH) {
  22392             egr->flags |= BCM_L3_ROUTE_LABEL;
  22393             egr->mpls_label = 
  22394                 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  22395                                     &vc_entry, MPLS_LABELf);
  22396             egr->mpls_ttl = 
  22397                 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  22398                                     &vc_entry, MPLS_TTLf);
  22399             if (egr->mpls_ttl) {
  22400                 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET;
  22401             }
  22402 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
  22403         if (soc_feature(unit, soc_feature_mpls_ecn)) {
  22404             int ecn_map_id;
  22405             int ecn_map_pri;
  22406             int ecn_map_hw_idx;
  22407             int ret;
  22408             soc_field_t ipecn_to_exp_ptr;
  22409             soc_field_t ipecn_to_exp_priority;
  22410 
  22411 #if defined(BCM_TRIDENT3_SUPPORT)
  22412             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  22413                 ipecn_to_exp_ptr = PKT_ECN_TO_EXP_MAPPING_PTRf;
  22414                 ipecn_to_exp_priority = PKT_ECN_TO_EXP_PRIORITYf;
  22415             } else 
  22416 #endif
  22417             {
  22418                 ipecn_to_exp_ptr = IP_ECN_TO_EXP_MAPPING_PTRf;
  22419                 ipecn_to_exp_priority = IP_ECN_TO_EXP_PRIORITYf;
  22420             }
  22421             ecn_map_hw_idx = soc_mem_field32_get(unit, 
  22422                                                  EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
  22423                                                  &vc_entry, 
  22424                                                  ipecn_to_exp_ptr);
  22425             ecn_map_pri = soc_mem_field32_get(unit, 
  22426                                               EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
  22427                                               &vc_entry, 
  22428                                               ipecn_to_exp_priority);
  22429             ret =  bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_idx, 
  22430                                           _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP, 
  22431                                           &ecn_map_id); 
  22432             if (BCM_SUCCESS(ret)) {
  22433                 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP;
  22434                 egr->mpls_ecn_map_id = ecn_map_id;
  22435                 if (ecn_map_pri) {
  22436                     egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST;
  22437                 }
  22438             }
  22439         }
  22440 #endif 
  22441         } else {
  22442             egr->mpls_label = BCM_MPLS_LABEL_INVALID;
  22443         }
  22444     } else {
  22445         egr->mpls_label = BCM_MPLS_LABEL_INVALID;
  22446     }
  22447    
  22448     return rv;
  22449 }
  22450 
  22451 /*
  22452  * Function:
  22453  *		bcm_tr_mpls_l3_label_delete
  22454  * Purpose:
  22455  *		Deletes  Inner_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index
  22456  * Parameters:
  22457  *		IN :  Unit
  22458  *           IN :  nh_index
  22459  * Returns:
  22460  *		BCM_E_XXX
  22461  */
  22462 
  22463 
  22464 int 
  22465 bcm_tr_mpls_l3_label_delete (int unit, int index)
  22466 {
  22467     int rv=BCM_E_NONE;
  22468     int  vc_swap_index=-1;
  22469     egr_l3_next_hop_entry_t egr_nh;
  22470     uint8  entry_type;
  22471     int  macda_index=-1;
  22472 
  22473     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  22474                                       index, &egr_nh));
  22475 
  22476     /* Retrieve  and Verify  ENTRY_TYPE */
  22477     entry_type = 
  22478         soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]);
  22479 
  22480     if (entry_type != 0x1) { /* != MPLS_MACDA_PROFILE */
  22481         return BCM_E_PARAM;
  22482     }
  22483 
  22484     /* Set Entry_Type to Normal */
  22485     entry_type = 0; /* Normal */
  22486     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  22487                         nh_entry_type_field[unit], entry_type);
  22488 
  22489     /* Delete MAC_DA_PROFILE_INDEX */
  22490     if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  22491         macda_index = 
  22492               soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  22493                                          MPLS__MAC_DA_PROFILE_INDEXf);
  22494     } else {
  22495         macda_index = 
  22496               soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  22497                                          MAC_DA_PROFILE_INDEXf);
  22498     }
  22499 
  22500     if (macda_index != -1) {
  22501         _bcm_mac_da_profile_entry_delete(unit, macda_index);
  22502     }
  22503 
  22504     if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) {
  22505         /* Retrieve VC_AND_SWAP_INDEX */
  22506         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  22507              vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  22508                                                            MPLS__VC_AND_SWAP_INDEXf);
  22509         } else {
  22510              vc_swap_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  22511                                                            VC_AND_SWAP_INDEXf);
  22512         }
  22513 
  22514 #if defined(BCM_TRIUMPH3_SUPPORT)
  22515         if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) {
  22516             BCM_IF_ERROR_RETURN(
  22517                 _bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit,
  22518                                                           vc_swap_index,
  22519                                                           index));
  22520         }
  22521 #endif
  22522 
  22523         _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, vc_swap_index, -1);
  22524 
  22525         BCM_IF_ERROR_RETURN
  22526              (_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, vc_swap_index));
  22527 
  22528         vc_swap_index = 0;
  22529         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  22530              soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22531                                   &egr_nh, MPLS__VC_AND_SWAP_INDEXf,
  22532                                   vc_swap_index);
  22533         } else {
  22534              soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22535                                   &egr_nh, VC_AND_SWAP_INDEXf,
  22536                                   vc_swap_index);
  22537         }
  22538      }
  22539 
  22540     rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm,
  22541                        MEM_BLOCK_ALL, index, &egr_nh);
  22542 
  22543 #ifdef BCM_WARM_BOOT_SUPPORT
  22544     SOC_CONTROL_LOCK(unit);
  22545     SOC_CONTROL(unit)->scache_dirty = 1;
  22546     SOC_CONTROL_UNLOCK(unit);
  22547 #endif
  22548 
  22549     return rv;
  22550 }
  22551 
  22552 /*
  22553  * Function:
  22554  *      bcm_tr_mpls_swap_nh_info_add
  22555  * Purpose:
  22556  *       Add  SWAP_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index
  22557  * Parameters:
  22558  *           IN :  Unit
  22559  *           IN : Egress object Pointer
  22560  *           IN :  nh_index
  22561  * Returns:
  22562  *           BCM_E_XXX
  22563  */
  22564 
  22565 int
  22566 bcm_tr_mpls_swap_nh_info_add (int unit, bcm_l3_egress_t *egr, int nh_index, uint32 flags)
  22567 {
  22568     ing_l3_next_hop_entry_t ing_nh;
  22569     egr_l3_next_hop_entry_t egr_nh;
  22570     egr_mpls_vc_and_swap_label_table_entry_t vc_entry, old_vc_entry;
  22571     int vc_swap_index = -1;
  22572     uint32 old_vc_swap_idx = -1;
  22573     int rv, num_vc;
  22574     int hw_map_idx, num_mpls_map;
  22575 
  22576     if (!(BCM_XGS3_L3_MPLS_LBL_VALID(egr->mpls_label) ||
  22577         _BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, egr->mpls_flags))) {
  22578         return BCM_E_PARAM;
  22579     }
  22580     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
  22581 
  22582     BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  22583                                       nh_index, &ing_nh));
  22584     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  22585                                       nh_index, &egr_nh));
  22586 
  22587       /* Retrieve hardware index for mapping pointer */
  22588     if ((egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) ||
  22589         (egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) {
  22590         /* Mapping pointer not used */
  22591         hw_map_idx = -1;
  22592     } else {
  22593         rv = _egr_qos_id2hw_idx(unit,egr->mpls_qos_map_id,&hw_map_idx);
  22594         num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
  22595         if ((rv != BCM_E_NONE) || hw_map_idx < 0 || hw_map_idx >= num_mpls_map) {
  22596             if (egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) {
  22597                 rv = BCM_E_PARAM;
  22598                 goto cleanup;
  22599             } else {
  22600                 hw_map_idx = 0; /* use default */
  22601             }
  22602         }
  22603     }
  22604 
  22605     if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  22606         /*
  22607          * Indexes in the first half of EGR_MPLS_VC_AND_SWAP_LABEL_TABLE
  22608          * also get used as the index into the EGR_PW_INIT_COUNTERS table.
  22609          * Set num_vc to half the EGR_MPLS_VC_AND_SWAP_LABEL_TABLE size.
  22610          * Choose from the non-counted section (second half) so the counted
  22611          * section is available for VPWS.
  22612          */
  22613         num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
  22614         num_vc /= 2;
  22615 
  22616         /* Check for egr->flags & BCM_L3_REPLACE */
  22617         if (flags & BCM_L3_REPLACE) {
  22618            /* Remember old  VC_AND_SWAP_INDEX */
  22619             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  22620               old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  22621                                                          MPLS__VC_AND_SWAP_INDEXf);
  22622             } else {
  22623                 old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  22624                         VC_AND_SWAP_INDEXf);
  22625             }
  22626             BCM_IF_ERROR_RETURN (soc_mem_read(unit,
  22627                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  22628                         MEM_BLOCK_ANY, old_vc_swap_idx, &old_vc_entry));
  22629             if (!(egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_TTL_SET)) {
  22630                 egr->mpls_ttl = soc_mem_field32_get(unit,
  22631                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  22632                         &old_vc_entry, MPLS_TTLf);
  22633                 if (egr->mpls_ttl) {
  22634                     egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET;
  22635                 }
  22636             }
  22637         }
  22638         rv =  _bcm_tr_mpls_get_vc_and_swap_table_index (unit, 0, NULL, NULL,
  22639                   egr, NULL, 
  22640                   _BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, egr->mpls_flags) ?
  22641                   _BCM_MPLS_ACTION_PRESERVED : _BCM_MPLS_ACTION_SWAP,
  22642                   &vc_swap_index);
  22643         _BCM_MPLS_CLEANUP(rv);
  22644         rv = _bcm_tr_mpls_vc_and_swap_table_entry_set(unit, NULL, NULL, egr,
  22645                  _BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, egr->mpls_flags) ?
  22646                  _BCM_MPLS_ACTION_PRESERVED : _BCM_MPLS_ACTION_SWAP,
  22647                  &vc_entry, hw_map_idx, vc_swap_index);
  22648         _BCM_MPLS_CLEANUP(rv);
  22649 #if defined(BCM_TRIUMPH2_SUPPORT) \
  22650     ||  defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
  22651         if (SOC_IS_TRIUMPH2(unit)
  22652             || SOC_IS_ENDURO(unit) || SOC_IS_TRIDENT(unit)) {
  22653             /* workaround a hardware issue which is corrected on newer chips
  22654              * that the EGR_SD_TAG_CONTROL register influnces L3 MPLS tunnel's
  22655              * TPID selection. This shouldn't happen since L3 MPLS
  22656              * isn't using SD_TAG.
  22657              */
  22658             soc_mem_field32_set(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  22659                                     &vc_entry, SD_TAG_ACTION_IF_NOT_PRESENTf,
  22660                                     3);
  22661         }
  22662 #endif
  22663         rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  22664                            MEM_BLOCK_ALL, vc_swap_index,
  22665                            &vc_entry);
  22666         _BCM_MPLS_CLEANUP(rv);
  22667         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  22668             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22669                                  &egr_nh, MPLS__VC_AND_SWAP_INDEXf,
  22670                                  vc_swap_index);
  22671             /* Enable HG.L3_bit */
  22672             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22673                    &egr_nh, MPLS__HG_L3_OVERRIDEf, 0x1);
  22674             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22675                    &egr_nh, MPLS__HG_MODIFY_ENABLEf, 0x1);
  22676 #if defined(INCLUDE_XFLOW_MACSEC)
  22677             if (soc_feature(unit, soc_feature_xflow_macsec) &&
  22678                 ((egr->flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_ENCRYPT) ||
  22679                 (egr->flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_DECRYPT))) {
  22680                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22681                         &egr_nh, MPLS__MACSEC_ENCRYPTf, 0);
  22682                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22683                         &egr_nh, MPLS__MACSEC_DECRYPTf, 0);
  22684                 if (egr->flags2 & BCM_L3_FLAGS2_XFLOW_MACSEC_ENCRYPT) {
  22685                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22686                             &egr_nh, MPLS__MACSEC_ENCRYPTf, 0x1);
  22687                 } else {
  22688                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22689                             &egr_nh, MPLS__MACSEC_DECRYPTf, 0x1);
  22690                 }
  22691                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22692                         &egr_nh, MPLS__HG_MC_DST_MODIDf, egr->module);
  22693                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22694                         &egr_nh, MPLS__HG_MC_DST_PORT_NUMf, egr->port);
  22695             }
  22696 #endif
  22697         } else {
  22698              soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22699                                   &egr_nh, VC_AND_SWAP_INDEXf,
  22700                                   vc_swap_index);
  22701              /* Enable HG.L3_bit */
  22702              soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22703                     &egr_nh, HG_L3_OVERRIDEf, 0x1);
  22704              soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22705                     &egr_nh, HG_MODIFY_ENABLEf, 0x1);
  22706         }
  22707     } else {
  22708 #ifdef BCM_TOMAHAWK3_SUPPORT
  22709         uint32 mpls_flags = 0;
  22710         uint8 mpls_exp = 0;
  22711         uint8 mpls_pkt_pri = 0;
  22712         uint8 mpls_pkt_cfi = 0;
  22713         int   mpls_ecn_map_id = ECN_MAP_ID_INVALID;
  22714         int   mpls_int_cn_map_id = ECN_MAP_ID_INVALID;
  22715         /* TH3 doesnt support EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm*/
  22716         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22717                             &egr_nh, MPLS__MPLS_LABEL_ACTIONf,
  22718                             _BCM_MPLS_ACTION_NOOP);
  22719         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22720                             &egr_nh, MPLS__MPLS_TTLf, 0x0);
  22721          mpls_flags = egr->mpls_flags;
  22722          mpls_pkt_pri = egr->mpls_pkt_pri;
  22723          mpls_pkt_cfi = egr->mpls_pkt_cfi;
  22724          mpls_exp = egr->mpls_exp;
  22725          if (soc_feature(unit, soc_feature_mpls_ecn)) {
  22726             if (mpls_flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP) {
  22727                 mpls_int_cn_map_id = egr->mpls_ecn_map_id;
  22728             }
  22729             if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP) {
  22730                 mpls_ecn_map_id = egr->mpls_ecn_map_id;
  22731             }
  22732          }
  22733 
  22734         if ((mpls_exp > 7) || (mpls_pkt_pri > 7) ||
  22735             (mpls_pkt_cfi > 1)) {
  22736             return BCM_E_PARAM;
  22737         }
  22738 
  22739         if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) ||
  22740             (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) {
  22741 
  22742             if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) ||
  22743                 (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ||
  22744                 (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_REMARK)) {
  22745                 return  BCM_E_PARAM;
  22746             }
  22747             /* Use the specified EXP, PRI and CFI */
  22748             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22749                                 &egr_nh, MPLS__MPLS_EXP_SELECTf,
  22750                                 0x0); /* USE_FIXED */
  22751             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22752                                 &egr_nh, MPLS__MPLS_EXPf,
  22753                                 mpls_exp);
  22754             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22755                                 &egr_nh, MPLS__NEW_PRIf,
  22756                                 mpls_pkt_pri);
  22757             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22758                                 &egr_nh, MPLS__NEW_CFIf,
  22759                                 mpls_pkt_cfi);
  22760         } else if (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) {
  22761             if (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET) {
  22762                 return BCM_E_PARAM;
  22763             }
  22764             /* Use EXP-map for EXP, PRI and CFI */
  22765             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22766                                 &egr_nh, MPLS__MPLS_EXP_SELECTf,
  22767                                 0x1); /* USE_MAPPING */
  22768             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22769                                 &egr_nh, MPLS__MPLS_EXP_MAPPING_PTRf,
  22770                                 hw_map_idx);
  22771         } else if (/*(label_action != _BCM_MPLS_ACTION_SWAP) && */
  22772                         (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ) {
  22773             /* Use EXP from incoming label. If there is no incoming label,
  22774              * use the specified EXP value. Use EXP-map for PRI/CFI.
  22775              */
  22776             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22777                                 &egr_nh, MPLS__MPLS_EXP_SELECTf,
  22778                                 0x2); /* USE_INNER */
  22779             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22780                                 &egr_nh, MPLS__MPLS_EXPf,
  22781                                 mpls_exp);
  22782 
  22783             /* Use EXP-PRI-map for PRI/CFI */
  22784             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22785                                 &egr_nh, MPLS__MPLS_EXP_MAPPING_PTRf,
  22786                                 hw_map_idx);
  22787         } else if (/*(label_action == _BCM_MPLS_ACTION_SWAP) && */
  22788                         (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ) {
  22789               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22790                                 &egr_nh, MPLS__MPLS_EXP_SELECTf,
  22791                                 0x3); /* USE_SWAP */
  22792               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22793                                 &egr_nh, MPLS__MPLS_EXPf, mpls_exp);
  22794               /* Use EXP-PRI-map for PRI/CFI */
  22795               soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22796                                 &egr_nh, MPLS__MPLS_EXP_MAPPING_PTRf,
  22797                                 hw_map_idx);
  22798         }
  22799         if (soc_feature(unit, soc_feature_mpls_ecn)) {
  22800             if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP) &&
  22801                 (mpls_int_cn_map_id != ECN_MAP_ID_INVALID)) {
  22802                 int ecn_map_index;
  22803                 int ecn_map_type;
  22804                 int ecn_map_num;
  22805                 int ecn_map_hw_idx;
  22806                 ecn_map_type = mpls_int_cn_map_id &
  22807                                 _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK;
  22808                 ecn_map_index = mpls_int_cn_map_id &
  22809                                 _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK;
  22810                 ecn_map_num =
  22811                     soc_mem_index_count(unit, EGR_INT_CN_TO_EXP_MAPPING_TABLEm) /
  22812                     _BCM_ECN_MAX_ENTRIES_PER_MAP;
  22813                 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_INTCN2EXP) {
  22814                     return BCM_E_PARAM;
  22815                 }
  22816                 if (ecn_map_index >= ecn_map_num) {
  22817                     return BCM_E_PARAM;
  22818                 }
  22819                 BCM_IF_ERROR_RETURN(
  22820                     bcmi_ecn_map_id2hw_idx(unit, mpls_int_cn_map_id, &ecn_map_hw_idx));
  22821                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22822                                     &egr_nh, MPLS__INT_CN_TO_EXP_MAPPING_PTRf,
  22823                                     ecn_map_hw_idx);
  22824                 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST) {
  22825                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22826                                         &egr_nh, MPLS__INT_CN_TO_EXP_PRIORITYf, 1);
  22827 
  22828                 } else {
  22829                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22830                                         &egr_nh, MPLS__INT_CN_TO_EXP_PRIORITYf, 0);
  22831 
  22832                 }
  22833             }
  22834             if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP) &&
  22835                 (mpls_ecn_map_id != ECN_MAP_ID_INVALID)) {
  22836                 int ecn_map_index;
  22837                 int ecn_map_type;
  22838                 int ecn_map_num;
  22839                 int ecn_map_hw_idx;
  22840                 ecn_map_type = mpls_ecn_map_id &
  22841                                 _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK;
  22842                 ecn_map_index = mpls_ecn_map_id &
  22843                                 _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK;
  22844                 ecn_map_num =
  22845                     soc_mem_index_count(unit, EGR_IP_ECN_TO_EXP_MAPPING_TABLEm) /
  22846                     _BCM_ECN_MAX_ENTRIES_PER_MAP;
  22847                 if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP) {
  22848                     return BCM_E_PARAM;
  22849                 }
  22850                 if (ecn_map_index >= ecn_map_num) {
  22851                     return BCM_E_PARAM;
  22852                 }
  22853                 BCM_IF_ERROR_RETURN(
  22854                     bcmi_ecn_map_id2hw_idx(unit, mpls_ecn_map_id, &ecn_map_hw_idx));
  22855 
  22856                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22857                                     &egr_nh, MPLS__IP_ECN_TO_EXP_MAPPING_PTRf,
  22858                                     ecn_map_hw_idx);
  22859                 if (mpls_flags & BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST) {
  22860                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22861                                         &egr_nh, MPLS__IP_ECN_TO_EXP_PRIORITYf, 1);
  22862 
  22863                 } else {
  22864                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  22865                                         &egr_nh, MPLS__IP_ECN_TO_EXP_PRIORITYf, 0);
  22866 
  22867                 }
  22868           }
  22869       }
  22870 #endif
  22871     }
  22872 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  22873     if (soc_feature(unit, soc_feature_mpls_nh_ttl_control)) {
  22874         if (egr->flags & BCM_L3_KEEP_TTL) {
  22875             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  22876                                 MPLS__DISABLE_TTL_DECREMENTf, 1);
  22877         } else {
  22878             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  22879                                 MPLS__DISABLE_TTL_DECREMENTf, 0);
  22880         }
  22881     }
  22882 #endif
  22883 
  22884     /* Write EGR_L3_NEXT_HOP entry */
  22885     rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm,
  22886                        MEM_BLOCK_ALL, nh_index, &egr_nh);
  22887     _BCM_MPLS_CLEANUP(rv);
  22888 
  22889     /* Write ING_L3_NEXT_HOP entry */
  22890     
  22891     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
  22892                         &ing_nh, ENTRY_TYPEf, 0x1); /* MPLS L3_OIF */
  22893     rv = soc_mem_write (unit, ING_L3_NEXT_HOPm,
  22894                         MEM_BLOCK_ALL, nh_index, &ing_nh);
  22895     _BCM_MPLS_CLEANUP(rv);
  22896 
  22897     /* Handle old VC_SWAP indexes */
  22898     if (old_vc_swap_idx != -1) {
  22899 #if defined(BCM_TRIUMPH3_SUPPORT)
  22900          if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) {
  22901              BCM_IF_ERROR_RETURN(
  22902                  _bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit,
  22903                                                            old_vc_swap_idx,
  22904                                                            nh_index));
  22905          }
  22906 #endif
  22907          _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, old_vc_swap_idx, -1);
  22908          BCM_IF_ERROR_RETURN
  22909              (_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, old_vc_swap_idx));
  22910     }
  22911 #if defined(BCM_TRIUMPH3_SUPPORT)
  22912     if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) {
  22913         rv = _bcm_tr_mpls_vc_and_swap_hash_nhop_add(unit,
  22914                                                     vc_swap_index,
  22915                                                     nh_index);
  22916         _BCM_MPLS_CLEANUP(rv);
  22917     }
  22918 #endif
  22919 #ifdef BCM_WARM_BOOT_SUPPORT
  22920     SOC_CONTROL_LOCK(unit);
  22921     SOC_CONTROL(unit)->scache_dirty = 1;
  22922     SOC_CONTROL_UNLOCK(unit);
  22923 #endif
  22924 
  22925     return rv;
  22926 
  22927   cleanup:
  22928 
  22929     /* coverity[negative_returns : FALSE] */
  22930     if (vc_swap_index != -1) {
  22931          _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, vc_swap_index, -1);
  22932          (void)_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, vc_swap_index);
  22933     }
  22934     return rv;
  22935 }
  22936 
  22937 /*
  22938  * Function:
  22939  *		bcm_tr_mpls_swap_nh_info_delete
  22940  * Purpose:
  22941  *		Delete  SWAP_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index
  22942  * Parameters:
  22943  *		IN   :  Unit
  22944  *           IN    :  nh_index
  22945  * Returns:
  22946  *		BCM_E_XXX
  22947  */
  22948 
  22949 int
  22950 bcm_tr_mpls_swap_nh_info_delete(int unit, int nh_index)
  22951 {
  22952     int rv = BCM_E_NONE, old_vc_swap_idx = -1;
  22953     ing_l3_next_hop_entry_t ing_nh;
  22954     egr_l3_next_hop_entry_t egr_nh;
  22955     int intf;
  22956     int tunnel_id;
  22957 
  22958     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm,
  22959                                       MEM_BLOCK_ANY, nh_index, &egr_nh));
  22960     BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm,
  22961                                       MEM_BLOCK_ANY, nh_index, &ing_nh));
  22962 
  22963     if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]) != 0x1) {
  22964         return BCM_E_NONE;
  22965     }
  22966 
  22967     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  22968          intf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOP_2m, &egr_nh,
  22969                                                  INTF_NUMf);
  22970     } else if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  22971          old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  22972                                                        MPLS__VC_AND_SWAP_INDEXf);
  22973          intf = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  22974                                                  MPLS__INTF_NUMf);
  22975     } else {
  22976          old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  22977                                                        VC_AND_SWAP_INDEXf);
  22978 
  22979          if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  22980              intf = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  22981                      L3__INTF_NUMf);
  22982          } else {
  22983          intf = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  22984                                                  INTF_NUMf);
  22985     }
  22986     }
  22987 
  22988     if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  22989        if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  22990             soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh,
  22991                                              MPLS__VC_AND_SWAP_INDEXf,
  22992                                              0);
  22993        } else {
  22994             soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh,
  22995                                              VC_AND_SWAP_INDEXf,
  22996                                              0);
  22997        }
  22998     } else {
  22999         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23000             &egr_nh, MPLS__MPLS_LABEL_ACTIONf, 0);
  23001     }
  23002     BCM_IF_ERROR_RETURN (soc_mem_write(unit, EGR_L3_NEXT_HOPm,
  23003                                        MEM_BLOCK_ALL, nh_index, &egr_nh));
  23004 #if defined(BCM_TRIUMPH3_SUPPORT)
  23005     if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) {
  23006         BCM_IF_ERROR_RETURN (
  23007             _bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit,
  23008                                                       old_vc_swap_idx,
  23009                                                       nh_index));
  23010     }
  23011 #endif
  23012 
  23013     if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  23014         /* clear VC_AND_SWAP_LABEL entry */
  23015         _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, old_vc_swap_idx, -1);
  23016 
  23017         /* Free VC_AND_SWAP_LABEL entry */
  23018         BCM_IF_ERROR_RETURN
  23019              (_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, old_vc_swap_idx));
  23020     }
  23021 
  23022     BCM_IF_ERROR_RETURN
  23023         (_bcm_xgs3_l3_get_tunnel_id(unit, intf, &tunnel_id));
  23024     if (!tunnel_id) {
  23025 
  23026         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
  23027                             &ing_nh, ENTRY_TYPEf, 0x0); 
  23028         rv = soc_mem_write (unit, ING_L3_NEXT_HOPm,
  23029                             MEM_BLOCK_ALL, nh_index, &ing_nh);
  23030     } 
  23031 
  23032 #ifdef BCM_WARM_BOOT_SUPPORT
  23033     SOC_CONTROL_LOCK(unit);
  23034     SOC_CONTROL(unit)->scache_dirty = 1;
  23035     SOC_CONTROL_UNLOCK(unit);
  23036 #endif
  23037 
  23038     return rv;
  23039 }
  23040 
  23041 /*
  23042  * Function:
  23043  *        bcm_tr_mpls_swap_nh_info_get
  23044  * Purpose:
  23045  *        Get  Label_Swap info within Egress Object for a specific EGR_NH Index
  23046  * Parameters:
  23047  *           IN :  Unit
  23048  *           OUT : Egress object Pointer
  23049  *           IN :  nh_index
  23050  * Returns:
  23051  *           BCM_E_XXX
  23052  */
  23053 
  23054 int
  23055 bcm_tr_mpls_swap_nh_info_get(int unit, bcm_l3_egress_t *egr, int nh_index)
  23056 {
  23057     egr_l3_next_hop_entry_t egr_nh;
  23058     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
  23059     int vc_swap_idx, ix;
  23060     uint32	 label_action = 0;
  23061     uint32 label_select = 0;
  23062     int vc_data_type = 0;
  23063 #if defined(BCM_TRIDENT3_SUPPORT)
  23064     uint32 mpls_format[2];
  23065 #endif
  23066 
  23067     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  23068                                       nh_index, &egr_nh));
  23069 
  23070 #if defined(BCM_TOMAHAWK3_SUPPORT)
  23071     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  23072         return bcm_th3_mpls_swap_nh_info_get(unit, egr, nh_index);
  23073     }
  23074 #endif
  23075 
  23076     if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  23077          vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  23078                                                        MPLS__VC_AND_SWAP_INDEXf);
  23079     } else {
  23080          vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  23081                                                        VC_AND_SWAP_INDEXf);
  23082     }
  23083 
  23084     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
  23085                                       MEM_BLOCK_ANY, vc_swap_idx, &vc_entry));
  23086     if (SOC_MEM_FIELD_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23087                 DATA_TYPEf)) {
  23088         vc_data_type =  soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23089                 &vc_entry, DATA_TYPEf);
  23090     }
  23091 
  23092     if (vc_data_type == _BCM_VC_SWAP_TBL_FLEX_DATA_TYPE) {
  23093 #if defined(BCM_TRIDENT3_SUPPORT)
  23094         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  23095             sal_memset(mpls_format, 0, sizeof(mpls_format));
  23096             soc_mem_field_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23097                     (uint32 *) &vc_entry,
  23098                     MPLS_PHP__MPLS_ENTRY_0_ACTION_SETf,
  23099                     (uint32 *) mpls_format);
  23100         }
  23101 #endif
  23102     }
  23103 
  23104 #if defined(BCM_TRIDENT3_SUPPORT)
  23105     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  23106         if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) {
  23107             label_action =
  23108                 MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_idx];
  23109         }
  23110     } else
  23111 #endif
  23112     {
  23113     label_action =  soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23114                                         &vc_entry, MPLS_LABEL_ACTIONf);
  23115     }
  23116 
  23117 #if defined(BCM_TRIDENT3_SUPPORT)
  23118     if(soc_feature(unit, soc_feature_td3_style_mpls)) {
  23119         if (vc_data_type == _BCM_VC_SWAP_TBL_FLEX_DATA_TYPE) {
  23120             label_select = soc_format_field32_get(unit, 
  23121                     MPLS_ENTRY_ACTION_SETfmt,
  23122                     (uint32 *)mpls_format, LABEL_SELECTf);
  23123 
  23124         } else {
  23125         label_select = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23126                 &vc_entry, LABEL_SELECTf);
  23127     }
  23128     }
  23129 #endif
  23130 
  23131     if (label_action == _BCM_MPLS_ACTION_SWAP ||
  23132         (soc_feature(unit, soc_feature_mpls_swap_label_preserve) &&
  23133         ((label_action == _BCM_MPLS_ACTION_PRESERVED) || label_select))) { /* SWAP */
  23134 
  23135         if (vc_data_type == _BCM_VC_SWAP_TBL_FLEX_DATA_TYPE) {
  23136 #if defined(BCM_TRIDENT3_SUPPORT)
  23137             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  23138                 if ((label_action == _BCM_MPLS_ACTION_PRESERVED) || label_select) {
  23139                     egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_PRESERVE;
  23140                     egr->mpls_label = BCM_MPLS_LABEL_INVALID;
  23141                 } else {
  23142                     egr->mpls_label = soc_format_field32_get(unit, 
  23143                             MPLS_ENTRY_ACTION_SETfmt,
  23144                             (uint32 *)mpls_format, MPLS_LABELf);
  23145                 }
  23146 
  23147                 egr->mpls_ttl = soc_format_field32_get(unit, 
  23148                         MPLS_ENTRY_ACTION_SETfmt,
  23149                         (uint32 *)mpls_format, MPLS_TTLf);
  23150 
  23151                 if (egr->mpls_ttl) {
  23152                     egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET;
  23153                 } else {
  23154                     egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_DECREMENT;
  23155                 }
  23156                 if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  23157                             (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x0) {
  23158                     /* Use the specified EXP, PRI and CFI */
  23159                     egr->flags |= BCM_MPLS_EGRESS_LABEL_EXP_SET;
  23160                     egr->flags |= BCM_MPLS_EGRESS_LABEL_PRI_SET;
  23161                     egr->mpls_exp =
  23162                         soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  23163                                 (uint32 *)mpls_format, MPLS_EXPf);
  23164                     egr->mpls_pkt_pri =
  23165                         soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  23166                                 (uint32 *)mpls_format, NEW_PRIf);
  23167                     egr->mpls_pkt_cfi =
  23168                         soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  23169                                 (uint32 *)mpls_format, NEW_CFIf);
  23170                 } else if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  23171                             (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x1) {
  23172                     /* Use EXP-map for EXP, PRI and CFI */
  23173                     egr->flags |= BCM_MPLS_EGRESS_LABEL_EXP_REMARK;
  23174                     egr->flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK;
  23175                     ix = soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  23176                             (uint32 *)mpls_format, MPLS_EXP_MAPPING_PTRf);
  23177                     BCM_IF_ERROR_RETURN(
  23178                             _egr_qos_hw_idx2id(unit, ix, &egr->mpls_qos_map_id));
  23179 
  23180                 } else if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  23181                             (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x3) {
  23182                     /* Use EXP from incoming MPLS label. If no incoming label, use the specified
  23183                      * EXP value. Use EXP-map for PRI/CFI.
  23184                      */
  23185                     egr->flags |= BCM_MPLS_EGRESS_LABEL_EXP_COPY;
  23186                     egr->flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK;
  23187                     egr->mpls_exp =
  23188                         soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  23189                                 (uint32 *)mpls_format, MPLS_EXPf);
  23190                     ix = soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  23191                             (uint32 *)mpls_format, MPLS_EXP_MAPPING_PTRf);
  23192 
  23193                     BCM_IF_ERROR_RETURN(
  23194                             _egr_qos_hw_idx2id(unit, ix, &egr->mpls_qos_map_id));
  23195                 }
  23196             }
  23197 #endif
  23198         } else {
  23199 
  23200         if (soc_feature(unit, soc_feature_mpls_swap_label_preserve) &&
  23201             ((label_action == _BCM_MPLS_ACTION_PRESERVED) || label_select)) {
  23202             egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_PRESERVE;
  23203             egr->mpls_label = BCM_MPLS_LABEL_INVALID;
  23204         } else {
  23205             egr->mpls_label =
  23206             soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23207                                 &vc_entry, MPLS_LABELf);
  23208         }
  23209         egr->mpls_ttl =
  23210             soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23211                                 &vc_entry, MPLS_TTLf);
  23212         if (egr->mpls_ttl) {
  23213             egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET;
  23214         } else {
  23215             egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_DECREMENT;
  23216         }
  23217         if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23218                                 &vc_entry, MPLS_EXP_SELECTf) == 0x0) {
  23219             /* Use the specified EXP, PRI and CFI */
  23220             egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_EXP_SET;
  23221             egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_PRI_SET;
  23222             egr->mpls_exp = 
  23223                 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23224                                     &vc_entry, MPLS_EXPf);
  23225             egr->mpls_pkt_pri = 
  23226                 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23227                                     &vc_entry, NEW_PRIf);
  23228             egr->mpls_pkt_cfi = 
  23229                 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23230                                     &vc_entry, NEW_CFIf);
  23231         } else if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23232                                        &vc_entry, MPLS_EXP_SELECTf) == 0x1) {
  23233             /* Use EXP-map for EXP, PRI and CFI */
  23234             egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_EXP_REMARK;
  23235             egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK;
  23236             ix = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23237                                      &vc_entry, MPLS_EXP_MAPPING_PTRf);
  23238                 BCM_IF_ERROR_RETURN(
  23239                     _egr_qos_hw_idx2id(unit, ix, &egr->mpls_qos_map_id));
  23240         } else if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23241                                        &vc_entry, MPLS_EXP_SELECTf) == 0x3) {
  23242             /* Use EXP from incoming MPLS label. If no incoming label, use the specified
  23243              * EXP value. Use EXP-map for PRI/CFI.
  23244              */
  23245             egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_EXP_COPY;
  23246             egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK;
  23247             egr->mpls_exp = 
  23248                 soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23249                                     &vc_entry, MPLS_EXPf);
  23250             ix = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23251                                      &vc_entry, MPLS_EXP_MAPPING_PTRf);
  23252                 BCM_IF_ERROR_RETURN(
  23253                     _egr_qos_hw_idx2id(unit, ix, &egr->mpls_qos_map_id));
  23254         }
  23255         }
  23256 #if defined(BCM_TOMAHAWK2_SUPPORT)
  23257         if (soc_feature(unit, soc_feature_mpls_ecn) &&
  23258                 !soc_feature(unit, soc_feature_intcn_to_exp_nosupport)) {
  23259             int ecn_map_id;
  23260             int ecn_map_pri;
  23261             int ecn_map_hw_idx;
  23262             int rv;
  23263             ecn_map_hw_idx = soc_mem_field32_get(unit, 
  23264                                 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry, 
  23265                                 INT_CN_TO_EXP_MAPPING_PTRf);
  23266             ecn_map_pri = soc_mem_field32_get(unit, 
  23267                               EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry, 
  23268                               INT_CN_TO_EXP_PRIORITYf);
  23269             rv = bcmi_ecn_map_hw_idx2id(unit, ecn_map_hw_idx, 
  23270                                         _BCM_XGS5_MPLS_ECN_MAP_TYPE_INTCN2EXP, 
  23271                                         &ecn_map_id); 
  23272             if (BCM_SUCCESS(rv)) {
  23273                 egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP;
  23274                 egr->mpls_ecn_map_id = ecn_map_id;
  23275                 if (ecn_map_pri) {
  23276                     egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST;
  23277                 }
  23278             }
  23279         }
  23280 #endif
  23281     } else {
  23282         egr->mpls_label = BCM_MPLS_LABEL_INVALID;
  23283     }
  23284     return BCM_E_NONE;
  23285 }
  23286 
  23287 /*
  23288  * Function:
  23289  *        bcm_tr_mpls_l3_nh_info_add
  23290  * Purpose:
  23291  *        Add  SWAP_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index
  23292  * Parameters:
  23293  *           IN :  Unit
  23294  *           IN/OUT : Tunnel Switch Pointer
  23295  *           IN :  nh_index
  23296  * Returns:
  23297  *           BCM_E_XXX
  23298  */
  23299 
  23300 int
  23301 bcm_tr_mpls_l3_nh_info_add(int unit, bcm_mpls_tunnel_switch_t *info, int *nh_index)
  23302 {
  23303     initial_ing_l3_next_hop_entry_t initial_ing_nh;
  23304     ing_l3_next_hop_entry_t ing_nh;
  23305     egr_l3_next_hop_entry_t egr_nh;
  23306 #if defined(BCM_TOMAHAWK3_SUPPORT)
  23307     egr_l3_next_hop_2_entry_t egr_nh_2;
  23308 #endif
  23309     egr_mac_da_profile_entry_t macda;
  23310     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
  23311     _bcm_tr_ing_nh_info_t ing_nh_info;
  23312     _bcm_tr_egr_nh_info_t egr_nh_info;
  23313     bcm_l3_egress_t nh_info, nh_obj;
  23314     bcm_module_t mod_out;
  23315     bcm_port_t port_out;
  23316     uint32 nh_flags, macda_index;
  23317     int rv, temp_nh_index = -1, num_vc=0;
  23318     void *entries[1];
  23319     int num_mpls_map, hw_map_idx;
  23320     uint32 mpath_flag=0;
  23321 
  23322     /* Initialize values */
  23323     if (info->mtu != 0) {
  23324         ing_nh_info.mtu = info->mtu;
  23325     }  else {
  23326         ing_nh_info.mtu = 0x3FFF;
  23327     }
  23328 
  23329     ing_nh_info.port = -1;
  23330     ing_nh_info.module = -1;
  23331     ing_nh_info.trunk = -1;
  23332     ing_nh_info.qtag = -1;
  23333     ing_nh_info.tag_type = -1;
  23334 
  23335     egr_nh_info.dvp = -1; /* Not applicable */
  23336     egr_nh_info.dvp_is_network = -1; /* Not applicable */
  23337     egr_nh_info.entry_type = -1;
  23338     egr_nh_info.sd_tag_action_present = -1;
  23339     egr_nh_info.sd_tag_action_not_present = -1;
  23340     egr_nh_info.intf_num = -1;
  23341     egr_nh_info.sd_tag_vlan = -1;
  23342     egr_nh_info.macda_index = -1;
  23343     egr_nh_info.vc_swap_index = -1;
  23344     egr_nh_info.pw_init_cnt = -1;
  23345 
  23346 
  23347     /* 
  23348      * Get egress next-hop index from egress object and
  23349      * increment egress object reference count. 
  23350      */
  23351     rv = bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if,
  23352                                             &mpath_flag, 1, &temp_nh_index);
  23353     _BCM_MPLS_CLEANUP(rv);
  23354     bcm_l3_egress_t_init(&nh_info);
  23355 
  23356 
  23357     /* Get egress next-hop info from the egress object */
  23358     rv = bcm_xgs3_nh_get(unit, temp_nh_index, &nh_info);
  23359     _BCM_MPLS_CLEANUP(rv);
  23360 
  23361 #if defined(BCM_KATANA_SUPPORT)
  23362     if (SOC_IS_KATANAX(unit)) {
  23363         ing_l3_next_hop_entry_t in_nh;
  23364 
  23365         rv = soc_mem_read (unit, ING_L3_NEXT_HOPm,
  23366                     MEM_BLOCK_ALL, temp_nh_index, &in_nh);
  23367         _BCM_MPLS_CLEANUP(rv);
  23368         ing_nh_info.qtag = soc_ING_L3_NEXT_HOPm_field32_get(unit, &in_nh,
  23369                                       EH_QUEUE_TAGf);
  23370         ing_nh_info.tag_type = soc_ING_L3_NEXT_HOPm_field32_get(unit,
  23371                                       &in_nh,
  23372                                       EH_TAG_TYPEf);
  23373     }
  23374 #endif
  23375 
  23376     /* Check if Egress Object contains a valid SWAP Label */
  23377     if (BCM_XGS3_L3_MPLS_LBL_VALID(nh_info.mpls_label)) {
  23378         return BCM_E_CONFIG;
  23379     }
  23380 
  23381     /*
  23382      * Indexes in the first half of EGR_MPLS_VC_AND_SWAP_LABEL_TABLE
  23383      * also get used as the index into the EGR_PW_INIT_COUNTERS table.
  23384      * Set num_vc to half the EGR_MPLS_VC_AND_SWAP_LABEL_TABLE size.
  23385      * Choose from the non-counted section (second half) so the counted
  23386      * section is available for VPWS.
  23387      */
  23388     if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) {
  23389         num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
  23390         num_vc /= 2;
  23391     }
  23392 
  23393     /*
  23394      * For SWAP operation, we need to allocate a unique next-hop
  23395      * index and populate the swap label info. Copy the destination
  23396      * port information from the egress object.
  23397      * 
  23398      * Allocate a next-hop entry. By calling bcm_xgs3_nh_add()
  23399      * with _BCM_L3_SHR_WRITE_DISABLE flag, a next-hop index is
  23400      * allocated but nothing is written to hardware. The "nh_info"
  23401      * in this case is not used, so just set to all zeros.
  23402      */
  23403     bcm_l3_egress_t_init(&nh_obj);
  23404 
  23405     nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE;
  23406     BCM_IF_ERROR_RETURN(bcm_xgs3_nh_add(unit, nh_flags, &nh_obj, nh_index));
  23407 
  23408     rv = _bcm_tr_mpls_add_egrNhop (unit, info->egress_if);
  23409     _BCM_MPLS_CLEANUP(rv);
  23410 
  23411     rv = _bcm_tr_mpls_add_vp_nh (unit, info->egress_if, *nh_index);
  23412     _BCM_MPLS_CLEANUP(rv);
  23413 
  23414     /* Copy the destination port information. */
  23415     if (nh_info.flags & BCM_L3_TGID) {
  23416         ing_nh_info.port = -1;
  23417         ing_nh_info.module = -1;
  23418         ing_nh_info.trunk = nh_info.trunk; 
  23419     } else {
  23420         BCM_IF_ERROR_RETURN
  23421             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, nh_info.module, nh_info.port, 
  23422                                     &mod_out, &port_out));
  23423         ing_nh_info.port = port_out;
  23424         ing_nh_info.module = mod_out;
  23425         ing_nh_info.trunk = -1; 
  23426     }
  23427     egr_nh_info.intf_num = nh_info.intf;
  23428     egr_nh_info.entry_type = 0x1; /* MPLS_MACDA_PROFILE */
  23429 
  23430     sal_memset(&macda, 0, sizeof(egr_mac_da_profile_entry_t));
  23431     soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, 
  23432                          &macda, MAC_ADDRESSf, nh_info.mac_addr);
  23433     entries[0] = &macda;
  23434     rv = _bcm_mac_da_profile_entry_add(unit, entries, 1, &macda_index);
  23435     egr_nh_info.macda_index = macda_index;
  23436     _BCM_MPLS_CLEANUP(rv);
  23437 
  23438     if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  23439         rv = _bcm_tr_mpls_get_vc_and_swap_table_index(unit, 0, NULL, info, NULL,
  23440                   NULL,
  23441                  _BCM_MPLS_EGRESS_LABEL_PRESERVE(unit,info->egress_label.flags)?
  23442                  _BCM_MPLS_ACTION_PRESERVED : _BCM_MPLS_ACTION_SWAP,
  23443                  &egr_nh_info.vc_swap_index);
  23444 
  23445 
  23446         _BCM_MPLS_CLEANUP(rv);
  23447     }
  23448 
  23449     /* Retrieve hardware index for mapping pointer */
  23450     num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
  23451 
  23452     if (info->egress_label.qos_map_id == 0) {
  23453         hw_map_idx = 0; /* use default */
  23454     } else {
  23455         BCM_IF_ERROR_RETURN(_egr_qos_id2hw_idx(unit,
  23456                         info->egress_label.qos_map_id,&hw_map_idx));
  23457     }
  23458     if (hw_map_idx < 0 || hw_map_idx >= num_mpls_map) {
  23459         rv = BCM_E_PARAM;
  23460         goto cleanup;
  23461     }
  23462 
  23463     
  23464 
  23465     /* Write EGR_L3_NEXT_HOP entry */
  23466     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
  23467 
  23468     /* Program the MPLS_VC_AND_SWAP table entry */
  23469     if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  23470         rv = _bcm_tr_mpls_vc_and_swap_table_entry_set(unit, NULL, info, NULL,
  23471              _BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, info->egress_label.flags) ?
  23472              _BCM_MPLS_ACTION_PRESERVED : _BCM_MPLS_ACTION_SWAP,
  23473              &vc_entry, hw_map_idx, egr_nh_info.vc_swap_index);
  23474          _BCM_MPLS_CLEANUP(rv);
  23475 
  23476         rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23477                            MEM_BLOCK_ALL, egr_nh_info.vc_swap_index,
  23478                            &vc_entry);
  23479         _BCM_MPLS_CLEANUP(rv);
  23480     }
  23481 #if defined(BCM_TOMAHAWK3_SUPPORT)
  23482     else {
  23483         if ((info->egress_label.flags & BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP) &&
  23484             (info->egress_label.int_cn_map_id != ECN_MAP_ID_INVALID) &&
  23485             (!soc_feature(unit, soc_feature_intcn_to_exp_nosupport))) {
  23486             int ecn_map_index;
  23487             int ecn_map_type;
  23488             int ecn_map_num;
  23489             int ecn_map_hw_idx;
  23490             ecn_map_type = info->egress_label.int_cn_map_id &
  23491                             _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK;
  23492             ecn_map_index = info->egress_label.int_cn_map_id &
  23493                             _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK;
  23494             ecn_map_num =
  23495                 soc_mem_index_count(unit, EGR_INT_CN_TO_EXP_MAPPING_TABLEm) /
  23496                 _BCM_ECN_MAX_ENTRIES_PER_MAP;
  23497             if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_INTCN2EXP) {
  23498                 return BCM_E_PARAM;
  23499             }
  23500             if (ecn_map_index >= ecn_map_num) {
  23501                 return BCM_E_PARAM;
  23502             }
  23503             BCM_IF_ERROR_RETURN(
  23504                 bcmi_ecn_map_id2hw_idx(unit, info->egress_label.int_cn_map_id, &ecn_map_hw_idx));
  23505             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23506                                 &egr_nh, MPLS__INT_CN_TO_EXP_MAPPING_PTRf,
  23507                                 ecn_map_hw_idx);
  23508             if (info->egress_label.flags & BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST) {
  23509                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23510                                     &egr_nh, MPLS__INT_CN_TO_EXP_PRIORITYf, 1);
  23511 
  23512             } else {
  23513                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23514                                     &egr_nh, MPLS__INT_CN_TO_EXP_PRIORITYf, 0);
  23515 
  23516             }
  23517         }
  23518         if ((info->egress_label.flags & BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP) &&
  23519             (info->egress_label.ecn_map_id != ECN_MAP_ID_INVALID)) {
  23520             int ecn_map_index;
  23521             int ecn_map_type;
  23522             int ecn_map_num;
  23523             int ecn_map_hw_idx;
  23524             soc_mem_t mem;
  23525             soc_field_t ipecn_to_exp_ptr;
  23526             soc_field_t ipecn_to_exp_priority;
  23527             ecn_map_type = info->egress_label.ecn_map_id &
  23528                             _BCM_XGS5_MPLS_ECN_MAP_TYPE_MASK;
  23529             ecn_map_index = info->egress_label.ecn_map_id &
  23530                             _BCM_XGS5_MPLS_ECN_MAP_NUM_MASK;
  23531             {
  23532                mem = EGR_IP_ECN_TO_EXP_MAPPING_TABLEm;
  23533            }
  23534            ecn_map_num =
  23535                soc_mem_index_count(unit, mem) /
  23536                _BCM_ECN_MAX_ENTRIES_PER_MAP;
  23537            if (ecn_map_type != _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP) {
  23538                return BCM_E_PARAM;
  23539            }
  23540            if (ecn_map_index >= ecn_map_num) {
  23541                return BCM_E_PARAM;
  23542            }
  23543 
  23544            BCM_IF_ERROR_RETURN(
  23545                bcmi_ecn_map_id2hw_idx(unit, info->egress_label.ecn_map_id, &ecn_map_hw_idx));
  23546 
  23547            ipecn_to_exp_ptr = MPLS__IP_ECN_TO_EXP_MAPPING_PTRf;
  23548            ipecn_to_exp_priority = MPLS__IP_ECN_TO_EXP_PRIORITYf;
  23549            soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23550                                &egr_nh, ipecn_to_exp_ptr,
  23551                                ecn_map_hw_idx);
  23552            if (info->egress_label.flags & BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST) {
  23553                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23554                                    &egr_nh, ipecn_to_exp_priority, 1);
  23555 
  23556            } else {
  23557                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23558                                    &egr_nh, ipecn_to_exp_priority, 0);
  23559            }
  23560        }
  23561     }
  23562 #endif
  23563    if (egr_nh_info.entry_type == 0x1) {
  23564        if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  23565            soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23566                    &egr_nh, L3__INTF_NUMf, egr_nh_info.intf_num);
  23567        } else
  23568 #if defined(BCM_TOMAHAWK3_SUPPORT)
  23569        if (SOC_MEM_IS_VALID(unit, EGR_L3_NEXT_HOP_2m)) {
  23570            sal_memset(&egr_nh_2, 0, sizeof(egr_l3_next_hop_2_entry_t));
  23571            soc_mem_field32_set(unit, EGR_L3_NEXT_HOP_2m,
  23572                    &egr_nh_2, INTF_NUMf, egr_nh_info.intf_num);
  23573        } else
  23574 #endif
  23575        {
  23576            soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23577                    &egr_nh, INTF_NUMf, egr_nh_info.intf_num);
  23578        }
  23579 
  23580          if (egr_nh_info.vc_swap_index != -1) {
  23581              if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  23582                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23583                                   &egr_nh, MPLS__VC_AND_SWAP_INDEXf,
  23584                                   egr_nh_info.vc_swap_index);
  23585              } else {
  23586                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23587                                   &egr_nh, VC_AND_SWAP_INDEXf,
  23588                                   egr_nh_info.vc_swap_index);
  23589              }
  23590          }
  23591 
  23592         if (egr_nh_info.macda_index != -1) {
  23593               if (soc_feature(unit, soc_feature_mpls_enhanced) ||
  23594                   soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  23595                    soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23596                             &egr_nh, MPLS__MAC_DA_PROFILE_INDEXf,
  23597                             egr_nh_info.macda_index);
  23598               } else {
  23599                    soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23600                              &egr_nh, MAC_DA_PROFILE_INDEXf,
  23601                              egr_nh_info.macda_index);
  23602               }
  23603         }
  23604 
  23605         if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm,MPLS__HG_MODIFY_ENABLEf)) {
  23606             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  23607                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23608                         &egr_nh, MPLS__HG_MODIFY_ENABLEf, 0x1);
  23609                /* Enable HG.L3_bit */
  23610                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23611                         &egr_nh, MPLS__HG_L3_OVERRIDEf, 0x1);
  23612 
  23613             } else {
  23614                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23615                          &egr_nh, HG_MODIFY_ENABLEf, 0x1);
  23616                /* Enable HG.L3_bit */
  23617                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  23618                         &egr_nh, HG_L3_OVERRIDEf, 0x1);
  23619             }
  23620         }
  23621 
  23622 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  23623         if (soc_feature(unit, soc_feature_mpls_nh_ttl_control)) {
  23624             if (info->flags & BCM_MPLS_SWITCH_KEEP_TTL) {
  23625                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  23626                                     MPLS__DISABLE_TTL_DECREMENTf, 1);
  23627             }
  23628         }
  23629 
  23630         if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
  23631                                 MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf)) {
  23632             if (info->flags2 &
  23633                 BCM_MPLS_SWITCH2_TUNNEL_HEADER_EGRESS_VLAN_TRANSLATION) {
  23634                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  23635                                         MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf, 1);
  23636             }
  23637         }
  23638 #endif
  23639 #if defined(BCM_TOMAHAWK3_SUPPORT)
  23640          if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  23641              bcm_l3_egress_t egr;
  23642              /*
  23643               * Get egress object information.
  23644               */
  23645              BCM_IF_ERROR_RETURN(bcm_xgs3_nh_get(unit, *nh_index, &egr));
  23646 
  23647              rv = _bcm_th3_mpls_egr_nh_label_set(unit, info, &egr,
  23648                      _BCM_MPLS_EGRESS_LABEL_PRESERVE(unit,
  23649                        info->egress_label.flags) ?  _BCM_MPLS_ACTION_PRESERVED :
  23650                                     _BCM_MPLS_ACTION_SWAP, hw_map_idx, &egr_nh);
  23651         }
  23652 #endif
  23653          soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  23654                         nh_entry_type_field[unit], egr_nh_info.entry_type);
  23655 
  23656          rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm,
  23657                        MEM_BLOCK_ALL, *nh_index, &egr_nh);
  23658          _BCM_MPLS_CLEANUP(rv);
  23659 #if defined(BCM_TOMAHAWK3_SUPPORT)
  23660          if (SOC_MEM_IS_VALID(unit, EGR_L3_NEXT_HOP_2m)) {
  23661              rv = soc_mem_write(unit, EGR_L3_NEXT_HOP_2m,
  23662                            MEM_BLOCK_ALL, *nh_index, &egr_nh_2);
  23663              _BCM_MPLS_CLEANUP(rv);
  23664          }
  23665 #endif
  23666     }
  23667 
  23668     /* Write ING_L3_NEXT_HOP entry */
  23669     sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t));
  23670     if (ing_nh_info.trunk == -1) {
  23671         if (soc_feature(unit, soc_feature_generic_dest)) {
  23672             soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
  23673                     DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
  23674                     ing_nh_info.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_info.port);
  23675         } else {
  23676             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
  23677                     &ing_nh, PORT_NUMf, ing_nh_info.port);
  23678             if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MODULE_IDf)) {
  23679                 soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
  23680                         &ing_nh, MODULE_IDf, ing_nh_info.module);
  23681             }
  23682         }
  23683     } else {    
  23684         if (soc_feature(unit, soc_feature_generic_dest)) {
  23685             soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
  23686                     DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_info.trunk);
  23687     } else {    
  23688         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
  23689                             &ing_nh, Tf, 1);
  23690         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
  23691                             &ing_nh, TGIDf, ing_nh_info.trunk);
  23692     }
  23693     }
  23694 
  23695     if ((ing_nh_info.qtag != -1) &&
  23696         SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm,EH_QUEUE_TAGf)) {
  23697         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
  23698                       EH_QUEUE_TAGf, ing_nh_info.qtag);
  23699     }
  23700     if ((ing_nh_info.tag_type != -1) &&
  23701         SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm,EH_TAG_TYPEf)) {
  23702         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
  23703                       EH_TAG_TYPEf, ing_nh_info.tag_type);
  23704     }
  23705 
  23706     
  23707     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
  23708                         &ing_nh, ENTRY_TYPEf, 0x1); /* MPLS L3_OIF */
  23709     rv = soc_mem_write (unit, ING_L3_NEXT_HOPm,
  23710                         MEM_BLOCK_ALL, *nh_index, &ing_nh);
  23711     _BCM_MPLS_CLEANUP(rv);
  23712 
  23713     if (SOC_MEM_IS_VALID(unit, INITIAL_ING_L3_NEXT_HOPm)) {
  23714         /* Write INITIAL_ING_L3_NEXT_HOP entry */
  23715         sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t));
  23716         if (ing_nh_info.trunk == -1) {
  23717             if (soc_feature(unit, soc_feature_generic_dest)) {
  23718                 soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh,
  23719                         DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
  23720                         ing_nh_info.module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_info.port);
  23721             } else {
  23722                 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
  23723                         &initial_ing_nh, PORT_NUMf, ing_nh_info.port);
  23724                 if (SOC_MEM_FIELD_VALID(unit, INITIAL_ING_L3_NEXT_HOPm, MODULE_IDf)) {
  23725                     soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
  23726                             &initial_ing_nh, MODULE_IDf, ing_nh_info.module);
  23727                 }
  23728             }
  23729         } else {
  23730             if (soc_feature(unit, soc_feature_generic_dest)) {
  23731                 soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm, &initial_ing_nh,
  23732                         DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_info.trunk);
  23733             } else {
  23734                 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
  23735                         &initial_ing_nh, Tf, 1);
  23736                 soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
  23737                         &initial_ing_nh, TGIDf, ing_nh_info.trunk);
  23738             }
  23739         }
  23740         rv = soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm,
  23741                            MEM_BLOCK_ALL, *nh_index, &initial_ing_nh);
  23742         _BCM_MPLS_CLEANUP(rv);
  23743    }
  23744 #if defined(BCM_TRIUMPH3_SUPPORT)
  23745     if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) {
  23746         rv = _bcm_tr_mpls_vc_and_swap_hash_nhop_add(unit,
  23747                                                     egr_nh_info.vc_swap_index,
  23748                                                     *nh_index);
  23749         _BCM_MPLS_CLEANUP(rv);
  23750     }
  23751 #endif
  23752     return rv;
  23753 
  23754   cleanup:
  23755     (void) bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, *nh_index);
  23756 
  23757     if (temp_nh_index != -1) {
  23758         (void) bcm_xgs3_nh_del(unit, 0, temp_nh_index);
  23759     }
  23760     if (egr_nh_info.macda_index != -1) {
  23761         _bcm_mac_da_profile_entry_delete(unit, egr_nh_info.macda_index);
  23762     }
  23763 
  23764     if (egr_nh_info.vc_swap_index >= 0) {
  23765         _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, 
  23766                              egr_nh_info.vc_swap_index, -1);
  23767         /* Free VC_AND_SWAP_LABEL entry */
  23768         (void)_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, 
  23769                              egr_nh_info.vc_swap_index);
  23770     }
  23771     return rv;
  23772 }
  23773 
  23774 /*
  23775  * Function:
  23776  *        bcm_tr_mpls_l3_nh_info_delete
  23777  * Purpose:
  23778  *        Delete  SWAP_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index
  23779  * Parameters:
  23780  *           IN :  Unit
  23781  *           IN :  nh_index
  23782  * Returns:
  23783  *           BCM_E_XXX
  23784  */
  23785 
  23786 int
  23787 bcm_tr_mpls_l3_nh_info_delete(int unit, int nh_index)
  23788 {
  23789     int rv, old_macda_idx = -1, old_vc_swap_idx = -1;
  23790     bcm_if_t old_egress_if = 0;
  23791     initial_ing_l3_next_hop_entry_t initial_ing_nh;
  23792     ing_l3_next_hop_entry_t ing_nh;
  23793     egr_l3_next_hop_entry_t egr_nh;
  23794 
  23795     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 
  23796                                       MEM_BLOCK_ANY, nh_index, &egr_nh));
  23797     BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 
  23798                                       MEM_BLOCK_ANY, nh_index, &ing_nh));
  23799     if (SOC_MEM_IS_VALID(unit, INITIAL_ING_L3_NEXT_HOPm)) {
  23800         BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_ING_L3_NEXT_HOPm,
  23801                                           MEM_BLOCK_ANY, nh_index, &initial_ing_nh));
  23802     }
  23803 
  23804     if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]) != 0x1) {
  23805         return BCM_E_NOT_FOUND;
  23806     }
  23807 
  23808     if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  23809          old_macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  23810                                                      MPLS__MAC_DA_PROFILE_INDEXf);
  23811     } else {
  23812          old_macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  23813                                                      MAC_DA_PROFILE_INDEXf);
  23814     }
  23815 
  23816     if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  23817         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  23818              old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  23819                                                            MPLS__VC_AND_SWAP_INDEXf);
  23820         } else {
  23821              old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  23822                                                            VC_AND_SWAP_INDEXf);
  23823         }
  23824     }
  23825     /* Find the tunnel_if */
  23826     rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) nh_index, &old_egress_if);
  23827     BCM_IF_ERROR_RETURN (rv);
  23828 
  23829     /* Clear EGR_L3_NEXT_HOP entry */
  23830     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
  23831     BCM_IF_ERROR_RETURN (soc_mem_write(unit, EGR_L3_NEXT_HOPm,
  23832                                        MEM_BLOCK_ALL, nh_index, &egr_nh));
  23833 
  23834     /* Clear ING_L3_NEXT_HOP entry */
  23835     sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t));
  23836     BCM_IF_ERROR_RETURN (soc_mem_write (unit, ING_L3_NEXT_HOPm,
  23837                                         MEM_BLOCK_ALL, nh_index, &ing_nh));
  23838 
  23839     /* Clear INITIAL_ING_L3_NEXT_HOP entry */
  23840     if (SOC_MEM_IS_VALID(unit, INITIAL_ING_L3_NEXT_HOPm)) {
  23841         sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t));
  23842         BCM_IF_ERROR_RETURN (soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm,
  23843                                        MEM_BLOCK_ALL, nh_index, &initial_ing_nh));
  23844     }
  23845 
  23846 #if defined(BCM_TRIUMPH3_SUPPORT)
  23847     if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) {
  23848         BCM_IF_ERROR_RETURN(
  23849             _bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit,
  23850                                                       old_vc_swap_idx,
  23851                                                       nh_index));
  23852     }
  23853 #endif
  23854 
  23855     if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  23856         /* clear VC_AND_SWAP_LABEL entry */
  23857         _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, old_vc_swap_idx, -1);
  23858 
  23859         /* Free VC_AND_SWAP_LABEL entry */
  23860         BCM_IF_ERROR_RETURN
  23861              (_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, old_vc_swap_idx));
  23862     }
  23863 
  23864     /* Delete old MAC profile reference */
  23865     rv = _bcm_mac_da_profile_entry_delete(unit, old_macda_idx);
  23866     BCM_IF_ERROR_RETURN(rv);
  23867 
  23868     /* Delete egress_if next-hop reference */
  23869     rv = bcm_xgs3_nh_del(unit, 0, (old_egress_if - BCM_XGS3_EGRESS_IDX_MIN(unit)));
  23870     BCM_IF_ERROR_RETURN(rv);
  23871 
  23872     if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  23873         BCM_IF_ERROR_RETURN(_bcm_tr_mpls_delete_vp_nh ( unit, nh_index, old_egress_if ));
  23874     }
  23875 
  23876     /* Free the next-hop entry. */
  23877     rv = bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, nh_index);
  23878     return rv;
  23879 }
  23880 
  23881 /*
  23882  * Function:
  23883  *        bcm_tr_mpls_l3_nh_info_get
  23884  * Purpose:
  23885  *        Get Tunnel_switch info for a specific EGR_NH Index
  23886  * Parameters:
  23887  *           IN :  Unit
  23888  *           OUT : Tunnel switch object pointer
  23889  *           IN :  nh_index
  23890  * Returns:
  23891  *           BCM_E_XXX
  23892  */
  23893 
  23894 int
  23895 bcm_tr_mpls_l3_nh_info_get(int unit, bcm_mpls_tunnel_switch_t *info, int nh_index)
  23896 {
  23897     egr_l3_next_hop_entry_t egr_nh;
  23898     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
  23899     int vc_swap_idx, ix;
  23900     int vc_data_type = 0;
  23901 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
  23902     int ecn_map_index;
  23903     int ecn_map_pri;
  23904 #endif
  23905 #ifdef BCM_TRIDENT3_SUPPORT
  23906     uint32 mpls_format[2];
  23907     int label_action = 0;
  23908 #endif
  23909 
  23910     info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit);
  23911 
  23912     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  23913                                       nh_index, &egr_nh));
  23914 
  23915 #if defined(BCM_TOMAHAWK3_SUPPORT)
  23916     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  23917         return bcm_th3_mpls_l3_nh_info_get(unit, info, nh_index);
  23918     }
  23919 #endif
  23920     if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  23921          vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  23922                                                        MPLS__VC_AND_SWAP_INDEXf);
  23923     } else {
  23924          vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  23925                                                        VC_AND_SWAP_INDEXf);
  23926     }
  23927 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  23928         if (soc_feature(unit, soc_feature_mpls_nh_ttl_control)) {
  23929             if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  23930                                     MPLS__DISABLE_TTL_DECREMENTf)) {
  23931                 info->flags |= BCM_MPLS_SWITCH_KEEP_TTL;
  23932             }
  23933         }
  23934         if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
  23935                                 MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf)) {
  23936             if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  23937                                     MPLS__DO_EVXLT_AFTER_TUNNEL_ENCAPf)) {
  23938                 info->flags2 |=
  23939                 BCM_MPLS_SWITCH2_TUNNEL_HEADER_EGRESS_VLAN_TRANSLATION;
  23940             }
  23941         }
  23942 #endif
  23943 
  23944     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 
  23945                                       MEM_BLOCK_ANY, vc_swap_idx, &vc_entry));
  23946     if (SOC_MEM_FIELD_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23947                 DATA_TYPEf)) {
  23948         vc_data_type = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23949                 &vc_entry, DATA_TYPEf);
  23950     }
  23951 
  23952     if (vc_data_type == _BCM_VC_SWAP_TBL_FLEX_DATA_TYPE) {
  23953 #if defined(BCM_TRIDENT3_SUPPORT)
  23954         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  23955             sal_memset(mpls_format, 0, sizeof(mpls_format));
  23956             soc_mem_field_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  23957                     (uint32 *) &vc_entry,
  23958                     MPLS_PHP__MPLS_ENTRY_0_ACTION_SETf,
  23959                     (uint32 *) mpls_format);
  23960 
  23961             if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) {
  23962                 label_action = MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_idx];
  23963             }
  23964             if (_BCM_MPLS_ACTION_PRESERVED == label_action) { 
  23965                 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRESERVE;
  23966                 info->egress_label.label = BCM_MPLS_LABEL_INVALID;
  23967             } else {
  23968                 info->egress_label.label = soc_format_field32_get(unit, 
  23969                         MPLS_ENTRY_ACTION_SETfmt,
  23970                         (uint32 *)mpls_format, MPLS_LABELf);
  23971             }
  23972 
  23973             info->egress_label.label = soc_format_field32_get(unit, 
  23974                     MPLS_ENTRY_ACTION_SETfmt,
  23975                     (uint32 *)mpls_format, MPLS_LABELf);
  23976 
  23977             info->egress_label.ttl = soc_format_field32_get(unit, 
  23978                     MPLS_ENTRY_ACTION_SETfmt,
  23979                     (uint32 *)mpls_format, MPLS_TTLf);
  23980 
  23981             if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  23982                         (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x0) {
  23983                 /* Use the specified EXP, PRI and CFI */
  23984                 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_SET;
  23985                 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_SET;
  23986                 info->egress_label.exp =
  23987                     soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  23988                             (uint32 *)mpls_format, MPLS_EXPf);
  23989                 info->egress_label.pkt_pri =
  23990                     soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  23991                             (uint32 *)mpls_format, NEW_PRIf);
  23992                 info->egress_label.pkt_cfi =
  23993                     soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  23994                             (uint32 *)mpls_format, NEW_CFIf);
  23995             } else if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  23996                         (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x1) {
  23997                 /* Use EXP-map for EXP, PRI and CFI */
  23998                 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_REMARK;
  23999                 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK;
  24000                 ix = soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  24001                         (uint32 *)mpls_format, MPLS_EXP_MAPPING_PTRf);
  24002                 BCM_IF_ERROR_RETURN(
  24003                         _egr_qos_hw_idx2id(unit, ix, &info->egress_label.qos_map_id));
  24004 
  24005             } else if (soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  24006                         (uint32 *)mpls_format, MPLS_EXP_SELECTf) == 0x2) {
  24007                 /* Use EXP from incoming MPLS label. If no incoming label, use the specified
  24008                  * EXP value. Use EXP-map for PRI/CFI.
  24009                  */
  24010                 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_COPY;
  24011                 info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK;
  24012                 info->egress_label.exp =
  24013                     soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  24014                             (uint32 *)mpls_format, MPLS_EXPf);
  24015                 ix = soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
  24016                         (uint32 *)mpls_format, MPLS_EXP_MAPPING_PTRf);
  24017 
  24018                 BCM_IF_ERROR_RETURN(
  24019                         _egr_qos_hw_idx2id(unit, ix, &info->egress_label.qos_map_id));
  24020             }
  24021         }
  24022 #endif
  24023     } else {
  24024     if (_BCM_MPLS_ACTION_PRESERVED == soc_mem_field32_get(unit, 
  24025         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry, MPLS_LABEL_ACTIONf)) {
  24026         info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRESERVE;
  24027         info->egress_label.label = BCM_MPLS_LABEL_INVALID;
  24028     } else {
  24029     info->egress_label.label = 
  24030         soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24031                             &vc_entry, MPLS_LABELf);
  24032     }
  24033 
  24034     info->egress_label.ttl = 
  24035         soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24036                             &vc_entry, MPLS_TTLf);
  24037     if (info->egress_label.ttl) {
  24038         info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET;
  24039     } else {
  24040         info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_TTL_DECREMENT;
  24041     }
  24042     if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24043                             &vc_entry, MPLS_EXP_SELECTf) == 0x0) {
  24044         /* Use the specified EXP, PRI and CFI */
  24045         info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_SET;
  24046         info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_SET;
  24047         info->egress_label.exp = 
  24048             soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24049                                 &vc_entry, MPLS_EXPf);
  24050         info->egress_label.pkt_pri = 
  24051             soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24052                                 &vc_entry, NEW_PRIf);
  24053         info->egress_label.pkt_cfi = 
  24054             soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24055                                 &vc_entry, NEW_CFIf);
  24056     } else if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24057                                    &vc_entry, MPLS_EXP_SELECTf) == 0x1) {
  24058         /* Use EXP-map for EXP, PRI and CFI */
  24059         info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_REMARK;
  24060         info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK;
  24061         ix = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24062                                  &vc_entry, MPLS_EXP_MAPPING_PTRf);
  24063                 BCM_IF_ERROR_RETURN(
  24064                     _egr_qos_hw_idx2id(unit, ix, &info->egress_label.qos_map_id));
  24065     } else if (soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24066                                    &vc_entry, MPLS_EXP_SELECTf) == 0x3) {
  24067         /* Use EXP from incoming MPLS label. If no incoming label, use the specified
  24068          * EXP value. Use EXP-map for PRI/CFI.
  24069          */
  24070         info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_EXP_COPY;
  24071         info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRI_REMARK;
  24072         info->egress_label.exp = 
  24073             soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24074                                 &vc_entry, MPLS_EXPf);
  24075         ix = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24076                                  &vc_entry, MPLS_EXP_MAPPING_PTRf);
  24077         BCM_IF_ERROR_RETURN(
  24078                     _egr_qos_hw_idx2id(unit, ix, &info->egress_label.qos_map_id));
  24079     }
  24080     }
  24081 #if defined(BCM_SWAP_TO_SELF_SUPPORT)
  24082     if (soc_feature(unit, soc_feature_mpls_swap_label_preserve)) {
  24083         uint32 mpls_label_action = 0, label_select = 0;
  24084 #if defined(BCM_TRIDENT3_SUPPORT)
  24085         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  24086             if (vc_data_type == _BCM_VC_SWAP_TBL_FLEX_DATA_TYPE) {
  24087                 label_select = soc_format_field32_get(unit, 
  24088                         MPLS_ENTRY_ACTION_SETfmt,
  24089                         (uint32 *)mpls_format, LABEL_SELECTf);
  24090             } else {
  24091                 label_select = soc_mem_field32_get(unit,
  24092                         EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24093                                    &vc_entry, LABEL_SELECTf);
  24094             }
  24095 
  24096             if (MPLS_INFO(unit)->egr_vc_swap_lbl_action != NULL) {
  24097                 mpls_label_action = 
  24098                     MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_idx];
  24099             }
  24100         } else
  24101 #endif
  24102         {
  24103             mpls_label_action = soc_mem_field32_get(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24104                                    &vc_entry, MPLS_LABEL_ACTIONf);
  24105         }
  24106 
  24107         if (label_select || (mpls_label_action == _BCM_MPLS_ACTION_PRESERVED)) {
  24108              info->egress_label.flags |= BCM_MPLS_EGRESS_LABEL_PRESERVE;
  24109         }
  24110     }
  24111     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  24112         info->egress_label.spl_label_push_type = soc_mem_field32_get(unit,
  24113             EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry,
  24114             SPECIAL_LABEL_PUSH_TYPEf);
  24115     }
  24116 #endif
  24117 
  24118 #ifdef BCM_TOMAHAWK2_SUPPORT
  24119     if (soc_feature(unit, soc_feature_mpls_ecn) &&
  24120             !soc_feature(unit, soc_feature_intcn_to_exp_nosupport)) {
  24121         ecn_map_index = soc_mem_field32_get(unit, 
  24122                                             EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24123                                             &vc_entry, 
  24124                                             INT_CN_TO_EXP_MAPPING_PTRf);
  24125         if (bcmi_xgs5_ecn_map_used_get(unit, ecn_map_index, 
  24126                                        _bcmEcnmapTypeIntcn2Exp)) {
  24127             info->egress_label.int_cn_map_id = 
  24128                 _BCM_XGS5_MPLS_ECN_MAP_TYPE_INTCN2EXP | ecn_map_index;
  24129             ecn_map_pri = soc_mem_field32_get(unit, 
  24130                                               EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24131                                               &vc_entry, 
  24132                                               INT_CN_TO_EXP_PRIORITYf);
  24133             if (ecn_map_pri) {
  24134                 info->egress_label.flags |= 
  24135                     BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST;
  24136             }
  24137             info->egress_label.flags |= 
  24138                 BCM_MPLS_EGRESS_LABEL_INT_CN_TO_EXP_MAP;
  24139         }
  24140     }
  24141 #endif /* BCM_TOMAHAWK2_SUPPORT */ 
  24142 #if defined(BCM_TRIDENT3_SUPPORT)
  24143     if (soc_feature(unit, soc_feature_mpls_ecn)) {
  24144         ecn_map_index = soc_mem_field32_get(unit,
  24145                                             EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24146                                             &vc_entry,
  24147                                             PKT_ECN_TO_EXP_MAPPING_PTRf);
  24148 
  24149         if (bcmi_xgs5_ecn_map_used_get(unit, ecn_map_index,
  24150                                        _bcmEcnmapTypeIpEcn2Exp)) {
  24151             info->egress_label.ecn_map_id =
  24152                 _BCM_XGS5_MPLS_ECN_MAP_TYPE_ECN2EXP | ecn_map_index;
  24153             ecn_map_pri = soc_mem_field32_get(unit,
  24154                                               EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  24155                                               &vc_entry,
  24156                                               PKT_ECN_TO_EXP_PRIORITYf);
  24157             if (ecn_map_pri) {
  24158                 info->egress_label.flags |=
  24159                     BCM_MPLS_EGRESS_LABEL_ECN_EXP_MAP_TRUST;
  24160             }
  24161             info->egress_label.flags |=
  24162                 BCM_MPLS_EGRESS_LABEL_ECN_TO_EXP_MAP;
  24163         }
  24164     }
  24165 #endif /* BCM_TRIDENT3_SUPPORT */
  24166     return BCM_E_NONE;
  24167 }
  24168 
  24169 /* Convert key part of application format to HW entry. */
  24170 STATIC int
  24171 _bcm_tr_mpls_entry_set_key(int unit, bcm_mpls_tunnel_switch_t *info,
  24172                            mpls_entry_entry_t *ment)
  24173 {
  24174     bcm_module_t mod_out;
  24175     bcm_port_t port_out;
  24176     bcm_trunk_t trunk_id;
  24177     int rv, gport_id;
  24178     soc_mem_t mem = MPLS_ENTRYm;
  24179 
  24180     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  24181         mem = MPLS_ENTRY_SINGLEm;
  24182     }
  24183 
  24184     sal_memset(ment, 0, sizeof(mpls_entry_entry_t));
  24185 
  24186     if (info->port == BCM_GPORT_INVALID) {
  24187         /* Global label, mod/port not part of lookup key */
  24188         if (SOC_MEM_FIELD_VALID(unit, mem, MODULE_IDf)) {
  24189             soc_mem_field32_set(unit, mem, ment, MODULE_IDf, 0);
  24190         }
  24191         soc_mem_field32_set(unit, mem, ment, PORT_NUMf, 0);
  24192         if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) {
  24193             soc_mem_field32_set(unit, mem, ment, MPLS_LABELf, info->label);
  24194         } else {
  24195             return BCM_E_PARAM;
  24196         }
  24197         soc_mem_field32_set(unit, mem, ment, VALIDf, 1);
  24198         return BCM_E_NONE;
  24199     }
  24200 
  24201     rv = _bcm_esw_gport_resolve(unit, info->port, &mod_out, 
  24202                                 &port_out, &trunk_id, &gport_id);
  24203     BCM_IF_ERROR_RETURN(rv);
  24204 
  24205     if (BCM_GPORT_IS_TRUNK(info->port)) {
  24206         soc_mem_field32_set(unit, mem, ment, Tf, 1);
  24207         soc_mem_field32_set(unit, mem, ment, TGIDf, trunk_id);
  24208     } else {
  24209         if (SOC_MEM_FIELD_VALID(unit, mem, MODULE_IDf)) {
  24210             soc_mem_field32_set(unit, mem, ment, MODULE_IDf, mod_out);
  24211         }
  24212         soc_mem_field32_set(unit, mem, ment, PORT_NUMf, port_out);
  24213     }
  24214     if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) {
  24215         soc_mem_field32_set(unit, mem, ment, MPLS_LABELf, info->label);
  24216     } else {
  24217         return BCM_E_PARAM;
  24218     }
  24219     soc_mem_field32_set(unit, mem, ment, VALIDf, 1);
  24220     
  24221     return BCM_E_NONE;
  24222 }
  24223 
  24224 /* Convert key part of HW entry to application format. */
  24225 STATIC int
  24226 _bcm_tr_mpls_entry_get_key(int unit, mpls_entry_entry_t *ment,
  24227                            bcm_mpls_tunnel_switch_t *info)
  24228 {
  24229     bcm_port_t port_in, port_out;
  24230     bcm_module_t mod_in, mod_out;
  24231     bcm_trunk_t trunk_id;
  24232 
  24233     port_in = soc_MPLS_ENTRYm_field32_get(unit, ment, PORT_NUMf);
  24234     mod_in = soc_MPLS_ENTRYm_field32_get(unit, ment, MODULE_IDf);
  24235     if (soc_MPLS_ENTRYm_field32_get(unit, ment, Tf)) {
  24236         trunk_id = soc_MPLS_ENTRYm_field32_get(unit, ment, TGIDf);
  24237         BCM_GPORT_TRUNK_SET(info->port, trunk_id);
  24238     } else if ((port_in == 0) && (mod_in == 0)) {
  24239         /* Global label, mod/port not part of lookup key */
  24240         info->port = BCM_GPORT_INVALID;
  24241     } else {
  24242         BCM_IF_ERROR_RETURN
  24243             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
  24244                                     mod_in, port_in, &mod_out, &port_out));
  24245         BCM_GPORT_MODPORT_SET(info->port, mod_out, port_out);
  24246     } 
  24247     info->label = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS_LABELf);
  24248 
  24249     return BCM_E_NONE;
  24250 }
  24251 
  24252 /* Convert data part of HW entry to application format. */
  24253 STATIC int
  24254 _bcm_tr_mpls_entry_get_data(int unit, mpls_entry_entry_t *ment,
  24255                             bcm_mpls_tunnel_switch_t *info)
  24256 {
  24257     int rv, action, nh_index, vrf;
  24258     bcm_if_t egress_if=0;
  24259     int mode = 0;
  24260     soc_mem_t mem = MPLS_ENTRYm;
  24261 
  24262     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  24263         mem = MPLS_ENTRY_SINGLEm;
  24264     }
  24265 
  24266     BCM_IF_ERROR_RETURN(bcm_xgs3_l3_ingress_mode_get(unit, &mode));
  24267 
  24268     action = soc_mem_field32_get(unit, mem, ment, MPLS_ACTION_IF_BOSf);
  24269     switch(action) {
  24270     case 0x2:
  24271         info->action = BCM_MPLS_SWITCH_ACTION_POP;
  24272         if (!mode) {
  24273             vrf = soc_mem_field32_get(unit, mem, ment, L3_IIFf);
  24274             vrf -= _BCM_TR_MPLS_L3_IIF_BASE;
  24275             _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_L3, vrf);
  24276         } else {
  24277             info->ingress_if = soc_mem_field32_get(unit, mem, ment, L3_IIFf);
  24278         }
  24279         break;
  24280     case 0x3:
  24281         info->action = BCM_MPLS_SWITCH_ACTION_SWAP;
  24282         nh_index = soc_mem_field32_get(unit, mem, ment,
  24283                                                NEXT_HOP_INDEXf);
  24284         rv = bcm_tr_mpls_get_vp_nh (unit, nh_index,&egress_if);
  24285         if (rv == BCM_E_NONE) {
  24286             rv = bcm_tr_mpls_l3_nh_info_get(unit, info, nh_index);
  24287             info->egress_if = egress_if;
  24288         } else {
  24289             info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit);
  24290             info->egress_label.label = BCM_MPLS_LABEL_INVALID;
  24291             rv = BCM_E_NONE;
  24292         }
  24293         BCM_IF_ERROR_RETURN(rv);
  24294         break;
  24295     case 0x4:
  24296         info->action = BCM_MPLS_SWITCH_ACTION_PHP;
  24297         nh_index = soc_mem_field32_get(unit, mem, ment,
  24298                                                NEXT_HOP_INDEXf);
  24299         info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit);
  24300         break;
  24301     case 0x5:
  24302         info->action = BCM_MPLS_SWITCH_ACTION_PHP;
  24303         nh_index = soc_mem_field32_get(unit, mem, ment,
  24304                                                ECMP_PTRf);
  24305         info->egress_if = nh_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit);
  24306         break;
  24307     default:
  24308         return BCM_E_INTERNAL;
  24309         break;
  24310     }
  24311     if (soc_mem_field32_get(unit, mem, ment, PW_TERM_NUM_VALIDf)) {
  24312         info->flags |= BCM_MPLS_SWITCH_COUNTED;
  24313     }
  24314 
  24315     if (!soc_mem_field32_get(unit, mem, ment, DECAP_USE_TTLf)) {
  24316         info->flags |= BCM_MPLS_SWITCH_INNER_TTL;
  24317     }
  24318     if (soc_mem_field32_get(unit, mem, ment, DECAP_USE_EXP_FOR_INNERf)) {
  24319         if (info->action != BCM_MPLS_SWITCH_ACTION_SWAP) {
  24320             info->flags |= BCM_MPLS_SWITCH_INNER_EXP;
  24321         }
  24322     }
  24323     if (soc_mem_field32_get(unit, mem, ment,
  24324                                     DECAP_USE_EXP_FOR_PRIf) == 0x1) {
  24325 
  24326         /* Use specified EXP-map to determine internal prio/color */
  24327         info->flags |= BCM_MPLS_SWITCH_INT_PRI_MAP;
  24328         info->exp_map = 
  24329             soc_mem_field32_get(unit, mem, ment, EXP_MAPPING_PTRf);
  24330         info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS;
  24331     } else if (soc_mem_field32_get(unit, mem, ment,
  24332                                            DECAP_USE_EXP_FOR_PRIf) == 0x2) {
  24333 
  24334         /* Use the specified internal priority value */
  24335         info->flags |= BCM_MPLS_SWITCH_INT_PRI_SET;
  24336         info->int_pri =
  24337             soc_mem_field32_get(unit, mem, ment, NEW_PRIf);
  24338 
  24339         /* Use specified EXP-map to determine internal color */
  24340         info->flags |= BCM_MPLS_SWITCH_COLOR_MAP;
  24341         info->exp_map = 
  24342             soc_mem_field32_get(unit, mem, ment, EXP_MAPPING_PTRf);
  24343         info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS;
  24344     }
  24345     if (SOC_MEM_FIELD_VALID(unit,MPLS_ENTRYm,
  24346                             DO_NOT_CHANGE_PAYLOAD_DSCPf)) {
  24347         if (soc_mem_field32_get(unit, mem, ment,
  24348                                         DO_NOT_CHANGE_PAYLOAD_DSCPf) == 0) {
  24349             if ((info->action == BCM_MPLS_SWITCH_ACTION_PHP) ||
  24350                 (info->action == BCM_MPLS_SWITCH_ACTION_POP)) {
  24351                      info->flags |=
  24352                          (BCM_MPLS_SWITCH_OUTER_EXP | BCM_MPLS_SWITCH_OUTER_TTL);
  24353             }
  24354         }
  24355     }
  24356     return BCM_E_NONE;
  24357 }
  24358 
  24359 /*
  24360  * Function:
  24361  *      bcm_tr_mpls_egress_object_modify
  24362  * Purpose:
  24363  *      Modify Egress NH entry
  24364  * Parameters:
  24365  *      unit - Device Number
  24366  *      nh_index - Next Hop Index/ECMP index
  24367  *      new_entry_type - New Entry type
  24368  * Returns:
  24369  *      BCM_E_XXX
  24370  */
  24371 
  24372 int
  24373 bcm_tr_mpls_egress_object_modify(int unit, int nh_index, int new_entry_type)
  24374 {
  24375     bcm_l3_egress_t nh_info;
  24376     egr_l3_next_hop_entry_t new_egr_nh;
  24377     uint32 macda_index=-1;
  24378     void *entries[1];
  24379     int rv = BCM_E_NONE;
  24380     int old_entry_type;
  24381     egr_mac_da_profile_entry_t macda;
  24382 
  24383 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  24384     uint32 flex_ctr_offset_mode, flex_ctr_pool_number, flex_ctr_base_idx;
  24385 #endif
  24386     BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL,
  24387                           nh_index, &new_egr_nh));
  24388 
  24389     old_entry_type = 
  24390                soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &new_egr_nh,
  24391                             nh_entry_type_field[unit]);
  24392 
  24393     if ((old_entry_type == 0) && (new_entry_type == 1)) {
  24394         BCM_IF_ERROR_RETURN(bcm_xgs3_nh_get(unit, nh_index, &nh_info));
  24395 
  24396         sal_memset(&macda, 0, sizeof(egr_mac_da_profile_entry_t));
  24397         soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm,
  24398                              &macda, MAC_ADDRESSf, nh_info.mac_addr);
  24399         entries[0] = &macda;
  24400         BCM_IF_ERROR_RETURN(_bcm_mac_da_profile_entry_add(unit, entries, 1,
  24401                                                           (uint32 *) &macda_index));
  24402 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  24403         if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
  24404             /* 1 Store the old flex counter */
  24405             BCM_IF_ERROR_RETURN(
  24406                 _bcm_esw_get_flex_counter_fields_values(unit, nh_index,
  24407                                                         EGR_L3_NEXT_HOPm, 
  24408                                                         &new_egr_nh,
  24409                                                         0,
  24410                                                         &flex_ctr_offset_mode, 
  24411                                                         &flex_ctr_pool_number, 
  24412                                                         &flex_ctr_base_idx));
  24413             /* 2 Clear flex counter in old entry view */
  24414             BCM_IF_ERROR_RETURN(
  24415                 _bcm_esw_set_flex_counter_fields_values(unit, nh_index, 
  24416                                                         EGR_L3_NEXT_HOPm, 
  24417                                                         &new_egr_nh,
  24418                                                         0,
  24419                                                         0, 
  24420                                                         0, 
  24421                                                         0));
  24422         }
  24423 #endif
  24424 
  24425 #if defined(BCM_TOMAHAWK3_SUPPORT)
  24426         if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  24427                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24428                     &new_egr_nh, MPLS__MPLS_LABELf, 0);
  24429                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24430                     &new_egr_nh, MPLS__MPLS_LABEL_ACTIONf, 0);
  24431                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24432                     &new_egr_nh, MPLS__MPLS_TTLf, 0);
  24433                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24434                     &new_egr_nh, MPLS__MPLS_EXPf, 0);
  24435                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24436                     &new_egr_nh, MPLS__MPLS_EXP_SELECTf, 0);
  24437                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24438                     &new_egr_nh, MPLS__MPLS_EXP_MAPPING_PTRf, 0);
  24439                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24440                     &new_egr_nh, MPLS__IP_ECN_TO_EXP_MAPPING_PTRf, 0);
  24441                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24442                     &new_egr_nh, MPLS__INT_CN_TO_EXP_PRIORITYf, 0);
  24443                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24444                     &new_egr_nh, MPLS__INT_CN_TO_EXP_MAPPING_PTRf, 0);
  24445         }
  24446 #endif
  24447         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  24448             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24449                 &new_egr_nh, MPLS__MAC_DA_PROFILE_INDEXf,
  24450                 macda_index);
  24451 
  24452             if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, MPLS__DVPf)) {
  24453                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24454                     &new_egr_nh, MPLS__DVPf, 0);
  24455             }
  24456             if (soc_feature(unit,
  24457                 soc_feature_multiple_split_horizon_group)) {
  24458                 if (!(soc_feature(unit, soc_feature_td3_style_mpls))) {
  24459                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24460                     &new_egr_nh, MPLS__DVP_NETWORK_GROUPf, 0);
  24461                 }
  24462             } else if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, MPLS__DVP_IS_NETWORK_PORTf)) {
  24463 
  24464                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24465                     &new_egr_nh, MPLS__DVP_IS_NETWORK_PORTf, 0);
  24466             }
  24467 
  24468             if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  24469                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24470                          &new_egr_nh, MPLS__HG_MODIFY_ENABLEf, 0x1);
  24471                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24472                          &new_egr_nh, MPLS__HG_HDR_SELf, 0);
  24473                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24474                          &new_egr_nh, MPLS__HG_MC_DST_MODIDf, 0);
  24475                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24476                          &new_egr_nh, MPLS__HG_MC_DST_PORT_NUMf, 0);
  24477                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24478                          &new_egr_nh, MPLS__HG_ADD_SYS_RSVD_VIDf, 0);
  24479                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24480                          &new_egr_nh, MPLS__HG_LEARN_OVERRIDEf, 0);
  24481                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24482                          &new_egr_nh, MPLS__HG_L3_OVERRIDEf, 0);
  24483                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24484                          &new_egr_nh, MPLS__PW_INIT_NUMf, 0);
  24485                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24486                          &new_egr_nh, MPLS__VC_AND_SWAP_INDEXf, 0);
  24487                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24488                          &new_egr_nh, MPLS__UMC_DROPf, 0);
  24489                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24490                          &new_egr_nh, MPLS__UUC_DROPf, 0);
  24491                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24492                          &new_egr_nh, MPLS__BC_DROPf, 0);
  24493             }
  24494 
  24495         } else {
  24496                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24497                          &new_egr_nh, MAC_DA_PROFILE_INDEXf,
  24498                          macda_index);
  24499                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24500                         &new_egr_nh, DVPf, 0);
  24501                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24502                         &new_egr_nh, DVP_IS_NETWORK_PORTf, 0);
  24503                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24504                         &new_egr_nh, HG_MODIFY_ENABLEf, 0x1);
  24505                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24506                         &new_egr_nh, HG_HDR_SELf, 0);
  24507                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24508                         &new_egr_nh, HG_MC_DST_MODIDf, 0);
  24509                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24510                         &new_egr_nh, HG_MC_DST_PORT_NUMf, 0);
  24511                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24512                         &new_egr_nh, HG_ADD_SYS_RSVD_VIDf, 0);
  24513                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24514                         &new_egr_nh, HG_LEARN_OVERRIDEf, 0);
  24515                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24516                         &new_egr_nh, HG_L3_OVERRIDEf, 0);
  24517                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24518                         &new_egr_nh, PW_INIT_NUMf, 0);
  24519                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24520                         &new_egr_nh, VC_AND_SWAP_INDEXf, 0);
  24521         }
  24522 
  24523 #ifdef BCM_KATANA_SUPPORT
  24524            if (soc_feature(unit, soc_feature_vlan_xlate)) {
  24525            soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24526                            &new_egr_nh, MPLS__USE_DVP_IN_EVXLT_KEYf, 0);
  24527         }
  24528 #endif
  24529           
  24530         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &new_egr_nh,
  24531                             nh_entry_type_field[unit], new_entry_type);
  24532 
  24533 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  24534         if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
  24535             /* Restore flex counter in new entry view */
  24536             BCM_IF_ERROR_RETURN(
  24537                 _bcm_esw_set_flex_counter_fields_values(unit, nh_index, 
  24538                                                         EGR_L3_NEXT_HOPm, 
  24539                                                         &new_egr_nh,
  24540                                                         0,
  24541                                                         flex_ctr_offset_mode, 
  24542                                                         flex_ctr_pool_number, 
  24543                                                         flex_ctr_base_idx));
  24544         }
  24545 #endif
  24546 
  24547         rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm,
  24548                            MEM_BLOCK_ALL, nh_index, &new_egr_nh);
  24549         if (rv < 0) {
  24550             if (macda_index != (uint32)-1) {
  24551                 (void) _bcm_mac_da_profile_entry_delete(unit, macda_index);
  24552             }
  24553         }
  24554     }else if ((old_entry_type == 1) && (new_entry_type == 0)) {
  24555         /* Delete MAC_DA_PROFILE_INDEX */
  24556         bcm_mac_t mac_addr;
  24557         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  24558             macda_index =
  24559                   soc_EGR_L3_NEXT_HOPm_field32_get(unit, &new_egr_nh,
  24560                                          MPLS__MAC_DA_PROFILE_INDEXf);
  24561         } else {
  24562            macda_index =
  24563                   soc_EGR_L3_NEXT_HOPm_field32_get(unit, &new_egr_nh,
  24564                                          MAC_DA_PROFILE_INDEXf);
  24565         }
  24566 
  24567         /* Read entry from MAC-DA-PROFILEm */
  24568         BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MAC_DA_PROFILEm,
  24569                              MEM_BLOCK_ANY, macda_index, &macda));
  24570         /* Obtain Mac-Address */
  24571         soc_mem_mac_addr_get(unit, EGR_MAC_DA_PROFILEm,
  24572                              &macda, MAC_ADDRESSf, mac_addr);
  24573         if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3__MAC_ADDRESSf)) { 
  24574             soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, &new_egr_nh, 
  24575                                  L3__MAC_ADDRESSf, mac_addr); 
  24576         } else {
  24577             soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, &new_egr_nh,
  24578                                  MAC_ADDRESSf, mac_addr);
  24579         }
  24580         if (macda_index != (uint32)-1) {
  24581            (void) _bcm_mac_da_profile_entry_delete(unit, macda_index);
  24582         } 
  24583 
  24584 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  24585         if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
  24586             /* 1 Store the old flex counter */
  24587             BCM_IF_ERROR_RETURN(
  24588                 _bcm_esw_get_flex_counter_fields_values(unit, nh_index, 
  24589                                                         EGR_L3_NEXT_HOPm, 
  24590                                                         &new_egr_nh,
  24591                                                         0,
  24592                                                         &flex_ctr_offset_mode, 
  24593                                                         &flex_ctr_pool_number, 
  24594                                                         &flex_ctr_base_idx));
  24595             /* 2 Clear flex counter in old entry view */
  24596             BCM_IF_ERROR_RETURN(
  24597                 _bcm_esw_set_flex_counter_fields_values(unit, nh_index, 
  24598                                                         EGR_L3_NEXT_HOPm, 
  24599                                                         &new_egr_nh, 
  24600                                                         0,
  24601                                                         0, 
  24602                                                         0, 
  24603                                                         0));
  24604         }
  24605 #endif
  24606 
  24607         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  24608                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24609                         &new_egr_nh, MPLS__MAC_DA_PROFILE_INDEXf, 0);
  24610         } else {
  24611                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
  24612                          &new_egr_nh, MAC_DA_PROFILE_INDEXf, 0);
  24613         }
  24614 
  24615         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &new_egr_nh,
  24616                             nh_entry_type_field[unit], new_entry_type);
  24617 
  24618 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  24619         if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
  24620             /* Restore flex counter in new entry view */
  24621             BCM_IF_ERROR_RETURN(
  24622                 _bcm_esw_set_flex_counter_fields_values(unit, nh_index, 
  24623                                                         EGR_L3_NEXT_HOPm, 
  24624                                                         &new_egr_nh,
  24625                                                         0,
  24626                                                         flex_ctr_offset_mode, 
  24627                                                         flex_ctr_pool_number, 
  24628                                                         flex_ctr_base_idx));
  24629         }
  24630 #endif
  24631 
  24632         rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm,
  24633                            MEM_BLOCK_ALL, nh_index, &new_egr_nh);
  24634 
  24635     }
  24636 
  24637     return rv;
  24638 }
  24639 
  24640 /*
  24641  * Function:
  24642  *      bcm_tr_mpls_egress_entry_modify
  24643  * Purpose:
  24644  *      Modify Egress entry
  24645  * Parameters:
  24646  *      unit - Device Number
  24647  *      nh_index - Next Hop Index/ECMP index
  24648  *      mpath_flag - Flag to to indicate NH/ECMP
  24649  *      new_entry_type - New Entry type
  24650  * Returns:
  24651  *      BCM_E_XXX
  24652  */
  24653 
  24654 int
  24655 bcm_tr_mpls_egress_entry_modify(int unit, int nh_index,
  24656         int mpath_flag, int new_entry_type)
  24657 {
  24658     int i = 0, ecmp_member_count = 0;
  24659     int alloc_size, index;
  24660     bcm_l3_egress_ecmp_t ecmp_info;
  24661     bcm_l3_ecmp_member_t *ecmp_member_array = NULL;
  24662     int rv = BCM_E_NONE;
  24663    
  24664     if (mpath_flag & BCM_L3_MULTIPATH) {
  24665     
  24666         alloc_size = sizeof(bcm_l3_ecmp_member_t) * BCM_XGS3_L3_ECMP_MAX(unit);
  24667         ecmp_member_array = sal_alloc(alloc_size, "ecmp member array");
  24668         if (NULL == ecmp_member_array) {
  24669             return BCM_E_MEMORY;
  24670         }
  24671         sal_memset(ecmp_member_array, 0, alloc_size);
  24672 
  24673         ecmp_info.ecmp_intf = nh_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit);
  24674         rv = bcm_xgs3_l3_ecmp_get(unit, &ecmp_info, BCM_XGS3_L3_ECMP_MAX(unit),
  24675                                   ecmp_member_array, &ecmp_member_count);
  24676         if (BCM_FAILURE(rv)) {
  24677             goto clean_up;
  24678         }
  24679 
  24680         while (i < ecmp_member_count) {
  24681             if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit,
  24682                         ecmp_member_array[i].egress_if)) {
  24683                 index = (ecmp_member_array[i].egress_if -
  24684                         BCM_XGS3_EGRESS_IDX_MIN(unit));
  24685             }
  24686 #if defined(BCM_TOMAHAWK3_SUPPORT)
  24687             else if ((soc_feature(unit, soc_feature_th3_style_simple_mpls)) &&
  24688                      (BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit,
  24689                         ecmp_member_array[i].egress_if))) {
  24690                 index = (ecmp_member_array[i].egress_if -
  24691                         BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit));
  24692                 rv = bcm_tr_mpls_egress_entry_modify(unit, index, mpath_flag, new_entry_type);
  24693                 if (BCM_FAILURE(rv)) {
  24694                     goto clean_up;
  24695                 }
  24696                 i++;
  24697                 continue;
  24698             }
  24699 #endif
  24700             else {
  24701                 index = (ecmp_member_array[i].egress_if -
  24702                         BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
  24703             }
  24704 
  24705             rv = bcm_tr_mpls_egress_object_modify(unit, index, new_entry_type);
  24706             if (BCM_FAILURE(rv)) {
  24707                 goto clean_up;
  24708             }
  24709             i++;
  24710         }
  24711     } else {
  24712         rv = bcm_tr_mpls_egress_object_modify(unit, nh_index, new_entry_type);
  24713     }
  24714 
  24715 clean_up:
  24716     if (ecmp_member_array) {
  24717         sal_free(ecmp_member_array);
  24718         ecmp_member_array = NULL;
  24719     }
  24720 
  24721     return rv;
  24722 }
  24723 
  24724 /*
  24725  * Function:
  24726  *      bcm_mpls_tunnel_switch_add
  24727  * Purpose:
  24728  *      Add an MPLS label entry.
  24729  * Parameters:
  24730  *      unit - Device Number
  24731  *      info - Label (switch) information
  24732  * Returns:
  24733  *      BCM_E_XXX
  24734  */
  24735 int
  24736 bcm_tr_mpls_tunnel_switch_add(int unit, bcm_mpls_tunnel_switch_t *info)
  24737 {
  24738     mpls_entry_entry_t ment;
  24739     int mode=0, nh_index = -1, vrf=0, rv, num_pw_term, old_pw_cnt = -1, pw_cnt = -1;
  24740     int index, action = -1, old_nh_index = -1, old_ecmp_index = -1;
  24741     int  tunnel_switch_update=0;
  24742     uint32 mpath_flag=0;
  24743     int  ref_count=0;
  24744     bcm_if_t  egress_if=0;
  24745 
  24746     rv = bcm_xgs3_l3_egress_mode_get(unit, &mode);
  24747     BCM_IF_ERROR_RETURN(rv);
  24748     if (!mode) {
  24749         LOG_INFO(BSL_LS_BCM_L3,
  24750                  (BSL_META_U(unit,
  24751                              "L3 egress mode must be set first\n")));
  24752         return BCM_E_DISABLED;
  24753     }
  24754 
  24755     /* Check for Port_independent Label mapping */
  24756     if (!BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) {
  24757         return BCM_E_PARAM;
  24758     }
  24759 
  24760     rv = bcm_tr_mpls_port_independent_range (unit, info->label, info->port);
  24761     if (rv < 0) {
  24762         return rv;
  24763     }
  24764 
  24765     BCM_IF_ERROR_RETURN(_bcm_tr_mpls_entry_set_key(unit, info, &ment));
  24766 
  24767     /* See if entry already exists */
  24768     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
  24769                         &ment, &ment, 0);
  24770 
  24771     /* default not to use DSCP from ING_MPLS_EXP_MAPPING table */
  24772     if (SOC_MEM_FIELD_VALID(unit,MPLS_ENTRYm,DO_NOT_CHANGE_PAYLOAD_DSCPf)) {
  24773         soc_MPLS_ENTRYm_field32_set(unit, &ment,
  24774                                           DO_NOT_CHANGE_PAYLOAD_DSCPf, 1);
  24775     }
  24776 
  24777     if (rv == SOC_E_NONE) {
  24778         /* Entry exists, save old info */
  24779         tunnel_switch_update = 1;
  24780         action = soc_MPLS_ENTRYm_field32_get(unit, &ment, MPLS_ACTION_IF_BOSf);
  24781         if ((action == 0x3) || (action == 0x4)) {
  24782             /* SWAP_NHI or L3_NHI */
  24783             old_nh_index = soc_MPLS_ENTRYm_field32_get(unit, &ment, NEXT_HOP_INDEXf);
  24784         } else if (action == 0x5) {
  24785             /* L3_ECMP */
  24786             old_ecmp_index = soc_MPLS_ENTRYm_field32_get(unit, &ment, ECMP_PTRf);
  24787         }
  24788 
  24789         if (soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUM_VALIDf)) {
  24790             old_pw_cnt = soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUMf);
  24791         } 
  24792     } else if (rv != SOC_E_NOT_FOUND) {
  24793         return rv;
  24794     }
  24795 
  24796     switch(info->action) {
  24797     case BCM_MPLS_SWITCH_ACTION_SWAP:
  24798         if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, info->egress_if)) {
  24799             return BCM_E_PARAM;
  24800         }
  24801         soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_NOT_BOSf,
  24802                                     0x3); /* SWAP_NHI */
  24803         soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_BOSf,
  24804                                     0x3); /* SWAP NHI */
  24805         break;
  24806     case BCM_MPLS_SWITCH_ACTION_POP:
  24807         soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_NOT_BOSf,
  24808                                     0x1); /* POP */
  24809         soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_BOSf,
  24810                                     0x2); /* L3_IIF */ 
  24811         /* uniform qos model if either of these two flags set.
  24812          * Only apply to L3 MPLS and BOS
  24813          */
  24814         if (info->flags & (BCM_MPLS_SWITCH_OUTER_EXP |
  24815                            BCM_MPLS_SWITCH_OUTER_TTL) ) {
  24816             if (SOC_MEM_FIELD_VALID(unit,MPLS_ENTRYm,
  24817                              DO_NOT_CHANGE_PAYLOAD_DSCPf)) {
  24818                 soc_MPLS_ENTRYm_field32_set(unit, &ment,
  24819                                   DO_NOT_CHANGE_PAYLOAD_DSCPf, 0);
  24820             }
  24821         }
  24822 
  24823         break;
  24824     case BCM_MPLS_SWITCH_ACTION_PHP:
  24825         soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_NOT_BOSf,
  24826                                     0x2); /* PHP_NHI */
  24827         if (BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, info->egress_if)) {
  24828             soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_BOSf,
  24829                                         0x5); /* L3_ECMP */ 
  24830         } else if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, info->egress_if)) {
  24831             soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS_ACTION_IF_BOSf,
  24832                                         0x4); /* L3_NHI */ 
  24833         } else {
  24834             return BCM_E_PARAM;
  24835         }
  24836         /* uniform qos model if either of these two flags set.
  24837          * Only apply to L3 MPLS and BOS
  24838          */
  24839         if (info->flags & (BCM_MPLS_SWITCH_OUTER_EXP |
  24840                            BCM_MPLS_SWITCH_OUTER_TTL) ) {
  24841             if (SOC_MEM_FIELD_VALID(unit,MPLS_ENTRYm,
  24842                              DO_NOT_CHANGE_PAYLOAD_DSCPf)) {
  24843                 soc_MPLS_ENTRYm_field32_set(unit, &ment,
  24844                                   DO_NOT_CHANGE_PAYLOAD_DSCPf, 0);
  24845             }
  24846         }
  24847         break;
  24848     default:
  24849         return BCM_E_PARAM;
  24850         break;
  24851     }
  24852     if (info->action == BCM_MPLS_SWITCH_ACTION_POP) {
  24853         mode = -1;
  24854         if (_BCM_MPLS_VPN_IS_L3(info->vpn)) {
  24855             _BCM_MPLS_VPN_GET(vrf, _BCM_MPLS_VPN_TYPE_L3, info->vpn);
  24856             if (!_BCM_MPLS_VRF_USED_GET(unit, vrf)) {
  24857                 return BCM_E_PARAM;
  24858             }
  24859 
  24860             /* Check L3 Ingress Interface mode. */ 
  24861             mode = 0;
  24862             rv = bcm_xgs3_l3_ingress_mode_get(unit, &mode);
  24863             BCM_IF_ERROR_RETURN(rv);
  24864         }
  24865         if (!mode) {
  24866              _bcm_l3_ingress_intf_t iif;
  24867              sal_memset(&iif, 0, sizeof(_bcm_l3_ingress_intf_t));
  24868              iif.intf_id =  _BCM_TR_MPLS_L3_IIF_BASE + vrf;
  24869              rv = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif);
  24870              if (BCM_FAILURE(rv)) {
  24871                  return rv;
  24872              }
  24873              iif.vrf = vrf;
  24874              rv = _bcm_tr_l3_ingress_interface_set(unit, &iif, NULL, NULL);
  24875              if (BCM_FAILURE(rv)) {
  24876                  return rv;
  24877              }
  24878              soc_MPLS_ENTRYm_field32_set(unit, &ment, L3_IIFf, 
  24879                                         _BCM_TR_MPLS_L3_IIF_BASE + vrf);
  24880          } else {
  24881              soc_MPLS_ENTRYm_field32_set(unit, &ment, L3_IIFf, info->ingress_if);
  24882          }
  24883     } else if (info->action == BCM_MPLS_SWITCH_ACTION_PHP) {
  24884 
  24885         /*
  24886          * Get egress next-hop index from egress object and
  24887          * increment egress object reference count.
  24888          */
  24889 
  24890         BCM_IF_ERROR_RETURN(bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if,
  24891                                                                &mpath_flag, 1, &nh_index));
  24892        
  24893         if (mpath_flag != BCM_L3_MULTIPATH) { 
  24894             /* Fix: Entry_Type = 1, for PHP Packets with more than 1 Label */
  24895             /* Read the egress next_hop entry pointed by Egress-Object */   
  24896             rv = bcm_tr_mpls_egress_entry_modify(unit, nh_index, mpath_flag, 1);
  24897             if (rv < 0 ) {
  24898                return rv;
  24899             }
  24900         }
  24901         if (mpath_flag == BCM_L3_MULTIPATH) {
  24902             soc_MPLS_ENTRYm_field32_set(unit, &ment, ECMP_PTRf, nh_index);
  24903         } else {
  24904             soc_MPLS_ENTRYm_field32_set(unit, &ment, NEXT_HOP_INDEXf, nh_index);
  24905         }
  24906     } else if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) {
  24907         if (BCM_XGS3_L3_MPLS_LBL_VALID(info->egress_label.label)) {         
  24908             rv = bcm_tr_mpls_l3_nh_info_add(unit, info, &nh_index);
  24909             if (rv < 0) {
  24910                 goto cleanup;
  24911             }
  24912         } else {
  24913             rv = bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if,
  24914                                                     &mpath_flag, 1, &nh_index);
  24915             if (rv < 0) {
  24916                 return rv;
  24917             }
  24918         }
  24919         soc_MPLS_ENTRYm_field32_set(unit, &ment, NEXT_HOP_INDEXf, nh_index);
  24920     }/* BCM_MPLS_SWITCH_ACTION_SWAP */
  24921 
  24922     
  24923     soc_MPLS_ENTRYm_field32_set(unit, &ment, V4_ENABLEf, 1);
  24924     soc_MPLS_ENTRYm_field32_set(unit, &ment, V6_ENABLEf, 1);
  24925     if (info->flags & BCM_MPLS_SWITCH_INNER_TTL) {
  24926         if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) {
  24927             rv = BCM_E_PARAM;
  24928             goto cleanup;
  24929         }
  24930         soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_TTLf, 0);
  24931     } else {
  24932         soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_TTLf, 1);
  24933     }
  24934     if (info->flags & BCM_MPLS_SWITCH_INNER_EXP) {
  24935         if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) {
  24936             rv = BCM_E_PARAM;
  24937             goto cleanup;
  24938         }
  24939         soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_EXP_FOR_INNERf, 0);
  24940     } else {
  24941         /* For SWAP, Do-not PUSH EXP */
  24942         if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) {
  24943             soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_EXP_FOR_INNERf, 0);
  24944         } else {
  24945             soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_EXP_FOR_INNERf, 1);
  24946         }
  24947     }
  24948 
  24949     (void) bcm_tr_mpls_entry_internal_qos_set(unit, NULL, info, &ment);
  24950 
  24951     if ((info->flags & BCM_MPLS_SWITCH_COUNTED)) {
  24952        if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) {
  24953         if (old_pw_cnt == -1) {
  24954             num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm);
  24955             for (pw_cnt = 0; pw_cnt < num_pw_term; pw_cnt++) {
  24956                 if (!_BCM_MPLS_PW_TERM_USED_GET(unit, pw_cnt)) {
  24957                     break;
  24958                 }
  24959             }
  24960             if (pw_cnt == num_pw_term) {
  24961                 rv = BCM_E_RESOURCE;
  24962                 goto cleanup;
  24963             }
  24964             _BCM_MPLS_PW_TERM_USED_SET(unit, pw_cnt);
  24965             soc_MPLS_ENTRYm_field32_set(unit, &ment, PW_TERM_NUMf, pw_cnt);
  24966             soc_MPLS_ENTRYm_field32_set(unit, &ment, PW_TERM_NUM_VALIDf, 1);
  24967         }
  24968       }
  24969     }
  24970 #ifdef BCM_TRIUMPH3_SUPPORT
  24971     if (SOC_IS_TRIUMPH3(unit)) {
  24972         soc_MPLS_ENTRYm_field32_set(unit, &ment, KEY_TYPEf, 0x10);
  24973     }
  24974 #endif
  24975 
  24976     if (!tunnel_switch_update) {
  24977         rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &ment);
  24978     } else {
  24979         rv = soc_mem_write(unit, MPLS_ENTRYm,
  24980                            MEM_BLOCK_ALL, index,
  24981                            &ment);
  24982     }
  24983 
  24984     if (rv < 0) {
  24985         goto cleanup;
  24986     }
  24987 
  24988     if (tunnel_switch_update) {
  24989         /* Clean up old next-hop and counter info if entry was replaced */
  24990         if ((old_pw_cnt != -1) && !(info->flags & BCM_MPLS_SWITCH_COUNTED)) {
  24991             _BCM_MPLS_PW_TERM_USED_CLR(unit, old_pw_cnt);
  24992         }
  24993         if (action ==  0x3) { /* SWAP_NHI */
  24994             /* Check if tunnel_switch.egress_label mode is being used */
  24995             rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) old_nh_index, &egress_if);
  24996             if (rv == BCM_E_NONE) {
  24997                 rv = bcm_tr_mpls_l3_nh_info_delete(unit, old_nh_index);
  24998             } else {
  24999                 /* Decrement next-hop Reference count */
  25000                 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, old_nh_index);
  25001             }
  25002         } else if (action == 0x4) {
  25003             /* L3_NHI */
  25004             rv = bcm_xgs3_nh_del(unit, 0, old_nh_index);
  25005         } else if (action == 0x5) {
  25006             /* L3_ECMP */
  25007             rv = bcm_xgs3_ecmp_group_del(unit, old_ecmp_index, 0);
  25008         }
  25009     }
  25010     if (rv < 0) {
  25011         goto cleanup;
  25012     }
  25013 
  25014 #ifdef BCM_WARM_BOOT_SUPPORT
  25015     SOC_CONTROL_LOCK(unit);
  25016     SOC_CONTROL(unit)->scache_dirty = 1;
  25017     SOC_CONTROL_UNLOCK(unit);
  25018 #endif
  25019 
  25020     return rv;
  25021 
  25022   cleanup:
  25023     if (pw_cnt != -1) {
  25024         _BCM_MPLS_PW_TERM_USED_CLR(unit, pw_cnt);
  25025     }
  25026     if (nh_index != -1) {
  25027         if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) {
  25028             if (BCM_XGS3_L3_MPLS_LBL_VALID(info->egress_label.label) ||
  25029                 (info->action == BCM_MPLS_SWITCH_ACTION_PHP)) {
  25030                 (void) bcm_tr_mpls_l3_nh_info_delete(unit, nh_index);
  25031             } else {
  25032                 /* Decrement next-hop Reference count */
  25033                 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, nh_index);
  25034             }
  25035         } else if (info->action == BCM_MPLS_SWITCH_ACTION_PHP) {
  25036             (void) bcm_xgs3_nh_del(unit, 0, nh_index);
  25037         }
  25038     }
  25039     return rv;
  25040 }
  25041 
  25042 STATIC int
  25043 _bcm_tr_mpls_entry_delete(int unit, mpls_entry_entry_t *ment)
  25044 {   
  25045     ing_pw_term_counters_entry_t pw_cnt_entry;
  25046     int rv, action, ecmp_index = -1, nh_index = -1, pw_cnt = -1;
  25047     bcm_if_t  egress_if=0;
  25048     int  ref_count=0;
  25049 
  25050     if (soc_MPLS_ENTRYm_field32_get(unit, ment, PW_TERM_NUM_VALIDf)) {
  25051         pw_cnt = soc_MPLS_ENTRYm_field32_get(unit, ment, PW_TERM_NUMf);
  25052     }
  25053 
  25054     action = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS_ACTION_IF_BOSf);
  25055     if ((action == 0x3) || (action == 0x4)) {
  25056         /* SWAP_NHI or L3_NHI */
  25057         nh_index = soc_MPLS_ENTRYm_field32_get(unit, ment, NEXT_HOP_INDEXf);
  25058     } else if (action == 0x5) {
  25059         /* L3_ECMP */
  25060         ecmp_index = soc_MPLS_ENTRYm_field32_get(unit, ment, ECMP_PTRf);
  25061     }
  25062         
  25063     /* Delete the entry from HW */
  25064     rv = soc_mem_delete(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, ment);
  25065     if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) {
  25066          return rv;
  25067     }
  25068 
  25069 #if defined(BCM_TRIUMPH2_SUPPORT)
  25070     if (soc_feature(unit, soc_feature_gport_service_counters) &&
  25071         (0 != soc_MPLS_ENTRYm_field32_get(unit, ment,
  25072                                           USE_VINTF_CTR_IDXf)) &&
  25073         (0 != soc_MPLS_ENTRYm_field32_get(unit, ment,
  25074                                           VINTF_CTR_IDXf))) {
  25075         /* Release MPLS label stat use, if any */
  25076         _bcm_flex_stat_handle_t mpls_fsh;
  25077         mpls_entry_entry_t fs_ment;
  25078         uint32 key[2];
  25079 
  25080         sal_memset(&fs_ment, 0, sizeof(fs_ment));
  25081         /* Construct key-only entry, copy to FS handle */
  25082         soc_MPLS_ENTRYm_field32_set(unit, &fs_ment, VALIDf,
  25083                  soc_MPLS_ENTRYm_field32_get(unit, ment, VALIDf));
  25084         soc_mem_field_get(unit, MPLS_ENTRYm, (uint32 *) ment,
  25085                           KEYf, (uint32 *) key);
  25086         soc_mem_field_set(unit, MPLS_ENTRYm, (uint32 *) &fs_ment,
  25087                           KEYf, (uint32 *) key);
  25088         /* Technically, we should copy the KEY_TYPE field here,
  25089          * but the rest of the MPLS code appears to abuse the fact that
  25090          * the key type value is 0, so it was handled when we
  25091          * cleared the entry above.
  25092          */
  25093 
  25094         _BCM_FLEX_STAT_HANDLE_CLEAR(mpls_fsh);
  25095         _BCM_FLEX_STAT_HANDLE_COPY(mpls_fsh, fs_ment);
  25096         _bcm_esw_flex_stat_ext_handle_free(unit,
  25097                                            _bcmFlexStatTypeMplsLabel,
  25098                                            mpls_fsh);
  25099     }
  25100 #endif /* BCM_TRIUMPH2_SUPPORT  */
  25101 
  25102     if (pw_cnt != -1) {
  25103         sal_memset(&pw_cnt_entry, 0, sizeof(ing_pw_term_counters_entry_t));
  25104         (void) WRITE_ING_PW_TERM_COUNTERSm(unit, MEM_BLOCK_ALL, pw_cnt,
  25105                                            &pw_cnt_entry);
  25106         _BCM_MPLS_PW_TERM_USED_CLR(unit, pw_cnt);
  25107     }
  25108 
  25109     if (action == 0x3) {
  25110         /* SWAP_NHI */
  25111         /* Check if tunnel_switch.egress_label mode is being used */
  25112         rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) nh_index, &egress_if);
  25113         if (rv == BCM_E_NONE) {
  25114             rv = bcm_tr_mpls_l3_nh_info_delete(unit, nh_index);
  25115         } else {
  25116             /* Decrement next-hop Reference count */
  25117             rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, nh_index);
  25118         }
  25119     } else if (action == 0x4) {
  25120         /* L3_NHI */
  25121         rv = bcm_xgs3_nh_del(unit, 0, nh_index);
  25122     } else if (action == 0x5) {
  25123         /* L3_ECMP */
  25124         rv = bcm_xgs3_ecmp_group_del(unit, ecmp_index, 0);
  25125     }
  25126     return rv;
  25127 }
  25128 
  25129 /*
  25130  * Function:
  25131  *      bcm_mpls_tunnel_switch_delete
  25132  * Purpose:
  25133  *      Delete an MPLS label entry.
  25134  * Parameters:
  25135  *      unit - Device Number
  25136  *      info - Label (switch) information
  25137  * Returns:
  25138  *      BCM_E_XXX
  25139  */
  25140 int
  25141 bcm_tr_mpls_tunnel_switch_delete(int unit, bcm_mpls_tunnel_switch_t *info)
  25142 {
  25143     int rv, index;
  25144     mpls_entry_entry_t ment;
  25145 
  25146 
  25147     rv = _bcm_tr_mpls_entry_set_key(unit, info, &ment);
  25148     BCM_IF_ERROR_RETURN(rv);
  25149 
  25150     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
  25151                         &ment, &ment, 0);
  25152     if (rv < 0) {
  25153         return rv;
  25154     }
  25155     rv = _bcm_tr_mpls_entry_delete(unit, &ment);
  25156 
  25157 #ifdef BCM_WARM_BOOT_SUPPORT
  25158     SOC_CONTROL_LOCK(unit);
  25159     SOC_CONTROL(unit)->scache_dirty = 1;
  25160     SOC_CONTROL_UNLOCK(unit);
  25161 #endif
  25162 
  25163     return rv;
  25164 }
  25165 
  25166 /*
  25167  * Function:
  25168  *      bcm_mpls_tunnel_switch_delete_all
  25169  * Purpose:
  25170  *      Delete all MPLS label entries.
  25171  * Parameters:
  25172  *      unit   - Device Number
  25173  * Returns:
  25174  *      BCM_E_XXX
  25175  */
  25176 int
  25177 bcm_tr_mpls_tunnel_switch_delete_all(int unit)
  25178 {
  25179     int rv, i, num_entries;
  25180     mpls_entry_entry_t *ment, *mentp;
  25181     int imin, imax;
  25182     soc_mem_t mem = MPLS_ENTRYm;
  25183     soc_field_t validf = VALIDf;
  25184 
  25185     if(soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
  25186         mem = MPLS_ENTRY_SINGLEm;
  25187         validf = BASE_VALIDf;
  25188     }
  25189 
  25190     imin = soc_mem_index_min(unit, mem);
  25191     imax = soc_mem_index_max(unit, mem);
  25192     num_entries = soc_mem_index_count(unit, mem);
  25193 
  25194     ment = soc_cm_salloc(unit, num_entries * sizeof(*ment), "mpls_entry");
  25195     if (ment == NULL) {
  25196         return BCM_E_MEMORY;
  25197     }
  25198     sal_memset(ment, 0, num_entries * sizeof(*ment));
  25199 
  25200     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
  25201                             imin, imax, ment);
  25202     if (BCM_FAILURE(rv)) {
  25203         soc_cm_sfree(unit, ment);
  25204         return rv; 
  25205     }
  25206     for (i = 0; i < num_entries; i++) {
  25207         mentp = soc_mem_table_idx_to_pointer(unit, mem,
  25208                                              mpls_entry_entry_t *, ment, i);
  25209 
  25210         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  25211             if ((soc_mem_field32_get(unit, mem, mentp, BASE_VALID_0f) == 0) ||
  25212                 (soc_mem_field32_get(unit, mem, mentp, BASE_VALID_1f) == 0)) {
  25213                 continue;
  25214             }
  25215         } else {
  25216             if (!soc_mem_field32_get(unit, mem, mentp, validf)) {
  25217                 continue;
  25218             }
  25219         }
  25220         if (soc_mem_field32_get(unit, mem, mentp,
  25221                                         MPLS_ACTION_IF_BOSf) == 0x1) {
  25222             /* L2_SVP */
  25223             continue;
  25224         }
  25225         rv = _bcm_tr_mpls_entry_delete(unit, mentp);
  25226         if (rv < 0) {
  25227             soc_cm_sfree(unit, ment);
  25228             return rv;
  25229         }
  25230     }
  25231     soc_cm_sfree(unit, ment);
  25232 
  25233     return BCM_E_NONE;
  25234 }
  25235 
  25236 /*
  25237  * Function:
  25238  *      bcm_mpls_tunnel_switch_get
  25239  * Purpose:
  25240  *      Get an MPLS label entry.
  25241  * Parameters:
  25242  *      unit - Device Number
  25243  *      info - Label (switch) information
  25244  * Returns:
  25245  *      BCM_E_XXX
  25246  */
  25247 int
  25248 bcm_tr_mpls_tunnel_switch_get(int unit, bcm_mpls_tunnel_switch_t *info)
  25249 {
  25250     int rv, index;
  25251     mpls_entry_entry_t ment;
  25252 
  25253     rv = _bcm_tr_mpls_entry_set_key(unit, info, &ment);
  25254 
  25255 
  25256     BCM_IF_ERROR_RETURN(rv);
  25257 
  25258     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
  25259                         &ment, &ment, 0);
  25260 
  25261     if (rv < 0) {
  25262         return rv;
  25263     }
  25264     rv = _bcm_tr_mpls_entry_get_data(unit, &ment, info);
  25265 
  25266     return rv;
  25267 }
  25268 
  25269 /*
  25270  * Function:
  25271  *      bcm_mpls_tunnel_switch_traverse
  25272  * Purpose:
  25273  *      Traverse all valid MPLS label entries an call the
  25274  *      supplied callback routine.
  25275  * Parameters:
  25276  *      unit      - Device Number
  25277  *      cb        - User callback function, called once per MPLS entry.
  25278  *      user_data - cookie
  25279  * Returns:
  25280  *      BCM_E_XXX
  25281  */
  25282 int
  25283 bcm_tr_mpls_tunnel_switch_traverse(int unit, 
  25284                                    bcm_mpls_tunnel_switch_traverse_cb cb,
  25285                                    void *user_data)
  25286 {
  25287     int rv, i, num_entries;
  25288     mpls_entry_entry_t ment;
  25289     bcm_mpls_tunnel_switch_t info;
  25290 
  25291 
  25292     
  25293 
  25294     num_entries = soc_mem_index_count(unit, MPLS_ENTRYm);
  25295     for (i = 0; i < num_entries; i++) {
  25296         BCM_IF_ERROR_RETURN (READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, i, &ment));
  25297         /* Check MPLS Key_type */
  25298         if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  25299             if (0x0 != soc_MPLS_ENTRYm_field32_get(unit, &ment, KEY_TYPEf)) {
  25300                 continue;
  25301             }
  25302         }
  25303         /* Check for valid entry */
  25304         if (!soc_MPLS_ENTRYm_field32_get(unit, &ment, VALIDf)) {
  25305             continue;
  25306         }
  25307         if (soc_MPLS_ENTRYm_field32_get(unit, &ment,
  25308                                         MPLS_ACTION_IF_BOSf) == 0x1) {
  25309             /* L2_SVP */
  25310             continue;
  25311         }
  25312         sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t));
  25313         rv = _bcm_tr_mpls_entry_get_key(unit, &ment, &info);
  25314         if (rv < 0) {
  25315             return rv;
  25316         }
  25317         rv = _bcm_tr_mpls_entry_get_data(unit, &ment, &info);
  25318         if (rv < 0) {
  25319             return rv;
  25320         }
  25321 
  25322 #ifndef BCM_CB_ABORT_ON_ERR
  25323         (void) cb(unit, &info, user_data);
  25324 #else
  25325         rv = cb(unit, &info, user_data);
  25326         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
  25327             return rv;
  25328         }
  25329 #endif
  25330     }
  25331     return BCM_E_NONE;
  25332 }
  25333 
  25334 /*
  25335  * Function:
  25336  *      bcm_mpls_exp_map_create
  25337  * Purpose:
  25338  *      Create an MPLS EXP map instance.
  25339  * Parameters:
  25340  *      unit        - (IN)  SOC unit #
  25341  *      flags       - (IN)  MPLS flags
  25342  *      exp_map_id  - (OUT) Allocated EXP map ID
  25343  * Returns:
  25344  *      BCM_E_XXX
  25345  */
  25346 int
  25347 bcm_tr_mpls_exp_map_create(int unit, uint32 flags, int *exp_map_id)
  25348 {
  25349     int i, table_num, num_exp_map;
  25350     egr_mpls_pri_mapping_entry_t egr_mpls_pri_map[64];
  25351     egr_mpls_exp_mapping_1_entry_t egr_mpls_exp_map[64];
  25352     egr_mpls_exp_mapping_2_entry_t egr_mpls_exp_map2[64];
  25353     int id, index = -1;
  25354     void *entries[3];
  25355 
  25356     /* Check for unsupported Flag */
  25357     if (flags & (~(BCM_MPLS_EXP_MAP_WITH_ID |
  25358                    BCM_MPLS_EXP_MAP_INGRESS |
  25359                    BCM_MPLS_EXP_MAP_EGRESS |
  25360                    BCM_MPLS_EXP_MAP_EGRESS_L2 ))) {
  25361         return BCM_E_PARAM;
  25362     }
  25363 
  25364     /* Input parameters check. */
  25365     if (NULL == exp_map_id) {
  25366         return BCM_E_PARAM;
  25367     }
  25368 
  25369     if (flags & BCM_MPLS_EXP_MAP_INGRESS) {
  25370         /* ING_MPLS_EXP_MAPPING profiles indexed by EXP */
  25371         num_exp_map = _bcm_tr_get_ing_mpls_index_size(unit);
  25372 
  25373         if (flags & BCM_MPLS_EXP_MAP_WITH_ID) {
  25374             table_num = (*exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK);
  25375             if (table_num >= num_exp_map) {
  25376                 return BCM_E_PARAM;
  25377             }
  25378             if (_BCM_MPLS_ING_EXP_MAP_USED_GET(unit, table_num)) {
  25379                 return BCM_E_EXISTS;
  25380             }
  25381             _BCM_MPLS_ING_EXP_MAP_USED_SET(unit, table_num);
  25382 #ifdef BCM_WARM_BOOT_SUPPORT
  25383             SOC_CONTROL_LOCK(unit);
  25384             SOC_CONTROL(unit)->scache_dirty = 1;
  25385             SOC_CONTROL_UNLOCK(unit);
  25386 #endif
  25387             return BCM_E_NONE;
  25388         }
  25389 
  25390         for (i = 0; i < num_exp_map; i++) {
  25391             if (!_BCM_MPLS_ING_EXP_MAP_USED_GET(unit, i)) {
  25392                 _BCM_MPLS_ING_EXP_MAP_USED_SET(unit, i);
  25393                 *exp_map_id = (i | _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS);
  25394 #ifdef BCM_WARM_BOOT_SUPPORT
  25395                 SOC_CONTROL_LOCK(unit);
  25396                 SOC_CONTROL(unit)->scache_dirty = 1;
  25397                 SOC_CONTROL_UNLOCK(unit);
  25398 #endif
  25399                 return BCM_E_NONE;
  25400             }
  25401         }
  25402 
  25403     } else if (flags & BCM_MPLS_EXP_MAP_EGRESS) {
  25404         /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */
  25405         num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
  25406 
  25407         if (flags & BCM_MPLS_EXP_MAP_WITH_ID) {
  25408             table_num = (*exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK);
  25409             if (table_num >= num_exp_map) {
  25410                 return BCM_E_PARAM;
  25411             }
  25412             if (!_BCM_EGR_MPLS_MAP_USED_GET(unit, table_num)) {
  25413                 /* 
  25414                  * Reserve a chunk in the EGR_MPLS_EXP_MAPPING_1 and
  25415                  * EGR_MPLS_PRI_MAPPING tables. These two tables always
  25416                  * done together.
  25417                  */
  25418 #if defined(BCM_TRIDENT3_SUPPORT)
  25419                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  25420                     BCM_IF_ERROR_RETURN(
  25421                             bcm_td3_qos_map_create(unit, (uint32 *)&index, 64));
  25422                 } else
  25423 #endif
  25424                 {
  25425                 sal_memset(egr_mpls_pri_map, 0, sizeof(egr_mpls_pri_map));
  25426                 entries[0] = egr_mpls_pri_map;
  25427                 sal_memset(egr_mpls_exp_map, 0, sizeof(egr_mpls_exp_map));
  25428                 entries[1] = egr_mpls_exp_map;
  25429                 sal_memset(egr_mpls_exp_map2, 0, sizeof(egr_mpls_exp_map2));
  25430                 entries[2] = egr_mpls_exp_map2;
  25431                 BCM_IF_ERROR_RETURN
  25432                     (_bcm_egr_mpls_combo_map_entry_add(unit, entries, 64,
  25433                                                        (uint32 *)&index));
  25434                 }
  25435                 MPLS_INFO(unit)->egr_mpls_hw_idx[table_num] = index / 64;
  25436                 _BCM_EGR_MPLS_MAP_USED_SET(unit, table_num);
  25437             } else {
  25438                 return BCM_E_EXISTS;
  25439             }
  25440 #ifdef BCM_WARM_BOOT_SUPPORT
  25441             SOC_CONTROL_LOCK(unit);
  25442             SOC_CONTROL(unit)->scache_dirty = 1;
  25443             SOC_CONTROL_UNLOCK(unit);
  25444 #endif
  25445             return BCM_E_NONE;
  25446         }
  25447 
  25448         for (id = 0; id < num_exp_map; id++) {
  25449             if (!_BCM_EGR_MPLS_MAP_USED_GET(unit, id)) {
  25450                 *exp_map_id = (id | _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS);
  25451                 /* 
  25452                  * Reserve a chunk in the EGR_MPLS_EXP_MAPPING_1 and
  25453                  * EGR_MPLS_PRI_MAPPING tables. These two tables always
  25454                  * done together.
  25455                  */
  25456 #if defined(BCM_TRIDENT3_SUPPORT)
  25457                 if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  25458                     BCM_IF_ERROR_RETURN(
  25459                             bcm_td3_qos_map_create(unit, (uint32 *)&index, 64));
  25460                 } else
  25461 #endif
  25462                 {
  25463                 sal_memset(egr_mpls_pri_map, 0, sizeof(egr_mpls_pri_map));
  25464                 entries[0] = egr_mpls_pri_map;
  25465                 sal_memset(egr_mpls_exp_map, 0, sizeof(egr_mpls_exp_map));
  25466                 entries[1] = egr_mpls_exp_map;
  25467                 sal_memset(egr_mpls_exp_map2, 0, sizeof(egr_mpls_exp_map2));
  25468                 entries[2] = egr_mpls_exp_map2;
  25469                 BCM_IF_ERROR_RETURN
  25470                     (_bcm_egr_mpls_combo_map_entry_add(unit, entries, 64,
  25471                                                        (uint32 *)&index));
  25472                 }
  25473                 MPLS_INFO(unit)->egr_mpls_hw_idx[id] = index / 64;
  25474                 _BCM_EGR_MPLS_MAP_USED_SET(unit, id);
  25475 #ifdef BCM_WARM_BOOT_SUPPORT
  25476                 SOC_CONTROL_LOCK(unit);
  25477                 SOC_CONTROL(unit)->scache_dirty = 1;
  25478                 SOC_CONTROL_UNLOCK(unit);
  25479 #endif
  25480                 return BCM_E_NONE;
  25481             }
  25482         }
  25483     } else if (flags & BCM_MPLS_EXP_MAP_EGRESS_L2) {
  25484         /* EGR_MPLS_EXP_PRI_MAPPINGm profiles indexed by EXP */
  25485          num_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit);
  25486 
  25487          if (flags & BCM_MPLS_EXP_MAP_WITH_ID) {
  25488             table_num = (*exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK);
  25489             if (table_num > num_exp_map) {
  25490                 return BCM_E_PARAM;
  25491             }
  25492             if (_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, table_num)) {
  25493                 return BCM_E_EXISTS;
  25494             }
  25495             _BCM_MPLS_EGR_EXP_MAP_USED_SET(unit, table_num);
  25496 #ifdef BCM_WARM_BOOT_SUPPORT
  25497             SOC_CONTROL_LOCK(unit);
  25498             SOC_CONTROL(unit)->scache_dirty = 1;
  25499             SOC_CONTROL_UNLOCK(unit);
  25500 #endif
  25501             return BCM_E_NONE;
  25502          }
  25503 
  25504          for (i = 0; i < num_exp_map; i++) {
  25505             if (!_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, i)) {
  25506                 _BCM_MPLS_EGR_EXP_MAP_USED_SET(unit, i);
  25507 #ifdef BCM_WARM_BOOT_SUPPORT
  25508                 SOC_CONTROL_LOCK(unit);
  25509                 SOC_CONTROL(unit)->scache_dirty = 1;
  25510                 SOC_CONTROL_UNLOCK(unit);
  25511 #endif
  25512                 *exp_map_id = (i | _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS_L2);
  25513                 return BCM_E_NONE;
  25514             }
  25515          }
  25516     } else {
  25517         return BCM_E_PARAM;
  25518     }
  25519     return BCM_E_FULL;
  25520 }
  25521 
  25522 /*
  25523  * Function:
  25524  *      bcm_mpls_exp_map_destroy
  25525  * Purpose:
  25526  *      Destroy an existing MPLS EXP map instance.
  25527  * Parameters:
  25528  *      unit       - (IN) SOC unit #
  25529  *      exp_map_id - (IN) EXP map ID
  25530  * Returns:
  25531  *      BCM_E_XXX
  25532  */
  25533 int
  25534 bcm_tr_mpls_exp_map_destroy(int unit, int exp_map_id)
  25535 {
  25536     int num_exp_map, table_num, base_idx;
  25537 
  25538     if (exp_map_id < 0) {
  25539         return BCM_E_PARAM;
  25540     }
  25541     table_num = exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK;
  25542 
  25543     if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 
  25544         _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) {
  25545 
  25546         /* ING_MPLS_EXP_MAPPING profiles indexed by EXP */
  25547         num_exp_map = _bcm_tr_get_ing_mpls_index_size(unit);
  25548         if (table_num >= num_exp_map) {
  25549             return BCM_E_PARAM;
  25550         }
  25551         if (!_BCM_MPLS_ING_EXP_MAP_USED_GET(unit, table_num)) {
  25552             return BCM_E_NOT_FOUND;
  25553         }
  25554         _BCM_MPLS_ING_EXP_MAP_USED_CLR(unit, table_num);
  25555 #ifdef BCM_WARM_BOOT_SUPPORT
  25556         SOC_CONTROL_LOCK(unit);
  25557         SOC_CONTROL(unit)->scache_dirty = 1;
  25558         SOC_CONTROL_UNLOCK(unit);
  25559 #endif
  25560     } else if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 
  25561                _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS) {
  25562         /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */
  25563         num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
  25564 
  25565         if (table_num >= num_exp_map) {
  25566             return BCM_E_PARAM;
  25567         }
  25568         if (!_BCM_EGR_MPLS_MAP_USED_GET(unit, table_num)) {
  25569             return BCM_E_NOT_FOUND;
  25570         }
  25571         base_idx = MPLS_INFO(unit)->egr_mpls_hw_idx[table_num] * 64;
  25572         _BCM_EGR_MPLS_MAP_USED_CLR(unit, table_num);
  25573 #ifdef BCM_WARM_BOOT_SUPPORT
  25574         SOC_CONTROL_LOCK(unit);
  25575         SOC_CONTROL(unit)->scache_dirty = 1;
  25576         SOC_CONTROL_UNLOCK(unit);
  25577 #endif
  25578         /* Clear from profile memories */
  25579         BCM_IF_ERROR_RETURN
  25580             (_bcm_egr_mpls_combo_map_entry_delete(unit, base_idx));
  25581     } else if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 
  25582                _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS_L2) {
  25583 
  25584         /* EGR_MPLS_EXP_PRI_MAPPINGm profiles indexed by EXP */
  25585         num_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit);
  25586         if (table_num >= num_exp_map) {
  25587             return BCM_E_PARAM;
  25588         }
  25589         if (!_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, table_num)) {
  25590             return BCM_E_NOT_FOUND;
  25591         }
  25592         _BCM_MPLS_EGR_EXP_MAP_USED_CLR(unit, table_num);
  25593 #ifdef BCM_WARM_BOOT_SUPPORT
  25594         SOC_CONTROL_LOCK(unit);
  25595         SOC_CONTROL(unit)->scache_dirty = 1;
  25596         SOC_CONTROL_UNLOCK(unit);
  25597 #endif        
  25598     } else {
  25599         return BCM_E_PARAM;
  25600     }
  25601 
  25602     return BCM_E_NONE;
  25603 }
  25604 
  25605 /*
  25606  * Function:
  25607  *      bcm_mpls_exp_map_destroy_all
  25608  * Purpose:
  25609  *      Destroy all existing MPLS EXP map instances.
  25610  * Parameters:
  25611  *      unit       - (IN) SOC unit #
  25612  * Returns:
  25613  *      BCM_E_XXX
  25614  */
  25615 int
  25616 bcm_tr_mpls_exp_map_destroy_all(int unit)
  25617 {
  25618     int i, num_exp_map, base_idx;
  25619     int rv = BCM_E_NONE;
  25620 
  25621 
  25622     /* ING_MPLS_EXP_MAPPING profiles indexed by EXP */
  25623     num_exp_map = _bcm_tr_get_ing_mpls_index_size(unit);
  25624     for (i = 0; i < num_exp_map; i++) {
  25625         if (_BCM_MPLS_ING_EXP_MAP_USED_GET(unit, i)) {
  25626             _BCM_MPLS_ING_EXP_MAP_USED_CLR(unit, i);
  25627         }
  25628     }
  25629 
  25630     /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */
  25631     num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
  25632 
  25633     for (i = 0; i < num_exp_map; i++) {
  25634         if (_BCM_EGR_MPLS_MAP_USED_GET(unit, i)) {
  25635             _BCM_EGR_MPLS_MAP_USED_CLR(unit, i);
  25636             base_idx = MPLS_INFO(unit)->egr_mpls_hw_idx[i] * 64;
  25637             /* Clear from profile memories */
  25638             rv = _bcm_egr_mpls_combo_map_entry_delete(unit, base_idx);
  25639             if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) {
  25640                 return rv;
  25641             }
  25642         }
  25643     }
  25644 
  25645     /* EGR_MPLS_EXP_PRI_MAPPINGm profiles indexed by EXP */
  25646     num_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit);
  25647     for (i = 0; i < num_exp_map; i++) {
  25648         if (_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, i)) {
  25649             _BCM_MPLS_EGR_EXP_MAP_USED_CLR(unit, i);
  25650         }
  25651     }
  25652 
  25653     return BCM_E_NONE;
  25654 }
  25655 
  25656 
  25657 /*
  25658  * Function:
  25659  *      bcm_mpls_exp_map_set
  25660  * Purpose:
  25661  *      Set the mapping of { internal priority, color }
  25662  *      to a EXP value for MPLS headers
  25663  *      in the specified EXP map instance.
  25664  * Parameters:
  25665  *      unit        - (IN) SOC unit #
  25666  *      exp_map_id  - (IN) EXP map ID
  25667  *      map         - (IN) EXP map config structure 
  25668  * Returns:
  25669  *      BCM_E_XXX
  25670  */
  25671 int
  25672 bcm_tr_mpls_exp_map_set(int unit, int exp_map_id,
  25673                         bcm_mpls_exp_map_t *map)
  25674 {
  25675     int table_num, num_exp_map, cng, rv, index;
  25676 #if defined(BCM_TRIDENT3_SUPPORT)
  25677     egr_mpls_pri_mapping_entry_t exp_mpls_pri_entry;
  25678 #endif
  25679     egr_mpls_exp_pri_mapping_entry_t exp_pri_entry;
  25680     uint32 ing_pri_entry[SOC_MAX_MEM_FIELD_WORDS]; 
  25681     int max_int_pri = 15;
  25682     soc_mem_t mem;
  25683     soc_field_t pri_field;
  25684     int mode = 0;
  25685     
  25686     /* Check validity of exp_map_id */
  25687     if (exp_map_id < 0) {
  25688         return BCM_E_PARAM;
  25689     }
  25690 
  25691     if (!map) {
  25692         /* invalid pointer to map data */
  25693         return BCM_E_PARAM;
  25694     }
  25695 
  25696     table_num = exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK;
  25697 
  25698     if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 
  25699         _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) {
  25700 
  25701         /* ING_MPLS_EXP_MAPPING profiles indexed by EXP */
  25702         num_exp_map = _bcm_tr_get_ing_mpls_index_size(unit);
  25703 
  25704         if (!_BCM_MPLS_ING_EXP_MAP_USED_GET(unit, table_num)) {
  25705             return BCM_E_NOT_FOUND;
  25706         }
  25707 
  25708         if ((map->priority < BCM_PRIO_MIN) || (map->priority > max_int_pri) ||
  25709             (map->exp > 7)) {
  25710             return BCM_E_PARAM;
  25711         }
  25712  
  25713         cng = _BCM_COLOR_ENCODING(unit, map->color);
  25714  
  25715         /* Commit to HW */
  25716         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  25717             mem = PHB_MAPPING_TBL_3m;
  25718             pri_field = INT_PRIf;
  25719             /* 6 bit QOS field and 8-bit profile index
  25720              * Max 32 profiles are supported from mpls_entry
  25721              * Key is packet exp and profile index from mpls-entry */
  25722             index = (table_num << 6) | map->exp;
  25723         } else {
  25724             mem = ING_MPLS_EXP_MAPPINGm;
  25725             pri_field = PRIf;
  25726             /* Get the base index for this EXP map */
  25727             index = (table_num * 8) + map->exp;
  25728         }
  25729 
  25730         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, ing_pri_entry);
  25731         if (BCM_FAILURE(rv)) {
  25732             return rv;
  25733         }
  25734         soc_mem_field32_set(unit, mem, ing_pri_entry, pri_field, map->priority);
  25735         soc_mem_field32_set(unit, mem, ing_pri_entry, CNGf, cng);
  25736 
  25737         if (SOC_MEM_FIELD_VALID(unit, mem, DSCPf)) {
  25738 #if defined(BCM_TRIDENT3_SUPPORT)
  25739             if(soc_feature(unit, soc_feature_td3_style_mpls) && map->dscp == EXP_MAP_DSCP_INVALID) {
  25740             } else
  25741 #endif
  25742             {
  25743                  if (map->dscp >= (1 << soc_mem_field_length(unit, mem, DSCPf))) {
  25744                      return BCM_E_PARAM;
  25745                 }
  25746                 soc_mem_field32_set(unit, mem, ing_pri_entry, DSCPf, map->dscp);
  25747             }
  25748 #if defined(BCM_TRIDENT3_SUPPORT)
  25749             if (SOC_MEM_FIELD_VALID(unit, mem, DSCP_VALIDf)) {
  25750                 if (map->dscp != EXP_MAP_DSCP_INVALID) {
  25751                     soc_mem_field32_set(unit, mem, ing_pri_entry, DSCP_VALIDf, 1);
  25752                 } else {
  25753                     soc_mem_field32_set(unit, mem, ing_pri_entry, DSCP_VALIDf, 0);
  25754                 }
  25755             }
  25756 #endif
  25757         }
  25758         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, ing_pri_entry);
  25759         if (BCM_FAILURE(rv)) {
  25760             return rv;
  25761         }
  25762     } else if 
  25763         ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 
  25764          _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS) {
  25765 
  25766         /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */
  25767         num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
  25768 
  25769         if ((map == NULL) || (table_num >= num_exp_map) ||
  25770             (map->priority < BCM_PRIO_MIN) || (map->priority > max_int_pri) ||
  25771             (map->exp > 7) || (map->pkt_pri > 7) || (map->pkt_cfi > 1)) {
  25772             return BCM_E_PARAM;
  25773         }
  25774 
  25775         if (!_BCM_EGR_MPLS_MAP_USED_GET(unit, table_num)) {
  25776             return BCM_E_NOT_FOUND;
  25777         }
  25778 
  25779 #ifdef BCM_TRIDENT3_SUPPORT
  25780             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  25781                 rv = bcm_td3_mpls_combo_add(unit, BCM_QOS_MAP_EGRESS, map, exp_map_id,
  25782                         MPLS_INFO(unit)->egr_mpls_hw_idx[table_num], 64);
  25783 
  25784                 if (BCM_FAILURE(rv)) {
  25785                     return (rv);
  25786                 }
  25787             } else
  25788 #endif
  25789             {
  25790         int alloc_size, offset;
  25791         egr_mpls_pri_mapping_entry_t *egr_mpls_pri_map;
  25792         egr_mpls_exp_mapping_1_entry_t *egr_mpls_exp_map;
  25793         egr_mpls_exp_mapping_2_entry_t *egr_mpls_exp_map2;
  25794         void *entries[3];
  25795         uint32 *entry;
  25796 
  25797         /* Allocate memory for DMA */
  25798         alloc_size = 64 * sizeof (egr_mpls_pri_mapping_entry_t);
  25799         egr_mpls_pri_map = soc_cm_salloc(unit, alloc_size,
  25800                                          "TR2 egr mpls pri map");
  25801         if (NULL == egr_mpls_pri_map) {
  25802             return (BCM_E_MEMORY);
  25803         }
  25804         sal_memset(egr_mpls_pri_map, 0, alloc_size);
  25805 
  25806         alloc_size = 64 * sizeof (egr_mpls_exp_mapping_1_entry_t);
  25807         egr_mpls_exp_map = soc_cm_salloc(unit, alloc_size,
  25808                                          "TR2 egr mpls exp map");
  25809         if (NULL == egr_mpls_exp_map) {
  25810             sal_free(egr_mpls_pri_map);
  25811             return (BCM_E_MEMORY);
  25812         }
  25813         sal_memset(egr_mpls_exp_map, 0, alloc_size);
  25814 
  25815         alloc_size = 64 * sizeof (egr_mpls_exp_mapping_2_entry_t);
  25816         egr_mpls_exp_map2 = soc_cm_salloc(unit, alloc_size,
  25817                                          "TR2 egr mpls exp map2");
  25818         if (NULL == egr_mpls_exp_map2) {
  25819             sal_free(egr_mpls_pri_map);
  25820             sal_free(egr_mpls_exp_map);
  25821             return (BCM_E_MEMORY);
  25822         }
  25823         sal_memset(egr_mpls_exp_map2, 0, alloc_size);
  25824 
  25825         /* Base index of table in hardware */
  25826         index = MPLS_INFO(unit)->egr_mpls_hw_idx[table_num] * 64;
  25827 
  25828         /* Offset within table */
  25829         cng = _BCM_COLOR_ENCODING(unit, map->color);
  25830         offset = (map->priority << 2) | cng;
  25831 
  25832         /* Read the old profile chunk */
  25833         rv = soc_mem_read_range(unit, EGR_MPLS_PRI_MAPPINGm, MEM_BLOCK_ANY, 
  25834                                 index, index + 63, egr_mpls_pri_map);
  25835         if (BCM_FAILURE(rv)) {
  25836             soc_cm_sfree(unit, egr_mpls_pri_map);
  25837             soc_cm_sfree(unit, egr_mpls_exp_map);
  25838             return (rv);
  25839         }
  25840         if (SOC_MEM_IS_VALID(unit, EGR_MPLS_EXP_MAPPING_1m)) {
  25841             rv = soc_mem_read_range(unit, EGR_MPLS_EXP_MAPPING_1m, MEM_BLOCK_ANY, 
  25842                                     index, index + 63, egr_mpls_exp_map);
  25843             if (BCM_FAILURE(rv)) {
  25844                 soc_cm_sfree(unit, egr_mpls_pri_map);
  25845                 soc_cm_sfree(unit, egr_mpls_exp_map);
  25846                 return (rv);
  25847             }
  25848         }
  25849 
  25850         if (SOC_MEM_IS_VALID(unit, EGR_MPLS_EXP_MAPPING_2m)) {
  25851             rv = soc_mem_read_range(unit, EGR_MPLS_EXP_MAPPING_2m, MEM_BLOCK_ANY, 
  25852                                     index, index + 63, egr_mpls_exp_map2);
  25853             if (BCM_FAILURE(rv)) {
  25854                 soc_cm_sfree(unit, egr_mpls_pri_map);
  25855                 soc_cm_sfree(unit, egr_mpls_exp_map);
  25856                 soc_cm_sfree(unit, egr_mpls_exp_map2);
  25857                 return (rv);
  25858             }
  25859         }
  25860 
  25861         /* Modify what's needed */
  25862         entry = (uint32 *)&egr_mpls_pri_map[offset];
  25863         sal_memcpy(entry, soc_mem_entry_null(unit, EGR_MPLS_PRI_MAPPINGm), 
  25864                    soc_mem_entry_words(unit, EGR_MPLS_PRI_MAPPINGm) * 4);
  25865         soc_mem_field32_set(unit, EGR_MPLS_PRI_MAPPINGm, entry, 
  25866                             NEW_PRIf, map->pkt_pri);
  25867         soc_mem_field32_set(unit, EGR_MPLS_PRI_MAPPINGm, entry,
  25868                             NEW_CFIf, map->pkt_cfi);
  25869         if (SOC_MEM_IS_VALID(unit, EGR_MPLS_EXP_MAPPING_1m)) {
  25870             entry = (uint32 *)&egr_mpls_exp_map[offset];
  25871             sal_memcpy(entry, soc_mem_entry_null(unit, EGR_MPLS_EXP_MAPPING_1m), 
  25872                        soc_mem_entry_words(unit, EGR_MPLS_EXP_MAPPING_1m) * 4);
  25873             soc_mem_field32_set(unit, EGR_MPLS_EXP_MAPPING_1m, entry, 
  25874                                 MPLS_EXPf, map->exp);
  25875         }
  25876         if (SOC_MEM_IS_VALID(unit, EGR_MPLS_EXP_MAPPING_2m)) {
  25877             entry = (uint32 *)&egr_mpls_exp_map2[offset];
  25878             sal_memcpy(entry, soc_mem_entry_null(unit, EGR_MPLS_EXP_MAPPING_2m), 
  25879                        soc_mem_entry_words(unit, EGR_MPLS_EXP_MAPPING_2m) * 4);
  25880             soc_mem_field32_set(unit, EGR_MPLS_EXP_MAPPING_2m, entry, 
  25881                                 MPLS_EXPf, map->exp);
  25882         }
  25883 
  25884         /* Update hardware tables */
  25885         entries[0] = egr_mpls_pri_map;
  25886         entries[1] = egr_mpls_exp_map;
  25887         entries[2] = egr_mpls_exp_map2;
  25888         rv = _bcm_egr_mpls_combo_map_entry_update(unit, entries, index);
  25889         if (rv == SOC_E_NONE) {
  25890                     /* reference count increment occurs in entry_update only in dma mode,
  25891                      * hence deecrease the profile ref_count increased by entry_update */
  25892                     rv = _bcm_egr_mpls_combo_map_entry_write_mode_get(unit, index, &mode);
  25893                     if ((rv == SOC_E_NONE) && (mode == SOC_PROFILE_MEM_WRITE_DMA_MODE)) {
  25894             rv = _bcm_egr_mpls_combo_map_entry_delete(unit, index);
  25895         }
  25896                 }
  25897   
  25898         /* Free the DMA memory */
  25899         soc_cm_sfree(unit, egr_mpls_pri_map);
  25900         soc_cm_sfree(unit, egr_mpls_exp_map);
  25901         soc_cm_sfree(unit, egr_mpls_exp_map2);
  25902             }
  25903 
  25904 #ifdef BCM_WARM_BOOT_SUPPORT
  25905         SOC_CONTROL_LOCK(unit);
  25906         SOC_CONTROL(unit)->scache_dirty = 1;
  25907         SOC_CONTROL_UNLOCK(unit);
  25908 #endif
  25909     } else if 
  25910         ((exp_map_id  & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 
  25911          _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS_L2) {
  25912 
  25913         if ((map->exp > 7) || (map->pkt_pri > 7) || (map->pkt_cfi > 1)) {
  25914             return BCM_E_PARAM;
  25915         }
  25916 
  25917         /* EGR_MPLS_EXP_PRI_MAPPINGm  profiles indexed by EXP */
  25918         num_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit);
  25919 
  25920         /* index = Base index + Offset  for this EXP map */
  25921         index = (table_num * 8) + map->exp; 
  25922 
  25923         if (!_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, table_num)) {
  25924             return BCM_E_NOT_FOUND;
  25925         }
  25926 
  25927 #if defined(BCM_TRIDENT3_SUPPORT)
  25928         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  25929             BCM_IF_ERROR_RETURN(READ_EGR_MPLS_PRI_MAPPINGm(unit, MEM_BLOCK_ANY,
  25930                         index, &exp_mpls_pri_entry));
  25931             soc_EGR_MPLS_PRI_MAPPINGm_field32_set(unit, &exp_mpls_pri_entry,
  25932                     NEW_PRIf, map->pkt_pri);
  25933             soc_EGR_MPLS_PRI_MAPPINGm_field32_set(unit, &exp_mpls_pri_entry,
  25934                     NEW_CFIf, map->pkt_cfi);
  25935             BCM_IF_ERROR_RETURN(WRITE_EGR_MPLS_PRI_MAPPINGm(unit, MEM_BLOCK_ALL,
  25936                         index, &exp_mpls_pri_entry));
  25937         } else
  25938 #endif
  25939         {
  25940         BCM_IF_ERROR_RETURN(READ_EGR_MPLS_EXP_PRI_MAPPINGm(unit, MEM_BLOCK_ANY,
  25941                                                            index, &exp_pri_entry));
  25942         soc_EGR_MPLS_EXP_PRI_MAPPINGm_field32_set(unit, &exp_pri_entry, 
  25943                                                   NEW_PRIf, map->pkt_pri);
  25944         soc_EGR_MPLS_EXP_PRI_MAPPINGm_field32_set(unit, &exp_pri_entry, 
  25945                                                   NEW_CFIf, map->pkt_cfi);
  25946         BCM_IF_ERROR_RETURN(WRITE_EGR_MPLS_EXP_PRI_MAPPINGm(unit, MEM_BLOCK_ALL, 
  25947                                                             index, &exp_pri_entry));
  25948         }
  25949 
  25950     } else {
  25951         return BCM_E_PARAM;
  25952     }
  25953 
  25954     return BCM_E_NONE;
  25955 }
  25956     
  25957 /*
  25958  * Function:
  25959  *      bcm_mpls_exp_map_get
  25960  * Purpose:
  25961  *      Get the mapping of { internal priority, color }
  25962  *      to a EXP value for MPLS headers
  25963  *      in the specified EXP map instance.
  25964  * Parameters:
  25965  *      unit        - (IN)  SOC unit #
  25966  *      exp_map_id  - (IN)  EXP map ID
  25967  *      map         - (OUT) EXP map config structure 
  25968  * Returns:
  25969  *      BCM_E_XXX
  25970  */     
  25971 int     
  25972 bcm_tr_mpls_exp_map_get(int unit, int exp_map_id,
  25973                         bcm_mpls_exp_map_t *map)
  25974 {
  25975     int num_exp_map, cng, index, table_num;
  25976     egr_mpls_pri_mapping_entry_t pri_entry;
  25977     egr_mpls_exp_mapping_1_entry_t exp_entry;
  25978     egr_mpls_exp_pri_mapping_entry_t exp_pri_entry;
  25979     int max_int_pri = 15;
  25980     int rv=BCM_E_NONE;
  25981     uint32 ing_pri_entry[SOC_MAX_MEM_FIELD_WORDS];
  25982     soc_mem_t  mem;
  25983     soc_field_t pri_field;
  25984 #if defined(BCM_TRIDENT3_SUPPORT)
  25985     egr_mpls_pri_mapping_entry_t exp_mpls_pri_entry;
  25986 #endif
  25987 
  25988     if (exp_map_id < 0) {
  25989         return BCM_E_PARAM;
  25990     }
  25991 
  25992     table_num = exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK;
  25993 
  25994     if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 
  25995         _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) {
  25996 
  25997         /* ING_MPLS_EXP_MAPPING profiles indexed by EXP */
  25998         num_exp_map = _bcm_tr_get_ing_mpls_index_size(unit);
  25999 
  26000         if ((map == NULL) || (table_num >= num_exp_map)) {
  26001             return BCM_E_PARAM;
  26002         }
  26003         if (!_BCM_MPLS_ING_EXP_MAP_USED_GET(unit, table_num)) {
  26004             return BCM_E_NOT_FOUND;
  26005         }
  26006 
  26007         /* Commit to HW */
  26008         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  26009             mem = PHB_MAPPING_TBL_3m;
  26010             pri_field = INT_PRIf;
  26011             /* 6 bit QOS field and 8-bit profile index
  26012              * Max 32 profiles are supported from mpls_entry
  26013              * Key is packet exp and profile index from mpls-entry */
  26014             index = (table_num << 6) | map->exp;
  26015         } else {
  26016             mem = ING_MPLS_EXP_MAPPINGm;
  26017             pri_field = PRIf;
  26018             /* Get the base index for this EXP map */
  26019             index = (table_num * 8) + map->exp;
  26020         }
  26021 
  26022         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, ing_pri_entry);
  26023         if (BCM_FAILURE(rv)) {
  26024             return rv;
  26025         }
  26026         map->priority = soc_mem_field32_get(unit, mem, ing_pri_entry, pri_field);
  26027         cng = soc_mem_field32_get(unit, mem, ing_pri_entry, CNGf);
  26028         map->color = _BCM_COLOR_DECODING(unit, cng);
  26029         if (SOC_MEM_FIELD_VALID(unit,mem,DSCPf)) {
  26030 #if defined(BCM_TRIDENT3_SUPPORT)
  26031             int valid = 1;
  26032 
  26033             if (SOC_MEM_FIELD_VALID(unit, mem, DSCP_VALIDf)) {
  26034                 valid = soc_mem_field32_get(unit, mem, ing_pri_entry, DSCP_VALIDf);
  26035             }
  26036             if (!valid) {
  26037                 map->dscp = EXP_MAP_DSCP_INVALID;
  26038             } else
  26039 #endif
  26040             {
  26041                 map->dscp = soc_mem_field32_get(unit, mem, ing_pri_entry, DSCPf);
  26042             }
  26043         }
  26044     } else if
  26045         ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 
  26046          _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS) {
  26047         /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by ((int_pri << 2) + cng) */
  26048         num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
  26049     
  26050         if ((map == NULL) || (table_num >= num_exp_map) ||
  26051             (map->priority < BCM_PRIO_MIN) || (map->priority > max_int_pri)) {
  26052             return BCM_E_PARAM;
  26053         }
  26054 
  26055         if (!_BCM_EGR_MPLS_MAP_USED_GET(unit, table_num)) {
  26056             return BCM_E_NOT_FOUND;
  26057         }
  26058         cng = _BCM_COLOR_ENCODING(unit, map->color);
  26059 
  26060         /* Base index of table in hardware */
  26061         index = MPLS_INFO(unit)->egr_mpls_hw_idx[table_num] * 64;
  26062 
  26063         /* Add the offset based on priority and color values */
  26064         index += ((map->priority << 2) | (cng & 3));
  26065 
  26066         /* Get the values from HW */
  26067         BCM_IF_ERROR_RETURN(READ_EGR_MPLS_EXP_MAPPING_1m(unit, MEM_BLOCK_ANY,
  26068                                                          index, &exp_entry));
  26069         map->exp = soc_mem_field32_get(unit, EGR_MPLS_EXP_MAPPING_1m, 
  26070                                        &exp_entry, MPLS_EXPf);
  26071     
  26072         BCM_IF_ERROR_RETURN(READ_EGR_MPLS_PRI_MAPPINGm(unit, MEM_BLOCK_ANY,
  26073                                                        index, &pri_entry));
  26074         map->pkt_pri = soc_mem_field32_get(unit, EGR_MPLS_PRI_MAPPINGm, 
  26075                                            &pri_entry, NEW_PRIf);
  26076         map->pkt_cfi = soc_mem_field32_get(unit, EGR_MPLS_PRI_MAPPINGm, 
  26077                                            &pri_entry, NEW_CFIf);
  26078     } else if    
  26079         ((exp_map_id  & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 
  26080          _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS_L2) {
  26081 
  26082         /* EGR_MPLS_EXP_PRI_MAPPINGm profiles indexed by EXP */
  26083         num_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit);
  26084 
  26085         if ((map == NULL) || (table_num >= num_exp_map)) {
  26086             return BCM_E_PARAM;
  26087         }
  26088 
  26089         if (!_BCM_MPLS_EGR_EXP_MAP_USED_GET(unit, table_num)) {
  26090             return BCM_E_NOT_FOUND;
  26091         }
  26092 
  26093         /* index = Base index + Offset  for this EXP map */
  26094         index = (table_num * 8) + map->exp; 
  26095 
  26096         /* Read from HW */
  26097 #if defined(BCM_TRIDENT3_SUPPORT)
  26098         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  26099             BCM_IF_ERROR_RETURN(READ_EGR_MPLS_PRI_MAPPINGm(unit, MEM_BLOCK_ANY,
  26100                         index, &exp_mpls_pri_entry));
  26101             map->pkt_pri = soc_mem_field32_get(unit, EGR_MPLS_PRI_MAPPINGm,
  26102                     &exp_mpls_pri_entry, NEW_PRIf);
  26103             map->pkt_cfi = soc_mem_field32_get(unit, EGR_MPLS_PRI_MAPPINGm,
  26104                     &exp_mpls_pri_entry, NEW_CFIf);
  26105         } else
  26106 #endif
  26107         {
  26108         BCM_IF_ERROR_RETURN(READ_EGR_MPLS_EXP_PRI_MAPPINGm(unit, MEM_BLOCK_ANY,
  26109                                                            index, &exp_pri_entry));
  26110         map->pkt_pri = soc_mem_field32_get(unit, EGR_MPLS_EXP_PRI_MAPPINGm, 
  26111                                            &exp_pri_entry, NEW_PRIf);
  26112         map->pkt_cfi = soc_mem_field32_get(unit, EGR_MPLS_EXP_PRI_MAPPINGm,
  26113                                            &exp_pri_entry, NEW_CFIf);
  26114         }
  26115     } else {
  26116         return BCM_E_PARAM;
  26117     }
  26118     return BCM_E_NONE;
  26119 }
  26120 
  26121 #ifdef BCM_APACHE_SUPPORT
  26122 /*
  26123  * Function:
  26124  *      bcm_tr_mpls_exp_to_phb_cng_map_create
  26125  * Purpose:
  26126  *      Create an MPLS EXP to PBH and CNG map instance.
  26127  * Parameters:
  26128  *      unit        - (IN)  SOC unit #
  26129  *      flags       - (IN)  MPLS flags
  26130  *      exp_map_id  - (OUT) Allocated EXP map ID
  26131  * Returns:
  26132  *      BCM_E_XXX
  26133  */
  26134 int
  26135 bcm_tr_mpls_exp_to_phb_cng_map_create(int unit, uint32 flags, int *exp_map_id)
  26136 {
  26137     int i, table_num, num_exp_map;
  26138 
  26139     /* Check for unsupported Flag */
  26140     if (flags & (~(BCM_MPLS_EXP_MAP_WITH_ID |
  26141                    BCM_MPLS_EXP_MAP_INGRESS |
  26142                    BCM_MPLS_EXP_MAP_EGRESS |
  26143                    BCM_QOS_MAP_OAM_MPLS_EXP))) {
  26144         return BCM_E_PARAM;
  26145     }
  26146 
  26147     /* Input parameters check. */
  26148     if (NULL == exp_map_id) {
  26149         return BCM_E_PARAM;
  26150     }
  26151 
  26152     if (flags & BCM_MPLS_EXP_MAP_INGRESS) {
  26153         /* ING_MPLS_EXP_MAPPING_1 profiles indexed by EXP */
  26154         num_exp_map = soc_mem_index_count(unit, ING_MPLS_EXP_MAPPING_1m) / 16;
  26155 
  26156         if (flags & BCM_MPLS_EXP_MAP_WITH_ID) {
  26157             table_num = (*exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK);
  26158             if (table_num >= num_exp_map) {
  26159                 return BCM_E_PARAM;
  26160             }
  26161             if (_BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) {
  26162                 return BCM_E_EXISTS;
  26163             }
  26164             _BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_SET(unit, table_num);
  26165 #ifdef BCM_WARM_BOOT_SUPPORT
  26166             SOC_CONTROL_LOCK(unit);
  26167             SOC_CONTROL(unit)->scache_dirty = 1;
  26168             SOC_CONTROL_UNLOCK(unit);
  26169 #endif
  26170 
  26171             *exp_map_id = table_num | (_BCM_QOS_MAP_TYPE_EXP_TO_PHB_CNG_MAP
  26172                     << _BCM_QOS_MAP_SHIFT);
  26173             *exp_map_id = (*exp_map_id |
  26174                            _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS);
  26175             return BCM_E_NONE;
  26176         }
  26177 
  26178         for (i = 0; i < num_exp_map; i++) {
  26179             if (!_BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_GET(unit, i)) {
  26180                 _BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_SET(unit, i);
  26181                 *exp_map_id = i | (_BCM_QOS_MAP_TYPE_EXP_TO_PHB_CNG_MAP
  26182                                                      << _BCM_QOS_MAP_SHIFT);
  26183                 *exp_map_id = (*exp_map_id |
  26184                                _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS);
  26185 #ifdef BCM_WARM_BOOT_SUPPORT
  26186                 SOC_CONTROL_LOCK(unit);
  26187                 SOC_CONTROL(unit)->scache_dirty = 1;
  26188                 SOC_CONTROL_UNLOCK(unit);
  26189 #endif
  26190                 return BCM_E_NONE;
  26191             }
  26192         }
  26193 
  26194     } else if (flags & BCM_MPLS_EXP_MAP_EGRESS) {
  26195         /* EGR_MPLS_EXP_MAPPING_3 profiles indexed by MPLS_EXP */
  26196         num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 8;
  26197 
  26198         if (flags & BCM_MPLS_EXP_MAP_WITH_ID) {
  26199             table_num = (*exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK);
  26200             if (table_num >= num_exp_map) {
  26201                 return BCM_E_PARAM;
  26202             }
  26203             if (!_BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) {
  26204                 /* Reserve a chunk in the EGR_MPLS_EXP_MAPPING_3 */
  26205                 _BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_SET(unit, table_num);
  26206             } else {
  26207                 return BCM_E_EXISTS;
  26208             }
  26209 #ifdef BCM_WARM_BOOT_SUPPORT
  26210             SOC_CONTROL_LOCK(unit);
  26211             SOC_CONTROL(unit)->scache_dirty = 1;
  26212             SOC_CONTROL_UNLOCK(unit);
  26213 #endif
  26214             *exp_map_id = table_num | (_BCM_QOS_MAP_TYPE_EXP_TO_PHB_CNG_MAP
  26215                     << _BCM_QOS_MAP_SHIFT);
  26216             *exp_map_id = (*exp_map_id |
  26217                            _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS);
  26218             return BCM_E_NONE;
  26219         }
  26220 
  26221         for (i = 0; i < num_exp_map; i++) {
  26222             if (!_BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_GET(unit, i)) {
  26223                 *exp_map_id = i | (_BCM_QOS_MAP_TYPE_EXP_TO_PHB_CNG_MAP
  26224                                                      << _BCM_QOS_MAP_SHIFT);
  26225                 *exp_map_id = (*exp_map_id |
  26226                                _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS);
  26227 
  26228                 _BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_SET(unit, i);
  26229 #ifdef BCM_WARM_BOOT_SUPPORT
  26230                 SOC_CONTROL_LOCK(unit);
  26231                 SOC_CONTROL(unit)->scache_dirty = 1;
  26232                 SOC_CONTROL_UNLOCK(unit);
  26233 #endif
  26234                 return BCM_E_NONE;
  26235             }
  26236         }
  26237     } else {
  26238         return BCM_E_PARAM;
  26239     }
  26240     return BCM_E_FULL;
  26241 }
  26242 
  26243 /*
  26244  * Function:
  26245  *      bcm_tr_mpls_exp_to_phb_cng_map_destroy
  26246  * Purpose:
  26247  *      Destroy an existing MPLS EXP to PBH and CNG map instance.
  26248  * Parameters:
  26249  *      unit       - (IN) SOC unit #
  26250  *      exp_map_id - (IN) EXP map ID
  26251  * Returns:
  26252  *      BCM_E_XXX
  26253  */
  26254 int
  26255 bcm_tr_mpls_exp_to_phb_cng_map_destroy(int unit, int exp_map_id)
  26256 {
  26257     int num_exp_map, table_num;
  26258 
  26259     if (exp_map_id < 0) {
  26260         return BCM_E_PARAM;
  26261     }
  26262     table_num = exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK;
  26263 
  26264     if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 
  26265         _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) {
  26266 
  26267         /* ING_MPLS_EXP_MAPPING_1 profiles indexed by EXP */
  26268         num_exp_map = soc_mem_index_count(unit, ING_MPLS_EXP_MAPPING_1m) / 16;
  26269         if (table_num >= num_exp_map) {
  26270             return BCM_E_PARAM;
  26271         }
  26272         if (!_BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) {
  26273             return BCM_E_NOT_FOUND;
  26274         }
  26275         _BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_CLR(unit, table_num);
  26276 #ifdef BCM_WARM_BOOT_SUPPORT
  26277         SOC_CONTROL_LOCK(unit);
  26278         SOC_CONTROL(unit)->scache_dirty = 1;
  26279         SOC_CONTROL_UNLOCK(unit);
  26280 #endif
  26281     } else if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 
  26282                _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS) {
  26283 
  26284         /* EGR_MPLS_EXP_MAPPING_3m profiles indexed by EXP */
  26285         num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_3m) / 8;
  26286         if (table_num >= num_exp_map) {
  26287             return BCM_E_PARAM;
  26288         }
  26289         if (!_BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) {
  26290             return BCM_E_NOT_FOUND;
  26291         }
  26292         _BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_CLR(unit, table_num);
  26293 #ifdef BCM_WARM_BOOT_SUPPORT
  26294         SOC_CONTROL_LOCK(unit);
  26295         SOC_CONTROL(unit)->scache_dirty = 1;
  26296         SOC_CONTROL_UNLOCK(unit);
  26297 #endif        
  26298     } else {
  26299         return BCM_E_PARAM;
  26300     }
  26301 
  26302     return BCM_E_NONE;
  26303 }
  26304 
  26305 /*
  26306  * Function:
  26307  *      bcm_tr_mpls_exp_to_phb_cng_map_set
  26308  * Purpose:
  26309  *      Set the mapping of { PHB, CNG }
  26310  *      to a EXP value for MPLS headers
  26311  *      in the specified EXP map instance.
  26312  * Parameters:
  26313  *      unit        - (IN) SOC unit #
  26314  *      flags       - (IN) flags
  26315  *      exp_map_id  - (IN) EXP map ID
  26316  *      map         - (IN) EXP map config structure 
  26317  * Returns:
  26318  *      BCM_E_XXX
  26319  */
  26320 int
  26321 bcm_tr_mpls_exp_to_phb_cng_map_set(int unit, int exp_map_id,
  26322                         bcm_mpls_exp_map_t *map)
  26323 {
  26324     int table_num, num_exp_map, cng, index;
  26325     egr_mpls_exp_mapping_3_entry_t exp_pri_entry;
  26326     ing_mpls_exp_mapping_1_entry_t ing_pri_entry;
  26327     
  26328     /* Check validity of exp_map_id */
  26329     if (exp_map_id < 0) {
  26330         return BCM_E_PARAM;
  26331     }
  26332 
  26333     if (!map) {
  26334         /* invalid pointer to map data */
  26335         return BCM_E_PARAM;
  26336     }
  26337 
  26338     table_num = exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK;
  26339 
  26340     if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 
  26341         _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) {
  26342 
  26343         /* ING_MPLS_EXP_MAPPING_1 profiles indexed by EXP */
  26344         num_exp_map = soc_mem_index_count(unit, ING_MPLS_EXP_MAPPING_1m) / 16;
  26345         if (table_num >= num_exp_map) {
  26346             return BCM_E_PARAM;
  26347         }
  26348 
  26349         if (!_BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) {
  26350             return BCM_E_NOT_FOUND;
  26351         }
  26352 
  26353         cng = _BCM_COLOR_ENCODING(unit, map->color);
  26354  
  26355         /* Get the base index for this EXP map */
  26356         index = (table_num * 8) + map->exp; 
  26357  
  26358         /* Commit to HW */
  26359         BCM_IF_ERROR_RETURN(READ_ING_MPLS_EXP_MAPPING_1m(unit, MEM_BLOCK_ANY,
  26360                                                        index, &ing_pri_entry));
  26361         soc_ING_MPLS_EXP_MAPPING_1m_field32_set(unit, &ing_pri_entry, 
  26362                                               PHBf, map->priority);
  26363         soc_ING_MPLS_EXP_MAPPING_1m_field32_set(unit, &ing_pri_entry, 
  26364                                               CNGf, cng);
  26365         BCM_IF_ERROR_RETURN(WRITE_ING_MPLS_EXP_MAPPING_1m(unit, MEM_BLOCK_ALL, 
  26366                                                         index, &ing_pri_entry));
  26367     } else if 
  26368         ((exp_map_id  & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 
  26369          _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS) {
  26370 
  26371         if ((map->exp > 7) || (map->pkt_pri > 7) || (map->pkt_cfi > 1)) {
  26372             return BCM_E_PARAM;
  26373         }
  26374 
  26375         /* EGR_MPLS_EXP_MAPPING_3m  profiles indexed by EXP */
  26376         num_exp_map = bcmi_egr_mpls_exp_pri_mapping_num_exp_map_get(unit);
  26377         if (table_num >= num_exp_map) {
  26378             return BCM_E_PARAM;
  26379         }
  26380 
  26381         cng = _BCM_COLOR_ENCODING(unit, map->color);
  26382 
  26383         /* index = Base index + Offset  for this EXP map */
  26384         index = (table_num * 8) + map->exp; 
  26385 
  26386         if (!_BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) {
  26387             return BCM_E_NOT_FOUND;
  26388         }
  26389 
  26390         BCM_IF_ERROR_RETURN(READ_EGR_MPLS_EXP_MAPPING_3m(unit, MEM_BLOCK_ANY,
  26391                                                            index, &exp_pri_entry));
  26392         soc_EGR_MPLS_EXP_MAPPING_3m_field32_set(unit, &exp_pri_entry, 
  26393                                                   PHBf, map->priority);
  26394         soc_EGR_MPLS_EXP_MAPPING_3m_field32_set(unit, &exp_pri_entry, 
  26395                                                   CNGf, cng);
  26396         BCM_IF_ERROR_RETURN(WRITE_EGR_MPLS_EXP_MAPPING_3m(unit, MEM_BLOCK_ALL, 
  26397                                                             index, &exp_pri_entry));
  26398 
  26399     } else {
  26400         return BCM_E_PARAM;
  26401     }
  26402 
  26403     return BCM_E_NONE;
  26404 }
  26405     
  26406 /*
  26407  * Function:
  26408  *      bcm_tr_mpls_exp_to_phb_cng_map_get
  26409  * Purpose:
  26410  *      Get the mapping of { PHB, CNG }
  26411  *      to a EXP value for MPLS headers
  26412  *      in the specified EXP map instance.
  26413  * Parameters:
  26414  *      unit        - (IN)  SOC unit #
  26415  *      exp_map_id  - (IN)  EXP map ID
  26416  *      map         - (OUT) EXP map config structure 
  26417  * Returns:
  26418  *      BCM_E_XXX
  26419  */     
  26420 int     
  26421 bcm_tr_mpls_exp_to_phb_cng_map_get(int unit, int exp_map_id,
  26422                         bcm_mpls_exp_map_t *map)
  26423 {
  26424     int num_exp_map, cng, index, table_num;
  26425     egr_mpls_exp_mapping_3_entry_t exp_entry;
  26426     ing_mpls_exp_mapping_1_entry_t ing_pri_entry;
  26427 
  26428 
  26429     if (exp_map_id < 0) {
  26430         return BCM_E_PARAM;
  26431     }
  26432 
  26433     table_num = exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK;
  26434 
  26435     if ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 
  26436         _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) {
  26437 
  26438         /* ING_MPLS_EXP_MAPPING_1 profiles indexed by EXP */
  26439         num_exp_map = soc_mem_index_count(unit, ING_MPLS_EXP_MAPPING_1m) / 16;
  26440 
  26441         if ((map == NULL) || (table_num >= num_exp_map)) {
  26442             return BCM_E_PARAM;
  26443         }
  26444         if (!_BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) {
  26445             return BCM_E_NOT_FOUND;
  26446         }
  26447 
  26448         /* Get the base index for this EXP map */
  26449         index = (table_num * 8) + map->exp; 
  26450 
  26451         /* Commit to HW */
  26452         BCM_IF_ERROR_RETURN(READ_ING_MPLS_EXP_MAPPING_1m(unit, MEM_BLOCK_ANY,
  26453                                                        index, &ing_pri_entry));
  26454         map->priority = soc_mem_field32_get(unit, ING_MPLS_EXP_MAPPING_1m, 
  26455                                             &ing_pri_entry, PHBf);
  26456         cng = soc_mem_field32_get(unit, ING_MPLS_EXP_MAPPING_1m,
  26457                                   &ing_pri_entry, CNGf);
  26458         map->color = _BCM_COLOR_DECODING(unit, cng);
  26459 
  26460     } else if
  26461         ((exp_map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 
  26462          _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_EGRESS) {
  26463         /* EGR_MPLS_EXP_MAPPING_1 profiles indexed by EXP*/
  26464         num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_3m) / 8;
  26465     
  26466         if ((map == NULL) || (table_num >= num_exp_map)) {
  26467             return BCM_E_PARAM;
  26468         }
  26469 
  26470         if (!_BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_GET(unit, table_num)) {
  26471             return BCM_E_NOT_FOUND;
  26472         }
  26473 
  26474         /* Get the base index for this EXP map */
  26475         index = (table_num * 8) + map->exp;
  26476 
  26477         /* Get the values from HW */
  26478         BCM_IF_ERROR_RETURN(READ_EGR_MPLS_EXP_MAPPING_3m(unit, MEM_BLOCK_ANY,
  26479                                                          index, &exp_entry));
  26480         map->priority = soc_mem_field32_get(unit, EGR_MPLS_EXP_MAPPING_3m, 
  26481                                        &exp_entry, PHBf);
  26482     
  26483         cng = soc_mem_field32_get(unit, EGR_MPLS_EXP_MAPPING_3m,
  26484                                   &exp_entry, CNGf);
  26485         map->color = _BCM_COLOR_DECODING(unit, cng);
  26486     } else {
  26487         return BCM_E_PARAM;
  26488     }
  26489     return BCM_E_NONE;
  26490 }
  26491 
  26492 int 
  26493 bcm_tr_mpls_exp_to_phb_cng_map_usage_get(int unit, uint32 flags, 
  26494                                            int exp_map_id)
  26495 {   
  26496     if((flags & BCM_QOS_MAP_INGRESS) && 
  26497             (!_BCM_MPLS_ING_EXP_TO_PHB_CNG_MAP_USED_GET(unit, exp_map_id))) {
  26498         return BCM_E_NOT_FOUND;
  26499     }
  26500     else if ((flags & BCM_QOS_MAP_EGRESS) && 
  26501             (!_BCM_MPLS_EGR_EXP_TO_PHB_CNG_MAP_USED_GET(unit, exp_map_id))) {
  26502         return BCM_E_NOT_FOUND;
  26503     }
  26504 
  26505     return BCM_E_NONE;
  26506 }
  26507 
  26508 int
  26509 bcm_tr_mpls_exp_to_phb_cng_map_profile_id_get(int unit, uint32 flags, 
  26510                                            int map_id, int *profile_id)
  26511 {
  26512     if(flags & BCM_QOS_MAP_INGRESS){
  26513         *profile_id = MPLS_INFO(unit)->ing_exp_to_phb_cng_map_bitmap[map_id];
  26514     } else if (flags & BCM_QOS_MAP_EGRESS){
  26515         *profile_id = MPLS_INFO(unit)->egr_exp_to_phb_cng_map_bitmap[map_id];
  26516     } else {
  26517         return BCM_E_PARAM; 
  26518     }
  26519     return BCM_E_NONE;
  26520 }
  26521 
  26522 int
  26523 bcm_tr_mpls_exp_to_phb_cng_map_profile_range_get(int unit, uint32 flags, 
  26524                                               int *count)
  26525 {
  26526     int num_exp_map = 0, value = 0;
  26527 
  26528     if(flags & BCM_QOS_MAP_INGRESS){
  26529         num_exp_map = soc_mem_index_count(unit, ING_MPLS_EXP_MAPPING_1m) / 16;
  26530         SHR_BITCOUNT_RANGE(MPLS_INFO(unit)->ing_exp_to_phb_cng_map_bitmap, 
  26531                            value, 0, num_exp_map);
  26532     } else if (flags & BCM_QOS_MAP_EGRESS){
  26533         num_exp_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_3m) / 8;
  26534         SHR_BITCOUNT_RANGE(MPLS_INFO(unit)->egr_exp_to_phb_cng_map_bitmap, 
  26535                            value, 0, num_exp_map);
  26536     }
  26537     *count = value;
  26538     return BCM_E_NONE;
  26539 }
  26540 
  26541 
  26542 #endif
  26543 
  26544 #ifdef BCM_TRIUMPH2_SUPPORT
  26545 STATIC int
  26546 _bcm_tr2_mpls_label_flex_stat_hw_index_set(int unit,
  26547                                      _bcm_flex_stat_handle_t handle,
  26548                                                int fs_idx, void *cookie)
  26549 {
  26550     int rv;
  26551     mpls_entry_entry_t *ment;
  26552 
  26553     /* The entry was found earlier, so we can use it here */
  26554     ment = (mpls_entry_entry_t *) cookie;
  26555 
  26556     /* Update the entry appropriately */
  26557     soc_mem_field32_set(unit, MPLS_ENTRYm, ment,
  26558                         VINTF_CTR_IDXf, fs_idx);
  26559     soc_mem_field32_set(unit, MPLS_ENTRYm, ment,
  26560                         USE_VINTF_CTR_IDXf, (fs_idx > 0) ? 1 : 0);
  26561  
  26562     /* Replace the existing entry */
  26563     rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, ment);
  26564     if (BCM_E_EXISTS == rv) {
  26565         return BCM_E_NONE;
  26566     } else if (BCM_SUCCESS(rv)) {
  26567         rv = BCM_E_NOT_FOUND;
  26568     }
  26569 
  26570     return rv;
  26571 }
  26572 
  26573 STATIC _bcm_flex_stat_t
  26574 _bcm_esw_mpls_label_stat_to_flex_stat(bcm_mpls_stat_t stat)
  26575 {
  26576     _bcm_flex_stat_t flex_stat;
  26577 
  26578     /* Only ingress stats from the MPLS_ENTRY table. */
  26579     switch (stat) {
  26580     case bcmMplsInPkts:
  26581         flex_stat = _bcmFlexStatIngressPackets;
  26582         break;
  26583     case bcmMplsInBytes:
  26584         flex_stat = _bcmFlexStatIngressBytes;
  26585         break;
  26586     default:
  26587         flex_stat = _bcmFlexStatNum;
  26588     }
  26589 
  26590     return flex_stat;
  26591 }
  26592 
  26593 /*
  26594  * Function:
  26595  *      bcm_tr2_mpls_label_stat_enable_set
  26596  * Purpose:
  26597  *      Enable statistics collection for MPLS label or MPLS gport
  26598  * Parameters:
  26599  *      unit - (IN) Unit number.
  26600  *      label - (IN) MPLS label
  26601  *      port - (IN) MPLS gport
  26602  *      enable - (IN) Non-zero to enable counter collection, zero to disable.
  26603  *      cnt_inx - (IN) counter index. zero means not allocated
  26604  * Returns:
  26605  *      BCM_E_xxx
  26606  * Notes:
  26607  */
  26608 int 
  26609 bcm_tr2_mpls_label_stat_enable_set(int unit, bcm_mpls_label_t label, 
  26610                                    bcm_gport_t port, int enable,int cnt_inx)
  26611 {
  26612     /* This enables the flexible statistics gathering for MPLS labels */
  26613     int rv=BCM_E_UNAVAIL;
  26614     int index;
  26615     bcm_mpls_tunnel_switch_t info;
  26616     mpls_entry_entry_t ment;
  26617     _bcm_flex_stat_handle_t mpls_fsh;
  26618 
  26619     if (BCM_GPORT_IS_MPLS_PORT(port)) {
  26620         /* When the gport is an MPLS port, we'll turn on the
  26621          * port-based tracking for backward-compatibility.
  26622          */
  26623         return _bcm_esw_flex_stat_enable_set(unit, _bcmFlexStatTypeGport,
  26624                      _bcm_esw_port_flex_stat_hw_index_set,
  26625                      cnt_inx? INT_TO_PTR(_BCM_FLEX_STAT_HW_INGRESS): NULL,
  26626                                           port, enable,cnt_inx);
  26627     }
  26628 
  26629     sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t));
  26630     info.port = port;
  26631     if (BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
  26632         info.label = label;
  26633     } else {
  26634         return BCM_E_PARAM;
  26635     }
  26636 
  26637     rv = _bcm_tr_mpls_entry_set_key(unit, &info, &ment);
  26638     BCM_IF_ERROR_RETURN(rv);
  26639 
  26640     /* We don't use the handle retrieval function here because
  26641      * we've already found the matching entry from which to extract
  26642      * the key.  
  26643      */
  26644     /* Fill handle for MPLS label info */
  26645     _BCM_FLEX_STAT_HANDLE_CLEAR(mpls_fsh);
  26646     /* Handle is key of MPLS entry */
  26647     _BCM_FLEX_STAT_HANDLE_COPY(mpls_fsh, ment);
  26648 
  26649     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
  26650                         &ment, &ment, 0);
  26651 
  26652     if (rv == SOC_E_NONE) {
  26653         /* Entry exists, and we are inside MPLS lock, so proceed with
  26654          * attaching the counter. */
  26655         rv = _bcm_esw_flex_stat_ext_enable_set(unit,
  26656                                                _bcmFlexStatTypeMplsLabel,
  26657                              _bcm_tr2_mpls_label_flex_stat_hw_index_set,
  26658                                     (void *) &ment, mpls_fsh, enable,cnt_inx);
  26659     }
  26660 
  26661     return rv;
  26662 }
  26663 #endif /* BCM_TRIUMPH2_SUPPORT */
  26664 
  26665 /*
  26666  * Function:
  26667  *      bcm_tr_mpls_label_stat_get
  26668  * Purpose:
  26669  *      Get L2 MPLS PW Stats
  26670  *      if sync_mode is set, sync the sw accumulated count
  26671  *      with hw count value first, else return sw count.  
  26672  * Parameters:
  26673  *      unit      - (IN) SOC unit #
  26674  *      sync_mode - (IN) hwcount is to be synced to sw count 
  26675  *      label     - (IN) MPLS label
  26676  *      port      - (IN) MPLS gport
  26677  *      stat      - (IN)  specify the Stat type
  26678  *      val       - (OUT) 64-bit Stats value
  26679  * Returns:
  26680  *      BCM_E_XXX
  26681  */     
  26682 
  26683 int
  26684 bcm_tr_mpls_label_stat_get(int unit, int sync_mode, bcm_mpls_label_t label, 
  26685                            bcm_gport_t port, bcm_mpls_stat_t stat, uint64 *val)
  26686 {
  26687     int rv=BCM_E_UNAVAIL, index;
  26688     bcm_mpls_tunnel_switch_t info;
  26689     mpls_entry_entry_t ment;
  26690     ing_pw_term_counters_entry_t cent;
  26691     egr_pw_init_counters_entry_t pw_init_entry;
  26692     egr_l3_next_hop_entry_t egr_nh;
  26693     ing_dvp_table_entry_t dvp;
  26694     int vp, nh_index;
  26695     uint32  hw_val[2];
  26696     uint32 val_high, val_low;
  26697     uint32 pkt_counter;
  26698     uint32 pw_term_cnt, pw_init_cnt, num_pw_mask;
  26699 
  26700     /* Based on Switch Type */
  26701 #ifdef BCM_TRIUMPH2_SUPPORT
  26702     if (soc_feature(unit, soc_feature_gport_service_counters)) {
  26703         _bcm_flex_stat_handle_t mpls_fsh;
  26704 
  26705         COMPILER_64_ZERO(*val);
  26706 
  26707         if (BCM_GPORT_IS_MPLS_PORT(port)) {
  26708             bcm_port_stat_t flex_stat=0;
  26709             switch (stat) {
  26710             case bcmMplsInPkts:
  26711                 flex_stat = bcmPortStatIngressPackets;
  26712                 break;
  26713             case bcmMplsInBytes:
  26714                 flex_stat = bcmPortStatIngressBytes;
  26715                 break;
  26716             case bcmMplsOutPkts:
  26717                 flex_stat = bcmPortStatEgressPackets;
  26718                 break;
  26719             case bcmMplsOutBytes:
  26720                 flex_stat = bcmPortStatEgressBytes;
  26721                 break;
  26722             }
  26723 
  26724             rv = _bcm_esw_port_stat_get(unit, sync_mode, port, flex_stat, val);
  26725         } else {
  26726 
  26727             /* When not an MPLS gport, we use the label-based stats. */
  26728             sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t));
  26729             info.port = port;
  26730             if (BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
  26731                 info.label = label;
  26732             } else {
  26733                 return BCM_E_PARAM;
  26734             }
  26735 
  26736             rv = _bcm_tr_mpls_entry_set_key(unit, &info, &ment);
  26737             BCM_IF_ERROR_RETURN(rv);
  26738 
  26739             _BCM_FLEX_STAT_HANDLE_CLEAR(mpls_fsh);
  26740             _BCM_FLEX_STAT_HANDLE_COPY(mpls_fsh, ment);
  26741 
  26742 
  26743             rv = _bcm_esw_flex_stat_ext_get(unit, sync_mode,
  26744                                              _bcmFlexStatTypeMplsLabel,
  26745                                             mpls_fsh,
  26746                             _bcm_esw_mpls_label_stat_to_flex_stat(stat),
  26747                                             val);
  26748         }
  26749     } else
  26750 #endif /* BCM_TRIUMPH2_SUPPORT */
  26751     if (SOC_IS_TR_VL(unit)) {
  26752    
  26753         if ((stat == bcmMplsInBytes) || (stat == bcmMplsInPkts)) {
  26754             sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t));
  26755             info.port = port;
  26756             if (BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
  26757                 info.label = label;
  26758             } else {
  26759                 return BCM_E_PARAM;
  26760             }
  26761 
  26762             rv = _bcm_tr_mpls_entry_set_key(unit, &info, &ment);
  26763             BCM_IF_ERROR_RETURN(rv);
  26764 
  26765             rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
  26766                                 &ment, &ment, 0);
  26767 
  26768             if (rv == SOC_E_NONE) {
  26769                 if (!soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUM_VALIDf)) {
  26770                     return BCM_E_CONFIG;
  26771                 }
  26772                 pw_term_cnt = soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUMf);
  26773 
  26774                 if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) {
  26775                     rv = READ_ING_PW_TERM_COUNTERSm(unit, MEM_BLOCK_ANY, pw_term_cnt, &cent);
  26776                     if (rv < 0) {
  26777                         return rv;
  26778                     }
  26779                 } else {
  26780                     return BCM_E_UNAVAIL;
  26781                 }
  26782                 COMPILER_64_ZERO(*val);
  26783                 switch (stat) {
  26784                 case bcmMplsInBytes:
  26785                     if(SOC_IS_ENDURO(unit)) {
  26786                         hw_val[0] = hw_val[1] = 0;
  26787                         soc_mem_field_get(unit, ING_PW_TERM_COUNTERSm, 
  26788                                           (uint32 *) &cent, BYTE_COUNTERf, hw_val);
  26789                         COMPILER_64_SET(*val,  hw_val[1],hw_val[0]);
  26790                     }
  26791                     else {
  26792                         val_high = soc_mem_field32_get(unit, ING_PW_TERM_COUNTERSm, 
  26793                                                        &cent, BYTE_COUNTER_HIf);
  26794                         val_low  = soc_mem_field32_get(unit, ING_PW_TERM_COUNTERSm, 
  26795                                                        &cent, BYTE_COUNTER_LOf);
  26796                         COMPILER_64_SET(*val, val_high, val_low);
  26797                     }
  26798                     break;
  26799 
  26800                 case bcmMplsInPkts:
  26801                     val_low  = soc_mem_field32_get(unit, ING_PW_TERM_COUNTERSm, 
  26802                                                    &cent, PACKET_COUNTERf);
  26803                     COMPILER_64_SET(*val, 0, val_low);
  26804                     break;
  26805                     /*
  26806                      * COVERITY
  26807                      *
  26808                      * This default is unreachable. It is kept intentionally as a defensive default for future development. 
  26809                      */ 
  26810                     /* coverity[dead_error_begin] */
  26811                 default:
  26812                     break;
  26813                 }
  26814             }
  26815         } else if ((stat == bcmMplsOutBytes) || (stat == bcmMplsOutPkts) ) {
  26816 
  26817             /* Get egress next-hop index from MPLS GPORT */
  26818             vp = BCM_GPORT_MPLS_PORT_ID_GET(port);
  26819             if (vp == -1) {
  26820                  return BCM_E_PARAM;
  26821             }
  26822 
  26823             rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp);
  26824             if (rv < 0) {
  26825                 return rv;
  26826             }
  26827             nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 
  26828                                                       NEXT_HOP_INDEXf);
  26829      
  26830             /* Retrieve EGR L3 NHOP Entry */
  26831             BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  26832                                               nh_index, &egr_nh));
  26833 
  26834             /* Retrieve PW_INIT Index from EGR L3 NHOP Entry */
  26835             if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  26836                  pw_init_cnt =
  26837                         soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  26838                                      MPLS__PW_INIT_NUMf);
  26839             } else {
  26840                  pw_init_cnt =
  26841                         soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  26842                                      PW_INIT_NUMf);
  26843             }
  26844 
  26845              num_pw_mask = soc_mem_index_count(0, EGR_PW_INIT_COUNTERSm) - 1;
  26846              pw_init_cnt &= num_pw_mask;
  26847 
  26848             /* Retrieve the Counter Value */
  26849             sal_memset(&pw_init_entry, 0, sizeof(egr_pw_init_counters_entry_t));
  26850             if (SOC_MEM_IS_VALID(unit, EGR_PW_INIT_COUNTERSm)) {	
  26851                 rv = READ_EGR_PW_INIT_COUNTERSm(unit, MEM_BLOCK_ANY, pw_init_cnt, &pw_init_entry);
  26852                 if (rv < 0) {
  26853                     return rv;
  26854                 }
  26855             } else {
  26856                 return BCM_E_UNAVAIL;
  26857             }
  26858             COMPILER_64_ZERO(*val);
  26859             switch (stat) {
  26860             case bcmMplsOutBytes:
  26861                 if (SOC_MEM_FIELD_VALID (unit, EGR_PW_INIT_COUNTERSm, BYTE_COUNTERf)) {
  26862                     hw_val[0] = hw_val[1] = 0;
  26863                     soc_mem_field_get(unit, EGR_PW_INIT_COUNTERSm, 
  26864                                   (uint32 *) &pw_init_entry, BYTE_COUNTERf, hw_val);
  26865                     COMPILER_64_SET(*val,  hw_val[1],hw_val[0]);
  26866                 } else {
  26867                     return BCM_E_UNAVAIL;
  26868                 }
  26869                 break;
  26870 
  26871             case bcmMplsOutPkts:
  26872                 if (SOC_MEM_FIELD_VALID (unit, EGR_PW_INIT_COUNTERSm, PACKET_COUNTERf)) {
  26873                     pkt_counter  = soc_mem_field32_get(unit, EGR_PW_INIT_COUNTERSm, 
  26874                                                    &pw_init_entry, PACKET_COUNTERf); 
  26875                     val_low = (pkt_counter - (pkt_counter/65536));
  26876                     COMPILER_64_SET(*val, 0, val_low);
  26877                 } else {
  26878                     return BCM_E_UNAVAIL;
  26879                 }
  26880                 break;
  26881             default:
  26882                 break;
  26883             }
  26884         }
  26885     }
  26886     return rv;
  26887 }
  26888 
  26889 int
  26890 bcm_tr_mpls_label_stat_get32(int unit, int sync_mode, 
  26891                              bcm_mpls_label_t label, bcm_gport_t port,
  26892                              bcm_mpls_stat_t stat, uint32 *val)
  26893 {
  26894     int rv;
  26895     uint64 val64;
  26896 
  26897 
  26898     rv = bcm_tr_mpls_label_stat_get(unit, sync_mode, label, 
  26899                                     port, stat, &val64);
  26900     if (rv == BCM_E_NONE) {
  26901         *val = COMPILER_64_LO(val64);
  26902     }
  26903     return rv;
  26904 }
  26905 
  26906 /*
  26907  * Function:
  26908  *      bcm_tr_mpls_label_stat_clear
  26909  * Purpose:
  26910  *      Clear L2 MPLS PW Stats
  26911  * Parameters:
  26912  *      unit   - (IN) SOC unit #
  26913  *      label  - (IN) MPLS label
  26914  *      port   - (IN) MPLS gport
  26915  *      stat   - (IN)  specify the Stat type
  26916  * Returns:
  26917  *      BCM_E_XXX
  26918  */     
  26919 
  26920 int
  26921 bcm_tr_mpls_label_stat_clear(int unit, bcm_mpls_label_t label, bcm_gport_t port,
  26922                              bcm_mpls_stat_t stat)
  26923 {
  26924     int rv=BCM_E_UNAVAIL, pw_term_cnt, pw_init_cnt, index;
  26925     bcm_mpls_tunnel_switch_t info;
  26926     mpls_entry_entry_t ment;
  26927     ing_pw_term_counters_entry_t cent;
  26928     egr_pw_init_counters_entry_t pw_init_entry;
  26929     egr_l3_next_hop_entry_t egr_nh;
  26930     ing_dvp_table_entry_t dvp;
  26931     int vp, nh_index;
  26932     uint32 num_pw_mask;
  26933 
  26934     /* Based on Switch Type */
  26935 #ifdef BCM_TRIUMPH2_SUPPORT
  26936     if (soc_feature(unit, soc_feature_gport_service_counters)) {
  26937         _bcm_flex_stat_handle_t mpls_fsh;
  26938         bcm_port_stat_t flex_stat=0;
  26939         uint64 flex_value;
  26940 
  26941         COMPILER_64_ZERO(flex_value);
  26942 
  26943         if (BCM_GPORT_IS_MPLS_PORT(port)) {
  26944             switch (stat) {
  26945             case bcmMplsInPkts:
  26946                 flex_stat = bcmPortStatIngressPackets;
  26947                 break;
  26948             case bcmMplsInBytes:
  26949                 flex_stat = bcmPortStatIngressBytes;
  26950                 break;
  26951             case bcmMplsOutPkts:
  26952                 flex_stat = bcmPortStatEgressPackets;
  26953                 break;
  26954             case bcmMplsOutBytes:
  26955                 flex_stat = bcmPortStatEgressBytes;
  26956                 break;
  26957             }
  26958 
  26959             COMPILER_64_ZERO(flex_value);
  26960             rv = bcm_esw_port_stat_set(unit, port, flex_stat, flex_value);
  26961         } else {
  26962             sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t));
  26963             info.port = port;
  26964             if (BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
  26965                 info.label = label;
  26966             } else {
  26967                 return BCM_E_PARAM;
  26968             }
  26969 
  26970             rv = _bcm_tr_mpls_entry_set_key(unit, &info, &ment);
  26971             BCM_IF_ERROR_RETURN(rv);
  26972 
  26973             _BCM_FLEX_STAT_HANDLE_CLEAR(mpls_fsh);
  26974             _BCM_FLEX_STAT_HANDLE_COPY(mpls_fsh, ment);
  26975 
  26976             rv =  _bcm_esw_flex_stat_ext_set(unit, _bcmFlexStatTypeMplsLabel,
  26977                                              mpls_fsh,
  26978                             _bcm_esw_mpls_label_stat_to_flex_stat(stat),
  26979                                              flex_value);
  26980         }
  26981     } else
  26982 #endif /* BCM_TRIUMPH2_SUPPORT */
  26983     if (SOC_IS_TR_VL(unit)) {
  26984 
  26985         if ((stat == bcmMplsInBytes) || (stat == bcmMplsInPkts)) {
  26986             sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t));
  26987             info.port = port;
  26988             if (BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
  26989                 info.label = label;
  26990             } else {
  26991                 return BCM_E_PARAM;
  26992             }
  26993 
  26994             rv = _bcm_tr_mpls_entry_set_key(unit, &info, &ment);
  26995             BCM_IF_ERROR_RETURN(rv);
  26996 
  26997             rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
  26998                                 &ment, &ment, 0);
  26999             if (rv == SOC_E_NONE) {
  27000                 if (!soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUM_VALIDf)) {
  27001                     return BCM_E_CONFIG;
  27002                 }
  27003 
  27004                 /* Retrieve PW_TERM Index from MPLS_Entry */
  27005                 pw_term_cnt = soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUMf);
  27006 
  27007                 /* Clear the Counter Value */
  27008                 sal_memset(&cent, 0, sizeof(ing_pw_term_counters_entry_t));
  27009                 rv = WRITE_ING_PW_TERM_COUNTERSm(unit, MEM_BLOCK_ANY, pw_term_cnt, &cent);
  27010                 if (rv < 0) {
  27011                     return rv;
  27012                 }
  27013             }
  27014         } else if ((stat == bcmMplsOutBytes) || (stat == bcmMplsOutPkts) ) {
  27015 
  27016             /* Get egress next-hop index from MPLS GPORT */
  27017             vp = BCM_GPORT_MPLS_PORT_ID_GET(port);
  27018             if (vp == -1) {
  27019                return BCM_E_PARAM;
  27020             }
  27021 
  27022             rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp);
  27023             if (rv < 0) {
  27024                 return rv;
  27025             }
  27026             nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 
  27027                                                       NEXT_HOP_INDEXf);
  27028      
  27029             /* Retrieve EGR L3 NHOP Entry */
  27030             BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  27031                                               nh_index, &egr_nh));
  27032 
  27033             /* Retrieve PW_INIT Index from EGR L3 NHOP Entry */
  27034             pw_init_cnt = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, PW_INIT_NUMf);
  27035 
  27036             num_pw_mask = soc_mem_index_count(0, EGR_PW_INIT_COUNTERSm) - 1;
  27037             pw_init_cnt &= num_pw_mask;
  27038 
  27039             /* Clear the Counter Value */
  27040             sal_memset(&pw_init_entry, 0, sizeof(egr_pw_init_counters_entry_t));
  27041             rv = WRITE_EGR_PW_INIT_COUNTERSm(unit, MEM_BLOCK_ANY, pw_init_cnt, &pw_init_entry);
  27042             if (rv < 0) {
  27043                 return rv;
  27044             }
  27045         }
  27046     }
  27047     return rv;
  27048 }
  27049 
  27050 /*
  27051  * Function:
  27052  *      bcm_tr_mpls_port_learn_set
  27053  * Purpose:
  27054  *      Set the CML bits for an mpls port.
  27055  * Returns:
  27056  *      BCM_E_XXX
  27057  */
  27058 int
  27059 bcm_tr_mpls_port_learn_set(int unit, bcm_gport_t mpls_port_id, uint32 flags)
  27060 {
  27061     int vp, cml = 0, rv = BCM_E_NONE;
  27062     source_vp_entry_t svp;
  27063 
  27064     rv = _bcm_tr_mpls_check_init (unit);
  27065     if (rv < 0) {
  27066         return rv;
  27067     }
  27068 
  27069     cml = 0;
  27070     if (!(flags & BCM_PORT_LEARN_FWD)) {
  27071        cml |= (1 << 0);
  27072     }
  27073     if (flags & BCM_PORT_LEARN_CPU) {
  27074        cml |= (1 << 1);
  27075     }
  27076     if (flags & BCM_PORT_LEARN_PENDING) {
  27077        cml |= (1 << 2);
  27078     }
  27079     if (flags & BCM_PORT_LEARN_ARL) {
  27080        cml |= (1 << 3);
  27081     }
  27082 
  27083     /* Get the VP index from the gport */
  27084     vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port_id);
  27085     if (vp == -1) {
  27086         return BCM_E_PARAM;
  27087     }
  27088 
  27089     /* Be sure the entry is used and is set for VPLS */
  27090     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  27091         return BCM_E_NOT_FOUND;
  27092     }
  27093     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
  27094     if (rv < 0) {
  27095         return rv;
  27096     }
  27097     if (soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) != 1) { /* VPLS */
  27098         return BCM_E_NOT_FOUND;
  27099     }
  27100     soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml);
  27101     soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml);
  27102     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
  27103     return rv;
  27104 }
  27105 
  27106 /*
  27107  * Function:    
  27108  *      bcm_tr_mpls_port_learn_get
  27109  * Purpose:
  27110  *      Get the CML bits for an mpls port
  27111  * Returns: 
  27112  *      BCM_E_XXX
  27113  */     
  27114 int     
  27115 bcm_tr_mpls_port_learn_get(int unit, bcm_gport_t mpls_port_id, uint32 *flags)
  27116 {
  27117     int rv, vp, cml = 0;
  27118     source_vp_entry_t svp;
  27119     
  27120     rv = _bcm_tr_mpls_check_init (unit);
  27121     if (rv < 0) {
  27122         return rv;
  27123     }
  27124     
  27125     /* Get the VP index from the gport */
  27126     vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port_id);
  27127     if (vp == -1) {
  27128        return BCM_E_PARAM;
  27129     }
  27130 
  27131     /* Be sure the entry is used and is set for VPLS */
  27132     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  27133         return BCM_E_NOT_FOUND;
  27134     }
  27135     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
  27136     if (rv < 0) {
  27137         return rv;
  27138     }
  27139     if (soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) != 1) { /* VPLS */
  27140         return BCM_E_NOT_FOUND;
  27141     }
  27142     cml = soc_SOURCE_VPm_field32_get(unit, &svp, CML_FLAGS_NEWf);
  27143     
  27144     *flags = 0;
  27145     if (!(cml & (1 << 0))) {
  27146        *flags |= BCM_PORT_LEARN_FWD;
  27147     }
  27148     if (cml & (1 << 1)) {
  27149        *flags |= BCM_PORT_LEARN_CPU;
  27150     }
  27151     if (cml & (1 << 2)) {
  27152        *flags |= BCM_PORT_LEARN_PENDING;
  27153     }
  27154     if (cml & (1 << 3)) {
  27155        *flags |= BCM_PORT_LEARN_ARL;
  27156     }
  27157     return BCM_E_NONE;
  27158 }
  27159 
  27160 /*
  27161  * Function:
  27162  *      bcm_tr_mpls_mcast_flood_set
  27163  * Purpose:
  27164  *      Set the PFM for a VPLS VFI.
  27165  * Returns:
  27166  *      BCM_E_XXX
  27167  */
  27168 int
  27169 bcm_tr_mpls_mcast_flood_set(int unit, bcm_vlan_t vlan,
  27170                             bcm_vlan_mcast_flood_t mode)
  27171 {
  27172     int vfi, pfm = 0, rv = BCM_E_NONE;
  27173 
  27174     rv = _bcm_tr_mpls_check_init (unit);
  27175     if (rv < 0) {
  27176         return rv;
  27177     }
  27178 
  27179     _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vlan);
  27180 
  27181     switch (mode) {
  27182     case BCM_VLAN_MCAST_FLOOD_ALL:
  27183         pfm = 0;
  27184         break;
  27185     case BCM_VLAN_MCAST_FLOOD_NONE:
  27186         pfm = 2;
  27187         break;
  27188     default:
  27189         pfm = 1;
  27190         break;
  27191     }
  27192 
  27193     if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
  27194         return BCM_E_NOT_FOUND;
  27195     }
  27196     /* Update the HW entry */
  27197     rv = soc_mem_field32_modify(unit, VFIm, vfi, PFMf, pfm);
  27198     return rv;
  27199 }
  27200 
  27201 /*
  27202  * Function:
  27203  *      bcm_tr_mpls_mcast_flood_get
  27204  * Purpose:
  27205  *      Get the PFM for a VPLS VFI.
  27206  * Returns: 
  27207  *      BCM_E_XXX
  27208  */     
  27209 int
  27210 bcm_tr_mpls_mcast_flood_get(int unit, bcm_vlan_t vlan,
  27211                             bcm_vlan_mcast_flood_t *mode)
  27212 {
  27213     int vfi, pfm = 0, rv = BCM_E_NONE;
  27214     vfi_entry_t vfi_entry;
  27215 
  27216     rv = _bcm_tr_mpls_check_init (unit);
  27217     if (rv < 0) {
  27218         return rv;
  27219     }
  27220 
  27221     _BCM_MPLS_VPN_GET(vfi, _BCM_MPLS_VPN_TYPE_VPLS, vlan);
  27222 
  27223     if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeMpls)) {
  27224         return BCM_E_NOT_FOUND;
  27225     }
  27226     rv = READ_VFIm(unit, MEM_BLOCK_ANY, vfi, &vfi_entry);
  27227     if (rv < 0) {
  27228         return rv;
  27229     }
  27230     pfm = soc_VFIm_field32_get(unit, &vfi_entry, PFMf);
  27231 
  27232     switch (pfm) {
  27233     case 0:
  27234         *mode = BCM_VLAN_MCAST_FLOOD_ALL;
  27235         break;
  27236     case 2:
  27237         *mode = BCM_VLAN_MCAST_FLOOD_NONE;
  27238         break;
  27239     default:
  27240         *mode = BCM_VLAN_MCAST_FLOOD_UNKNOWN;
  27241         break;
  27242     }
  27243     return rv;
  27244 }
  27245 
  27246 /*
  27247  * Function:
  27248  *      bcm_tr_mpls_port_phys_gport_get
  27249  * Purpose:
  27250  *      Get the PFM for a VPLS VFI.
  27251  * Returns: 
  27252  *      BCM_E_XXX
  27253  */     
  27254 
  27255 int 
  27256 bcm_tr_mpls_port_phys_gport_get(int unit, int vp, bcm_gport_t *gp)
  27257 {
  27258     int nh_index;
  27259     ing_dvp_table_entry_t dvp;
  27260     ing_l3_next_hop_entry_t ing_nh;
  27261     bcm_module_t mod_out, mod_in;
  27262     bcm_port_t port_out, port_in;
  27263     bcm_trunk_t trunk_id;
  27264     uint32 dt, dv;
  27265 
  27266     BCM_IF_ERROR_RETURN(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
  27267     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
  27268     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
  27269                                      nh_index, &ing_nh));
  27270 
  27271     if (soc_feature(unit, soc_feature_generic_dest)) {
  27272         dv = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm,
  27273                 &ing_nh, DESTINATIONf, &dt);
  27274         if (dt == SOC_MEM_FIF_DEST_LAG) {
  27275             /* Trunk group */
  27276             trunk_id = dv & SOC_MEM_FIF_DGPP_TGID_MASK;
  27277             BCM_GPORT_TRUNK_SET(*gp, trunk_id);
  27278 
  27279         } else {
  27280             port_in = dv & SOC_MEM_FIF_DGPP_PORT_MASK;
  27281             mod_in = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
  27282                 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
  27283 
  27284             BCM_IF_ERROR_RETURN
  27285                 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_in, port_in,
  27286                                          &mod_out, &port_out));
  27287             BCM_GPORT_MODPORT_SET(*gp, mod_out, port_out);
  27288         }
  27289     } else {
  27290     if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
  27291         trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf);
  27292         BCM_GPORT_TRUNK_SET(*gp, trunk_id);
  27293     } else {
  27294         mod_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
  27295         port_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf);
  27296         BCM_IF_ERROR_RETURN
  27297             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_in, port_in, 
  27298                                     &mod_out, &port_out));
  27299         BCM_GPORT_MODPORT_SET(*gp, mod_out, port_out);
  27300     }
  27301     }
  27302     return BCM_E_NONE;
  27303 }
  27304 
  27305 #ifndef BCM_SW_STATE_DUMP_DISABLE
  27306 /*
  27307  * Function:
  27308  *     _bcm_mpls_sw_dump
  27309  * Purpose:
  27310  *     Displays MPLS State information maintained by software.
  27311  * Parameters:
  27312  *     unit - Device unit number
  27313  * Returns:
  27314  *     None
  27315  */
  27316 void
  27317 _bcm_mpls_sw_dump(int unit)
  27318 {
  27319     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
  27320     int i, num_vp = 0, num_vc = 0, num_tnl = 0, num_trunk = 0;
  27321 #ifdef BCM_KATANA_SUPPORT
  27322     int num_queue = 0;
  27323 #endif /* BCM_KATANA_SUPPORT */
  27324     soc_mem_t mem = 0;
  27325 
  27326     if (!mpls_info->initialized) {
  27327         LOG_CLI((BSL_META_U(unit,
  27328                             "\nMPLS data structure is not initialized\n")));
  27329         return;
  27330     }
  27331 
  27332     LOG_CLI((BSL_META_U(unit,
  27333                         "\nSW Information MPLS - Unit %d\n"), unit));
  27334 
  27335     if (SOC_MEM_IS_VALID(unit, SOURCE_VPm)) {
  27336         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  27337     }
  27338 
  27339     LOG_CLI((BSL_META_U(unit,
  27340                         "\n  Match Info    : \n")));
  27341     for (i = 0; i < num_vp; i++) {
  27342         if ((mpls_info->match_key[i].trunk_id == -1) && 
  27343             (mpls_info->match_key[i].modid == -1) &&
  27344             (mpls_info->match_key[i].port == 0)) {
  27345             continue;
  27346         }
  27347         LOG_CLI((BSL_META_U(unit,
  27348                             "\n  MPLS port vp = %d\n"), i));
  27349         LOG_CLI((BSL_META_U(unit,
  27350                             "Flags = %x\n"), mpls_info->match_key[i].flags));
  27351         LOG_CLI((BSL_META_U(unit,
  27352                             "Index = %x\n"), mpls_info->match_key[i].index));
  27353         LOG_CLI((BSL_META_U(unit,
  27354                             "TGID = %d\n"), mpls_info->match_key[i].trunk_id));
  27355         LOG_CLI((BSL_META_U(unit,
  27356                             "Modid = %d\n"), mpls_info->match_key[i].modid));
  27357         LOG_CLI((BSL_META_U(unit,
  27358                             "Port = %d\n"), mpls_info->match_key[i].port));
  27359         LOG_CLI((BSL_META_U(unit,
  27360                             "Match VLAN = %d\n"), 
  27361                  mpls_info->match_key[i].match_vlan));
  27362         LOG_CLI((BSL_META_U(unit,
  27363                             "Match Inner VLAN = %d\n"), 
  27364                  mpls_info->match_key[i].match_inner_vlan));
  27365         LOG_CLI((BSL_META_U(unit,
  27366                             "Match Label = %d\n"), 
  27367                  mpls_info->match_key[i].match_label));
  27368         LOG_CLI((BSL_META_U(unit,
  27369                             "Match Count = %d\n"),
  27370                  mpls_info->match_key[i].match_count));
  27371     }
  27372     
  27373     if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) {
  27374         num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
  27375     }
  27376     for (i = 0; i < num_vc; i++) {
  27377         if (mpls_info->vc_swap_ref_count[i]) {
  27378               LOG_CLI((BSL_META_U(unit,
  27379                                   "Label = %d  RefCount=%d\n"), 
  27380                        i, mpls_info->vc_swap_ref_count[i]));
  27381         }
  27382     }
  27383 
  27384     /* VPWS VPs to VPN mapping */
  27385     
  27386     LOG_CLI((BSL_META_U(unit,
  27387                         "\nVPN to VPWS VP mapping:\n")));
  27388     LOG_CLI((BSL_META_U(unit,
  27389                         "-----------------------\n")));
  27390     LOG_CLI((BSL_META_U(unit,
  27391                         "VPN      VPWS VPs\n")));
  27392     for (i=0; i<(num_vp/2); i++) {
  27393         if (mpls_info->vpws_vp_map[i].vp1 != -1 &&
  27394             mpls_info->vpws_vp_map[i].vp2 != -1) {
  27395             LOG_CLI((BSL_META_U(unit,
  27396                                 "%d     %d & %d\n"),(0x2000+i), 
  27397                      mpls_info->vpws_vp_map[i].vp1,
  27398                      mpls_info->vpws_vp_map[i].vp2));
  27399         }
  27400     }
  27401 #if defined(BCM_TRIDENT3_SUPPORT)
  27402     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
  27403         mem = EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm;
  27404     } else
  27405 #endif
  27406     {
  27407         mem = EGR_IP_TUNNEL_MPLSm;
  27408     }
  27409     num_tnl = soc_mem_index_count(unit, mem);
  27410     for (i = 0; i < num_tnl * _BCM_MPLS_NUM_MPLS_ENTRIES_PER_INDEX(unit); i++) {
  27411         if (mpls_info->egr_tunnel_ref_count[i]) {
  27412               LOG_CLI((BSL_META_U(unit,
  27413                                   "Egress MPLS Tunnel = %d  RefCount=%d\n"), 
  27414                        i, mpls_info->egr_tunnel_ref_count[i]));
  27415         }
  27416     }
  27417 
  27418     /* Print VP - NH mapping */
  27419     LOG_CLI((BSL_META_U(unit,
  27420                         "\n VP to NH mapping:\n")));
  27421     LOG_CLI((BSL_META_U(unit,
  27422                         "-----------------------\n")));
  27423     _bcm_tr_mpls_dump_egrNhop(unit);
  27424     LOG_CLI((BSL_META_U(unit,
  27425                         "\n")));
  27426 #ifdef BCM_KATANA_SUPPORT
  27427     if (soc_feature(unit, soc_feature_extended_queueing)) {
  27428         num_queue = soc_mem_index_count(unit, ING_QUEUE_MAPm);
  27429         LOG_CLI((BSL_META_U(unit,"\n Ingress Queue map reference count:\n")));
  27430         LOG_CLI((BSL_META_U(unit,"-----------------------\n")));
  27431         for (i = 0; i < num_queue; i++) {
  27432             if (mpls_info->ing_qmap_ref_count[i]) {
  27433                   LOG_CLI((BSL_META_U(unit,
  27434                                "\n Ingress Queue Map Index = %d  RefCount=%d\n"),
  27435                                       i, mpls_info->ing_qmap_ref_count[i]));
  27436             }
  27437         }
  27438     }
  27439 #endif /* BCM_KATANA_SUPPORT */
  27440 
  27441     /* Trunk to VP mapping */
  27442     if (SOC_MEM_IS_VALID(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm)) {
  27443         num_trunk = soc_mem_index_count(unit, TRUNK_GROUPm);
  27444     }
  27445 
  27446     LOG_CLI((BSL_META_U(unit,
  27447                         "\nTrunk to VP mapping:\n")));
  27448     LOG_CLI((BSL_META_U(unit,
  27449                         "-----------------------\n")));
  27450     LOG_CLI((BSL_META_U(unit,
  27451                         "TRUNK      VP\n")));
  27452     for (i = 0; i < num_trunk; i++) {
  27453         if (mpls_info->trunk_vp_map[i] != -1) {
  27454             LOG_CLI((BSL_META_U(unit,
  27455                                 "%d     %d\n"),
  27456                     i, mpls_info->trunk_vp_map[i]));
  27457         }
  27458     }
  27459 #ifdef BCM_SPECIAL_LABEL_SUPPORT
  27460             if (soc_feature(unit, soc_feature_mpls_special_label)) {
  27461                 int num_entry = 0;
  27462                 bcmi_mpls_special_label_control_t *ptr;
  27463 
  27464                 ptr = bcmi_special_label_precedence_state[unit];
  27465                 num_entry =
  27466                         soc_mem_index_count(unit, SPECIAL_LABEL_CONTROLm);
  27467                 for (i = 0; i < num_entry; i++) {
  27468                     if (ptr[i].valid) {
  27469                         LOG_CLI((BSL_META_U(unit,"Index = %d : Label Value = 0x%x    Label Mask= 0x%x   Label Type = %s  ref_count= %d\n"),
  27470                            i, ptr[i].label_value, ptr[i].label_mask, label_type_array[ptr[i].label_type], ptr[i].ref_count));
  27471                     }
  27472                 }
  27473             }
  27474 #endif
  27475 
  27476 #if defined BCM_TRIUMPH2_SUPPORT
  27477     if (soc_feature(unit, soc_feature_mpls_failover)) { 
  27478     for (i = 0; i < num_vp; i++) {
  27479         if (mpls_info->failover_vp[i] == 0) {
  27480             continue;
  27481         }
  27482         LOG_CLI((BSL_META_U(unit,
  27483                             "\n  MPLS vp %d failover vp = %d\n"), i, 
  27484                             mpls_info->failover_vp[i]));
  27485     }
  27486     }
  27487 #endif
  27488     return;
  27489 }
  27490 #endif /* BCM_SW_STATE_DUMP_DISABLE */
  27491 
  27492 
  27493 #ifdef BCM_TRIUMPH2_SUPPORT
  27494 int
  27495 _bcm_esw_mpls_flex_stat_index_set(int unit, bcm_gport_t port, int fs_idx,uint32 flags)
  27496 {
  27497     int rv, vp, nh_index=0;
  27498     source_vp_entry_t svp;
  27499     ing_dvp_table_entry_t dvp;
  27500     egr_l3_next_hop_entry_t egr_nh;
  27501     uint32 entry_type=0;
  27502     initial_prot_nhi_table_entry_t prot_entry;
  27503     int vpless_failover_port = FALSE;
  27504 
  27505     if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(port)) {
  27506         vpless_failover_port = TRUE;
  27507         port = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(port);
  27508     }
  27509 
  27510     vp = BCM_GPORT_MPLS_PORT_ID_GET(port);
  27511     if (vp == -1) {
  27512         return BCM_E_PARAM;
  27513     }
  27514 
  27515     rv = bcm_tr_mpls_lock(unit);
  27516     if (BCM_FAILURE(rv)) {
  27517         return rv;
  27518     }
  27519     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  27520         bcm_tr_mpls_unlock(unit);
  27521         return BCM_E_NOT_FOUND;
  27522     } else {
  27523         /* Ingress side */
  27524         if (flags & _BCM_FLEX_STAT_HW_INGRESS) {
  27525             rv = soc_mem_read(unit, SOURCE_VPm, MEM_BLOCK_ANY, vp, &svp);
  27526             if (BCM_SUCCESS(rv)) {
  27527                 if (soc_mem_field_valid(unit, SOURCE_VPm, USE_VINTF_CTR_IDXf)) {
  27528                     soc_mem_field32_set(unit, SOURCE_VPm, &svp, USE_VINTF_CTR_IDXf,
  27529                                         fs_idx > 0 ? 1 : 0);
  27530                 }
  27531                 soc_mem_field32_set(unit, SOURCE_VPm, &svp, VINTF_CTR_IDXf,
  27532                                     fs_idx);
  27533                 rv = soc_mem_write(unit, SOURCE_VPm, MEM_BLOCK_ALL, vp, &svp);
  27534             }
  27535         }
  27536         /* Egress side */
  27537         if (flags & _BCM_FLEX_STAT_HW_EGRESS) {
  27538             if (BCM_SUCCESS(rv)) {
  27539                 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp);
  27540                 if (BCM_SUCCESS(rv)) {
  27541                     nh_index = soc_mem_field32_get(unit, ING_DVP_TABLEm, &dvp,
  27542                                                    NEXT_HOP_INDEXf);
  27543                     if (vpless_failover_port == TRUE) {
  27544                         rv = READ_INITIAL_PROT_NHI_TABLEm(unit,MEM_BLOCK_ANY, nh_index, &prot_entry);
  27545                         if (BCM_SUCCESS(rv)) {
  27546                             nh_index = soc_INITIAL_PROT_NHI_TABLEm_field32_get(unit,&prot_entry,
  27547                                        PROT_NEXT_HOP_INDEXf);
  27548                         }
  27549                     }
  27550                 }
  27551             }
  27552             if (BCM_SUCCESS(rv)) {
  27553                 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, nh_index,
  27554                                   &egr_nh);
  27555             }
  27556             if (BCM_SUCCESS(rv)) {
  27557                 entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, ENTRY_TYPEf);
  27558                 if(entry_type == 1) {
  27559                      if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
  27560                                     MPLS__USE_VINTF_CTR_IDXf)) {
  27561                             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  27562                                     MPLS__USE_VINTF_CTR_IDXf,
  27563                                     fs_idx > 0 ? 1 : 0);
  27564                      }
  27565                      soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  27566                                     MPLS__VINTF_CTR_IDXf, fs_idx);
  27567                   } else if (entry_type == 2) {
  27568                      if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
  27569                                     SD_TAG__USE_VINTF_CTR_IDXf)) {
  27570                             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  27571                                     SD_TAG__USE_VINTF_CTR_IDXf,
  27572                                     fs_idx > 0 ? 1 : 0);
  27573                      }
  27574                      soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
  27575                                     SD_TAG__VINTF_CTR_IDXf, fs_idx);
  27576                 }
  27577                 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, nh_index,
  27578                                      &egr_nh);
  27579             }
  27580         }
  27581     }
  27582 
  27583     bcm_tr_mpls_unlock(unit);
  27584     return rv;
  27585 }
  27586 
  27587 int
  27588 _bcm_tr2_mpls_svp_field_set(int unit, bcm_gport_t vp, 
  27589                            soc_field_t field, int value)
  27590 {
  27591     int rv = BCM_E_NONE;
  27592     source_vp_entry_t svp;
  27593 
  27594     rv = bcm_tr_mpls_lock(unit);
  27595     if (BCM_FAILURE(rv)) {
  27596         return rv;
  27597     }
  27598     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
  27599     if (rv < 0) {
  27600         bcm_tr_mpls_unlock(unit);
  27601         return rv;
  27602     }
  27603     if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, field)) {
  27604         soc_SOURCE_VPm_field32_set(unit, &svp, field, value);
  27605     } else {
  27606         bcm_tr_mpls_unlock(unit);
  27607         return BCM_E_UNAVAIL;
  27608     }
  27609     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
  27610     bcm_tr_mpls_unlock(unit);
  27611     return rv;
  27612 }
  27613 
  27614 #endif /* BCM_TRIUMPH2_SUPPORT */
  27615 
  27616 int _bcm_tr_mpls_vpws_egress_if_get(int unit, bcm_gport_t gport, bcm_if_t *egress_if)
  27617 {
  27618     int vp = -1;
  27619     uint32 nh_index;
  27620     ing_dvp_table_entry_t dvp;
  27621 
  27622     vp = BCM_GPORT_MPLS_PORT_ID_GET(gport);
  27623     if (vp == -1) {
  27624         return BCM_E_PARAM;
  27625     }
  27626 
  27627     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
  27628         return BCM_E_PARAM;
  27629     }
  27630     
  27631     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
  27632     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
  27633     *egress_if = nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
  27634 
  27635     return BCM_E_NONE;
  27636 }
  27637 
  27638 #if defined(BCM_TRIDENT3_SUPPORT)
  27639 /*
  27640  * Function:
  27641  *        bcm_td3_mpls_php_info_add
  27642  * Purpose:
  27643  *        Add VC_AND_SWAP_TABLE for a specific EGR_NH Index
  27644  * Parameters:
  27645  *           IN :  Unit
  27646  *           IN/OUT : Tunnel Switch Pointer
  27647  *           IN :  nh_index
  27648  * Returns:
  27649  *           BCM_E_XXX
  27650  */
  27651 
  27652 int
  27653 bcmi_td3_mpls_php_vcswap_info_add(int unit, bcm_mpls_tunnel_switch_t *php_info, int *nh_index)
  27654 {
  27655     bcm_l3_egress_t nh_info;
  27656     _bcm_tr_egr_nh_info_t egr_nh_info;
  27657     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
  27658     int rv = BCM_E_NONE, temp_nh_index = -1;
  27659     uint32 mpath_flag=0;
  27660     egr_nh_info.vc_swap_index = -1;
  27661 
  27662     /* 
  27663      * Get egress next-hop index from egress object and
  27664      * increment egress object reference count. 
  27665      */
  27666     if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, php_info->egress_if)) {
  27667         rv = bcm_xgs3_get_nh_from_egress_object(unit, php_info->egress_if,
  27668                 &mpath_flag, 1, &temp_nh_index);
  27669 
  27670         bcm_l3_egress_t_init(&nh_info);
  27671 
  27672         /* Get egress next-hop info from the egress object */
  27673         rv = bcm_xgs3_nh_get(unit, temp_nh_index, &nh_info);
  27674 
  27675         BCM_IF_ERROR_RETURN(rv);
  27676     }
  27677 
  27678     rv = _bcm_tr_mpls_get_vc_and_swap_table_index(unit, 0, NULL, php_info, NULL,
  27679             NULL, _BCM_MPLS_ACTION_PRESERVED, &egr_nh_info.vc_swap_index);
  27680 
  27681     BCM_IF_ERROR_RETURN(rv);
  27682 
  27683     /* Program the MPLS_VC_AND_SWAP table entry */
  27684     rv = _bcm_tr_mpls_vc_and_swap_table_entry_set(unit, NULL, php_info, NULL,
  27685             _BCM_MPLS_ACTION_PRESERVED,
  27686             &vc_entry, 0, egr_nh_info.vc_swap_index);
  27687     _BCM_MPLS_CLEANUP(rv);
  27688 
  27689     /* Write the entry into index, index is derived above successfully. */
  27690     rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
  27691             MEM_BLOCK_ALL, egr_nh_info.vc_swap_index,
  27692             &vc_entry);
  27693 
  27694     _BCM_MPLS_CLEANUP(rv);
  27695 
  27696     /* Write EGR_L3_NEXT_HOP entry */
  27697     rv = soc_mem_field32_modify(unit, EGR_L3_NEXT_HOPm, *nh_index,
  27698             MPLS__VC_AND_SWAP_INDEXf, egr_nh_info.vc_swap_index);
  27699    _BCM_MPLS_CLEANUP(rv);
  27700 
  27701 #if defined(BCM_TRIUMPH3_SUPPORT)
  27702     if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) {
  27703         rv = _bcm_tr_mpls_vc_and_swap_hash_nhop_add(unit,
  27704                 egr_nh_info.vc_swap_index,
  27705                 *nh_index);
  27706         _BCM_MPLS_CLEANUP(rv);
  27707     }
  27708 #endif
  27709 
  27710     return rv;
  27711 
  27712 cleanup:
  27713     if (egr_nh_info.vc_swap_index >= 0) {
  27714         _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, 
  27715                 egr_nh_info.vc_swap_index, -1);
  27716         /* Free VC_AND_SWAP_LABEL entry */
  27717         (void)_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, 
  27718                 egr_nh_info.vc_swap_index);
  27719     }
  27720     return rv;
  27721 }
  27722 
  27723 
  27724 /*
  27725  * Function:
  27726  *       bcmi_td3_mpls_php_vcswap_info_delete 
  27727  * Purpose:
  27728  *        Delete  VC_AND_SWAP_TABLE for a specific EGR_NH Index
  27729  * Parameters:
  27730  *           IN :  Unit
  27731  *           IN :  nh_index
  27732  * Returns:
  27733  *           BCM_E_XXX
  27734  */
  27735 
  27736 int
  27737 bcmi_td3_mpls_php_vcswap_info_delete(int unit, int nh_index,int type)
  27738 {
  27739     int rv = BCM_E_NONE, old_vc_swap_idx = -1;
  27740     egr_l3_next_hop_entry_t egr_nh;
  27741 
  27742     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 
  27743                                       MEM_BLOCK_ANY, nh_index, &egr_nh));
  27744 
  27745     if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, nh_entry_type_field[unit]) != 0x1) {
  27746         return BCM_E_NOT_FOUND;
  27747     }
  27748 
  27749     if (soc_feature(unit, soc_feature_mpls_enhanced)) {
  27750          old_vc_swap_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
  27751                                                        MPLS__VC_AND_SWAP_INDEXf);
  27752     } 
  27753 
  27754     /* Clear VC_SWAP_INDEX in EGR_L3_NEXT_HOP entry */
  27755     if (old_vc_swap_idx != -1) {
  27756         int vc_and_swap_ref_count = 0;
  27757         int nh_ref_count = BCM_XGS3_L3_ENT_REF_CNT(BCM_XGS3_L3_TBL_PTR(unit, next_hop), nh_index);
  27758 
  27759         _bcm_tr_mpls_vc_and_swap_ref_count_get(unit, old_vc_swap_idx, &vc_and_swap_ref_count);
  27760         if ((nh_ref_count <= 3) ||  (vc_and_swap_ref_count <= 1)) {
  27761             rv = soc_mem_field32_modify(unit, EGR_L3_NEXT_HOPm, nh_index,
  27762                                         MPLS__VC_AND_SWAP_INDEXf, 0);
  27763     }
  27764 
  27765 #if defined(BCM_TRIUMPH3_SUPPORT)
  27766         if (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid)) {
  27767             BCM_IF_ERROR_RETURN(
  27768                     _bcm_tr_mpls_vc_and_swap_hash_nhop_delete(unit,
  27769                         old_vc_swap_idx,
  27770                         nh_index));
  27771         }
  27772 #endif
  27773 
  27774         /* clear VC_AND_SWAP_LABEL entry */
  27775         _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, old_vc_swap_idx, -1);
  27776 
  27777         /* Free VC_AND_SWAP_LABEL entry */
  27778         BCM_IF_ERROR_RETURN
  27779             (_bcm_tr_mpls_vc_and_swap_table_index_reset (unit, old_vc_swap_idx));
  27780     }
  27781 
  27782     return rv;
  27783 }
  27784 
  27785 #endif
  27786 #else /* BCM_TRIUMPH_SUPPORT && BCM_MPLS_SUPPORT && INCLUDE_L3 */
  27787 int bcm_tr_mpls_not_empty;
  27788 #endif /* BCM_TRIUMPH_SUPPORT && BCM_MPLS_SUPPORT && INCLUDE_L3 */