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


      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: Katana MPLS enhancements
      9  */
     10 #include <soc/defs.h>
     11 
     12 #include <assert.h>
     13 #include <shared/bsl.h>
     14 #include <sal/core/libc.h>
     15 #if defined(BCM_KATANA_SUPPORT) && defined(BCM_MPLS_SUPPORT) && \
     16     defined(INCLUDE_L3)
     17 
     18 #include <shared/util.h>
     19 #include <soc/mem.h>
     20 #include <soc/cm.h>
     21 #include <soc/drv.h>
     22 #include <soc/register.h>
     23 #include <soc/memory.h>
     24 #include <bcm/qos.h>
     25 #include <bcm/error.h>
     26 #include <bcm_int/esw/triumph2.h>
     27 #include <bcm_int/esw/triumph3.h>
     28 #include <bcm_int/esw/triumph.h>
     29 #include <bcm_int/esw/port.h>
     30 #include <bcm_int/esw/firebolt.h>
     31 #include <bcm_int/esw/trx.h>
     32 #include <bcm_int/esw/virtual.h>
     33 #include <bcm_int/esw/xgs3.h>
     34 #include <bcm_int/esw_dispatch.h> 
     35 #include <bcm_int/esw/switch.h>
     36 #include <bcm_int/esw/mpls.h>
     37 #include <bcm_int/esw/katana.h>
     38 #include <bcm_int/esw/flex_ctr.h>
     39 #include <bcm_int/esw/multicast.h>
     40 #include <bcm_int/common/multicast.h>
     41 
     42 
     43  /*
     44   * Function:
     45   * 	 _bcm_kt_mpls_p2mp_loopback_enable
     46   * Purpose:
     47   * 	 Enable loopback for MPLS P2MP
     48   * Parameters:
     49   *   IN : unit
     50   * Returns:
     51   * 	 BCM_E_XXX
     52   */
     53  
     54 STATIC int
     55 _bcm_kt_mpls_p2mp_loopback_enable(int unit)
     56 {
     57     int rv = BCM_E_NONE;
     58     multipass_loopback_bitmap_entry_t  p2mp_loopback;
     59     soc_field_t lport_fields[] = {
     60 #ifndef  BCM_KATANA2_SUPPORT
     61         PORT_TYPEf,
     62 #endif
     63         MPLS_ENABLEf,
     64         V4L3_ENABLEf,
     65         V6L3_ENABLEf
     66     };
     67     uint32 lport_values[] = {
     68 #ifndef  BCM_KATANA2_SUPPORT
     69         0x2,
     70 #endif
     71         0x1,  /* MPLS_ENABLEf */
     72         0x1,  /* V4L3_ENABLEf */
     73         0x1   /* V6L3_ENABLEf */
     74     };
     75 
     76     if (SOC_IS_KATANA(unit)) {
     77         sal_memset(&p2mp_loopback, 0,
     78                 sizeof(multipass_loopback_bitmap_entry_t));
     79 
     80         /* Enable Loopback */
     81         soc_mem_field32_set(unit, MULTIPASS_LOOPBACK_BITMAPm,
     82                 &p2mp_loopback, BITMAP_W1f, 0x8);
     83         rv = soc_mem_write(unit, MULTIPASS_LOOPBACK_BITMAPm,
     84                 MEM_BLOCK_ALL, 0, &p2mp_loopback);
     85         if (rv < 0) {
     86             return rv;
     87         }
     88     }
     89 
     90     /* Update LPORT Profile Table */
     91     rv = _bcm_lport_profile_fields32_modify(unit, LPORT_PROFILE_LPORT_TAB,
     92             COUNTOF(lport_fields),
     93             lport_fields, lport_values);
     94 
     95     return rv;
     96 }
     97 
     98  /*
     99   * Function:
    100   * 	 _bcm_kt_mpls_p2mp_loopback_disable
    101   * Purpose:
    102   * 	 Disable loopback for MPLS P2MP
    103   * Parameters:
    104   *   IN : unit
    105   * Returns:
    106   * 	 BCM_E_XXX
    107   */
    108  
    109 STATIC int
    110 _bcm_kt_mpls_p2mp_loopback_disable(int unit)
    111 {
    112     int rv = BCM_E_NONE;
    113     multipass_loopback_bitmap_entry_t  p2mp_loopback;
    114     soc_field_t lport_fields[] = {
    115 #ifndef  BCM_KATANA2_SUPPORT
    116         PORT_TYPEf,
    117 #endif
    118         MPLS_ENABLEf,
    119         V4L3_ENABLEf,
    120         V6L3_ENABLEf
    121     };
    122     uint32 lport_values[] = {
    123 #ifndef  BCM_KATANA2_SUPPORT
    124         0x0,  /* PORT_TYPEf */
    125 #endif
    126         0x0,  /* MPLS_ENABLEf */
    127         0x0,  /* V4L3_ENABLEf */
    128         0x0   /* V6L3_ENABLEf */
    129     };
    130 
    131     if (SOC_IS_KATANA(unit)) {
    132         sal_memset(&p2mp_loopback, 0,
    133                 sizeof(multipass_loopback_bitmap_entry_t));
    134 
    135         /* Disable Loopback */
    136         soc_mem_field32_set(unit, MULTIPASS_LOOPBACK_BITMAPm,
    137                 &p2mp_loopback, BITMAP_W1f, 0x0);
    138         rv = soc_mem_write(unit, MULTIPASS_LOOPBACK_BITMAPm,
    139                 MEM_BLOCK_ALL, 0, &p2mp_loopback);
    140         if (rv < 0) {
    141             return rv;
    142         }
    143     }
    144 
    145     /* Update LPORT Profile Table */
    146     rv = _bcm_lport_profile_fields32_modify(unit, LPORT_PROFILE_LPORT_TAB,
    147             COUNTOF(lport_fields),
    148             lport_fields, lport_values);
    149 
    150     return rv;
    151 }
    152 
    153 
    154 /*
    155  * Function:
    156  *      _bcm_kt_mpls_entry_delete
    157  * Purpose:
    158  *      Delete entry from MPLS_ENTRY table
    159  * Parameters:
    160  *      unit - Device Number
    161  *      ment - MPLS Label entry to delete
    162  * Returns:
    163  *      BCM_E_XXX
    164  */
    165 
    166 STATIC int
    167 _bcm_kt_mpls_entry_delete(int unit, mpls_entry_entry_t *ment, 
    168                                                        bcm_mpls_tunnel_switch_t *info, int index)
    169 {   
    170     ing_pw_term_counters_entry_t pw_cnt_entry;
    171     int rv, action, ecmp_index = -1, nh_index = -1, pw_cnt = -1;
    172     bcm_if_t  egress_if=0;
    173     int  ref_count=0, forwarding_field_type=-1, ipmc_index=-1;
    174     int two_pass=-1, l3_iif=-1, is_set=0;
    175 
    176     if (soc_MPLS_ENTRYm_field32_get(unit, ment, PW_TERM_NUM_VALIDf)) {
    177         pw_cnt = soc_MPLS_ENTRYm_field32_get(unit, ment, PW_TERM_NUMf);
    178     }
    179 
    180     action = soc_MPLS_ENTRYm_field32_get(unit, ment, 
    181                                                       MPLS_ACTION_IF_BOSf);
    182     forwarding_field_type =  soc_MPLS_ENTRYm_field32_get(unit, ment,  
    183                                                       FORWARDING_FIELD_TYPEf);
    184 
    185     if (forwarding_field_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) {
    186         ipmc_index = soc_MPLS_ENTRYm_field32_get(unit, ment, 
    187                                                       FORWARDING_FIELDf);
    188         two_pass = soc_MPLS_ENTRYm_field32_get(unit, ment, 
    189                                                       MPLS_SECOND_PASS_ACTION_VALIDf);
    190         rv = bcm_xgs3_ipmc_id_is_set(unit, ipmc_index, &is_set);
    191         if (BCM_SUCCESS(rv)) {
    192             if (is_set) {
    193                /* First Delete IPMC_entry, then delete P2MP Label entry */
    194                return BCM_E_BUSY;
    195             }
    196         }
    197         if ((two_pass) && (info->action != -1)) {
    198             if (info->action == BCM_MPLS_SWITCH_ACTION_PHP) {
    199                    l3_iif = soc_MPLS_ENTRYm_field32_get(unit, ment, 
    200                                                       L3_IIF_2f);
    201                    soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf,
    202                                 0x0); /* INVALID */
    203                     soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf,
    204                                 0x2); /* L3_IIF */
    205                  soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIFf,
    206                                 l3_iif);
    207             }
    208             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_VALIDf,
    209                                 0x0);
    210             (void) _bcm_kt_mpls_p2mp_loopback_disable(unit);
    211             BCM_IF_ERROR_RETURN(rv);
    212 
    213             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_BOSf,
    214                                 0x0); 
    215             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_NOT_BOSf,
    216                                 0x0);
    217             soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIF_2f,
    218                                 0x0);
    219             rv = soc_mem_write(unit, MPLS_ENTRYm,
    220                            MEM_BLOCK_ALL, index,
    221                            ment);
    222             return rv;
    223         }
    224     } else if (forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) {
    225         /* SWAP_NHI or L3_NHI */
    226         nh_index = soc_MPLS_ENTRYm_field32_get(unit, ment, NEXT_HOP_INDEXf);
    227     } else if (forwarding_field_type == _BCM_MPLS_FORWARD_ECMP_GROUP) {
    228         /* L3_ECMP */
    229         ecmp_index = soc_MPLS_ENTRYm_field32_get(unit, ment, ECMP_PTRf);
    230     }
    231         
    232     /* Delete the entry from HW */
    233     rv = soc_mem_delete(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, ment);
    234     if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) {
    235          return rv;
    236     }
    237 
    238     if (pw_cnt != -1) {
    239         sal_memset(&pw_cnt_entry, 0, sizeof(ing_pw_term_counters_entry_t));
    240         (void) WRITE_ING_PW_TERM_COUNTERSm(unit, MEM_BLOCK_ALL, pw_cnt,
    241                                            &pw_cnt_entry);
    242         (void) bcm_tr_mpls_pw_used_clear(unit, pw_cnt);
    243     }
    244 
    245     if (forwarding_field_type != _BCM_MPLS_FORWARD_MULTICAST_GROUP) {
    246         if ((forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) && (action == 0x3)) {
    247             /* SWAP_NHI */
    248             /* Check if tunnel_switch.egress_label mode is being used */
    249             rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) nh_index, &egress_if);
    250             if (rv == BCM_E_NONE) {
    251                 rv = bcm_tr_mpls_l3_nh_info_delete(unit, nh_index);
    252             } else {
    253                 /* Decrement next-hop Reference count */
    254                 rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, nh_index);
    255             }
    256         } else if ((forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) && (action == 0x4)) {
    257             /* L3_NHI */
    258             rv = bcm_xgs3_nh_del(unit, 0, nh_index);
    259         } else if (forwarding_field_type == _BCM_MPLS_FORWARD_ECMP_GROUP) {
    260             /* L3_ECMP */
    261             rv = bcm_xgs3_ecmp_group_del(unit, ecmp_index, 0);
    262         }
    263     }
    264     return rv;
    265 }
    266 
    267 /*
    268  * Function:
    269  *      _bcm_kt_mpls_entry_set_key
    270  * Purpose:
    271  *      Convert key part of application format to HW entry.
    272  * Parameters:
    273  *      unit - Device Number
    274  *      info - Label (switch) information
    275 *      ment - MPLS entry
    276  * Returns:
    277  *      BCM_E_XXX
    278  */
    279 
    280 STATIC int
    281 _bcm_kt_mpls_entry_set_key(int unit, bcm_mpls_tunnel_switch_t *info,
    282                            mpls_entry_entry_t *ment)
    283 {
    284     bcm_module_t mod_out;
    285     bcm_port_t port_out;
    286     bcm_trunk_t trunk_id;
    287     int rv, gport_id;
    288 
    289     sal_memset(ment, 0, sizeof(mpls_entry_entry_t));
    290 
    291     if (info->port == BCM_GPORT_INVALID) {
    292         /* Global label, mod/port not part of lookup key */
    293         soc_MPLS_ENTRYm_field32_set(unit, ment, MODULE_IDf, 0);
    294         soc_MPLS_ENTRYm_field32_set(unit, ment, PORT_NUMf, 0);
    295         if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) {
    296             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_LABELf, info->label);
    297         } else {
    298             return BCM_E_PARAM;
    299         }
    300         soc_MPLS_ENTRYm_field32_set(unit, ment, VALIDf, 1);
    301         return BCM_E_NONE;
    302     }
    303 
    304     rv = _bcm_esw_gport_resolve(unit, info->port, &mod_out, 
    305                                 &port_out, &trunk_id, &gport_id);
    306     BCM_IF_ERROR_RETURN(rv);
    307 
    308     if (BCM_GPORT_IS_TRUNK(info->port)) {
    309         soc_MPLS_ENTRYm_field32_set(unit, ment, Tf, 1);
    310         soc_MPLS_ENTRYm_field32_set(unit, ment, TGIDf, trunk_id);
    311     } else {
    312         soc_MPLS_ENTRYm_field32_set(unit, ment, MODULE_IDf, mod_out);
    313         soc_MPLS_ENTRYm_field32_set(unit, ment, PORT_NUMf, port_out);
    314     }
    315     if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) {
    316         soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_LABELf, info->label);
    317     } else {
    318         return BCM_E_PARAM;
    319     }
    320     soc_MPLS_ENTRYm_field32_set(unit, ment, VALIDf, 1);
    321     soc_MPLS_ENTRYm_field32_set(unit, ment, KEY_TYPEf, 0);
    322     
    323     return BCM_E_NONE;
    324 }
    325 
    326 
    327 /*
    328  * Function:
    329  *      _bcm_kt_mpls_entry_get_key
    330  * Purpose:
    331  *      Convert key part of HW entry to application format. 
    332  * Parameters:
    333  *      unit - Device Number
    334  *      ment - mpls entry
    335  *      info - Label (switch) information
    336  * Returns:
    337  *      BCM_E_XXX
    338  */
    339 
    340 STATIC int
    341 _bcm_kt_mpls_entry_get_key(int unit, mpls_entry_entry_t *ment,
    342                            bcm_mpls_tunnel_switch_t *info)
    343 {
    344     bcm_port_t port_in, port_out;
    345     bcm_module_t mod_in, mod_out;
    346     bcm_trunk_t trunk_id;
    347 
    348     port_in = soc_MPLS_ENTRYm_field32_get(unit, ment, PORT_NUMf);
    349     mod_in = soc_MPLS_ENTRYm_field32_get(unit, ment, MODULE_IDf);
    350     if (soc_MPLS_ENTRYm_field32_get(unit, ment, Tf)) {
    351         trunk_id = soc_MPLS_ENTRYm_field32_get(unit, ment, TGIDf);
    352         BCM_GPORT_TRUNK_SET(info->port, trunk_id);
    353     } else if ((port_in == 0) && (mod_in == 0)) {
    354         /* Global label, mod/port not part of lookup key */
    355         info->port = BCM_GPORT_INVALID;
    356     } else {
    357         BCM_IF_ERROR_RETURN
    358             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
    359                                     mod_in, port_in, &mod_out, &port_out));
    360         BCM_GPORT_MODPORT_SET(info->port, mod_out, port_out);
    361     } 
    362     info->label = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS_LABELf);
    363 
    364     return BCM_E_NONE;
    365 }
    366 
    367 /*
    368  * Function:
    369  *      _bcm_kt_mpls_entry_get_data
    370  * Purpose:
    371  *      Convert data part of HW entry to application format. 
    372  * Parameters:
    373  *      unit - Device Number
    374  *       ment - mpls entry
    375  *      info - Label (switch) information
    376  * Returns:
    377  *      BCM_E_XXX
    378  */
    379 
    380 STATIC int
    381 _bcm_kt_mpls_entry_get_data(int unit, mpls_entry_entry_t *ment,
    382                             bcm_mpls_tunnel_switch_t *info)
    383 {
    384     int action, nh_index, ecmp_group, vrf, ipmc_index;
    385     uint32 forwarding_type=0;
    386     bcm_if_t egress_if=0;
    387     int rv=BCM_E_NONE;
    388     int mode = 0;
    389 
    390     BCM_IF_ERROR_RETURN(bcm_xgs3_l3_ingress_mode_get(unit, &mode));
    391 
    392     action = soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS_ACTION_IF_BOSf);
    393     switch(action) {
    394     case 0x2:
    395         info->action = BCM_MPLS_SWITCH_ACTION_POP;
    396         forwarding_type = soc_MPLS_ENTRYm_field32_get(unit, ment,
    397                                                FORWARDING_FIELD_TYPEf);
    398         if (forwarding_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) {
    399             info->flags |= BCM_MPLS_SWITCH_P2MP;
    400             if (!mode) {
    401                 vrf = soc_MPLS_ENTRYm_field32_get(unit, ment, L3_IIF_2f);
    402                 vrf -= _BCM_TR_MPLS_L3_IIF_BASE;
    403                 _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_L3, vrf);
    404             } else {
    405                 info->ingress_if = soc_MPLS_ENTRYm_field32_get(unit, ment, L3_IIF_2f);
    406             }
    407         } else {
    408             if (!mode) {
    409                 vrf = soc_MPLS_ENTRYm_field32_get(unit, ment, L3_IIFf);
    410                 /*
    411                  * If the ingress mode is not set, then L3_IIF is added
    412                  * above the intreface of _BCM_TR_MPLS_L3_IIF_BASE.
    413                  * If this is 0 then 0 vpn index was sent.
    414                  */
    415                 if (vrf != 0) {
    416                     vrf -= _BCM_TR_MPLS_L3_IIF_BASE;
    417                     _BCM_MPLS_VPN_SET(info->vpn, _BCM_MPLS_VPN_TYPE_L3, vrf);
    418                 }
    419             } else {
    420                 info->ingress_if = soc_MPLS_ENTRYm_field32_get(unit, ment, L3_IIFf);
    421             }
    422         }
    423         break;
    424     case 0x3:
    425         info->action = BCM_MPLS_SWITCH_ACTION_SWAP;
    426         forwarding_type = soc_MPLS_ENTRYm_field32_get(unit, ment,
    427                                                FORWARDING_FIELD_TYPEf);
    428         if (forwarding_type == _BCM_MPLS_FORWARD_NEXT_HOP) {
    429               nh_index = soc_MPLS_ENTRYm_field32_get(unit, ment,
    430                                                NEXT_HOP_INDEXf);
    431               rv = bcm_tr_mpls_get_vp_nh (unit, nh_index, &egress_if);
    432               if (rv == BCM_E_NONE) {
    433                   rv = bcm_tr_mpls_l3_nh_info_get(unit, info, nh_index);
    434                   BCM_IF_ERROR_RETURN(rv);
    435               } else {
    436                   info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit);
    437                   info->egress_label.label = BCM_MPLS_LABEL_INVALID;
    438               }
    439         } else if (forwarding_type == _BCM_MPLS_FORWARD_ECMP_GROUP) {
    440               ecmp_group = soc_MPLS_ENTRYm_field32_get(unit, ment,
    441                                                ECMP_PTRf);
    442               info->egress_if = ecmp_group + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 
    443               info->egress_label.label = BCM_MPLS_LABEL_INVALID;
    444         } else if (forwarding_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) {
    445               ipmc_index = soc_MPLS_ENTRYm_field32_get(unit, ment, 
    446                                                            FORWARDING_FIELDf);
    447               info->flags |= BCM_MPLS_SWITCH_P2MP;
    448               info->egress_label.label = BCM_MPLS_LABEL_INVALID;
    449               _BCM_MULTICAST_GROUP_SET(info->mc_group, 
    450                   _BCM_MULTICAST_TYPE_EGRESS_OBJECT, ipmc_index);
    451         }
    452         break;
    453     case 0x4:
    454         info->action = BCM_MPLS_SWITCH_ACTION_PHP;
    455         forwarding_type = soc_MPLS_ENTRYm_field32_get(unit, ment,
    456                                                FORWARDING_FIELD_TYPEf);
    457         if (forwarding_type == _BCM_MPLS_FORWARD_NEXT_HOP) {
    458               nh_index = soc_MPLS_ENTRYm_field32_get(unit, ment,
    459                                                NEXT_HOP_INDEXf);
    460               info->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit);
    461         } else if (forwarding_type == _BCM_MPLS_FORWARD_ECMP_GROUP) {
    462               ecmp_group = soc_MPLS_ENTRYm_field32_get(unit, ment,
    463                                                ECMP_PTRf);
    464               info->egress_if = ecmp_group + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit); 
    465         }
    466         break;
    467     default:
    468         return BCM_E_INTERNAL;
    469         break;
    470     }
    471     if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, MPLS__DROP_DATA_ENABLEf)) {
    472         if (soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__DROP_DATA_ENABLEf)) {
    473             info->flags |= BCM_MPLS_SWITCH_DROP;
    474         }
    475     }
    476 
    477     if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, MPLS__RX_PROT_GROUPf)) {
    478         if (soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__RX_PROT_GROUPf)) {
    479             info->failover_id = 
    480                 soc_MPLS_ENTRYm_field32_get(unit, ment, MPLS__RX_PROT_GROUPf);
    481         }
    482     }
    483 
    484     if (soc_MPLS_ENTRYm_field32_get(unit, ment, PW_TERM_NUM_VALIDf)) {
    485         info->flags |= BCM_MPLS_SWITCH_COUNTED;
    486     }
    487     if (!soc_MPLS_ENTRYm_field32_get(unit, ment, DECAP_USE_TTLf)) {
    488         info->flags |= BCM_MPLS_SWITCH_INNER_TTL;
    489     }
    490     if (soc_MPLS_ENTRYm_field32_get(unit, ment, DECAP_USE_EXP_FOR_INNERf)) {
    491         info->flags |= BCM_MPLS_SWITCH_INNER_EXP;
    492     }
    493     if (soc_MPLS_ENTRYm_field32_get(unit, ment, 
    494                                     DECAP_USE_EXP_FOR_PRIf) == 0x1) {
    495 
    496         /* Use specified EXP-map to determine internal prio/color */
    497         info->flags |= BCM_MPLS_SWITCH_INT_PRI_MAP;
    498         info->exp_map = 
    499             soc_MPLS_ENTRYm_field32_get(unit, ment, EXP_MAPPING_PTRf);
    500         info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS;
    501     } else if (soc_MPLS_ENTRYm_field32_get(unit, ment, 
    502                                            DECAP_USE_EXP_FOR_PRIf) == 0x2) {
    503 
    504         /* Use the specified internal priority value */
    505         info->flags |= BCM_MPLS_SWITCH_INT_PRI_SET;
    506         info->int_pri =
    507             soc_MPLS_ENTRYm_field32_get(unit, ment, NEW_PRIf);
    508 
    509         /* Use specified EXP-map to determine internal color */
    510         info->flags |= BCM_MPLS_SWITCH_COLOR_MAP;
    511         info->exp_map = 
    512             soc_MPLS_ENTRYm_field32_get(unit, ment, EXP_MAPPING_PTRf);
    513         info->exp_map |= _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS;
    514     }
    515     return BCM_E_NONE;
    516 }
    517 /*
    518  * Function:
    519  *      _bcm_kt_mpls_port_stat_get_table_info
    520  * Description:
    521  *      Provides relevant flex table information(table-name,index with
    522  *      direction)  for specific vpn and gport
    523  *
    524  * Parameters:
    525  *      unit             - (IN) unit number
    526  *      vpn              - (IN) VPN Id
    527  *      port             - (IN) MPLS GPORT ID
    528  *      num_of_tables    - (OUT) Number of flex counter tables
    529  *      table_info       - (OUT) Flex counter tables information
    530  *
    531  * Return Value:
    532  *      BCM_E_XXX
    533  * Notes:
    534  */
    535 STATIC
    536 bcm_error_t _bcm_kt_mpls_port_stat_get_table_info(
    537             int                        unit,
    538             bcm_vpn_t                  vpn,
    539             bcm_gport_t                port,
    540             uint32                     *num_of_tables,
    541             bcm_stat_flex_table_info_t *table_info)
    542 {
    543     int                   vp=0, rv = BCM_E_NONE;
    544     ing_dvp_table_entry_t dvp={{0}};
    545     int                   nh_index=0;
    546     initial_prot_nhi_table_entry_t prot_entry;
    547     int vpless_failover_port = FALSE;
    548 
    549     if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(port)) {
    550         vpless_failover_port = TRUE;
    551         port = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(port);
    552     }
    553 
    554     (*num_of_tables)=0;
    555     if (!soc_feature(unit,soc_feature_advanced_flex_counter)) {
    556         return BCM_E_UNAVAIL;
    557     }
    558     if (soc_feature(unit, soc_feature_mpls)) {
    559         BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit));
    560         if (!_BCM_MPLS_VPN_IS_VPLS(vpn) &&
    561             !_BCM_MPLS_VPN_IS_VPWS(vpn)) {
    562             bcm_tr_mpls_unlock (unit);
    563             return BCM_E_PARAM;
    564         }
    565         vp = BCM_GPORT_MPLS_PORT_ID_GET(port);
    566         if (vp == -1) {
    567             bcm_tr_mpls_unlock (unit);
    568             return BCM_E_PARAM;
    569         }
    570         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
    571             bcm_tr_mpls_unlock (unit);
    572             return BCM_E_NOT_FOUND;
    573         }
    574         table_info[*num_of_tables].table= SOURCE_VPm;
    575         table_info[*num_of_tables].index=vp;
    576         table_info[*num_of_tables].direction=bcmStatFlexDirectionIngress;
    577         (*num_of_tables)++;
    578         if(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp) == BCM_E_NONE) {
    579            nh_index=soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
    580            if (vpless_failover_port == TRUE) {
    581                rv = READ_INITIAL_PROT_NHI_TABLEm(unit, MEM_BLOCK_ANY, nh_index,
    582                                                  &prot_entry);
    583                if (BCM_FAILURE(rv)) {
    584                    bcm_tr_mpls_unlock (unit);
    585                    return rv;
    586                }
    587                nh_index = soc_INITIAL_PROT_NHI_TABLEm_field32_get(unit,
    588                               &prot_entry, PROT_NEXT_HOP_INDEXf);
    589            }
    590            table_info[*num_of_tables].table= EGR_L3_NEXT_HOPm;
    591            table_info[*num_of_tables].index=nh_index;
    592            table_info[*num_of_tables].direction=bcmStatFlexDirectionEgress;
    593            (*num_of_tables)++;
    594         }
    595         bcm_tr_mpls_unlock (unit);
    596         return BCM_E_NONE;
    597     }
    598     return BCM_E_UNAVAIL;
    599 }
    600 /*
    601  * Function:
    602  *      _bcm_kt_mpls_label_stat_get_table_info
    603  * Description:
    604  *      Provides relevant flex table information(table-name,index with
    605  *      direction)  for given mpls label and gport
    606  *
    607  * Parameters:
    608  *      unit             - (IN) unit number
    609  *      label            - (IN) MPLS Label
    610  *      port             - (IN) MPLS Gport
    611  *      object           - (IN) STAT object
    612  *      num_of_tables    - (OUT) Number of flex counter tables
    613  *      table_info       - (OUT) Flex counter tables information
    614  *
    615  * Return Value:
    616  *      BCM_E_XXX
    617  * Notes:
    618  */
    619 
    620 STATIC
    621 bcm_error_t _bcm_kt_mpls_label_stat_get_table_info(
    622             int                        unit,
    623             bcm_mpls_label_t           label,
    624             bcm_gport_t                port,
    625             bcm_stat_object_t          object,
    626             uint32                     *num_of_tables,
    627             bcm_stat_flex_table_info_t *table_info)
    628 {
    629     bcm_error_t              rv=BCM_E_NOT_FOUND;
    630     bcm_mpls_tunnel_switch_t mpls_tunnel_switch={0};
    631     mpls_entry_entry_t       ment={{0}};
    632     int                      index[2] = {0, 0};
    633     soc_mem_t                mem[2] = {MPLS_ENTRYm, L3_TUNNELm};
    634     int                      i, num_found = 0;
    635     (*num_of_tables)=0;
    636     if (!soc_feature(unit,soc_feature_advanced_flex_counter)) {
    637         return BCM_E_UNAVAIL;
    638     }
    639 
    640     if (soc_feature(unit, soc_feature_mpls)) {
    641         mpls_tunnel_switch.port = port;
    642         if (BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
    643             mpls_tunnel_switch.label = label;
    644         } else {
    645             return BCM_E_PARAM;
    646         }
    647 
    648         BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit));
    649         if (object != bcmStatObjectIngMplsFrrLabel) {
    650             rv = _bcm_kt_mpls_entry_set_key(unit, &mpls_tunnel_switch, &ment);
    651             if (rv == BCM_E_NONE) {
    652                 if ((rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY,
    653                                 &index[num_found], &ment, &ment, 0)) == BCM_E_NONE) {
    654                     mem[num_found] = MPLS_ENTRYm;
    655                     num_found++;
    656                 }
    657             }
    658         }
    659 
    660 #ifdef BCM_KATANA2_SUPPORT
    661         if (soc_feature(unit, soc_feature_mpls_frr_lookup)) {
    662             if ((!num_found && (object == bcmStatObjectIngMplsFrrLabel)) ||
    663                     (object == bcmStatObjectMaxValue)) {
    664                 rv =  _bcm_tr3_mpls_tunnel_switch_frr_get(unit,
    665                         &mpls_tunnel_switch, &index[num_found]);
    666                 if (rv == BCM_E_NONE) {
    667                     mem[num_found] = L3_TUNNELm;
    668                     num_found++;
    669                 }
    670             }
    671         }
    672 #endif
    673         bcm_tr_mpls_unlock(unit);
    674     }
    675 
    676     if (num_found && (rv == BCM_E_NOT_FOUND)) {
    677         rv = BCM_E_NONE;
    678     }
    679 
    680     for (i = 0; i < num_found; i++) {
    681         table_info[*num_of_tables].table = mem[i];
    682         table_info[*num_of_tables].index = index[i];
    683         table_info[*num_of_tables].direction = bcmStatFlexDirectionIngress;
    684         (*num_of_tables)++;
    685     }
    686 
    687     return rv;
    688 }
    689 
    690 /*
    691  * Function:
    692  *      _bcm_kt_egress_object_p2mp_set
    693  * Purpose:
    694  *      Set P2MP entry type within Egress Object entry
    695  * Parameters:
    696  *      unit - Device Number
    697  *      nh_index - Next Hop Index
    698  *      flag - Indicates SWAP or PHP
    699  *      value - Value to set
    700  * Returns:
    701  *      BCM_E_XXX
    702  */
    703 
    704 int
    705 _bcm_kt_egress_object_p2mp_set(int unit, bcm_multicast_t  mc_group, int flag, uint32 value)
    706 {
    707     int rv=BCM_E_UNAVAIL;
    708     egr_l3_next_hop_entry_t egr_nh;
    709     int num_encap_id=0, num_sub_encap_id = 0, num_total_encap_id = 0;
    710     bcm_if_t *encap_id_array = NULL;
    711     bcm_if_t *sub_encap_id_array = NULL;
    712     bcm_if_t encap_id;
    713     int *q_array = NULL;
    714     int i;
    715     int nh_index;
    716     int if_max = BCM_MULTICAST_PORT_MAX;
    717 
    718 
    719     /* Get the number of encap IDs of the multicast group */
    720     rv = bcm_esw_multicast_egress_get(unit, mc_group, 0,
    721                                       NULL, NULL, &num_encap_id);
    722     if (rv < 0) {
    723         goto cleanup;
    724     }
    725 
    726     if (num_encap_id != 0) {
    727         encap_id_array = sal_alloc(sizeof(bcm_if_t) * num_encap_id,
    728                 "encap_id_array");
    729         if (NULL == encap_id_array) {
    730             rv = BCM_E_MEMORY;
    731             goto cleanup;
    732         }
    733         sal_memset(encap_id_array, 0, sizeof(bcm_if_t) * num_encap_id);
    734 
    735         /* Get all the encap IDs of the multicast group */
    736         rv = bcm_esw_multicast_egress_get(unit, mc_group, num_encap_id,
    737                 NULL, encap_id_array, &num_encap_id);
    738         if (rv < 0) {
    739             goto cleanup;
    740         }
    741     }
    742 
    743     q_array = sal_alloc(if_max * sizeof(bcm_if_t),
    744                             "mcast q array");
    745     if (q_array == NULL) {
    746         rv = BCM_E_MEMORY;
    747         goto cleanup;
    748     }
    749 
    750     sub_encap_id_array = sal_alloc(if_max * sizeof(bcm_if_t),
    751                             "mcast encap array");
    752     if (sub_encap_id_array == NULL) {
    753         rv = BCM_E_MEMORY;
    754         goto cleanup;
    755     }
    756 
    757 
    758     sal_memset(sub_encap_id_array, 0, sizeof(bcm_if_t) * if_max);
    759     /* Get the number of subscriber encap IDs of the multicast group */
    760     rv = bcm_esw_multicast_egress_subscriber_get(unit, mc_group, (if_max - 1),
    761             NULL, sub_encap_id_array, q_array, &num_sub_encap_id);
    762     if (rv < 0) {
    763         goto cleanup;
    764     }
    765 
    766     num_total_encap_id = num_encap_id + num_sub_encap_id;
    767 
    768     /* Convert encap IDs to next hop indices */
    769 
    770     for (i = 0; i < num_total_encap_id; i++) {
    771         encap_id = (i < num_encap_id) ? encap_id_array[i] :
    772             sub_encap_id_array[(i - num_encap_id)];
    773         if (BCM_IF_INVALID != (uint32)encap_id) {
    774             nh_index = encap_id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
    775             rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm,
    776                                   MEM_BLOCK_ANY, nh_index, &egr_nh);
    777             if (rv < 0) {
    778                 goto cleanup;
    779             }
    780 
    781             switch (flag) {
    782                  case BCM_MPLS_SWITCH_ACTION_SWAP:
    783                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
    784                                             MPLS__LABEL_ACTION_SWAPf, value);
    785                         break;
    786 
    787                  case BCM_MPLS_SWITCH_ACTION_PHP:
    788                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
    789                                             MPLS__LABEL_ACTION_PHPf, value);
    790                         break;
    791 
    792                  default:
    793                         break;
    794             }
    795             rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm,
    796                                             MEM_BLOCK_ALL, nh_index, &egr_nh);
    797             if (rv < 0) {
    798                 goto cleanup;
    799             }
    800         }
    801     }
    802 
    803 cleanup:
    804     if (sub_encap_id_array) {
    805         sal_free(sub_encap_id_array);
    806     }
    807     if (q_array) {
    808         sal_free(q_array);
    809     }
    810     if (encap_id_array) {
    811         sal_free(encap_id_array);
    812     }
    813 
    814     return rv;
    815 }
    816 
    817 /*
    818  * Function:
    819  *      _bcm_kt_mpls_process_swap_label_action
    820  * Purpose:
    821  *      Process tunnel_switch.action = SWAP
    822  * Parameters:
    823  *      unit - Device Number
    824  *      info - Label (switch) information
    825  * Returns:
    826  *      BCM_E_XXX
    827  */
    828 
    829 int
    830 _bcm_kt_mpls_process_swap_label_action(int unit, bcm_mpls_tunnel_switch_t *info,
    831                                                                                      int tunnel_switch_update,
    832                                                                                      int forwarding_field_type,
    833                                                                                      int *nh_index,
    834                                                                                      mpls_entry_entry_t *ment )
    835 {
    836     int rv = BCM_E_NONE;
    837     uint32 mpath_flag=0;
    838     int mc_index = -1;
    839 
    840     if (info->flags & BCM_MPLS_SWITCH_P2MP) {
    841         if ((tunnel_switch_update == 1) && 
    842               (forwarding_field_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) ) {
    843                 /* Case of Leaf_LSR + Branch_LSR => BUD_LSR */
    844             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf,
    845                                 0x0); /* INVALID */
    846             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf,
    847                                 0x3); /* SWAP */
    848             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_VALIDf,
    849                                 0x1);
    850             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_BOSf,
    851                                 0x2); /*POP_USE_L3_IIF */
    852             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_NOT_BOSf,
    853                                 0x0); /* INVALID */
    854             if (_BCM_MULTICAST_IS_SET(info->mc_group)) {
    855                 mc_index = _BCM_MULTICAST_ID_GET(info->mc_group);
    856                 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELDf, 
    857                                 mc_index);
    858             } else {
    859                 return BCM_E_PARAM;
    860             }
    861             soc_MPLS_ENTRYm_field32_set(unit, ment,  FORWARDING_FIELD_TYPEf, 
    862                                 _BCM_MPLS_FORWARD_MULTICAST_GROUP);
    863             rv = _bcm_kt_mpls_p2mp_loopback_enable(unit);
    864             BCM_IF_ERROR_RETURN(rv);
    865         } else {
    866             /* Case of P2MP BRANCH_LSR */
    867             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf,
    868                                 0x0); /* INVALID */
    869             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf,
    870                                 0x3); /* SWAP NHI */
    871             if (_BCM_MULTICAST_IS_SET(info->mc_group)) {
    872                 mc_index = _BCM_MULTICAST_ID_GET(info->mc_group);
    873                 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELDf, 
    874                                 mc_index);
    875             } else {
    876                 return BCM_E_PARAM;
    877             }
    878             soc_MPLS_ENTRYm_field32_set(unit, ment,  FORWARDING_FIELD_TYPEf, 
    879                                 _BCM_MPLS_FORWARD_MULTICAST_GROUP);
    880         }
    881         rv = _bcm_kt_egress_object_p2mp_set(unit, info->mc_group, 
    882                              BCM_MPLS_SWITCH_ACTION_SWAP, 0x1);
    883     } else {
    884 
    885         if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, info->egress_if)) {
    886             if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, info->egress_if)) {
    887                 return BCM_E_PARAM;
    888             }
    889         }
    890 
    891         /* Case of LSR */
    892         soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf,
    893                                 0x3); /* SWAP_NHI */
    894         soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf,
    895                                 0x3); /* SWAP NHI */
    896         if (BCM_XGS3_L3_MPLS_LBL_VALID(info->egress_label.label)) {         
    897             rv = bcm_tr_mpls_l3_nh_info_add(unit, info, nh_index);
    898             if (rv < 0) {
    899                 return rv;
    900             }
    901             soc_MPLS_ENTRYm_field32_set(unit, ment, NEXT_HOP_INDEXf, *nh_index);
    902             soc_MPLS_ENTRYm_field32_set(unit, ment,  FORWARDING_FIELD_TYPEf, 
    903                                                                _BCM_MPLS_FORWARD_NEXT_HOP);
    904         } else {
    905              rv = bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if,
    906                                                     &mpath_flag, 1, nh_index);
    907              if (rv < 0) {
    908                  return rv;
    909              }
    910              if (mpath_flag == BCM_L3_MULTIPATH) {
    911                   soc_MPLS_ENTRYm_field32_set(unit, ment, ECMP_PTRf, *nh_index);
    912                   soc_MPLS_ENTRYm_field32_set(unit, ment,  FORWARDING_FIELD_TYPEf, 
    913                                                                      _BCM_MPLS_FORWARD_ECMP_GROUP);
    914              } else {
    915                   soc_MPLS_ENTRYm_field32_set(unit, ment, NEXT_HOP_INDEXf, *nh_index);
    916                   soc_MPLS_ENTRYm_field32_set(unit, ment,  FORWARDING_FIELD_TYPEf, 
    917                                                                      _BCM_MPLS_FORWARD_NEXT_HOP);
    918              }
    919         }
    920     }
    921     return rv;
    922 }
    923 
    924 
    925 /*
    926  * Function:
    927  *      _bcm_kt_mpls_process_pop_label_action
    928  * Purpose:
    929  *      Process tunnel_switch.action = SWAP
    930  * Parameters:
    931  *      unit - Device Number
    932  *      info - Label (switch) information
    933  * Returns:
    934  *      BCM_E_XXX
    935  */
    936 
    937 int
    938 _bcm_kt_mpls_process_pop_label_action(int unit, bcm_mpls_tunnel_switch_t *info,
    939                                                                                      int tunnel_switch_update,
    940                                                                                      int forwarding_field_type,
    941                                                                                      int old_action,
    942                                                                                      mpls_entry_entry_t *ment )
    943 {
    944     int rv = BCM_E_NONE;
    945     int  vrf=-1, mode=-1;
    946 
    947     if (_BCM_MPLS_VPN_IS_L3(info->vpn)) {
    948             _BCM_MPLS_VPN_GET(vrf, _BCM_MPLS_VPN_TYPE_L3, info->vpn);
    949 
    950             if (!bcm_tr_mpls_vrf_used_get(unit, vrf)) {
    951                 return BCM_E_PARAM;
    952             }
    953 
    954             /* Check L3 Ingress Interface mode. */ 
    955             mode = 0;
    956             rv = bcm_xgs3_l3_ingress_mode_get(unit, &mode);
    957             BCM_IF_ERROR_RETURN(rv);
    958     }
    959 
    960     if (info->flags & BCM_MPLS_SWITCH_P2MP) {
    961         if ((tunnel_switch_update == 1) && 
    962               (forwarding_field_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) ) {
    963             /* Case of Branch_LSR + Leaf_LSR => BUD_LSR */
    964             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf,
    965                                 0x0); /* INVALID */
    966             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf,
    967                                 old_action); /* SWAP OR PHP */
    968             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_VALIDf,
    969                                 0x1);
    970             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_BOSf,
    971                                 0x2); /*POP_USE_L3_IIF */
    972             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_NOT_BOSf,
    973                                 0x0); /* INVALID */
    974             if (!mode) {
    975                  soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIF_2f, 
    976                                             _BCM_TR_MPLS_L3_IIF_BASE + vrf);
    977             } else {
    978                  soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIF_2f, info->ingress_if);
    979             }
    980             rv = _bcm_kt_mpls_p2mp_loopback_enable(unit);
    981         } else {
    982             /* Case of LEAF_LSR */
    983             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf,
    984                                 0x0); /* INVALID */
    985             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf,
    986                                 0x2); /* L3_IIF */
    987             if (!mode) {
    988                  soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIFf, 
    989                                             _BCM_TR_MPLS_L3_IIF_BASE + vrf);
    990             } else {
    991                  soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIFf, info->ingress_if);
    992             }
    993         }
    994     } else {
    995         /* Case of LSR */
    996         soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf,
    997                                 0x1); /* POP */
    998         soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf,
    999                                 0x2); /* L3_IIF */
   1000         if (!mode) {
   1001             _bcm_l3_ingress_intf_t iif;
   1002             sal_memset(&iif, 0, sizeof(_bcm_l3_ingress_intf_t));
   1003             iif.intf_id =  _BCM_TR_MPLS_L3_IIF_BASE + vrf;
   1004             rv = _bcm_tr_l3_ingress_interface_get(unit, NULL, &iif);
   1005             if (BCM_FAILURE(rv)) {
   1006                 return rv;
   1007             }
   1008             iif.vrf = vrf;
   1009             rv = _bcm_tr_l3_ingress_interface_set(unit, &iif, NULL, NULL);
   1010             if (BCM_FAILURE(rv)) {
   1011                 return rv;
   1012             }
   1013 
   1014             soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIFf,
   1015                     _BCM_TR_MPLS_L3_IIF_BASE + vrf);
   1016         } else {
   1017              soc_MPLS_ENTRYm_field32_set(unit, ment, L3_IIFf, info->ingress_if);
   1018         }
   1019     }
   1020     return rv;
   1021 }
   1022 
   1023 
   1024 /*
   1025  * Function:
   1026  *      _bcm_kt_mpls_process_php_label_action
   1027  * Purpose:
   1028  *      Process tunnel_switch.action = PHP
   1029  * Parameters:
   1030  *      unit - Device Number
   1031  *      info - Label (switch) information
   1032  * Returns:
   1033  *      BCM_E_XXX
   1034  */
   1035 
   1036 int
   1037 _bcm_kt_mpls_process_php_label_action(int unit, bcm_mpls_tunnel_switch_t *info,
   1038                                                                                      int tunnel_switch_update,
   1039                                                                                      int forwarding_field_type,
   1040                                                                                      int *nh_index,
   1041                                                                                      mpls_entry_entry_t *ment )
   1042 {
   1043     int rv = BCM_E_NONE;
   1044     uint32 mpath_flag=0;
   1045     int mc_index=-1;
   1046 
   1047 
   1048     if (info->flags & BCM_MPLS_SWITCH_P2MP) {
   1049         if ((tunnel_switch_update == 1) && 
   1050               (forwarding_field_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) ) {
   1051                 /* Case of Leaf_LSR + Branch_LSR => BUD_LSR */
   1052             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf,
   1053                                 0x0); /* INVALID */
   1054             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf,
   1055                                 0x4); /* PHP */
   1056             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_VALIDf,
   1057                                 0x1);
   1058             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_BOSf,
   1059                                 0x2); /*POP_USE_L3_IIF */
   1060             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_SECOND_PASS_ACTION_IF_NOT_BOSf,
   1061                                 0x0); /* INVALID */
   1062             if (_BCM_MULTICAST_IS_SET(info->mc_group)) {
   1063                 mc_index = _BCM_MULTICAST_ID_GET(info->mc_group);
   1064                 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELDf, 
   1065                                 mc_index);
   1066             } else {
   1067                 return BCM_E_PARAM;
   1068             }
   1069             soc_MPLS_ENTRYm_field32_set(unit, ment,  FORWARDING_FIELD_TYPEf, 
   1070                                 _BCM_MPLS_FORWARD_MULTICAST_GROUP);
   1071             rv = _bcm_kt_mpls_p2mp_loopback_enable(unit);
   1072             BCM_IF_ERROR_RETURN(rv);
   1073         } else {
   1074             /* Case of P2MP BRANCH_LSR */
   1075             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf,
   1076                                 0x0); /* INVALID */
   1077             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf,
   1078                                 0x4); /* PHP NHI */
   1079             if (_BCM_MULTICAST_IS_SET(info->mc_group)) {
   1080                 mc_index = _BCM_MULTICAST_ID_GET(info->mc_group);
   1081                 soc_MPLS_ENTRYm_field32_set(unit, ment, FORWARDING_FIELDf, 
   1082                                 mc_index);
   1083             } else {
   1084                 return BCM_E_PARAM;
   1085             }
   1086             soc_MPLS_ENTRYm_field32_set(unit, ment,  FORWARDING_FIELD_TYPEf, 
   1087                                 _BCM_MPLS_FORWARD_MULTICAST_GROUP);
   1088         }
   1089         rv = bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if,
   1090                                                     &mpath_flag, 1, nh_index);
   1091         if (rv < 0) {
   1092              return rv;
   1093         }
   1094         rv = _bcm_kt_egress_object_p2mp_set(unit, info->mc_group, 
   1095                              BCM_MPLS_SWITCH_ACTION_PHP, 0x1);
   1096 
   1097     } else {
   1098 
   1099         if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, info->egress_if)) {
   1100             if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, info->egress_if)) {
   1101                 return BCM_E_PARAM;
   1102             }
   1103         }
   1104         soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_NOT_BOSf,
   1105                                     0x2); /* PHP_NHI */
   1106         soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_ACTION_IF_BOSf,
   1107                                     0x4); /* PHP_NHI */ 
   1108         /*
   1109          * Get egress next-hop index from egress object and
   1110          * increment egress object reference count.
   1111          */
   1112 
   1113         BCM_IF_ERROR_RETURN(bcm_xgs3_get_nh_from_egress_object(unit, info->egress_if,
   1114                                                                &mpath_flag, 1, nh_index));
   1115 
   1116         /* Fix: Entry_Type = 1, for PHP Packets with more than 1 Label */
   1117         /* Read the egress next_hop entry pointed by Egress-Object */   
   1118         rv = bcm_tr_mpls_egress_entry_modify(unit, *nh_index, mpath_flag, 1);
   1119         if (rv < 0 ) {
   1120            return rv;
   1121         }
   1122         if (mpath_flag == BCM_L3_MULTIPATH) {
   1123             soc_MPLS_ENTRYm_field32_set(unit, ment, ECMP_PTRf, *nh_index);
   1124             soc_MPLS_ENTRYm_field32_set(unit, ment,  FORWARDING_FIELD_TYPEf, 
   1125                                                                      _BCM_MPLS_FORWARD_ECMP_GROUP);
   1126         } else {
   1127             soc_MPLS_ENTRYm_field32_set(unit, ment, NEXT_HOP_INDEXf, *nh_index);
   1128             soc_MPLS_ENTRYm_field32_set(unit, ment,  FORWARDING_FIELD_TYPEf, 
   1129                                                                      _BCM_MPLS_FORWARD_NEXT_HOP);
   1130         }
   1131     }
   1132     return rv;
   1133 }
   1134 
   1135 /*
   1136  * Function:
   1137  *      bcm_mpls_tunnel_switch_add
   1138  * Purpose:
   1139  *      Add an MPLS label entry.
   1140  * Parameters:
   1141  *      unit - Device Number
   1142  *      info - Label (switch) information
   1143  * Returns:
   1144  *      BCM_E_XXX
   1145  */
   1146 int
   1147 bcm_kt_mpls_tunnel_switch_add(int unit, bcm_mpls_tunnel_switch_t *info)
   1148 {
   1149     mpls_entry_entry_t ment;
   1150     int mode=0, nh_index = -1, rv, num_pw_term, old_pw_cnt = -1, pw_cnt = -1;
   1151     int index, forwarding_field_type=-1, old_action = -1;
   1152     int old_nh_index = -1, old_ecmp_index = -1, old_ipmc_index=-1;
   1153     int  tunnel_switch_update=0;
   1154     int  ref_count=0;
   1155     bcm_if_t  egress_if=0;
   1156 
   1157     rv = bcm_xgs3_l3_egress_mode_get(unit, &mode);
   1158     BCM_IF_ERROR_RETURN(rv);
   1159     if (!mode) {
   1160         LOG_INFO(BSL_LS_BCM_L3,
   1161                  (BSL_META_U(unit,
   1162                              "L3 egress mode must be set first\n")));
   1163         return BCM_E_DISABLED;
   1164     }
   1165 
   1166     /* Check for Port_independent Label mapping */
   1167     if (!BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) {
   1168         return BCM_E_PARAM;
   1169     }
   1170 
   1171     /* BCM_MPLS_SWITCH_KEEP_TTL flag will work only for swap action and
   1172      * it is ineffective for other actions.
   1173      */
   1174     if ((info->flags & BCM_MPLS_SWITCH_KEEP_TTL) &&
   1175         (info->action != BCM_MPLS_SWITCH_ACTION_SWAP)) {
   1176         return BCM_E_PARAM;
   1177     }
   1178 
   1179     rv = bcm_tr_mpls_port_independent_range (unit, info->label, info->port);
   1180     if (rv < 0) {
   1181         return rv;
   1182     }
   1183 #ifdef  BCM_KATANA2_SUPPORT
   1184     if (SOC_IS_KATANA2(unit)) { 
   1185         if (info->flags & BCM_MPLS_SWITCH_FRR) {
   1186             rv = _bcm_tr3_mpls_tunnel_switch_frr_set(unit, info);
   1187             return rv;
   1188          }
   1189     }
   1190 #endif /* BCM_KATANA2_SUPPORT */
   1191     BCM_IF_ERROR_RETURN(_bcm_kt_mpls_entry_set_key(unit, info, &ment));
   1192 
   1193     /* See if entry already exists */
   1194     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
   1195                         &ment, &ment, 0);
   1196 
   1197     if (rv == SOC_E_NONE) {
   1198         /* Entry exists, save old info */
   1199         tunnel_switch_update = 1;
   1200         old_action = soc_MPLS_ENTRYm_field32_get(unit, &ment, MPLS_ACTION_IF_BOSf);
   1201         forwarding_field_type =  soc_MPLS_ENTRYm_field32_get(unit, &ment,  FORWARDING_FIELD_TYPEf);
   1202         if ((old_action == 0x3) || (old_action == 0x4)) {
   1203             if (forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) {
   1204                  old_nh_index = soc_MPLS_ENTRYm_field32_get(unit, &ment, NEXT_HOP_INDEXf);
   1205             } else if (forwarding_field_type == _BCM_MPLS_FORWARD_ECMP_GROUP) {
   1206                  old_ecmp_index = soc_MPLS_ENTRYm_field32_get(unit, &ment, ECMP_PTRf);
   1207             }  else if (forwarding_field_type == _BCM_MPLS_FORWARD_MULTICAST_GROUP) {
   1208                  old_ipmc_index = soc_MPLS_ENTRYm_field32_get(unit, &ment, FORWARDING_FIELDf);
   1209                  
   1210                  if (old_ipmc_index) {
   1211                  }
   1212             }
   1213         }
   1214         if (soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUM_VALIDf)) {
   1215             old_pw_cnt = soc_MPLS_ENTRYm_field32_get(unit, &ment, PW_TERM_NUMf);
   1216         } 
   1217     } else if (rv != SOC_E_NOT_FOUND) {
   1218         return rv;
   1219     }
   1220 
   1221     switch(info->action) {
   1222          case BCM_MPLS_SWITCH_ACTION_SWAP:
   1223               rv = _bcm_kt_mpls_process_swap_label_action(unit, info,
   1224                              tunnel_switch_update, forwarding_field_type, &nh_index, &ment );
   1225               if (rv < 0) {
   1226                    goto cleanup;
   1227               }
   1228               break;
   1229 
   1230          case BCM_MPLS_SWITCH_ACTION_POP:
   1231               rv = _bcm_kt_mpls_process_pop_label_action(unit, info,
   1232                              tunnel_switch_update, forwarding_field_type, old_action, &ment );
   1233               if (rv < 0) {
   1234                    goto cleanup;
   1235               }
   1236               break;
   1237 
   1238          case BCM_MPLS_SWITCH_ACTION_PHP:
   1239               rv = _bcm_kt_mpls_process_php_label_action(unit, info,
   1240                              tunnel_switch_update, forwarding_field_type, &nh_index, &ment );
   1241               if (rv < 0) {
   1242                    goto cleanup;
   1243               }
   1244               break;
   1245 
   1246          default:
   1247               return BCM_E_PARAM;
   1248               break;
   1249     }
   1250 
   1251     
   1252     soc_MPLS_ENTRYm_field32_set(unit, &ment, V4_ENABLEf, 1);
   1253     soc_MPLS_ENTRYm_field32_set(unit, &ment, V6_ENABLEf, 1);
   1254     if (info->flags & BCM_MPLS_SWITCH_INNER_TTL) {
   1255         if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) {
   1256             rv = BCM_E_PARAM;
   1257             goto cleanup;
   1258         }
   1259         soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_TTLf, 0);
   1260     } else {
   1261         soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_TTLf, 1);
   1262     }
   1263     if (info->flags & BCM_MPLS_SWITCH_INNER_EXP) {
   1264         if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) {
   1265             rv = BCM_E_PARAM;
   1266             goto cleanup;
   1267         }
   1268         soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_EXP_FOR_INNERf, 0);
   1269     } else {
   1270         /* For SWAP, Do-not PUSH EXP */
   1271         if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) {
   1272             soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_EXP_FOR_INNERf, 0);
   1273         } else {
   1274             soc_MPLS_ENTRYm_field32_set(unit, &ment, DECAP_USE_EXP_FOR_INNERf, 1);
   1275         }
   1276     }
   1277 
   1278     (void) bcm_tr_mpls_entry_internal_qos_set(unit, NULL, info, &ment);
   1279 
   1280     if ((info->flags & BCM_MPLS_SWITCH_COUNTED)) {
   1281        if (SOC_MEM_IS_VALID(unit, ING_PW_TERM_COUNTERSm)) {
   1282         if (old_pw_cnt == -1) {
   1283             num_pw_term = soc_mem_index_count(unit, ING_PW_TERM_COUNTERSm);
   1284             for (pw_cnt = 0; pw_cnt < num_pw_term; pw_cnt++) {
   1285                 if (! bcm_tr_mpls_pw_used_get(unit, pw_cnt)) {
   1286                     break;
   1287                 }
   1288             }
   1289             if (pw_cnt == num_pw_term) {
   1290                 rv = BCM_E_RESOURCE;
   1291                 goto cleanup;
   1292             }
   1293             (void) bcm_tr_mpls_pw_used_set(unit, pw_cnt);
   1294             soc_MPLS_ENTRYm_field32_set(unit, &ment, PW_TERM_NUMf, pw_cnt);
   1295             soc_MPLS_ENTRYm_field32_set(unit, &ment, PW_TERM_NUM_VALIDf, 1);
   1296         }
   1297       }
   1298     }
   1299 
   1300     if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, MPLS__DROP_DATA_ENABLEf)) {
   1301          soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__DROP_DATA_ENABLEf,
   1302             (info->flags & BCM_MPLS_SWITCH_DROP) ? 1 : 0);
   1303     }
   1304 
   1305     if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, MPLS__RX_PROT_GROUPf)) {
   1306         if ((info->failover_id >= 0) &&
   1307             (info->failover_id <= soc_mem_index_max(unit, RX_PROT_GROUP_TABLEm))) {
   1308             soc_MPLS_ENTRYm_field32_set(unit, &ment, MPLS__RX_PROT_GROUPf,
   1309                 info->failover_id);
   1310         }
   1311     }
   1312 
   1313     if (!tunnel_switch_update) {
   1314         rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &ment);
   1315     } else {
   1316         rv = soc_mem_write(unit, MPLS_ENTRYm,
   1317                            MEM_BLOCK_ALL, index,
   1318                            &ment);
   1319     }
   1320 
   1321     if (rv < 0) {
   1322         goto cleanup;
   1323     }
   1324 
   1325     if ((tunnel_switch_update) && 
   1326               (forwarding_field_type != _BCM_MPLS_FORWARD_MULTICAST_GROUP)) {
   1327         /* Clean up old next-hop and counter info if entry was replaced */
   1328         if ((old_pw_cnt != -1) && !(info->flags & BCM_MPLS_SWITCH_COUNTED)) {
   1329            (void) bcm_tr_mpls_pw_used_clear(unit, old_pw_cnt);
   1330         }
   1331         if (old_action ==  0x3) { /* SWAP_NHI */
   1332             /* Check if tunnel_switch.egress_label mode is being used */
   1333             if (forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) {
   1334                 rv = bcm_tr_mpls_get_vp_nh (unit, (bcm_if_t) old_nh_index, &egress_if);
   1335                 if (rv == BCM_E_NONE) {
   1336                     rv = bcm_tr_mpls_l3_nh_info_delete(unit,  old_nh_index);
   1337                 } else {
   1338                     /* Decrement next-hop Reference count */
   1339                     rv = bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count,  old_nh_index);
   1340                 }
   1341             } else {
   1342                 if (forwarding_field_type == _BCM_MPLS_FORWARD_ECMP_GROUP) {
   1343                     rv = bcm_xgs3_ecmp_group_del(unit, old_ecmp_index, 0);
   1344                 }
   1345             }
   1346         } else if (old_action == 0x4) {/* PHP_NHI */
   1347             /* L3_NHI */
   1348             if (forwarding_field_type == _BCM_MPLS_FORWARD_NEXT_HOP) {
   1349                 rv = bcm_xgs3_nh_del(unit, 0, old_nh_index);
   1350             } else if (forwarding_field_type == _BCM_MPLS_FORWARD_ECMP_GROUP) {
   1351                 rv = bcm_xgs3_ecmp_group_del(unit, old_ecmp_index, 0);
   1352             }
   1353         }
   1354     }
   1355     if (rv < 0) {
   1356         goto cleanup;
   1357     }
   1358 
   1359 #ifdef BCM_WARM_BOOT_SUPPORT
   1360     SOC_CONTROL_LOCK(unit);
   1361     SOC_CONTROL(unit)->scache_dirty = 1;
   1362     SOC_CONTROL_UNLOCK(unit);
   1363 #endif
   1364 
   1365     return rv;
   1366 
   1367   cleanup:
   1368     if (pw_cnt != -1) {
   1369         (void) bcm_tr_mpls_pw_used_clear(unit, pw_cnt);
   1370     }
   1371     if (nh_index != -1) {
   1372         if (info->action == BCM_MPLS_SWITCH_ACTION_SWAP) {
   1373             if (BCM_XGS3_L3_MPLS_LBL_VALID(info->egress_label.label) ||
   1374                 (info->action == BCM_MPLS_SWITCH_ACTION_PHP)) {
   1375                 (void) bcm_tr_mpls_l3_nh_info_delete(unit, nh_index);
   1376             }
   1377         } else if (info->action == BCM_MPLS_SWITCH_ACTION_PHP) {
   1378             (void) bcm_xgs3_nh_del(unit, 0, nh_index);
   1379         }
   1380     }
   1381     return rv;
   1382 }
   1383 
   1384 /*
   1385  * Function:
   1386  *      bcm_mpls_tunnel_switch_delete
   1387  * Purpose:
   1388  *      Delete an MPLS label entry.
   1389  * Parameters:
   1390  *      unit - Device Number
   1391  *      info - Label (switch) information
   1392  * Returns:
   1393  *      BCM_E_XXX
   1394  */
   1395 int
   1396 bcm_kt_mpls_tunnel_switch_delete(int unit, bcm_mpls_tunnel_switch_t *info)
   1397 {
   1398     int rv, index;
   1399     mpls_entry_entry_t ment;
   1400 #ifdef  BCM_KATANA2_SUPPORT
   1401     if ((SOC_IS_KATANA2(unit)) && (info->flags & BCM_MPLS_SWITCH_FRR)) { 
   1402         rv = _bcm_tr3_mpls_tunnel_switch_frr_delete(unit, info);
   1403     } else
   1404 #endif /*BCM_KATANA2_SUPPORT*/
   1405     {
   1406         rv = _bcm_kt_mpls_entry_set_key(unit, info, &ment);
   1407         BCM_IF_ERROR_RETURN(rv);
   1408 
   1409         rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
   1410                 &ment, &ment, 0);
   1411         if (rv < 0) {
   1412             return rv;
   1413         }
   1414         rv = _bcm_kt_mpls_entry_delete(unit, &ment, info, index);
   1415     }
   1416 #ifdef BCM_WARM_BOOT_SUPPORT
   1417     SOC_CONTROL_LOCK(unit);
   1418     SOC_CONTROL(unit)->scache_dirty = 1;
   1419     SOC_CONTROL_UNLOCK(unit);
   1420 #endif
   1421 
   1422     return rv;
   1423 }
   1424 
   1425 /*
   1426  * Function:
   1427  *      bcm_mpls_tunnel_switch_delete_all
   1428  * Purpose:
   1429  *      Delete all MPLS label entries.
   1430  * Parameters:
   1431  *      unit   - Device Number
   1432  * Returns:
   1433  *      BCM_E_XXX
   1434  */
   1435 int
   1436 bcm_kt_mpls_tunnel_switch_delete_all(int unit)
   1437 {
   1438     int rv, i, j, num_entries;
   1439     mpls_entry_entry_t ment;
   1440     bcm_mpls_tunnel_switch_t info;
   1441     soc_tunnel_term_t tnl_entry;
   1442     int num_del = 0;
   1443 
   1444     
   1445 
   1446     num_entries = soc_mem_index_count(unit, MPLS_ENTRYm);
   1447     for (i = 0; i < num_entries; i++) {
   1448 
   1449         rv = READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, i, &ment);
   1450         if (rv < 0) {
   1451             return rv;
   1452         }
   1453         if (!soc_MPLS_ENTRYm_field32_get(unit, &ment, VALIDf)) {
   1454             continue;
   1455         }
   1456         if (soc_MPLS_ENTRYm_field32_get(unit, &ment,
   1457                                         MPLS_ACTION_IF_BOSf) == 0x1) {
   1458             /* L2_SVP */
   1459             continue;
   1460         }
   1461         sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t));
   1462 
   1463         /* Delete entries by default only once unless
   1464          * its a P2MP entry with second pass action valid
   1465          */
   1466         num_del = 1;
   1467 
   1468         rv = _bcm_kt_mpls_entry_get_key(unit, &ment, &info);
   1469         if (rv < 0) {
   1470             return rv;
   1471         }
   1472         rv = _bcm_kt_mpls_entry_get_data(unit, &ment, &info);
   1473         if (rv < 0) {
   1474             return rv;
   1475         }
   1476 
   1477         /* Check if entry is a P2MP entry with second pass action valid */
   1478         if ((soc_MPLS_ENTRYm_field32_get(unit, &ment, FORWARDING_FIELD_TYPEf))
   1479                                                 == _BCM_MPLS_FORWARD_MULTICAST_GROUP) {
   1480             if(soc_MPLS_ENTRYm_field32_get(unit, &ment,
   1481                                            MPLS_SECOND_PASS_ACTION_VALIDf)) {
   1482                 num_del  = 2;
   1483             }
   1484         }
   1485 
   1486         for (j=0 ; j < num_del; j++) {
   1487             rv = _bcm_kt_mpls_entry_delete(unit, &ment, &info, i );
   1488             if (rv < 0) {
   1489                 return rv;
   1490             }
   1491         }
   1492     }
   1493 
   1494     num_entries = soc_mem_index_count(unit, L3_TUNNELm);
   1495     for (i = 0; i < num_entries; i++) {
   1496         sal_memset(&tnl_entry, 0, sizeof(tnl_entry));
   1497         rv = READ_L3_TUNNELm(unit, MEM_BLOCK_ANY, i, (uint32 *)&tnl_entry.entry_arr[0]);
   1498         if (rv < 0) {
   1499             return rv;
   1500         }
   1501         if (!soc_L3_TUNNELm_field32_get(unit, &tnl_entry, VALIDf)) {
   1502             continue;
   1503         }
   1504         if (0x2 != soc_L3_TUNNELm_field32_get(unit, &tnl_entry, KEY_TYPEf)) {
   1505             continue;
   1506         }
   1507 
   1508         rv = soc_tunnel_term_delete(unit, &tnl_entry);
   1509         if (rv < 0) {
   1510             return rv;
   1511         }
   1512 
   1513         /*_soc_tunnel_term_slot_free() api moves last entry to
   1514          * deleted entry position using _soc_tunnel_term_entry_shift().
   1515          * Therefore adding this index change to support delete all*/
   1516         i--;
   1517     }
   1518 
   1519     return BCM_E_NONE;
   1520 }
   1521 
   1522 /*
   1523  * Function:
   1524  *      bcm_mpls_tunnel_switch_get
   1525  * Purpose:
   1526  *      Get an MPLS label entry.
   1527  * Parameters:
   1528  *      unit - Device Number
   1529  *      info - Label (switch) information
   1530  * Returns:
   1531  *      BCM_E_XXX
   1532  */
   1533 int
   1534 bcm_kt_mpls_tunnel_switch_get(int unit, bcm_mpls_tunnel_switch_t *info)
   1535 {
   1536     int rv, index;
   1537     mpls_entry_entry_t ment;
   1538 #ifdef  BCM_KATANA2_SUPPORT
   1539     if ((SOC_IS_KATANA2(unit)) && (info->flags & BCM_MPLS_SWITCH_FRR)) { 
   1540         rv = _bcm_tr3_mpls_tunnel_switch_frr_get(unit, info, &index);
   1541     } else
   1542 #endif /*BCM_KATANA2_SUPPORT*/
   1543     {
   1544         rv = _bcm_kt_mpls_entry_set_key(unit, info, &ment);
   1545 
   1546 
   1547         BCM_IF_ERROR_RETURN(rv);
   1548 
   1549         rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
   1550                 &ment, &ment, 0);
   1551 
   1552         if (rv < 0) {
   1553             return rv;
   1554         }
   1555         rv = _bcm_kt_mpls_entry_get_data(unit, &ment, info);
   1556     }
   1557     return rv;
   1558 }
   1559 
   1560 /*
   1561  * Function:
   1562  *      bcm_mpls_tunnel_switch_traverse
   1563  * Purpose:
   1564  *      Traverse all valid MPLS label entries an call the
   1565  *      supplied callback routine.
   1566  * Parameters:
   1567  *      unit      - Device Number
   1568  *      cb        - User callback function, called once per MPLS entry.
   1569  *      user_data - cookie
   1570  * Returns:
   1571  *      BCM_E_XXX
   1572  */
   1573 int
   1574 bcm_kt_mpls_tunnel_switch_traverse(int unit, 
   1575                                    bcm_mpls_tunnel_switch_traverse_cb cb,
   1576                                    void *user_data)
   1577 {
   1578     int rv, i, num_entries;
   1579     mpls_entry_entry_t ment;
   1580     bcm_mpls_tunnel_switch_t info;
   1581 #ifdef  BCM_KATANA2_SUPPORT
   1582     soc_tunnel_term_t tnl_entry;
   1583     uint32 key_type=0;
   1584 #endif
   1585     
   1586 
   1587     num_entries = soc_mem_index_count(unit, MPLS_ENTRYm);
   1588     for (i = 0; i < num_entries; i++) {
   1589         BCM_IF_ERROR_RETURN (READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, i, &ment));
   1590         if (!soc_MPLS_ENTRYm_field32_get(unit, &ment, VALIDf)) {
   1591             continue;
   1592         }
   1593         if (soc_MPLS_ENTRYm_field32_get(unit, &ment,
   1594                                         MPLS_ACTION_IF_BOSf) == 0x1) {
   1595             /* L2_SVP */
   1596             continue;
   1597         }
   1598         sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t));
   1599         rv = _bcm_kt_mpls_entry_get_key(unit, &ment, &info);
   1600         if (rv < 0) {
   1601             return rv;
   1602         }
   1603         rv = _bcm_kt_mpls_entry_get_data(unit, &ment, &info);
   1604         if (rv < 0) {
   1605             return rv;
   1606         }
   1607         rv = cb(unit, &info, user_data);
   1608 #ifdef BCM_CB_ABORT_ON_ERR
   1609         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   1610             return rv;
   1611         }
   1612 #endif
   1613     }
   1614 #ifdef  BCM_KATANA2_SUPPORT
   1615     if ((SOC_IS_KATANA2(unit))) { 
   1616 
   1617         /* traverse L3_TUNNEL entries */
   1618         num_entries = soc_mem_index_count(unit, L3_TUNNELm);
   1619 
   1620         for (i = 0; i < num_entries; i++) {
   1621 
   1622             sal_memset(&tnl_entry, 0, sizeof(tnl_entry));
   1623             BCM_IF_ERROR_RETURN
   1624                 (READ_L3_TUNNELm(unit, MEM_BLOCK_ANY, i, (uint32 *)&tnl_entry.entry_arr[0]));
   1625 
   1626             if (!soc_L3_TUNNELm_field32_get (unit, &tnl_entry, VALIDf)) {
   1627                 continue;
   1628             }
   1629 
   1630             /* Check for MPLS entry key  */
   1631             key_type = soc_L3_TUNNELm_field32_get(unit, &tnl_entry, KEY_TYPEf);
   1632             if (key_type != 0x2) {
   1633                 continue;
   1634             }
   1635 
   1636             sal_memset(&info, 0, sizeof(bcm_mpls_tunnel_switch_t));
   1637             rv = _bcm_tr3_mpls_tunnel_switch_frr_entry_key_get (unit, &tnl_entry, &info);
   1638             if (rv < 0) {
   1639                 return rv;
   1640             }
   1641 
   1642             (void) _bcm_tr3_mpls_tunnel_switch_frr_parse(unit, &tnl_entry, &info);
   1643 
   1644             rv = cb(unit, &info, user_data);
   1645 #ifdef BCM_CB_ABORT_ON_ERR
   1646             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   1647                 return rv;
   1648             }
   1649 #endif
   1650         }
   1651     }
   1652 #endif /*BCM_KATANA2_SUPPORT*/
   1653 
   1654     return BCM_E_NONE;
   1655 }
   1656 
   1657 /*
   1658  * Function:
   1659  *      bcm_kt_mpls_port_stat_attach
   1660  * Description:
   1661  *      Attach counters entries to the given mpls gport and vpn
   1662  *
   1663  * Parameters:
   1664  *      unit             - (IN) unit number
   1665  *      vpn              - (IN) VPN Id
   1666  *      port             - (IN) MPLS GPORT ID
   1667  *      stat_counter_id  - (IN) Stat Counter ID.
   1668  *
   1669  * Return Value:
   1670  *      BCM_E_XXX
   1671  * Notes:
   1672  */
   1673 bcm_error_t bcm_kt_mpls_port_stat_attach(
   1674                    int         unit,
   1675                    bcm_vpn_t   vpn,
   1676                    bcm_gport_t port,
   1677                    uint32      stat_counter_id)
   1678 {
   1679     soc_mem_t                 table=0;
   1680     bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress;
   1681     uint32                    pool_number=0;
   1682     uint32                    base_index=0;
   1683     bcm_stat_flex_mode_t      offset_mode=0;
   1684     bcm_stat_object_t         object=bcmStatObjectIngPort;
   1685     bcm_stat_group_mode_t     group_mode= bcmStatGroupModeSingle;
   1686     uint32                    count=0;
   1687     uint32                     actual_num_tables=0;
   1688     uint32                     num_of_tables=0;
   1689     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   1690 
   1691     _bcm_esw_stat_get_counter_id_info(
   1692                   unit,
   1693                   stat_counter_id,
   1694                   &group_mode,&object,&offset_mode,&pool_number,&base_index);
   1695     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_object(unit,object,&direction));
   1696     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit,group_mode));
   1697     BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info(
   1698                         unit,object,1,&actual_num_tables,&table,&direction));
   1699 
   1700     BCM_IF_ERROR_RETURN(_bcm_kt_mpls_port_stat_get_table_info(
   1701                    unit, vpn,port,&num_of_tables,&table_info[0]));
   1702     for (count=0; count < num_of_tables ; count++) {
   1703          if ((table_info[count].direction == direction) &&
   1704            (table_info[count].table == table) ) {
   1705               if (direction == bcmStatFlexDirectionIngress) {
   1706               return _bcm_esw_stat_flex_attach_ingress_table_counters(
   1707                      unit,
   1708                      table_info[count].table,
   1709                      table_info[count].index,
   1710                      offset_mode,
   1711                      base_index,
   1712                      pool_number);
   1713            } else {
   1714               return _bcm_esw_stat_flex_attach_egress_table_counters(
   1715                      unit,
   1716                      table_info[count].table,
   1717                      table_info[count].index,
   1718                      0,
   1719                      offset_mode,
   1720                      base_index,
   1721                      pool_number);
   1722            } 
   1723       }
   1724     }
   1725     return BCM_E_UNAVAIL;
   1726 }
   1727 /*
   1728  * Function:
   1729  *      bcm_kt_mpls_port_stat_detach
   1730  * Description:
   1731  *      Detach counters entries to the given mpls port and vpn
   1732  *
   1733  * Parameters:
   1734  *      unit             - (IN) unit number
   1735  *      vpn              - (IN) VPN Id
   1736  *      port             - (IN) MPLS GPORT ID
   1737  *
   1738  * Return Value:
   1739  *      BCM_E_XXX
   1740  * Notes:
   1741  */
   1742 bcm_error_t bcm_kt_mpls_port_stat_detach(
   1743                    int         unit,
   1744                    bcm_vpn_t   vpn,
   1745                    bcm_gport_t port)
   1746 {
   1747     uint32                     count=0;
   1748     uint32                     num_of_tables=0;
   1749     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   1750     bcm_error_t                rv = BCM_E_NONE;
   1751     bcm_error_t                err_code[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {BCM_E_NONE};
   1752 
   1753     BCM_IF_ERROR_RETURN(_bcm_kt_mpls_port_stat_get_table_info(
   1754                    unit, vpn,port,&num_of_tables,&table_info[0]));
   1755 
   1756     for (count=0; count < num_of_tables ; count++) {
   1757         if (table_info[count].direction == bcmStatFlexDirectionIngress) {
   1758             rv = _bcm_esw_stat_flex_detach_ingress_table_counters(
   1759                         unit, table_info[count].table, table_info[count].index);
   1760             if (BCM_E_NONE != rv &&
   1761                 BCM_E_NONE == err_code[bcmStatFlexDirectionIngress]) {
   1762                 err_code[bcmStatFlexDirectionIngress] = rv;
   1763             }
   1764         } else {
   1765             rv = _bcm_esw_stat_flex_detach_egress_table_counters(
   1766                         unit, 0, table_info[count].table,
   1767                         table_info[count].index);
   1768             if (BCM_E_NONE != rv &&
   1769                 BCM_E_NONE == err_code[bcmStatFlexDirectionEgress]) {
   1770                 err_code[bcmStatFlexDirectionEgress] = rv;
   1771             }
   1772         }
   1773     }
   1774 
   1775     BCM_STAT_FLEX_DETACH_RETURN(err_code)
   1776 }
   1777 /*
   1778  * Function:
   1779  *      bcm_kt_mpls_port_stat_counter_get
   1780  * Description:
   1781  *      Get counter statistic values for specific vpn and gport
   1782  *      if sync_mode is set, sync the sw accumulated count
   1783  *      with hw count value first, else return sw count.  
   1784  *
   1785  * Parameters:
   1786  *      unit             - (IN) unit number
   1787  *      sync_mode        - if sync sw accumulated count with hw count 
   1788  *      vpn              - (IN) VPN Id
   1789  *      port             - (IN) MPLS GPORT ID
   1790  *      stat             - (IN) Type of the counter to retrieve
   1791  *                              I.e. ingress/egress byte/packet)
   1792  *      num_entries      - (IN) Number of counter Entries
   1793  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   1794  *      counter_values   - (OUT) Pointer to counter values
   1795  *
   1796  * Return Value:
   1797  *      BCM_E_XXX
   1798  * Notes:
   1799  */
   1800 bcm_error_t bcm_kt_mpls_port_stat_counter_get(
   1801                    int                  unit,
   1802                    int                  sync_mode,
   1803                    bcm_vpn_t            vpn,
   1804                    bcm_gport_t          port,
   1805                    bcm_mpls_stat_t      stat,
   1806                    uint32               num_entries,
   1807                    uint32               *counter_indexes,
   1808                    bcm_stat_value_t     *counter_values)
   1809 {
   1810     uint32                          table_count=0;
   1811     uint32                          index_count=0;
   1812     uint32                          num_of_tables=0;
   1813     bcm_stat_flex_direction_t       direction=bcmStatFlexDirectionIngress;
   1814     uint32                          byte_flag=0;
   1815     bcm_stat_flex_table_info_t      table_info[
   1816                                     BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   1817 
   1818     if ((stat == bcmMplsInBytes) ||
   1819         (stat == bcmMplsInPkts)) {
   1820          direction = bcmStatFlexDirectionIngress;
   1821     } else {
   1822          direction = bcmStatFlexDirectionEgress;
   1823     }
   1824     if ((stat == bcmMplsInPkts) ||
   1825         (stat == bcmMplsOutPkts)) {
   1826         byte_flag=0;
   1827     } else {
   1828         byte_flag=1;
   1829     }
   1830     
   1831     BCM_IF_ERROR_RETURN(_bcm_kt_mpls_port_stat_get_table_info(
   1832                    unit, vpn,port,&num_of_tables,&table_info[0]));
   1833 
   1834     for (table_count=0; table_count < num_of_tables ; table_count++) {
   1835       if (table_info[table_count].direction == direction) {
   1836           for (index_count=0; index_count < num_entries ; index_count++) {
   1837             BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get(
   1838                          unit, sync_mode,
   1839                          table_info[table_count].index,
   1840                          table_info[table_count].table,
   1841                          0,
   1842                          byte_flag,
   1843                          counter_indexes[index_count],
   1844                          &counter_values[index_count]));
   1845           }
   1846       }
   1847     }
   1848     return BCM_E_NONE;
   1849 }
   1850 /*
   1851  * Function:
   1852  *      bcm_kt_mpls_port_stat_counter_set
   1853  * Description:
   1854  *      Set counter statistic values for specific vpn and gport
   1855  *
   1856  * Parameters:
   1857  *      unit             - (IN) unit number
   1858  *      vpn              - (IN) VPN Id
   1859  *      port             - (IN) MPLS GPORT ID
   1860  *      stat             - (IN) Type of the counter to retrieve
   1861  *                              I.e. ingress/egress byte/packet)
   1862  *      num_entries      - (IN) Number of counter Entries
   1863  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   1864  *      counter_values   - (OUT) Pointer to counter values
   1865  *
   1866  * Return Value:
   1867  *      BCM_E_XXX
   1868  * Notes:
   1869  */
   1870 bcm_error_t bcm_kt_mpls_port_stat_counter_set(
   1871                    int                  unit,
   1872                    bcm_vpn_t            vpn,
   1873                    bcm_gport_t          port,
   1874                    bcm_mpls_stat_t      stat,
   1875                    uint32               num_entries,
   1876                    uint32               *counter_indexes,
   1877                    bcm_stat_value_t     *counter_values)
   1878 {
   1879     uint32                          table_count=0;
   1880     uint32                          index_count=0;
   1881     uint32                          num_of_tables=0;
   1882     bcm_stat_flex_direction_t       direction=bcmStatFlexDirectionIngress;
   1883     uint32                          byte_flag=0;
   1884     bcm_stat_flex_table_info_t      table_info[
   1885                                     BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   1886 
   1887     if ((stat == bcmMplsInBytes) ||
   1888         (stat == bcmMplsInPkts)) {
   1889          direction = bcmStatFlexDirectionIngress;
   1890     } else {
   1891          direction = bcmStatFlexDirectionEgress;
   1892     }
   1893     if ((stat == bcmMplsInPkts) ||
   1894         (stat == bcmMplsOutPkts)) {
   1895         byte_flag=0;
   1896     } else {
   1897         byte_flag=1;
   1898     }
   1899     
   1900     BCM_IF_ERROR_RETURN(_bcm_kt_mpls_port_stat_get_table_info(
   1901                    unit, vpn,port,&num_of_tables,&table_info[0]));
   1902 
   1903     for (table_count=0; table_count < num_of_tables ; table_count++) {
   1904       if (table_info[table_count].direction == direction) {
   1905           for (index_count=0; index_count < num_entries ; index_count++) {
   1906             BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set(
   1907                          unit,
   1908                          table_info[table_count].index,
   1909                          table_info[table_count].table,
   1910                          0,
   1911                          byte_flag,
   1912                          counter_indexes[index_count],
   1913                          &counter_values[index_count]));
   1914           }
   1915       }
   1916     }
   1917     return BCM_E_NONE;
   1918 }
   1919 /*
   1920  * Function:
   1921  *      bcm_kt_mpls_port_stat_id_get
   1922  * Description:
   1923  *      Get stat counter id associated with specific vpn and gport
   1924  *
   1925  * Parameters:
   1926  *      unit             - (IN) unit number
   1927  *      vpn              - (IN) VPN Id
   1928  *      port             - (IN) MPLS GPORT ID
   1929  *      stat             - (IN) Type of the counter to retrieve
   1930  *                              I.e. ingress/egress byte/packet)
   1931  *      Stat_counter_id  - (OUT) Stat Counter ID
   1932  *
   1933  * Return Value:
   1934  *      BCM_E_XXX
   1935  * Notes:
   1936  */
   1937 bcm_error_t bcm_kt_mpls_port_stat_id_get(
   1938                    int             unit,
   1939                    bcm_vpn_t       vpn,
   1940                    bcm_gport_t     port,
   1941                    bcm_mpls_stat_t stat,
   1942                    uint32          *stat_counter_id)
   1943 {
   1944     bcm_stat_flex_direction_t  direction=bcmStatFlexDirectionIngress;
   1945     uint32                     num_of_tables=0;
   1946     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   1947     uint32                     index=0;
   1948     uint32                     num_stat_counter_ids=0;
   1949 
   1950     if ((stat == bcmMplsInBytes) ||
   1951         (stat == bcmMplsInPkts)) {
   1952          direction = bcmStatFlexDirectionIngress;
   1953     } else {
   1954          direction = bcmStatFlexDirectionEgress;
   1955       }
   1956     BCM_IF_ERROR_RETURN(_bcm_kt_mpls_port_stat_get_table_info(
   1957                         unit,vpn,port,&num_of_tables,&table_info[0]));
   1958     for (index=0; index < num_of_tables ; index++) {
   1959          if (table_info[index].direction == direction)
   1960              return _bcm_esw_stat_flex_get_counter_id(
   1961                                   unit, 1, &table_info[index],
   1962                                   &num_stat_counter_ids,stat_counter_id);
   1963   }
   1964     return BCM_E_NOT_FOUND;
   1965 }
   1966 /*
   1967  * Function:
   1968  *      bcm_kt_mpls_label_stat_attach
   1969  * Description:
   1970  *      Attach counters entries to the given mpls label and gport
   1971  *
   1972  * Parameters:
   1973  *      unit             - (IN) unit number
   1974  *      label            - (IN) MPLS Label
   1975  *      port             - (IN) MPLS Gport
   1976  *      stat_counter_id  - (IN) Stat Counter ID.
   1977  *
   1978  * Return Value:
   1979  *      BCM_E_XXX
   1980  * Notes:
   1981  */
   1982 bcm_error_t bcm_kt_mpls_label_stat_attach(
   1983                    int              unit,
   1984                    bcm_mpls_label_t label,
   1985                    bcm_gport_t      port,
   1986                    uint32           stat_counter_id)
   1987 {
   1988     soc_mem_t                 table=0;
   1989     bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress;
   1990     uint32                    pool_number=0;
   1991     uint32                    base_index=0;
   1992     bcm_stat_flex_mode_t      offset_mode=0;
   1993     bcm_stat_object_t         object=bcmStatObjectIngPort;
   1994     bcm_stat_group_mode_t     group_mode= bcmStatGroupModeSingle;
   1995     uint32                    count=0;
   1996     uint32                     actual_num_tables=0;
   1997     uint32                     num_of_tables=0;
   1998     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   1999 
   2000 
   2001     if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   2002         return BCM_E_PARAM;
   2003     }
   2004 
   2005     _bcm_esw_stat_get_counter_id_info(
   2006                   unit, stat_counter_id,
   2007                   &group_mode,&object,&offset_mode,&pool_number,&base_index);
   2008     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_object(unit,object,&direction));
   2009     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit,group_mode));
   2010     BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info(
   2011                         unit,object,1,&actual_num_tables,&table,&direction));
   2012 
   2013     BCM_IF_ERROR_RETURN(_bcm_kt_mpls_label_stat_get_table_info(
   2014                    unit, label, port, object, &num_of_tables,&table_info[0]));
   2015     for (count=0; count < num_of_tables ; count++) {
   2016          if ((table_info[count].direction == direction) &&
   2017            (table_info[count].table == table) ) {
   2018               if (direction == bcmStatFlexDirectionIngress) {
   2019               return _bcm_esw_stat_flex_attach_ingress_table_counters(
   2020                      unit,
   2021                      table_info[count].table,
   2022                      table_info[count].index,
   2023                      offset_mode,
   2024                      base_index,
   2025                      pool_number);
   2026            } else {
   2027               return _bcm_esw_stat_flex_attach_egress_table_counters(
   2028                      unit,
   2029                      table_info[count].table,
   2030                      table_info[count].index,
   2031                      0,
   2032                      offset_mode,
   2033                      base_index,
   2034                      pool_number);
   2035            } 
   2036       }
   2037     }
   2038     return BCM_E_NOT_FOUND;
   2039 }
   2040 /*
   2041  * Function:
   2042  *      bcm_kt_mpls_label_stat_detach
   2043  * Description:
   2044  *      Detach counters entries to the given mpls label and gport
   2045  *
   2046  * Parameters:
   2047  *      unit             - (IN) unit number
   2048  *      label            - (IN) MPLS Label
   2049  *      port             - (IN) MPLS Gport
   2050  *
   2051  * Return Value:
   2052  *      BCM_E_XXX
   2053  * Notes:
   2054  */
   2055 bcm_error_t bcm_kt_mpls_label_stat_detach(
   2056                    int              unit,
   2057                    bcm_mpls_label_t label,
   2058                    bcm_gport_t      port)
   2059 {
   2060     uint32                     count=0;
   2061     uint32                     num_of_tables=0;
   2062     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   2063     bcm_error_t                rv = BCM_E_NONE;
   2064     bcm_error_t                err_code[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {BCM_E_NONE};
   2065 
   2066     if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   2067         return BCM_E_PARAM;
   2068     }
   2069 
   2070     BCM_IF_ERROR_RETURN(_bcm_kt_mpls_label_stat_get_table_info(
   2071                 unit, label, port, bcmStatObjectMaxValue,
   2072                 &num_of_tables,&table_info[0]));
   2073 
   2074     for (count=0; count < num_of_tables ; count++) {
   2075       if (table_info[count].direction == bcmStatFlexDirectionIngress) {
   2076            rv = _bcm_esw_stat_flex_detach_ingress_table_counters(
   2077                         unit, table_info[count].table, table_info[count].index);
   2078            if (BCM_E_NONE != rv &&
   2079                 BCM_E_NONE == err_code[bcmStatFlexDirectionIngress]) {
   2080                 err_code[bcmStatFlexDirectionIngress] = rv;
   2081            }
   2082       } else {
   2083            rv = _bcm_esw_stat_flex_detach_egress_table_counters(
   2084                         unit, 0, table_info[count].table,
   2085                         table_info[count].index);
   2086            if (BCM_E_NONE != rv &&
   2087                 BCM_E_NONE == err_code[bcmStatFlexDirectionEgress]) {
   2088                 err_code[bcmStatFlexDirectionEgress] = rv;
   2089            }
   2090       }
   2091     }
   2092 
   2093     BCM_STAT_FLEX_DETACH_RETURN(err_code)
   2094 }
   2095 /*
   2096  * Function:
   2097  *      bcm_kt_mpls_label_stat_counter_get
   2098  * Description:
   2099  *      Get counter statistic values for specific MPLS label and gport
   2100  *      if sync_mode is set, sync the sw accumulated count
   2101  *      with hw count value first, else return sw count.  
   2102  *
   2103  *
   2104  * Parameters:
   2105  *      unit             - (IN) unit number
   2106  *      sync_mode        - if sync sw accumulated count with hw count 
   2107  *      label            - (IN) MPLS Label
   2108  *      port             - (IN) MPLS Gport
   2109  *      stat             - (IN) Type of the counter to retrieve
   2110  *                              I.e. ingress/egress byte/packet)
   2111  *      num_entries      - (IN) Number of counter Entries
   2112  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   2113  *      counter_values   - (OUT) Pointer to counter values
   2114  *
   2115  * Return Value:
   2116  *      BCM_E_XXX
   2117  * Notes:
   2118  */
   2119 bcm_error_t bcm_kt_mpls_label_stat_counter_get(
   2120                    int                  unit,
   2121                    int                  sync_mode,
   2122                    bcm_mpls_label_t     label,
   2123                    bcm_gport_t          port,
   2124                    bcm_mpls_stat_t      stat,
   2125                    uint32               num_entries,
   2126                    uint32               *counter_indexes,
   2127                    bcm_stat_value_t     *counter_values)
   2128 {
   2129     uint32                          table_count=0;
   2130     uint32                          index_count=0;
   2131     uint32                          num_of_tables=0;
   2132     bcm_stat_flex_direction_t       direction=bcmStatFlexDirectionIngress;
   2133     uint32                          byte_flag=0;
   2134     bcm_stat_flex_table_info_t      table_info[
   2135                                     BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   2136 
   2137     if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   2138         return BCM_E_PARAM;
   2139     }
   2140 
   2141     if ((stat == bcmMplsInBytes) ||
   2142         (stat == bcmMplsInPkts)) {
   2143          direction = bcmStatFlexDirectionIngress;
   2144     } else {
   2145          direction = bcmStatFlexDirectionEgress;
   2146     }
   2147     if ((stat == bcmMplsInPkts) ||
   2148         (stat == bcmMplsOutPkts)) {
   2149         byte_flag=0;
   2150     } else {
   2151         byte_flag=1;
   2152     }
   2153     
   2154     BCM_IF_ERROR_RETURN(_bcm_kt_mpls_label_stat_get_table_info(
   2155                 unit, label, port, bcmStatObjectMaxValue,
   2156                 &num_of_tables, &table_info[0]));
   2157 
   2158     for (table_count=0; table_count < num_of_tables ; table_count++) {
   2159       if (table_info[table_count].direction == direction) {
   2160           for (index_count=0; index_count < num_entries ; index_count++) {
   2161             BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get(
   2162                          unit, sync_mode,
   2163                          table_info[table_count].index,
   2164                          table_info[table_count].table,
   2165                          0,
   2166                          byte_flag,
   2167                          counter_indexes[index_count],
   2168                          &counter_values[index_count]));
   2169           }
   2170       }
   2171     }
   2172     return BCM_E_NONE;
   2173 }
   2174 /*
   2175  * Function:
   2176  *      bcm_kt_mpls_label_stat_counter_set
   2177  * Description:
   2178  *      Set counter statistic values for specific MPLS label and gport
   2179  *
   2180  * Parameters:
   2181  *      unit             - (IN) unit number
   2182  *      label            - (IN) MPLS Label
   2183  *      port             - (IN) MPLS Gport
   2184  *      stat             - (IN) Type of the counter to retrieve
   2185  *                              I.e. ingress/egress byte/packet)
   2186  *      num_entries      - (IN) Number of counter Entries
   2187  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   2188  *      counter_values   - (IN) Pointer to counter values
   2189  *
   2190  * Return Value:
   2191  *      BCM_E_XXX
   2192  * Notes:
   2193  */
   2194 bcm_error_t bcm_kt_mpls_label_stat_counter_set(
   2195                    int                  unit,
   2196                    bcm_mpls_label_t     label,
   2197                    bcm_gport_t          port,
   2198                    bcm_mpls_stat_t      stat,
   2199                    uint32               num_entries,
   2200                    uint32               *counter_indexes,
   2201                    bcm_stat_value_t     *counter_values)
   2202 {
   2203     uint32                          table_count=0;
   2204     uint32                          index_count=0;
   2205     uint32                          num_of_tables=0;
   2206     bcm_stat_flex_direction_t       direction=bcmStatFlexDirectionIngress;
   2207     uint32                          byte_flag=0;
   2208     bcm_stat_flex_table_info_t      table_info[
   2209                                     BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   2210     bcm_vpn_t                       vpn = 0;
   2211 
   2212     if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   2213         return BCM_E_PARAM;
   2214     }
   2215 
   2216     if ((stat == bcmMplsInBytes) ||
   2217         (stat == bcmMplsInPkts)) {
   2218          direction = bcmStatFlexDirectionIngress;
   2219     } else {
   2220          direction = bcmStatFlexDirectionEgress;
   2221     }
   2222     if ((stat == bcmMplsInPkts) ||
   2223         (stat == bcmMplsOutPkts)) {
   2224         byte_flag=0;
   2225     } else {
   2226         byte_flag=1;
   2227     }
   2228     
   2229     if (BCM_GPORT_IS_MPLS_PORT(port)) {
   2230         /* Just create a valid vpn id to pass the check */
   2231         _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1);
   2232         BCM_IF_ERROR_RETURN(_bcm_kt_mpls_port_stat_get_table_info(
   2233             unit, vpn, port, &num_of_tables, &table_info[0]));
   2234     } else {
   2235         BCM_IF_ERROR_RETURN(_bcm_kt_mpls_label_stat_get_table_info(
   2236                     unit, label, port, bcmStatObjectMaxValue,
   2237                     &num_of_tables, &table_info[0]));
   2238     }
   2239     for (table_count=0; table_count < num_of_tables ; table_count++) {
   2240       if (table_info[table_count].direction == direction) {
   2241           for (index_count=0; index_count < num_entries ; index_count++) {
   2242             BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set(
   2243                          unit,
   2244                          table_info[table_count].index,
   2245                          table_info[table_count].table,
   2246                          0,
   2247                          byte_flag,
   2248                          counter_indexes[index_count],
   2249                          &counter_values[index_count]));
   2250           }
   2251       }
   2252     }
   2253     return BCM_E_NONE;
   2254 }
   2255 /*
   2256  * Function:
   2257  *      bcm_kt_mpls_label_stat_id_get
   2258  * Description:
   2259  *      Get stat counter id associated with given vlan
   2260  *
   2261  * Parameters:
   2262  *      unit             - (IN) unit number
   2263  *      label            - (IN) MPLS Label
   2264  *      port             - (IN) MPLS Gport
   2265  *      stat             - (IN) Type of the counter to retrieve
   2266  *                              I.e. ingress/egress byte/packet)
   2267  *      Stat_counter_id  - (OUT) Stat Counter ID
   2268  *
   2269  * Return Value:
   2270  *      BCM_E_XXX
   2271  * Notes:
   2272  */
   2273 bcm_error_t bcm_kt_mpls_label_stat_id_get(
   2274             int                  unit,
   2275             bcm_mpls_label_t     label,
   2276             bcm_gport_t          port,
   2277             bcm_mpls_stat_t      stat,
   2278             uint32               *stat_counter_id)
   2279 {
   2280     bcm_stat_flex_direction_t  direction=bcmStatFlexDirectionIngress;
   2281     uint32                     num_of_tables=0;
   2282     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   2283     uint32                     index=0;
   2284     uint32                     num_stat_counter_ids=0;
   2285 
   2286     if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   2287         return BCM_E_PARAM;
   2288     }
   2289 
   2290     if ((stat == bcmMplsInBytes) ||
   2291         (stat == bcmMplsInPkts)) {
   2292          direction = bcmStatFlexDirectionIngress;
   2293     } else {
   2294          direction = bcmStatFlexDirectionEgress;
   2295     }
   2296     BCM_IF_ERROR_RETURN(_bcm_kt_mpls_label_stat_get_table_info(
   2297                 unit, label, port, bcmStatObjectMaxValue,
   2298                 &num_of_tables,&table_info[0]));
   2299     for (index=0; index < num_of_tables ; index++) {
   2300          if (table_info[index].direction == direction)
   2301              return _bcm_esw_stat_flex_get_counter_id(
   2302                                   unit, 1, &table_info[index],
   2303                                   &num_stat_counter_ids,stat_counter_id);
   2304     }
   2305     return BCM_E_NOT_FOUND;
   2306 }
   2307 /*
   2308  * Function:
   2309  *      bcm_kt_mpls_label_stat_enable_set
   2310  * Purpose:
   2311  *      Enable statistics collection for MPLS label or MPLS gport
   2312  * Parameters:
   2313  *      unit - (IN) Unit number.
   2314  *      label - (IN) MPLS label
   2315  *      port - (IN) MPLS gport
   2316  *      enable - (IN) Non-zero to enable counter collection, zero to disable.
   2317  * Returns:
   2318  *      BCM_E_xxx
   2319  * Notes:
   2320  */
   2321 int bcm_kt_mpls_label_stat_enable_set(
   2322     int              unit, 
   2323     bcm_mpls_label_t label,
   2324     bcm_gport_t      port, 
   2325     int              enable)
   2326 {
   2327     uint32                     num_of_tables=0;
   2328     uint32                     num_stat_counter_ids=0;
   2329     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   2330     bcm_stat_object_t          object=bcmStatObjectIngPort;
   2331     uint32                     stat_counter_id[
   2332                                        BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]={0};
   2333     uint32                     num_entries=0;
   2334     int                        index=0;
   2335 
   2336     if (BCM_GPORT_IS_MPLS_PORT(port)) {
   2337         /* When the gport is an MPLS port, we'll turn on the
   2338          * port-based tracking to comply with API definition.
   2339          */
   2340 
   2341         int vpn;
   2342 
   2343         /* just create a valid vpn id to pass the check */
   2344         _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1);
   2345         BCM_IF_ERROR_RETURN(_bcm_kt_mpls_port_stat_get_table_info(
   2346                         unit,vpn,port,&num_of_tables,&table_info[0]));
   2347         if (enable ) {
   2348             for(index=0;index < num_of_tables ;index++) {
   2349                 if (table_info[index].direction == bcmStatFlexDirectionIngress) {
   2350                     BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_ingress_object(
   2351                                         unit,table_info[index].table,
   2352                                         table_info[index].index,NULL,&object));
   2353                 } else {
   2354                     BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_egress_object(
   2355                                         unit,table_info[index].table,
   2356                                         table_info[index].table,NULL,&object));
   2357                 }
   2358                 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_create(
   2359                                     unit,object,bcmStatGroupModeSingle,
   2360                                 &stat_counter_id[table_info[index].direction],
   2361                                 &num_entries));
   2362                 BCM_IF_ERROR_RETURN(bcm_kt_mpls_port_stat_attach(
   2363                                 unit,vpn,port,
   2364                                 stat_counter_id[table_info[index].direction]));
   2365             }
   2366             return BCM_E_NONE;
   2367         } else {
   2368             BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_counter_id(
   2369                             unit, num_of_tables,&table_info[0],
   2370                             &num_stat_counter_ids,&stat_counter_id[0]));
   2371             if ((stat_counter_id[bcmStatFlexDirectionIngress] == 0) &&
   2372                 (stat_counter_id[bcmStatFlexDirectionEgress] == 0)) {
   2373                  return BCM_E_PARAM;
   2374             }
   2375             BCM_IF_ERROR_RETURN(bcm_kt_mpls_port_stat_detach(unit,vpn,port));
   2376             if (stat_counter_id[bcmStatFlexDirectionIngress] != 0) {
   2377                 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy(
   2378                                 unit,
   2379                                 stat_counter_id[bcmStatFlexDirectionIngress]));
   2380             }
   2381             if (stat_counter_id[bcmStatFlexDirectionEgress] != 0) {
   2382                 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy(
   2383                                 unit,
   2384                                 stat_counter_id[bcmStatFlexDirectionEgress]));
   2385             }
   2386             return BCM_E_NONE;
   2387         }
   2388 
   2389     }
   2390 
   2391     if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   2392         return BCM_E_PARAM;
   2393     }
   2394 
   2395     BCM_IF_ERROR_RETURN(_bcm_kt_mpls_label_stat_get_table_info(
   2396                         unit, label, port, bcmStatObjectMaxValue,
   2397                         &num_of_tables, &table_info[0]));
   2398     if (enable ) {
   2399         for(index=0;index < num_of_tables ;index++) {
   2400             if (table_info[index].direction == bcmStatFlexDirectionIngress) {
   2401                 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_ingress_object(
   2402                                     unit,table_info[index].table,
   2403                                     table_info[index].index,NULL,&object));
   2404             } else {
   2405                 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_egress_object(
   2406                                     unit,table_info[index].table,
   2407                                     table_info[index].table,NULL,&object));
   2408             }
   2409             BCM_IF_ERROR_RETURN(bcm_esw_stat_group_create(
   2410                                 unit,object,bcmStatGroupModeSingle,
   2411                                 &stat_counter_id[table_info[index].direction],
   2412                                 &num_entries));
   2413             BCM_IF_ERROR_RETURN(bcm_esw_mpls_label_stat_attach(
   2414                                 unit,label,port,
   2415                                 stat_counter_id[table_info[index].direction]));
   2416         }
   2417         return BCM_E_NONE;
   2418     } else {
   2419         BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_counter_id(
   2420                             unit, num_of_tables,&table_info[0],
   2421                             &num_stat_counter_ids,&stat_counter_id[0]));
   2422         if ((stat_counter_id[bcmStatFlexDirectionIngress] == 0) &&
   2423             (stat_counter_id[bcmStatFlexDirectionEgress] == 0)) {
   2424              return BCM_E_PARAM;
   2425         }
   2426         BCM_IF_ERROR_RETURN(bcm_esw_mpls_label_stat_detach(unit,label,port));
   2427         if (stat_counter_id[bcmStatFlexDirectionIngress] != 0) {
   2428             BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy(
   2429                                 unit,
   2430                                 stat_counter_id[bcmStatFlexDirectionIngress]));
   2431         }
   2432         if (stat_counter_id[bcmStatFlexDirectionEgress] != 0) {
   2433             BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy(
   2434                                 unit,
   2435                                 stat_counter_id[bcmStatFlexDirectionEgress]));
   2436         }
   2437         return BCM_E_NONE;
   2438     }
   2439 
   2440 }
   2441 /*
   2442  * Function:
   2443  *      bcm_kt_mpls_label_stat_get
   2444  * Purpose:
   2445  *      Get L2 MPLS PW Stats
   2446  * Parameters:
   2447  *      unit   - (IN) SOC unit #
   2448  *      label  - (IN) MPLS label
   2449  *      port   - (IN) MPLS gport
   2450  *      stat   - (IN)  specify the Stat type
   2451  *      val    - (OUT) 64-bit Stats value
   2452  * Returns:
   2453  *      BCM_E_XXX
   2454  */
   2455 
   2456 int bcm_kt_mpls_label_stat_get(int              unit,
   2457                                int              sync_mode,
   2458                                bcm_mpls_label_t label, 
   2459                                bcm_gport_t      port,
   2460                                bcm_mpls_stat_t  stat, 
   2461                                uint64           *val)
   2462 {
   2463     uint32           counter_indexes=0   ;
   2464     bcm_stat_value_t counter_values={0};
   2465 
   2466    if (BCM_GPORT_IS_MPLS_PORT(port)) {
   2467         int vpn;
   2468 
   2469         /* just create a valid vpn id to pass the check */
   2470         _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1);
   2471 
   2472         BCM_IF_ERROR_RETURN(bcm_kt_mpls_port_stat_counter_get(unit, sync_mode, 
   2473                                                               vpn, port, 
   2474                                                               stat, 1,
   2475                                                               &counter_indexes,
   2476                                                               &counter_values));
   2477     } else {
   2478         if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   2479             return BCM_E_PARAM;
   2480         }
   2481 
   2482         BCM_IF_ERROR_RETURN(bcm_kt_mpls_label_stat_counter_get(unit, sync_mode, 
   2483                                                                label, port, 
   2484                                                                stat, 1,
   2485                                                                &counter_indexes,
   2486                                                               &counter_values));
   2487     }
   2488 
   2489     if ((stat == bcmMplsInPkts) ||
   2490         (stat == bcmMplsOutPkts)) {
   2491          COMPILER_64_SET(*val,
   2492                          COMPILER_64_HI(counter_values.packets64),
   2493                          COMPILER_64_LO(counter_values.packets64));
   2494     } else {
   2495          COMPILER_64_SET(*val,
   2496                          COMPILER_64_HI(counter_values.bytes),
   2497                          COMPILER_64_LO(counter_values.bytes));
   2498     }
   2499     return BCM_E_NONE;
   2500 }
   2501 /*
   2502  * Function:
   2503  *      bcm_kt_mpls_label_stat_get32
   2504  * Purpose:
   2505  *      Get L2 MPLS PW Stats
   2506  *      if sync_mode is set, sync the sw accumulated count
   2507  *      with hw count value first, else return sw count.  
   2508  * Parameters:
   2509  *      unit       - (IN) SOC unit #
   2510  *      sync_mode  - (IN) hwcount is to be synced to sw count 
   2511  *      label      - (IN) MPLS label
   2512  *      port       - (IN) MPLS gport
   2513  *      stat       - (IN)  specify the Stat type
   2514  *      val        - (OUT) 32-bit Stats value
   2515  * Returns:
   2516  *      BCM_E_XXX
   2517  */
   2518 
   2519 int bcm_kt_mpls_label_stat_get32(int              unit,
   2520                                  int              sync_mode, 
   2521                                  bcm_mpls_label_t label, 
   2522                                  bcm_gport_t      port, 
   2523                                  bcm_mpls_stat_t  stat, 
   2524                                  uint32           *val)
   2525 {
   2526     uint32           counter_indexes=0;
   2527     bcm_stat_value_t counter_values={0};
   2528 
   2529     if (BCM_GPORT_IS_MPLS_PORT(port)) {
   2530         int vpn;
   2531 
   2532         /* just create a valid vpn id to pass the check */
   2533         _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1);
   2534 
   2535         BCM_IF_ERROR_RETURN(bcm_kt_mpls_port_stat_counter_get(unit, sync_mode, 
   2536                                                               vpn, port, 
   2537                                                               stat, 1,
   2538                                                               &counter_indexes,
   2539                                                               &counter_values));
   2540     } else {
   2541         if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   2542             return BCM_E_PARAM;
   2543         }
   2544 
   2545         BCM_IF_ERROR_RETURN(_bcm_esw_mpls_label_stat_counter_get(unit, 
   2546                                                                  sync_mode,
   2547                                                                  label, port,
   2548                                                                  stat, 1,
   2549                                                               &counter_indexes,
   2550                                                               &counter_values));
   2551     }
   2552     if ((stat == bcmMplsInPkts) ||
   2553         (stat == bcmMplsOutPkts)) {
   2554          *val = counter_values.packets;
   2555     } else {
   2556          /* Ignoring Hi bytes value */
   2557          *val = COMPILER_64_LO(counter_values.bytes);
   2558     }
   2559     return BCM_E_NONE;
   2560 }
   2561 /*
   2562  * Function:
   2563  *      bcm_kt_mpls_label_stat_clear
   2564  * Purpose:
   2565  *      Clear L2 MPLS PW Stats
   2566  * Parameters:
   2567  *      unit   - (IN) SOC unit #
   2568  *      label  - (IN) MPLS label
   2569  *      port   - (IN) MPLS gport
   2570  *      stat   - (IN)  specify the Stat type
   2571  * Returns:
   2572  *      BCM_E_XXX
   2573  */
   2574 
   2575 int bcm_kt_mpls_label_stat_clear(
   2576     int              unit, 
   2577     bcm_mpls_label_t label, 
   2578     bcm_gport_t      port, 
   2579     bcm_mpls_stat_t  stat)
   2580 {
   2581     uint32           counter_indexes=0   ;
   2582     bcm_stat_value_t counter_values={0};
   2583 
   2584     if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   2585         return BCM_E_PARAM;
   2586     }
   2587 
   2588     BCM_IF_ERROR_RETURN(bcm_esw_mpls_label_stat_counter_set(
   2589                         unit,label,port,stat,1,
   2590                         &counter_indexes,&counter_values));
   2591     return BCM_E_NONE;
   2592 }
   2593 
   2594 
   2595 
   2596 
   2597 #else /* BCM_KATANA_SUPPORT && BCM_MPLS_SUPPORT && INCLUDE_L3 */
   2598 int bcm_esw_katana_mpls_not_empty;
   2599 #endif /* BCM_KATANA_SUPPORT && BCM_MPLS_SUPPORT && INCLUDE_L3 */