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


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:    mpls.c
      8  * Purpose: Manages MPLS functions
      9  */
     10 
     11 #ifdef INCLUDE_L3
     12 
     13 #include <sal/core/libc.h>
     14 
     15 #include <soc/defs.h>
     16 #include <soc/drv.h>
     17 #include <soc/mem.h>
     18 #include <soc/l2u.h>
     19 #include <soc/l3x.h>
     20 #include <soc/util.h>
     21 #include <soc/debug.h>
     22 #include <bcm/l2.h>
     23 #include <bcm/l3.h>
     24 #include <bcm/port.h>
     25 #include <bcm/error.h>
     26 #include <bcm/vlan.h>
     27 #include <bcm/rate.h>
     28 #include <bcm/ipmc.h>
     29 #include <bcm/mpls.h>
     30 #include <bcm/stack.h>
     31 #include <bcm/topo.h>
     32 
     33 #include <bcm_int/esw/virtual.h>
     34 #include <bcm_int/esw/mbcm.h>
     35 #include <bcm_int/esw/l3.h>
     36 #include <bcm_int/esw/firebolt.h>
     37 #if defined(BCM_TRIUMPH_SUPPORT)
     38 #include <bcm_int/esw/triumph.h>
     39 #endif /* BCM_TRIUMPH_SUPPORT */
     40 #if defined(BCM_TRIUMPH2_SUPPORT)
     41 #include <bcm_int/esw/triumph2.h>
     42 #endif /* BCM_TRIUMPH2_SUPPORT */
     43 #if defined(BCM_KATANA_SUPPORT)
     44 #include <bcm_int/esw/katana.h>
     45 #endif /* BCM_TRIUMPH_SUPPORT */
     46 #if (defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT))
     47 #include <bcm_int/esw/xgs5.h>
     48 #endif /* BCM_TOMAHAWK_SUPPORT */
     49 #if defined(BCM_TRIUMPH3_SUPPORT)
     50 #include <bcm_int/esw/triumph3.h>
     51 #endif /* BCM_TRIUMPH3_SUPPORT */
     52 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
     53 #include <bcm_int/esw/trident2plus.h>
     54 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
     55 #if defined(BCM_TRIDENT3_SUPPORT)
     56 #include <bcm_int/esw/trident3.h>
     57 #endif /* BCM_TRIDENT3_SUPPORT */
     58 
     59 #include <bcm_int/esw_dispatch.h>
     60 #include <bcm_int/esw/xgs3.h>
     61 
     62 /*
     63  * Function:
     64  *      bcm_mpls_init
     65  * Purpose:
     66  *      Initialize the MPLS software module, clear all HW MPLS states
     67  * Parameters:
     68  *      unit     - Device Number
     69  * Returns:
     70  *      BCM_E_XXXX
     71  */
     72 
     73 int
     74 bcm_esw_mpls_init(int unit)
     75 {
     76 #ifdef BCM_MPLS_SUPPORT
     77 #ifdef BCM_TRIUMPH_SUPPORT
     78     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
     79         return bcm_tr_mpls_init(unit);
     80     }
     81 #endif
     82 #endif
     83     return BCM_E_UNAVAIL;
     84 }
     85 
     86 /*
     87  * Function:
     88  *      bcm_mpls_cleanup
     89  * Purpose:
     90  *      Detach the MPLS software module, clear all HW MPLS states
     91  * Parameters:
     92  *      unit     - Device Number
     93  * Returns:
     94  *      BCM_E_XXXX
     95  */
     96 
     97 int
     98 bcm_esw_mpls_cleanup(int unit)
     99 {
    100 #ifdef BCM_MPLS_SUPPORT
    101 #ifdef BCM_TRIUMPH_SUPPORT
    102     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    103         return bcm_tr_mpls_cleanup(unit);
    104     }
    105 #endif
    106 #endif
    107     return BCM_E_NONE;
    108 }
    109 
    110 #ifdef BCM_WARM_BOOT_SUPPORT
    111 int
    112 _bcm_esw_mpls_sync(int unit)
    113 {
    114 #ifdef BCM_MPLS_SUPPORT
    115 #ifdef BCM_TRIUMPH_SUPPORT
    116     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    117         return bcm_tr_mpls_sync(unit);
    118     }
    119 #endif
    120 #endif
    121 
    122     return BCM_E_NONE;
    123 }
    124 
    125 int
    126 _bcm_esw_mpls_match_key_recover(int unit)
    127 {
    128 #ifdef BCM_MPLS_SUPPORT
    129 #ifdef BCM_TRIUMPH3_SUPPORT
    130     if (SOC_IS_TRIUMPH3(unit)) {
    131         return _bcm_tr3_mpls_match_key_recover(unit);
    132     } else
    133 #endif
    134 #ifdef BCM_TRIUMPH_SUPPORT
    135     {
    136         return _bcm_tr_mpls_match_key_recover(unit);
    137     }
    138 #endif /* BCM_TRIUMPH_SUPPORT */
    139 #endif /* MPLS_SUPPORT */
    140 
    141     return BCM_E_NONE;
    142 }
    143 
    144 /*
    145  * Function:
    146  *      _bcm_esw_mpls_tunnel_switch_traverse_no_lock
    147  * Purpose:
    148  *      Traverse all valid MPLS label entries and call the
    149  *      supplied callback routine without lock.
    150  * Parameters:
    151  *      unit      - Device Number
    152  *      cb        - User callback function, called once per MPLS entry.
    153  *      user_data - cookie
    154  * Returns:
    155  *      BCM_E_XXX
    156  */
    157 int
    158 _bcm_esw_mpls_tunnel_switch_traverse_no_lock(int unit,
    159                                   bcm_mpls_tunnel_switch_traverse_cb cb,
    160                                   void *user_data)
    161 {
    162     int rv = BCM_E_NONE;
    163 
    164 #ifdef BCM_MPLS_SUPPORT
    165 #ifdef BCM_TRIUMPH3_SUPPORT
    166     if (SOC_IS_TRIUMPH3(unit) && soc_feature(unit, soc_feature_mpls)) {
    167        rv = bcm_tr3_mpls_tunnel_switch_traverse(unit, cb, user_data);
    168        return rv;
    169     }
    170 #endif
    171 
    172 #ifdef BCM_KATANA_SUPPORT
    173     if (SOC_IS_KATANAX(unit) && soc_feature(unit, soc_feature_mpls)) {
    174         rv = bcm_kt_mpls_tunnel_switch_traverse(unit, cb, user_data);
    175         return rv;
    176     }
    177 #endif
    178 
    179 #ifdef BCM_TRIUMPH_SUPPORT
    180     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    181        if (soc_feature(unit, soc_feature_mpls_lsr_ecmp)) {
    182 #if (defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT))
    183            rv = bcmi_xgs5_mpls_tunnel_switch_traverse(unit, cb, user_data);
    184 #endif
    185        } else {
    186            rv = bcm_tr_mpls_tunnel_switch_traverse(unit, cb, user_data);
    187        }
    188        return rv;
    189     }
    190 #endif
    191 #endif
    192     return rv;
    193 }
    194 
    195 #endif
    196 
    197 /*
    198  * Function:
    199  *      bcm_mpls_vpn_id_create
    200  * Purpose:
    201  *      Create a VPN
    202  * Parameters:
    203  *      unit  - (IN)  Device Number
    204  *      info  - (IN/OUT) VPN configuration info
    205  * Returns:
    206  *      BCM_E_XXXX
    207  */
    208 int
    209 bcm_esw_mpls_vpn_id_create(int unit, bcm_mpls_vpn_config_t *info)
    210 {
    211 int rv = BCM_E_UNAVAIL;
    212 #ifdef BCM_MPLS_SUPPORT
    213 #ifdef BCM_TRIUMPH_SUPPORT
    214 #ifdef BCM_TOMAHAWK3_SUPPORT
    215     if (soc_feature(unit, soc_feature_th3_style_simple_mpls) &&
    216        ((info->flags & BCM_MPLS_VPN_VPWS) ||
    217         (info->flags & BCM_MPLS_VPN_VPLS))) {
    218         return BCM_E_UNAVAIL;
    219     }
    220 #endif
    221     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    222         rv = bcm_tr_mpls_lock (unit) ;
    223         if ( rv == BCM_E_NONE ) {
    224              rv = bcm_tr_mpls_vpn_id_create(unit, info);
    225              bcm_tr_mpls_unlock (unit);
    226         }
    227         return rv;
    228     }
    229 #endif
    230 #endif
    231     return rv;
    232 }
    233 
    234 /*
    235  * Function:
    236  *      bcm_mpls_vpn_id_destroy
    237  * Purpose:
    238  *      Destroy a VPN
    239  * Parameters:
    240  *      unit       - (IN)  Device Number
    241  *      vpn        - (IN)  VPN instance
    242  * Returns:
    243  *      BCM_E_XXXX
    244  */
    245 int
    246 bcm_esw_mpls_vpn_id_destroy(int unit, bcm_vpn_t vpn)
    247 {
    248 int rv = BCM_E_UNAVAIL;
    249 #ifdef BCM_MPLS_SUPPORT
    250 #ifdef BCM_TRIUMPH_SUPPORT
    251     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    252        rv = bcm_tr_mpls_lock(unit);
    253        if ( rv == BCM_E_NONE ) {
    254              rv = bcm_tr_mpls_vpn_id_destroy(unit, vpn);
    255              bcm_tr_mpls_unlock (unit);
    256        }
    257        return rv;
    258     }
    259 #endif
    260 #endif
    261     return rv;
    262 }
    263 
    264 /*
    265  * Function:
    266  *      bcm_mpls_vpn_id_destroy_all
    267  * Purpose:
    268  *      Destroy all VPNs
    269  * Parameters:
    270  *      unit       - (IN)  Device Number
    271  * Returns:
    272  *      BCM_E_XXXX
    273  */
    274 int
    275 bcm_esw_mpls_vpn_id_destroy_all(int unit)
    276 {
    277 int rv = BCM_E_UNAVAIL;
    278 #ifdef BCM_MPLS_SUPPORT
    279 #ifdef BCM_TRIUMPH_SUPPORT
    280     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    281        rv = bcm_tr_mpls_lock(unit);
    282        if ( rv == BCM_E_NONE ) {
    283            rv = bcm_tr_mpls_vpn_id_destroy_all(unit);
    284            bcm_tr_mpls_unlock (unit);
    285        }
    286        return rv;
    287     }
    288 #endif
    289 #endif
    290     return rv;
    291 }
    292 
    293 /*
    294  * Function:
    295  *      bcm_mpls_vpn_id_get
    296  * Purpose:
    297  *      Get a VPN
    298  * Parameters:
    299  *      unit  - (IN)  Device Number
    300  *      vpn   - (IN)  VPN instance
    301  *      info  - (OUT) VPN configuration info
    302  * Returns:
    303  *      BCM_E_XXXX
    304  */
    305 int
    306 bcm_esw_mpls_vpn_id_get(int unit, bcm_vpn_t vpn, bcm_mpls_vpn_config_t *info)
    307 {
    308 int rv = BCM_E_UNAVAIL;
    309 #ifdef BCM_MPLS_SUPPORT
    310 #ifdef BCM_TRIUMPH_SUPPORT
    311     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    312         rv = bcm_tr_mpls_lock(unit);
    313         if ( rv == BCM_E_NONE ) {
    314             rv =  bcm_tr_mpls_vpn_id_get(unit, vpn, info);
    315             bcm_tr_mpls_unlock (unit);
    316         }
    317         return rv;
    318     }
    319 #endif
    320 #endif
    321     return rv;
    322 }
    323 
    324 /*
    325  * Function:
    326  *      bcm_mpls_vpn_traverse
    327  * Purpose:
    328  *      MPLS VPN Traverse
    329  * Parameters:
    330  *      unit  - (IN)  Device Number
    331  *      cb   - (IN)  User callback function, called once per entry
    332  *      user_data  -  (IN/OUT) Cookie
    333  * Returns:
    334  *      BCM_E_XXXX
    335  */
    336 int 
    337 bcm_esw_mpls_vpn_traverse(int unit, bcm_mpls_vpn_traverse_cb cb, 
    338                                                           void *user_data)
    339 {
    340 int rv = BCM_E_UNAVAIL;
    341 #ifdef BCM_MPLS_SUPPORT
    342 #ifdef BCM_TRIUMPH_SUPPORT
    343     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    344         rv = bcm_tr_mpls_lock(unit);
    345         if ( rv == BCM_E_NONE ) {
    346             rv = bcm_tr_mpls_vpn_traverse(unit, cb, user_data);
    347             bcm_tr_mpls_unlock (unit);
    348         }
    349         return rv;
    350     }
    351 #endif
    352 #endif
    353     return rv;
    354 }
    355 
    356 /*
    357  * Function:
    358  *      bcm_mpls_port_add
    359  * Purpose:
    360  *      Add an mpls port to a VPN
    361  * Parameters:
    362  *      unit    - (IN) Device Number
    363  *      vpn     - (IN) VPN instance ID
    364  *      mpls_port - (IN/OUT) mpls port information (OUT : mpls_port_id)
    365  * Returns:
    366  *      BCM_E_XXX
    367  */
    368 int
    369 bcm_esw_mpls_port_add(int unit, bcm_vpn_t vpn, bcm_mpls_port_t *mpls_port)
    370 {
    371 int rv = BCM_E_UNAVAIL;
    372 #ifdef BCM_MPLS_SUPPORT
    373 #ifdef BCM_TRIUMPH_SUPPORT
    374 #ifdef BCM_TOMAHAWK3_SUPPORT
    375     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
    376         return BCM_E_UNAVAIL;
    377     }
    378 #endif
    379 
    380     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    381        L3_LOCK(unit);
    382        rv = bcm_tr_mpls_lock(unit);
    383        if ( rv == BCM_E_NONE ) {
    384            rv = bcm_tr_mpls_port_add(unit, vpn, mpls_port);
    385            bcm_tr_mpls_unlock (unit);
    386        }
    387        L3_UNLOCK(unit);
    388        return rv;
    389     }
    390 #endif
    391 #endif
    392     return rv;
    393 }
    394 
    395 /*
    396  * Function:
    397  *      bcm_mpls_port_delete
    398  * Purpose:
    399  *      Delete an mpls port from a VPN
    400  * Parameters:
    401  *      unit       - (IN) Device Number
    402  *      vpn        - (IN) VPN instance ID
    403  *      mpls_port_id - (IN) mpls port ID
    404  * Returns:
    405  *      BCM_E_XXX
    406  */
    407 int
    408 bcm_esw_mpls_port_delete(int unit, bcm_vpn_t vpn, bcm_gport_t mpls_port_id)
    409 {
    410 int rv = BCM_E_UNAVAIL;
    411 #ifdef BCM_MPLS_SUPPORT
    412 #ifdef BCM_TRIUMPH_SUPPORT
    413 #ifdef BCM_TOMAHAWK3_SUPPORT
    414     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
    415         return BCM_E_UNAVAIL;
    416     }
    417 #endif
    418 
    419     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    420        L3_LOCK(unit);
    421        rv = bcm_tr_mpls_lock(unit);
    422        if ( rv == BCM_E_NONE ) {
    423            rv = bcm_tr_mpls_port_delete(unit, vpn, mpls_port_id);
    424            bcm_tr_mpls_unlock (unit);
    425        }
    426        L3_UNLOCK(unit);
    427        return rv;
    428     }
    429 #endif
    430 #endif
    431     return rv;
    432 }
    433 
    434 /*
    435  * Function:
    436  *      bcm_mpls_port_delete_all
    437  * Purpose:
    438  *      Delete all mpls ports from a VPN
    439  * Parameters:
    440  *      unit - Device Number
    441  *      vpn - VPN instance ID
    442  * Returns:
    443  *      BCM_E_XXX
    444  */
    445 int
    446 bcm_esw_mpls_port_delete_all(int unit, bcm_vpn_t vpn)
    447 {
    448 int rv = BCM_E_UNAVAIL;
    449 #ifdef BCM_MPLS_SUPPORT
    450 #ifdef BCM_TRIUMPH_SUPPORT
    451 #ifdef BCM_TOMAHAWK3_SUPPORT
    452     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
    453         return BCM_E_UNAVAIL;
    454     }
    455 #endif
    456 
    457     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    458        L3_LOCK(unit);
    459        rv = bcm_tr_mpls_lock(unit);
    460        if ( rv == BCM_E_NONE ) {
    461            rv = bcm_tr_mpls_port_delete_all(unit, vpn);
    462            bcm_tr_mpls_unlock (unit);
    463        }
    464        L3_UNLOCK(unit);
    465        return rv;
    466     }
    467 #endif
    468 #endif
    469     return rv;
    470 }
    471 
    472 /*
    473  * Function:
    474  *      bcm_mpls_port_get
    475  * Purpose:
    476  *      Get an mpls port from a VPN
    477  * Parameters:
    478  *      unit    - (IN) Device Number
    479  *      vpn     - (IN) VPN instance ID
    480  *      mpls_port - (IN/OUT) mpls port information (IN : mpls_port_id)
    481  */
    482 int
    483 bcm_esw_mpls_port_get(int unit, bcm_vpn_t vpn, bcm_mpls_port_t *mpls_port)
    484 {
    485 int rv = BCM_E_UNAVAIL;
    486 #ifdef BCM_MPLS_SUPPORT
    487 #ifdef BCM_TRIUMPH_SUPPORT
    488 
    489 #ifdef BCM_TOMAHAWK3_SUPPORT
    490     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
    491         return BCM_E_UNAVAIL;
    492     }
    493 #endif
    494 
    495     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    496            rv = bcm_tr_mpls_lock(unit);
    497            if ( rv == BCM_E_NONE ) {
    498                rv = bcm_tr_mpls_port_get (unit, vpn, mpls_port);
    499                bcm_tr_mpls_unlock (unit);
    500            }
    501            return rv;
    502     }
    503 #endif
    504 #endif
    505     return rv;
    506 }
    507 
    508 /*
    509  * Function:
    510  *      bcm_mpls_port_get_all
    511  * Purpose:
    512  *      Get an mpls port from a VPN
    513  * Parameters:
    514  *      unit     - (IN) Device Number
    515  *      vpn      - (IN) VPN instance ID
    516  *      port_max   - (IN) Maximum number of ports in array
    517  *      port_array - (OUT) Array of mpls ports
    518  *      port_count - (OUT) Number of ports returned in array
    519  */
    520 int
    521 bcm_esw_mpls_port_get_all(int unit, bcm_vpn_t vpn, int port_max,
    522                             bcm_mpls_port_t *port_array, int *port_count)
    523 {
    524 int rv = BCM_E_UNAVAIL;
    525 #ifdef BCM_MPLS_SUPPORT
    526 #ifdef BCM_TRIUMPH_SUPPORT
    527 #ifdef BCM_TOMAHAWK3_SUPPORT
    528     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
    529         return BCM_E_UNAVAIL;
    530     }
    531 #endif
    532 
    533     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    534        rv = bcm_tr_mpls_lock(unit);
    535        if ( rv == BCM_E_NONE ) {
    536             rv = bcm_tr_mpls_port_get_all(unit, vpn, port_max,
    537                                   port_array, port_count);
    538             bcm_tr_mpls_unlock (unit);
    539        }
    540        return rv;
    541     }
    542 #endif
    543 #endif
    544     return rv;
    545 }
    546 
    547 /*
    548  * Function:
    549  *      bcm_mpls_tunnel_initiator_set
    550  * Purpose:
    551  *      Set the MPLS tunnel initiator parameters for an L3 interface.
    552  * Parameters:
    553  *      unit - Device Number
    554  *      intf - The egress L3 interface
    555  *      num_labels  - Number of labels in the array
    556  *      label_array - Array of MPLS label and header information
    557  * Returns:
    558  *      BCM_E_XXX
    559  */
    560 int
    561 bcm_esw_mpls_tunnel_initiator_set (int unit, bcm_if_t intf, int num_labels,
    562                                    bcm_mpls_egress_label_t *label_array)
    563 {
    564 int rv = BCM_E_UNAVAIL;
    565 #ifdef BCM_MPLS_SUPPORT
    566 #ifdef BCM_TRIUMPH_SUPPORT
    567     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    568             L3_LOCK(unit);
    569             rv = bcm_tr_mpls_lock(unit);
    570             if (rv == BCM_E_NONE ) {
    571 #if defined(BCM_APACHE_SUPPORT) || defined(BCM_TOMAHAWK2_SUPPORT) || \
    572                 defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
    573                 if (soc_feature(unit, soc_feature_egr_ip_tnl_mpls_double_wide) ||
    574                     (soc_feature(unit, soc_feature_th3_style_simple_mpls))) {
    575                     rv = bcmi_xgs5_mpls_tunnel_initiator_set(unit, intf,
    576                                             num_labels, label_array);
    577                 } else
    578 #endif
    579                 {
    580                     rv = bcm_tr_mpls_tunnel_initiator_set(unit, intf,
    581                                             num_labels, label_array);
    582                 }
    583                 bcm_tr_mpls_unlock (unit);
    584            }
    585            L3_UNLOCK(unit);
    586            return rv;
    587     }
    588 #endif
    589 #endif
    590     return rv;
    591 }
    592 
    593 /*
    594  * Function:
    595  *      bcm_mpls_tunnel_initiator_clear
    596  * Purpose:
    597  *      Clear the MPLS tunnel initiator parameters for an L3 interface.
    598  * Parameters:
    599  *      unit - Device Number
    600  *      intf - The egress L3 interface
    601  * Returns:
    602  *      BCM_E_XXX
    603  */
    604 int
    605 bcm_esw_mpls_tunnel_initiator_clear (int unit, bcm_if_t intf)
    606 {
    607 int rv = BCM_E_UNAVAIL;
    608 #ifdef BCM_MPLS_SUPPORT
    609 #ifdef BCM_TRIUMPH_SUPPORT
    610     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    611            L3_LOCK(unit);
    612            rv = bcm_tr_mpls_lock(unit);
    613            if ( rv == BCM_E_NONE ) {
    614 #if defined(BCM_APACHE_SUPPORT) || defined(BCM_TOMAHAWK2_SUPPORT) || \
    615                defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
    616                if (soc_feature(unit, soc_feature_egr_ip_tnl_mpls_double_wide) ||
    617                     (soc_feature(unit, soc_feature_th3_style_simple_mpls))) {
    618                    rv = bcmi_xgs5_mpls_tunnel_initiator_clear(unit, intf);
    619                } else
    620 #endif
    621                {
    622                    rv = bcm_tr_mpls_tunnel_initiator_clear(unit, intf);
    623                }
    624                bcm_tr_mpls_unlock (unit);
    625            }
    626            L3_UNLOCK(unit);
    627            return rv;
    628     }
    629 #endif
    630 #endif
    631     return rv;
    632 }
    633 
    634 /*
    635  * Function:
    636  *      bcm_mpls_tunnel_initiator_clear_all
    637  * Purpose:
    638  *      Clear all the MPLS tunnel initiator parameters all L3 Interfaces
    639  * Parameters:
    640  *      unit - Device Number
    641  * Returns:
    642  *      BCM_E_XXX
    643  */
    644 int
    645 bcm_esw_mpls_tunnel_initiator_clear_all (int unit)
    646 {
    647 int rv = BCM_E_UNAVAIL;
    648 #ifdef BCM_MPLS_SUPPORT
    649 #ifdef BCM_TRIUMPH_SUPPORT
    650     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    651         L3_LOCK(unit);
    652        if ( bcm_tr_mpls_lock (unit) == BCM_E_NONE ) {
    653 #if defined(BCM_APACHE_SUPPORT) || defined(BCM_TOMAHAWK2_SUPPORT) || \
    654            defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
    655            if (soc_feature(unit, soc_feature_egr_ip_tnl_mpls_double_wide) ||
    656                     (soc_feature(unit, soc_feature_th3_style_simple_mpls))) {
    657                rv = bcmi_xgs5_mpls_tunnel_initiator_clear_all(unit);
    658            } else
    659 #endif
    660            {
    661                rv = bcm_tr_mpls_tunnel_initiator_clear_all(unit);
    662            }
    663            bcm_tr_mpls_unlock (unit);
    664        }
    665        L3_UNLOCK(unit);
    666        return rv;
    667     }
    668 #endif
    669 #endif
    670     return rv;
    671 }
    672 
    673 /*
    674  * Function:
    675  *      bcm_mpls_tunnel_initiator_get
    676  * Purpose:
    677  *      Get the the MPLS tunnel initiator parameters for an L3 interface.
    678  * Parameters:
    679  *      unit        - (IN) Device Number
    680  *      intf        - (IN) The egress L3 interface
    681  *      label_max   - (IN) Number of entries in label_array
    682  *      label_array - (OUT) MPLS header information
    683  *      label_count - (OUT) Actual number of labels returned
    684  * Returns:
    685  *      BCM_E_XXX
    686  */
    687 int
    688 bcm_esw_mpls_tunnel_initiator_get (int unit, bcm_if_t intf, int label_max,
    689                                    bcm_mpls_egress_label_t *label_array,
    690                                    int *label_count)
    691 {
    692 int rv = BCM_E_UNAVAIL;
    693 #ifdef BCM_MPLS_SUPPORT
    694 #ifdef BCM_TRIUMPH_SUPPORT
    695     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    696            L3_LOCK(unit);
    697            rv = bcm_tr_mpls_lock(unit);
    698            if ( rv == BCM_E_NONE ) {
    699 #if defined(BCM_APACHE_SUPPORT) || defined(BCM_TOMAHAWK2_SUPPORT) || \
    700                defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
    701                if (soc_feature(unit, soc_feature_egr_ip_tnl_mpls_double_wide) ||
    702                     (soc_feature(unit, soc_feature_th3_style_simple_mpls))) {
    703                    rv  = bcmi_xgs5_mpls_tunnel_initiator_get(unit,
    704                                   intf, label_max,
    705                                   label_array, label_count);
    706                } else
    707 #endif
    708                {
    709                    rv = bcm_tr_mpls_tunnel_initiator_get(unit,
    710                                   intf, label_max,
    711                                   label_array, label_count);
    712                }
    713                bcm_tr_mpls_unlock (unit);
    714            }
    715            L3_UNLOCK(unit);
    716            return rv;
    717     }
    718 #endif
    719 #endif
    720     return rv;
    721 }
    722 
    723 /*
    724  * Function:
    725  *      bcm_mpls_tunnel_switch_add
    726  * Purpose:
    727  *      Add an MPLS label entry.
    728  * Parameters:
    729  *      unit - Device Number
    730  *      info - Label (switch) information
    731  * Returns:
    732  *      BCM_E_XXX
    733  */
    734 int
    735 bcm_esw_mpls_tunnel_switch_add (int unit, bcm_mpls_tunnel_switch_t *info)
    736 {
    737 int rv = BCM_E_UNAVAIL;
    738 #ifdef BCM_MPLS_SUPPORT
    739 #ifdef BCM_TRIUMPH3_SUPPORT
    740     if (SOC_IS_TRIUMPH3(unit) && soc_feature(unit, soc_feature_mpls)) {
    741            L3_LOCK(unit);
    742            rv = bcm_tr_mpls_lock(unit);
    743            if ( rv == BCM_E_NONE ) {
    744               rv = bcm_tr3_mpls_tunnel_switch_add(unit, info);
    745               bcm_tr_mpls_unlock (unit);
    746            }
    747            L3_UNLOCK(unit);
    748            return rv;
    749     }
    750 #endif
    751 #ifdef BCM_KATANA_SUPPORT
    752     if (SOC_IS_KATANAX(unit) && soc_feature(unit, soc_feature_mpls)) {
    753            L3_LOCK(unit);
    754            rv = bcm_tr_mpls_lock(unit);
    755            if ( rv == BCM_E_NONE ) {
    756               rv = bcm_kt_mpls_tunnel_switch_add(unit, info);
    757               bcm_tr_mpls_unlock (unit);
    758            }
    759            L3_UNLOCK(unit);
    760            return rv;
    761     }
    762 #endif
    763 #ifdef BCM_TRIUMPH_SUPPORT
    764     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    765            L3_LOCK(unit);
    766            rv = bcm_tr_mpls_lock(unit);
    767            if ( rv == BCM_E_NONE ) {
    768               if (soc_feature(unit, soc_feature_mpls_lsr_ecmp)) {
    769 #if (defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT))
    770                   rv = bcmi_xgs5_mpls_tunnel_switch_add(unit, info);
    771 #endif
    772               } else {
    773                   rv = bcm_tr_mpls_tunnel_switch_add(unit, info);
    774               }
    775            }
    776            bcm_tr_mpls_unlock (unit);
    777            L3_UNLOCK(unit);
    778            return rv;
    779     }
    780 #endif
    781 #endif
    782     return rv;
    783 }
    784 
    785 /*
    786  * Function:
    787  *      bcm_mpls_tunnel_switch_delete
    788  * Purpose:
    789  *      Delete an MPLS label entry.
    790  * Parameters:
    791  *      unit - Device Number
    792  *      info - Label (switch) information
    793  * Returns:
    794  *      BCM_E_XXX
    795  */
    796 int
    797 bcm_esw_mpls_tunnel_switch_delete (int unit, bcm_mpls_tunnel_switch_t *info)
    798 {
    799 int rv = BCM_E_UNAVAIL;
    800 #ifdef BCM_MPLS_SUPPORT
    801 #ifdef BCM_TRIUMPH3_SUPPORT
    802     if (SOC_IS_TRIUMPH3(unit) && soc_feature(unit, soc_feature_mpls)) {
    803            L3_LOCK(unit);
    804            rv = bcm_tr_mpls_lock(unit);
    805            if ( rv == BCM_E_NONE ) {
    806               rv = bcm_tr3_mpls_tunnel_switch_delete(unit, info);
    807               bcm_tr_mpls_unlock (unit);
    808            }
    809            L3_UNLOCK(unit);
    810            return rv;
    811     }
    812 #endif
    813 #ifdef BCM_KATANA_SUPPORT
    814     if (SOC_IS_KATANAX(unit) && soc_feature(unit, soc_feature_mpls)) {
    815            L3_LOCK(unit);
    816            rv = bcm_tr_mpls_lock(unit);
    817            if ( rv == BCM_E_NONE ) {
    818               rv = bcm_kt_mpls_tunnel_switch_delete(unit, info);
    819               bcm_tr_mpls_unlock (unit);
    820            }
    821            L3_UNLOCK(unit);
    822            return rv;
    823     }
    824 #endif
    825 #ifdef BCM_TRIUMPH_SUPPORT
    826     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    827            L3_LOCK(unit);
    828            rv = bcm_tr_mpls_lock(unit);
    829            if ( rv == BCM_E_NONE ) {
    830               if (soc_feature(unit, soc_feature_mpls_lsr_ecmp)) {
    831 #if (defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT))
    832                   rv = bcmi_xgs5_mpls_tunnel_switch_delete(unit, info);
    833 #endif
    834               } else {
    835                   rv = bcm_tr_mpls_tunnel_switch_delete(unit, info);
    836               }
    837            }
    838            bcm_tr_mpls_unlock (unit);
    839            L3_UNLOCK(unit);
    840            return rv;
    841     }
    842 #endif
    843 #endif
    844     return rv;
    845 }
    846 
    847 /*
    848  * Function:
    849  *      bcm_mpls_tunnel_switch_delete_all
    850  * Purpose:
    851  *      Delete all MPLS label entries.
    852  * Parameters:
    853  *      unit   - Device Number
    854  * Returns:
    855  *      BCM_E_XXX
    856  */
    857 int
    858 bcm_esw_mpls_tunnel_switch_delete_all (int unit)
    859 {
    860 int rv = BCM_E_UNAVAIL;
    861 #ifdef BCM_MPLS_SUPPORT
    862 #ifdef BCM_TRIUMPH3_SUPPORT
    863     if (SOC_IS_TRIUMPH3(unit) && soc_feature(unit, soc_feature_mpls)) {
    864            L3_LOCK(unit);
    865            rv = bcm_tr_mpls_lock(unit);
    866            if ( rv == BCM_E_NONE ) {
    867               rv = bcm_tr3_mpls_tunnel_switch_delete_all(unit);
    868               bcm_tr_mpls_unlock (unit);
    869            }
    870            L3_UNLOCK(unit);
    871            return rv;
    872     }
    873 #endif
    874 #ifdef BCM_KATANA_SUPPORT
    875     if (SOC_IS_KATANAX(unit) && soc_feature(unit, soc_feature_mpls)) {
    876            L3_LOCK(unit);
    877            rv = bcm_tr_mpls_lock(unit);
    878            if ( rv == BCM_E_NONE ) {
    879               rv = bcm_kt_mpls_tunnel_switch_delete_all(unit);
    880               bcm_tr_mpls_unlock (unit);
    881            }
    882            L3_UNLOCK(unit);
    883            return rv;
    884     }
    885 #endif
    886 #ifdef BCM_TRIUMPH_SUPPORT
    887     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    888               L3_LOCK(unit);
    889               rv = bcm_tr_mpls_lock(unit);
    890               if ( rv == BCM_E_NONE ) {
    891                   if (soc_feature(unit, soc_feature_mpls_lsr_ecmp)) {
    892 #if (defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT))
    893                       rv = bcmi_xgs5_mpls_tunnel_switch_delete_all(unit);
    894 #endif
    895                   } else {
    896                       rv = bcm_tr_mpls_tunnel_switch_delete_all(unit);
    897                   }
    898               }
    899               bcm_tr_mpls_unlock (unit);
    900               L3_UNLOCK(unit);
    901               return rv;
    902     }
    903 #endif
    904 #endif
    905     return rv;
    906 }
    907 
    908 /*
    909  * Function:
    910  *      bcm_mpls_tunnel_switch_get
    911  * Purpose:
    912  *      Get an MPLS label entry.
    913  * Parameters:
    914  *      unit - Device Number
    915  *      info - Label (switch) information
    916  * Returns:
    917  *      BCM_E_XXX
    918  */
    919 int
    920 bcm_esw_mpls_tunnel_switch_get (int unit, bcm_mpls_tunnel_switch_t *info)
    921 {
    922 int rv = BCM_E_UNAVAIL;
    923 #ifdef BCM_MPLS_SUPPORT
    924 #ifdef BCM_TRIUMPH3_SUPPORT
    925     if (SOC_IS_TRIUMPH3(unit) && soc_feature(unit, soc_feature_mpls)) {
    926            L3_LOCK(unit);
    927            rv = bcm_tr_mpls_lock(unit);
    928            if ( rv == BCM_E_NONE ) {
    929               rv = bcm_tr3_mpls_tunnel_switch_get(unit, info);
    930               bcm_tr_mpls_unlock (unit);
    931            }
    932            L3_UNLOCK(unit);
    933            return rv;
    934     }
    935 #endif
    936 #ifdef BCM_KATANA_SUPPORT
    937     if (SOC_IS_KATANAX(unit) && soc_feature(unit, soc_feature_mpls)) {
    938            rv = bcm_tr_mpls_lock(unit);
    939            if ( rv == BCM_E_NONE ) {
    940               rv = bcm_kt_mpls_tunnel_switch_get(unit, info);
    941               bcm_tr_mpls_unlock (unit);
    942            }
    943            return rv;
    944     }
    945 #endif
    946 #ifdef BCM_TRIUMPH_SUPPORT
    947     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
    948               rv = bcm_tr_mpls_lock(unit);
    949               if ( rv == BCM_E_NONE ) {
    950                    if (soc_feature(unit, soc_feature_mpls_lsr_ecmp)) {
    951 #if (defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT))
    952                        rv = bcmi_xgs5_mpls_tunnel_switch_get(unit, info);
    953 #endif
    954                    } else {
    955                        rv = bcm_tr_mpls_tunnel_switch_get(unit, info);
    956                    }
    957               }
    958               bcm_tr_mpls_unlock (unit);
    959               return rv;
    960     }
    961 #endif
    962 #endif
    963     return rv;
    964 }
    965 
    966 /*
    967  * Function:
    968  *      bcm_mpls_tunnel_switch_traverse
    969  * Purpose:
    970  *      Traverse all valid MPLS label entries and call the
    971  *      supplied callback routine.
    972  * Parameters:
    973  *      unit      - Device Number
    974  *      cb        - User callback function, called once per MPLS entry.
    975  *      user_data - cookie
    976  * Returns:
    977  *      BCM_E_XXX
    978  */
    979 int
    980 bcm_esw_mpls_tunnel_switch_traverse(int unit,
    981                                     bcm_mpls_tunnel_switch_traverse_cb cb,
    982                                     void *user_data)
    983 {
    984 int rv = BCM_E_UNAVAIL;
    985 #ifdef BCM_MPLS_SUPPORT
    986 #ifdef BCM_TRIUMPH3_SUPPORT
    987     if (SOC_IS_TRIUMPH3(unit) && soc_feature(unit, soc_feature_mpls)) {
    988            L3_LOCK(unit);
    989            rv = bcm_tr_mpls_lock(unit);
    990            if ( rv == BCM_E_NONE ) {
    991               rv = bcm_tr3_mpls_tunnel_switch_traverse(unit, cb, user_data);
    992               bcm_tr_mpls_unlock (unit);
    993            }
    994            L3_UNLOCK(unit);
    995            return rv;
    996     }
    997 #endif
    998 #ifdef BCM_KATANA_SUPPORT
    999     if (SOC_IS_KATANAX(unit) && soc_feature(unit, soc_feature_mpls)) {
   1000            rv = bcm_tr_mpls_lock(unit);
   1001            if ( rv == BCM_E_NONE ) {
   1002               rv = bcm_kt_mpls_tunnel_switch_traverse(unit, cb, user_data);
   1003               bcm_tr_mpls_unlock (unit);
   1004            }
   1005            return rv;
   1006     }
   1007 #endif
   1008 #ifdef BCM_TRIUMPH_SUPPORT
   1009     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
   1010               rv = bcm_tr_mpls_lock(unit);
   1011               if ( rv == BCM_E_NONE ) {
   1012                    if (soc_feature(unit, soc_feature_mpls_lsr_ecmp)) {
   1013 #if (defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT))
   1014                        rv = bcmi_xgs5_mpls_tunnel_switch_traverse(unit, cb, user_data);
   1015 #endif
   1016                    } else {
   1017                        rv = bcm_tr_mpls_tunnel_switch_traverse(unit, cb, user_data);
   1018                    }
   1019                    bcm_tr_mpls_unlock (unit);
   1020               }
   1021               return rv;
   1022     }
   1023 #endif
   1024 #endif
   1025     return rv;
   1026 }
   1027 
   1028 /*
   1029  * Function:
   1030  *      _bcm_esw_mpls_port_source_vp_lag_set
   1031  * Purpose:
   1032  *      Set source VP LAG for a mpls virtual port.
   1033  * Parameters:
   1034  *      unit  - (IN) SOC unit number.
   1035  *      gport - (IN) mpls virtual port GPORT ID.
   1036  *      vp_lag_vp - (IN) VP representing the VP LAG.
   1037  * Returns:
   1038  *      BCM_X_XXX
   1039  */
   1040 int
   1041 _bcm_esw_mpls_port_source_vp_lag_set(int unit, bcm_gport_t gport,
   1042         int vp_lag_vp)
   1043 {
   1044     int rv = BCM_E_UNAVAIL;
   1045 
   1046 #if defined(BCM_TRIDENT2_SUPPORT)
   1047     if (soc_feature(unit, soc_feature_mpls)
   1048         && soc_feature(unit, soc_feature_vp_lag)) {
   1049         rv = bcm_tr_mpls_lock(unit);
   1050         if (rv == BCM_E_NONE) {
   1051             rv = bcm_td2_mpls_port_source_vp_lag_set(unit, gport, vp_lag_vp);
   1052             bcm_tr_mpls_unlock(unit);
   1053         }
   1054     }
   1055 #endif /* BCM_TRIDENT2_SUPPORT */
   1056 
   1057     return rv;
   1058 }
   1059 
   1060 /*
   1061  * Function:
   1062  *      _bcm_esw_mpls_port_source_vp_lag_clear
   1063  * Purpose:
   1064  *      Clear source VP LAG for a mpls virtual port.
   1065  * Parameters:
   1066  *      unit  - (IN) SOC unit number.
   1067  *      gport - (IN) mpls virtual port GPORT ID.
   1068  *      vp_lag_vp - (IN) VP representing the VP LAG.
   1069  * Returns:
   1070  *      BCM_X_XXX
   1071  */
   1072 int
   1073 _bcm_esw_mpls_port_source_vp_lag_clear(int unit, bcm_gport_t gport,
   1074         int vp_lag_vp)
   1075 {
   1076     int rv = BCM_E_UNAVAIL;
   1077 
   1078 #if defined(BCM_TRIDENT2_SUPPORT)
   1079     if (soc_feature(unit, soc_feature_mpls)
   1080         && soc_feature(unit, soc_feature_vp_lag)) {
   1081         rv = bcm_tr_mpls_lock(unit);
   1082         if (rv == BCM_E_NONE) {
   1083             rv = bcm_td2_mpls_port_source_vp_lag_clear(unit, gport, vp_lag_vp);
   1084             bcm_tr_mpls_unlock(unit);
   1085         }
   1086     }
   1087 #endif /* BCM_TRIDENT2_SUPPORT */
   1088 
   1089     return rv;
   1090 }
   1091 
   1092 /*
   1093  * Function:
   1094  *      _bcm_esw_mpls_port_source_vp_lag_get
   1095  * Purpose:
   1096  *      Get source VP LAG for a mpls virtual port.
   1097  * Parameters:
   1098  *      unit  - (IN) SOC unit number.
   1099  *      gport - (IN) mpls virtual port GPORT ID.
   1100  *      vp_lag_vp - (OUT) VP representing the VP LAG.
   1101  * Returns:
   1102  *      BCM_X_XXX
   1103  */
   1104 int
   1105 _bcm_esw_mpls_port_source_vp_lag_get(int unit, bcm_gport_t gport,
   1106         int *vp_lag_vp)
   1107 {
   1108     int rv = BCM_E_UNAVAIL;
   1109 
   1110 #if defined(BCM_TRIDENT2_SUPPORT)
   1111     if (soc_feature(unit, soc_feature_mpls)
   1112         && soc_feature(unit, soc_feature_vp_lag)) {
   1113         rv = bcm_tr_mpls_lock(unit);
   1114         if (rv == BCM_E_NONE) {
   1115             rv = bcm_td2_mpls_port_source_vp_lag_get(unit, gport, vp_lag_vp);
   1116             bcm_tr_mpls_unlock(unit);
   1117         }
   1118     }
   1119 #endif /* BCM_TRIDENT2_SUPPORT */
   1120 
   1121     return rv;
   1122 }
   1123 
   1124 /*
   1125  * Function:
   1126  *      bcm_mpls_entropy_identifier_add
   1127  * Purpose:
   1128  *      Add an MPLS entropy label identifier
   1129  * Parameters:
   1130  *      unit - Device Number
   1131  *      info - Entropy Label information
   1132  * Returns:
   1133  *      BCM_E_XXX
   1134  */
   1135 int 
   1136 bcm_esw_mpls_entropy_identifier_add(
   1137     int unit, 
   1138     uint32 options, 
   1139     bcm_mpls_entropy_identifier_t *info)
   1140 {
   1141     int rv = BCM_E_UNAVAIL;
   1142 #ifdef BCM_MPLS_SUPPORT
   1143 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1144     if ((options & BCM_MPLS_ENTROPY_LABEL_IDENTIFIER_TOS) &&
   1145             soc_feature(unit, soc_feature_td2p_mpls_entropy_label)) {
   1146         L3_LOCK(unit);
   1147         rv = bcm_tr_mpls_lock(unit);
   1148         if ( rv == BCM_E_NONE ) {
   1149             rv = bcm_td2p_mpls_entropy_identifier_add(unit, options,
   1150                     info);
   1151             bcm_tr_mpls_unlock (unit);
   1152         }
   1153         L3_UNLOCK(unit);
   1154         return rv;
   1155     }
   1156 #endif
   1157 #endif
   1158     return rv;
   1159 }
   1160 
   1161 /*
   1162  * Function:
   1163  *      bcm_mpls_entropy_identifier_delete
   1164  * Purpose:
   1165  *      Delete an MPLS entropy label identifier
   1166  * Parameters:
   1167  *      unit - Device Number
   1168  *      info - Entropy Label information
   1169  * Returns:
   1170  *      BCM_E_XXX
   1171  */
   1172 int 
   1173 bcm_esw_mpls_entropy_identifier_delete(
   1174     int unit, 
   1175     bcm_mpls_entropy_identifier_t *info)
   1176 {
   1177     int rv = BCM_E_UNAVAIL;
   1178 #ifdef BCM_MPLS_SUPPORT
   1179 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1180     if (soc_feature(unit, soc_feature_td2p_mpls_entropy_label)) {
   1181         L3_LOCK(unit);
   1182         rv = bcm_tr_mpls_lock(unit);
   1183         if ( rv == BCM_E_NONE ) {
   1184             rv = bcm_td2p_mpls_entropy_identifier_delete(unit, info);
   1185             bcm_tr_mpls_unlock (unit);
   1186         }
   1187         L3_UNLOCK(unit);
   1188         return rv;
   1189     }
   1190 #endif
   1191 #endif
   1192     return rv;
   1193 }
   1194 
   1195 /*
   1196  * Function:
   1197  *      bcm_mpls_entropy_identifier_delete_all
   1198  * Purpose:
   1199  *      Delete all MPLS entropy label identifier entries.
   1200  * Parameters:
   1201  *      unit   - Device Number
   1202  * Returns:
   1203  *      BCM_E_XXX
   1204  */
   1205 int 
   1206 bcm_esw_mpls_entropy_identifier_delete_all(
   1207     int unit)
   1208 {
   1209     int rv = BCM_E_UNAVAIL;
   1210 #ifdef BCM_MPLS_SUPPORT
   1211 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1212     if (soc_feature(unit, soc_feature_td2p_mpls_entropy_label)) {
   1213         L3_LOCK(unit);
   1214         rv = bcm_tr_mpls_lock(unit);
   1215         if ( rv == BCM_E_NONE ) {
   1216             rv = bcm_td2p_mpls_entropy_identifier_delete_all(unit);
   1217             bcm_tr_mpls_unlock (unit);
   1218         }
   1219         L3_UNLOCK(unit);
   1220         return rv;
   1221     }
   1222 #endif
   1223 #endif
   1224     return rv;
   1225 }
   1226 
   1227 /*
   1228  * Function:
   1229  *      bcm_mpls_entropy_identifier_get
   1230  * Purpose:
   1231  *      Get an MPLS entrpoy label identifier entry
   1232  * Parameters:
   1233  *      unit - Device Number
   1234  *      info - Entropy Label information
   1235  * Returns:
   1236  *      BCM_E_XXX
   1237  */
   1238 int 
   1239 bcm_esw_mpls_entropy_identifier_get(
   1240     int unit, 
   1241     bcm_mpls_entropy_identifier_t *info)
   1242 {
   1243     int rv = BCM_E_UNAVAIL;
   1244 #ifdef BCM_MPLS_SUPPORT
   1245 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1246     if (soc_feature(unit, soc_feature_td2p_mpls_entropy_label)) {
   1247         L3_LOCK(unit);
   1248         rv = bcm_tr_mpls_lock(unit);
   1249         if ( rv == BCM_E_NONE ) {
   1250             rv = bcm_td2p_mpls_entropy_identifier_get(unit, info);
   1251             bcm_tr_mpls_unlock (unit);
   1252         }
   1253         L3_UNLOCK(unit);
   1254         return rv;
   1255     }
   1256 #endif
   1257 #endif
   1258     return rv;
   1259 }
   1260 
   1261 /*
   1262  * Function:
   1263  *      bcm_mpls_entropy_identifier_traverse
   1264  * Purpose:
   1265  *      Traverse all valid MPLS entropy label identifier entries 
   1266  *      and call the supplied callback routine.
   1267  * Parameters:
   1268  *      unit      - Device Number
   1269  *      cb        - User callback function, called once per MPLS ELI entry.
   1270  *      user_data - cookie
   1271  * Returns:
   1272  *      BCM_E_XXX
   1273  */
   1274 int 
   1275 bcm_esw_mpls_entropy_identifier_traverse(
   1276     int unit, 
   1277     bcm_mpls_entropy_identifier_traverse_cb cb, 
   1278     void *user_data)
   1279 {
   1280     int rv = BCM_E_UNAVAIL;
   1281 #ifdef BCM_MPLS_SUPPORT
   1282 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1283     if (soc_feature(unit, soc_feature_td2p_mpls_entropy_label)) {
   1284         L3_LOCK(unit);
   1285         rv = bcm_tr_mpls_lock(unit);
   1286         if ( rv == BCM_E_NONE ) {
   1287             rv = bcm_td2p_mpls_entropy_identifier_traverse(unit, cb, user_data);
   1288             bcm_tr_mpls_unlock (unit);
   1289         }
   1290         L3_UNLOCK(unit);
   1291         return rv;
   1292     }
   1293 #endif
   1294 #endif
   1295     return rv;
   1296 }
   1297 
   1298 /*
   1299  * Function:
   1300  *      bcm_esw_mpls_exp_map_create
   1301  * Purpose:
   1302  *      Create an MPLS EXP map instance.
   1303  * Parameters:
   1304  *      unit        - (IN)  SOC unit #
   1305  *      flags       - (IN)  MPLS flags
   1306  *      exp_map_id  - (OUT) Allocated EXP map ID
   1307  * Returns:
   1308  *      BCM_E_XXX
   1309  */
   1310 int
   1311 bcm_esw_mpls_exp_map_create(int unit, uint32 flags, int *exp_map_id)
   1312 {
   1313 int rv = BCM_E_UNAVAIL;
   1314 #ifdef BCM_MPLS_SUPPORT
   1315 #ifdef BCM_TRIUMPH_SUPPORT
   1316     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
   1317               rv = bcm_tr_mpls_lock(unit);
   1318          if ( rv == BCM_E_NONE ) {
   1319               rv = bcm_tr_mpls_exp_map_create(unit, flags, exp_map_id);
   1320               bcm_tr_mpls_unlock (unit);
   1321          }
   1322          return rv;
   1323     }
   1324 #endif
   1325 #endif
   1326     return rv;
   1327 }
   1328 
   1329 /*
   1330  * Function:
   1331  *      bcm_esw_mpls_exp_map_destroy
   1332  * Purpose:
   1333  *      Destroy an existing MPLS EXP map instance.
   1334  * Parameters:
   1335  *      unit       - (IN) SOC unit #
   1336  *      exp_map_id - (IN) EXP map ID
   1337  * Returns:
   1338  *      BCM_E_XXX
   1339  */
   1340 int
   1341 bcm_esw_mpls_exp_map_destroy(int unit, int exp_map_id)
   1342 {
   1343 int rv = BCM_E_UNAVAIL;
   1344 #ifdef BCM_MPLS_SUPPORT
   1345 #ifdef BCM_TRIUMPH_SUPPORT
   1346     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
   1347               rv = bcm_tr_mpls_lock(unit);
   1348          if ( rv == BCM_E_NONE ) {
   1349               rv = bcm_tr_mpls_exp_map_destroy(unit, exp_map_id);
   1350               bcm_tr_mpls_unlock (unit);
   1351          }
   1352          return rv;
   1353     }
   1354 #endif
   1355 #endif
   1356     return rv;
   1357 }
   1358 
   1359 /*
   1360  * Function:
   1361  *      bcm_esw_mpls_exp_map_set
   1362  * Purpose:
   1363  *      Set the mapping of { internal priority, color }
   1364  *      to a EXP value for MPLS headers
   1365  *      in the specified EXP map instance.
   1366  * Parameters:
   1367  *      unit         - (IN) SOC unit #
   1368  *      exp_map_id   - (IN) EXP map ID
   1369  *      priority     - (IN) Internal priority
   1370  *      color        - (IN) bcmColor*
   1371  *      exp          - (IN) EXP value
   1372  * Returns:
   1373  *      BCM_E_XXX
   1374  */
   1375 int
   1376 bcm_esw_mpls_exp_map_set(int unit, int exp_map_id,
   1377                          bcm_mpls_exp_map_t *exp_map)
   1378 {
   1379 int rv = BCM_E_UNAVAIL;
   1380 #ifdef BCM_MPLS_SUPPORT
   1381 #ifdef BCM_TRIUMPH_SUPPORT
   1382     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
   1383               rv = bcm_tr_mpls_lock(unit);
   1384        if ( rv == BCM_E_NONE ) {
   1385              rv = bcm_tr_mpls_exp_map_set(unit, exp_map_id, exp_map);
   1386              bcm_tr_mpls_unlock (unit);
   1387        }
   1388        return rv;
   1389     }
   1390 #endif
   1391 #endif
   1392     return rv;
   1393 }
   1394     
   1395 /*
   1396  * Function:
   1397  *      bcm_esw_mpls_exp_map_get
   1398  * Purpose:
   1399  *      Get the mapping of { internal priority, color }
   1400  *      to a EXP value for MPLS headers
   1401  *      in the specified EXP map instance.
   1402  * Parameters:
   1403  *      unit         - (IN)  SOC unit #
   1404  *      exp_map_id   - (IN)  EXP map ID
   1405  *      priority     - (IN)  Internal priority
   1406  *      color        - (IN)  bcmColor*
   1407  *      exp          - (OUT) EXP value
   1408  * Returns:
   1409  *      BCM_E_XXX
   1410  */
   1411 int
   1412 bcm_esw_mpls_exp_map_get(int unit, int exp_map_id,
   1413                          bcm_mpls_exp_map_t *exp_map)
   1414 {
   1415 int rv = BCM_E_UNAVAIL;
   1416 #ifdef BCM_MPLS_SUPPORT
   1417 #ifdef BCM_TRIUMPH_SUPPORT
   1418     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
   1419               rv = bcm_tr_mpls_lock(unit);
   1420          if ( rv == BCM_E_NONE ) {
   1421               rv = bcm_tr_mpls_exp_map_get(unit, exp_map_id, exp_map);
   1422               bcm_tr_mpls_unlock (unit);
   1423          }
   1424          return rv;
   1425     }
   1426 #endif
   1427 #endif
   1428     return rv;
   1429 }
   1430 
   1431 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1432 /*
   1433  * Function:
   1434  *     bcmi_td2p_mpls_tunnel_stat_get_table_info
   1435  * Description:
   1436  *      Provides relevant flex table information(table-name,index with
   1437  *      direction) based on the mpls tunnel info.
   1438  *
   1439  * Parameters:
   1440  *      unit             - (IN) unit number
   1441  *      intf_id          - (IN) Interface id of a egress L3 object.
   1442  *      num_of_tables    - (OUT) Number of flex counter tables
   1443  *      table_info       - (OUT) Flex counter tables information
   1444  *
   1445  * Return Value:
   1446  *      BCM_E_XXX
   1447  */
   1448 static
   1449 bcm_error_t bcmi_td2p_mpls_tunnel_stat_get_table_info(
   1450            int                        unit,
   1451            bcm_if_t                   intf_id,
   1452            uint32                     *num_of_tables,
   1453            bcm_stat_flex_table_info_t *table_info)
   1454 {
   1455     bcm_l3_egress_t egr_intf = {0};
   1456     egr_l3_intf_entry_t if_entry;
   1457     int mpls_index = 0;
   1458 
   1459     (*num_of_tables) = 0;
   1460     if (!soc_feature(unit,soc_feature_advanced_flex_counter)) {
   1461         return BCM_E_UNAVAIL;
   1462     }
   1463     BCM_IF_ERROR_RETURN(bcm_esw_l3_egress_get(unit, intf_id, &egr_intf));
   1464 
   1465     /* L3 interface info */
   1466     SOC_IF_ERROR_RETURN(READ_EGR_L3_INTFm(unit,
   1467                                 MEM_BLOCK_ANY, egr_intf.intf, &if_entry));
   1468     mpls_index = soc_EGR_L3_INTFm_field32_get(unit, &if_entry,
   1469                                               MPLS_TUNNEL_INDEXf);
   1470 #if defined(BCM_TRIDENT3_SUPPORT)
   1471     if (SOC_IS_TRIDENT3X(unit) && soc_feature(unit, soc_feature_td3_style_mpls)) {
   1472         table_info[*num_of_tables].table = EGR_IP_TUNNEL_MPLS_DOUBLE_WIDEm;
   1473     } else
   1474 #endif
   1475     {
   1476         table_info[*num_of_tables].table = EGR_IP_TUNNEL_MPLSm;
   1477     }
   1478     table_info[*num_of_tables].index = mpls_index;
   1479     table_info[*num_of_tables].direction = bcmStatFlexDirectionEgress;
   1480     (*num_of_tables)++;
   1481     return BCM_E_NONE;
   1482 }
   1483 
   1484 /*
   1485  * Function:
   1486  *      bcmi_td2p_mpls_tunnel_stat_attach
   1487  *
   1488  * Description:
   1489  *      Attach counters entries to the mpls tunnel derived from the
   1490  *      given L3 Egress interface
   1491  *
   1492  * Parameters:
   1493  *      unit             - (IN) unit number
   1494  *      intf_id          - (IN) Interface id
   1495  *      stat_counter_id  - (IN) Stat Counter ID
   1496  *
   1497  * Return Value:
   1498  *       BCM_E_XXX
   1499  */
   1500 STATIC bcm_error_t bcmi_td2p_mpls_tunnel_stat_attach(
   1501             int      unit,
   1502             bcm_if_t intf_id,
   1503             uint32   stat_counter_id)
   1504 {
   1505     soc_mem_t                  table = 0;
   1506     bcm_stat_flex_direction_t  direction = bcmStatFlexDirectionEgress;
   1507     uint32                     pool_number = 0;
   1508     uint32                     base_index = 0;
   1509     bcm_stat_flex_mode_t       offset_mode = 0;
   1510     bcm_stat_object_t          object = bcmStatObjectEgrMplsTunnelLabel;
   1511     bcm_stat_group_mode_t      group_mode = bcmStatGroupModeSingle;
   1512     uint32                     count = 0;
   1513     uint32                     actual_num_tables = 0;
   1514     uint32                     num_of_tables = 0;
   1515     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   1516 
   1517     _bcm_esw_stat_get_counter_id_info(
   1518                   unit, stat_counter_id,
   1519                   &group_mode, &object,
   1520                   &offset_mode, &pool_number, &base_index);
   1521     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_object(unit,
   1522                          object, &direction));
   1523     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit, group_mode));
   1524     BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info(unit,
   1525                         object, 1, &actual_num_tables, &table, &direction));
   1526 
   1527     BCM_IF_ERROR_RETURN(bcmi_td2p_mpls_tunnel_stat_get_table_info(
   1528                         unit, intf_id, &num_of_tables, &table_info[0]));
   1529     for (count = 0; count < num_of_tables ; count++) {
   1530          if ((table_info[count].direction == direction) &&
   1531              (table_info[count].table == table) ) {
   1532               if (direction == bcmStatFlexDirectionIngress) {
   1533                   return _bcm_esw_stat_flex_attach_ingress_table_counters(
   1534                          unit,
   1535                          table_info[count].table,
   1536                          table_info[count].index,
   1537                          offset_mode,
   1538                          base_index,
   1539                          pool_number);
   1540               } else {
   1541                   return _bcm_esw_stat_flex_attach_egress_table_counters(
   1542                          unit,
   1543                          table_info[count].table,
   1544                          table_info[count].index,
   1545                          object,
   1546                          offset_mode,
   1547                          base_index,
   1548                          pool_number);
   1549               }
   1550          }
   1551     }
   1552     return BCM_E_NOT_FOUND;
   1553 }
   1554 
   1555 
   1556 /*
   1557  * Function:
   1558  *       bcmi_td2p_mpls_tunnel_stat_detach
   1559  *
   1560  * Description:
   1561  *       Detach  counters entries to the mpls tunnel derived from the
   1562  *       given L3 Egress interface.
   1563  *
   1564  * Parameters:
   1565  *       unit             - (IN) unit number
   1566  *       intf_id          - (IN) Interface id of a egress L3 object.
   1567  *       stat_counter_id  - (IN) Stat Counter ID.
   1568  *
   1569  * Return Value:
   1570  *       BCM_E_XXX
   1571  */
   1572 STATIC
   1573 bcm_error_t bcmi_td2p_mpls_tunnel_stat_detach(
   1574             int      unit,
   1575             bcm_if_t intf_id,
   1576             uint32 stat_counter_id)
   1577 {
   1578     uint32                     count = 0;
   1579     uint32                     num_of_tables = 0;
   1580     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   1581     bcm_error_t                rv = BCM_E_NONE;
   1582     bcm_error_t                err_code[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {BCM_E_NONE};
   1583     bcm_stat_group_mode_t      group_mode = bcmStatGroupModeSingle;
   1584     bcm_stat_object_t          object = bcmStatObjectEgrMplsTunnelLabel;
   1585     bcm_stat_flex_mode_t       offset_mode = 0;
   1586     uint32                     pool_number = 0;
   1587     uint32                     base_index = 0;
   1588 
   1589     BCM_IF_ERROR_RETURN(bcmi_td2p_mpls_tunnel_stat_get_table_info(
   1590                    unit, intf_id, &num_of_tables, &table_info[0]));
   1591     if (stat_counter_id != 0) {
   1592         _bcm_esw_stat_get_counter_id_info(
   1593                 unit, stat_counter_id,
   1594                 &group_mode, &object,
   1595                 &offset_mode, &pool_number, &base_index);
   1596     }
   1597     for (count = 0; count < num_of_tables ; count++) {
   1598          if (table_info[count].direction == bcmStatFlexDirectionIngress) {
   1599              rv = _bcm_esw_stat_flex_detach_ingress_table_counters(
   1600                       unit, table_info[count].table, table_info[count].index);
   1601             if (BCM_E_NONE != rv &&
   1602                 BCM_E_NONE == err_code[bcmStatFlexDirectionIngress]) {
   1603                 err_code[bcmStatFlexDirectionIngress] = rv;
   1604             }
   1605          } else {
   1606              rv = _bcm_esw_stat_flex_detach_egress_table_counters(
   1607                         unit, object,
   1608                         table_info[count].table, table_info[count].index);
   1609              if (BCM_E_NONE != rv &&
   1610                 BCM_E_NONE == err_code[bcmStatFlexDirectionEgress]) {
   1611                 err_code[bcmStatFlexDirectionEgress] = 1;
   1612              }
   1613          }
   1614     }
   1615 
   1616     BCM_STAT_FLEX_DETACH_RETURN(err_code)
   1617 }
   1618 
   1619 /*
   1620  * Function:
   1621  *      bcmi_td2p_mpls_tunnel_stat_counter_get
   1622  *
   1623  * Description:
   1624  *      Get the specified counter statistic for a mpls tunnel derived from the
   1625  *      given L3 Egress interface
   1626  *      if sync_mode is set, sync the sw accumulated count
   1627  *      with hw count value first, else return sw count.
   1628  *
   1629  * Parameters:
   1630  *      unit             - (IN) unit number
   1631  *      sync_mode        - (IN) hwcount is to be synced to sw count
   1632  *      intf_id          - (IN) Interface id of a egress L3 object.
   1633  *      stat             - (IN) Type of the counter to retrieve
   1634  *                              I.e. ingress/egress byte/packet)
   1635  *      num_entries      - (IN) Number of counter Entries
   1636  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   1637  *      counter_values   - (OUT) Pointer to counter values
   1638  *
   1639  * Return Value:
   1640  *      BCM_E_XXX
   1641  */
   1642 STATIC
   1643 bcm_error_t bcmi_td2p_mpls_tunnel_stat_counter_get(
   1644                     int              unit,
   1645                     int              sync_mode,
   1646                     bcm_if_t         intf_id,
   1647                     uint32           stat_counter_id,
   1648                     bcm_mpls_stat_t    stat,
   1649                     uint32           num_entries,
   1650                     uint32           *counter_indexes,
   1651                     bcm_stat_value_t *counter_values)
   1652 {
   1653     uint32                     table_count = 0;
   1654     uint32                     index_count = 0;
   1655     uint32                     num_of_tables = 0;
   1656     bcm_stat_flex_direction_t  direction = bcmStatFlexDirectionIngress;
   1657     uint32                     byte_flag = 0;
   1658     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   1659     uint32                     pool_number = 0;
   1660     uint32                     base_index = 0;
   1661     bcm_stat_flex_mode_t       offset_mode = 0;
   1662     bcm_stat_object_t          object = bcmStatObjectEgrMplsTunnelLabel;
   1663     bcm_stat_group_mode_t      group_mode = bcmStatGroupModeSingle;
   1664 
   1665     if (stat_counter_id != 0) {
   1666         _bcm_esw_stat_get_counter_id_info(
   1667                 unit, stat_counter_id,
   1668                 &group_mode, &object,
   1669                 &offset_mode, &pool_number, &base_index);
   1670     }
   1671     if ((stat == bcmMplsOutPkts) ||
   1672         (stat == bcmMplsOutBytes)) {
   1673          direction = bcmStatFlexDirectionEgress;
   1674     } else {
   1675          direction = bcmStatFlexDirectionIngress;
   1676     }
   1677     if ((stat == bcmMplsInPkts)|| (stat == bcmMplsOutPkts)) {
   1678         byte_flag = 0;
   1679     } else {
   1680         byte_flag = 1;
   1681     }
   1682 
   1683     BCM_IF_ERROR_RETURN(bcmi_td2p_mpls_tunnel_stat_get_table_info(
   1684                         unit, intf_id, &num_of_tables, &table_info[0]));
   1685 
   1686     for (table_count = 0; table_count < num_of_tables ; table_count++) {
   1687          if (table_info[table_count].direction == direction) {
   1688              for (index_count = 0; index_count < num_entries ; index_count++) {
   1689                   BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get(
   1690                                       unit, sync_mode,
   1691                                       table_info[table_count].index,
   1692                                       table_info[table_count].table,
   1693                                       object,
   1694                                       byte_flag,
   1695                                       counter_indexes[index_count],
   1696                                       &counter_values[index_count]));
   1697              }
   1698          }
   1699     }
   1700     return BCM_E_NONE;
   1701 }
   1702 
   1703 
   1704 
   1705 /*
   1706  * Function:
   1707  *      bcmi_td2p_mpls_tunnel_stat_counter_set
   1708  *
   1709  * Description:
   1710  *      Set the specified counter statistic for a mpls tunnel derived from the
   1711  *      given L3 Egress interface
   1712  *
   1713  * Parameters:
   1714  *      unit             - (IN) unit number
   1715  *      intf_id          - (IN) Interface id of a egress L3 object.
   1716  *      stat             - (IN) Type of the counter to retrieve
   1717  *                              I.e. ingress/egress byte/packet)
   1718  *      num_entries      - (IN) Number of counter Entries
   1719  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   1720  *      counter_values   - (IN) Pointer to counter values
   1721  *
   1722  * Return Value:
   1723  *      BCM_E_XXX
   1724  */
   1725 STATIC
   1726 bcm_error_t bcmi_td2p_mpls_tunnel_stat_counter_set(
   1727             int              unit,
   1728             bcm_if_t         intf_id,
   1729             uint32           stat_counter_id,
   1730             bcm_mpls_stat_t  stat,
   1731             uint32           num_entries,
   1732             uint32           *counter_indexes,
   1733             bcm_stat_value_t *counter_values)
   1734 {
   1735     uint32                     table_count = 0;
   1736     uint32                     index_count = 0;
   1737     uint32                     num_of_tables = 0;
   1738     bcm_stat_flex_direction_t  direction = bcmStatFlexDirectionIngress;
   1739     uint32                     byte_flag = 0;
   1740     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   1741     uint32                     pool_number = 0;
   1742     uint32                     base_index = 0;
   1743     bcm_stat_flex_mode_t       offset_mode = 0;
   1744     bcm_stat_object_t          object = bcmStatObjectEgrMplsTunnelLabel;
   1745     bcm_stat_group_mode_t      group_mode = bcmStatGroupModeSingle;
   1746 
   1747    if ((stat == bcmMplsOutPkts) ||
   1748         (stat == bcmMplsOutBytes)) {
   1749          direction = bcmStatFlexDirectionEgress;
   1750     } else {
   1751          direction = bcmStatFlexDirectionIngress;
   1752     }
   1753     if ((stat == bcmMplsInPkts) || (stat == bcmMplsOutPkts)) {
   1754         byte_flag = 0;
   1755     } else {
   1756         byte_flag = 1;
   1757     }
   1758     if (stat_counter_id != 0) {
   1759         _bcm_esw_stat_get_counter_id_info(
   1760                 unit, stat_counter_id,
   1761                 &group_mode, &object,
   1762                 &offset_mode, &pool_number, &base_index);
   1763     }
   1764     BCM_IF_ERROR_RETURN(bcmi_td2p_mpls_tunnel_stat_get_table_info(
   1765                         unit, intf_id, &num_of_tables, &table_info[0]));
   1766 
   1767     for (table_count = 0; table_count < num_of_tables ; table_count++) {
   1768          if (table_info[table_count].direction == direction) {
   1769              for (index_count = 0; index_count < num_entries ; index_count++) {
   1770                   BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set(
   1771                                       unit,
   1772                                       table_info[table_count].index,
   1773                                       table_info[table_count].table,
   1774                                       object,
   1775                                       byte_flag,
   1776                                       counter_indexes[index_count],
   1777                                       &counter_values[index_count]));
   1778             }
   1779          }
   1780     }
   1781     return BCM_E_NONE;
   1782 }
   1783 
   1784 
   1785 /*
   1786  * Function:
   1787  *      bcmi_td2p_mpls_tunnel_stat_id_get
   1788  *
   1789  * Description:
   1790  *      Get stat counter id associated with given egress interface id
   1791  *
   1792  * Parameters:
   1793  *      unit             - (IN) unit number
   1794  *      intf_id          - (IN) Interface id of a egress L3 object.
   1795  *      stat             - (IN) Type of the counter to retrieve
   1796  *                              I.e. ingress/egress byte/packet)
   1797  *      Stat_counter_id  - (OUT) Stat Counter ID
   1798  *
   1799  * Return Value:
   1800  *      BCM_E_XXX
   1801  */
   1802 STATIC
   1803 int bcmi_td2p_mpls_tunnel_stat_id_get(
   1804             int             unit,
   1805             bcm_if_t        intf_id,
   1806             bcm_mpls_stat_t   stat,
   1807             uint32          *stat_counter_id)
   1808 {
   1809     bcm_stat_flex_direction_t  direction = bcmStatFlexDirectionIngress;
   1810     uint32                     num_of_tables = 0;
   1811     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   1812     uint32                     index = 0;
   1813     uint32                     num_stat_counter_ids = 0;
   1814 
   1815    if ((stat == bcmMplsInPkts) ||
   1816         (stat == bcmMplsInBytes)) {
   1817          direction = bcmStatFlexDirectionIngress;
   1818     } else {
   1819          direction = bcmStatFlexDirectionEgress;
   1820     }
   1821     BCM_IF_ERROR_RETURN(bcmi_td2p_mpls_tunnel_stat_get_table_info(
   1822                         unit, intf_id, &num_of_tables, &table_info[0]));
   1823     for (index = 0; index < num_of_tables ; index++) {
   1824          if (table_info[index].direction == direction)
   1825              return _bcm_esw_stat_flex_get_counter_id(
   1826                                   unit, 1, &table_info[index],
   1827                                   &num_stat_counter_ids, stat_counter_id);
   1828     }
   1829     return BCM_E_NOT_FOUND;
   1830 }
   1831 
   1832 /*
   1833  * Function:
   1834  *      bcmi_td2p_mpls_tunnel_label_counter_id_num_get
   1835  *
   1836  * Description:
   1837  *      Get array of counters ids' attached to the mpls tunnel
   1838  *
   1839  * Parameters:
   1840  *      unit             - (IN) unit number
   1841  *      intf_id          - (IN) Interface id
   1842  *      num_counters     - (IN) Number of counters attached
   1843  *                              to the interface id
   1844  *      Stat_counter_id  - (OUT) Array of stat counter ids
   1845  *                               associated with the interface id
   1846  *
   1847  * Return Value:
   1848  *       BCM_E_XXX
   1849  */
   1850 STATIC bcm_error_t bcmi_td2p_mpls_tunnel_label_counter_id_num_get(
   1851         int      unit,
   1852         bcm_if_t intf_id,
   1853         int      *num_counters,
   1854         uint32   *stat_counter_id)
   1855 {
   1856     uint32                     num_of_tables = 0;
   1857     int                        num_labels = 0;
   1858     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   1859 
   1860     BCM_IF_ERROR_RETURN(bcmi_td2p_mpls_tunnel_stat_get_table_info(
   1861                 unit, intf_id, &num_of_tables, &table_info[0]));
   1862 
   1863     BCM_IF_ERROR_RETURN(_bcm_tr_mpls_tunnel_chain_label_count_get(unit,
   1864                 table_info[0].index, &num_labels));
   1865 #if defined (INCLUDE_L3)
   1866     if (*num_counters <= num_labels) {
   1867         return _bcm_esw_stat_flex_get_multi_counter_id(unit,&table_info[0],
   1868                 num_counters, stat_counter_id);
   1869     } else {
   1870         return BCM_E_PARAM;
   1871     }
   1872 #endif
   1873     return BCM_E_UNAVAIL;
   1874 }
   1875 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   1876 
   1877 /*
   1878  * Function:
   1879  *      bcm_esw_mpls_tunnel_stat_attach
   1880  *
   1881  * Description:
   1882  *      Attach counters entries to the the mpls tunnel derived from the
   1883  *      given L3 Egress interface
   1884  *
   1885  * Parameters:
   1886  *      unit             - (IN) unit number
   1887  *      intf_id          - (IN) Interface id of a egress L3 object.
   1888  *      stat_counter_id  - (IN) Stat Counter ID.
   1889  *
   1890  * Return Value:
   1891  *      BCM_E_XXX
   1892  */
   1893 int bcm_esw_mpls_tunnel_stat_attach(
   1894             int      unit,
   1895             bcm_if_t intf_id,
   1896             uint32   stat_counter_id)
   1897 {
   1898 #ifdef BCM_MPLS_SUPPORT
   1899 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1900     if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   1901         return bcmi_td2p_mpls_tunnel_stat_attach(unit, intf_id, stat_counter_id);
   1902     }
   1903 #endif
   1904 #endif
   1905     return BCM_E_UNAVAIL;
   1906 }
   1907 /*
   1908  * Function:
   1909  *      bcm_esw_mpls_tunnel_stat_detach
   1910  *
   1911  * Description:
   1912  *      Detach  counters entries to the the mpls tunnel derived from the
   1913  *      given L3 Egress interface.
   1914  *
   1915  * Parameters:
   1916  *      unit             - (IN) unit number
   1917  *      intf_id          - (IN) Interface id of a egress L3 object.
   1918  *      stat_counter_id  - (IN) Stat Counter ID.
   1919  *
   1920  * Return Value:
   1921  *      BCM_E_XXX
   1922  */
   1923 int bcm_esw_mpls_tunnel_stat_detach(
   1924             int      unit,
   1925             bcm_if_t intf_id)
   1926 {
   1927 #ifdef BCM_MPLS_SUPPORT
   1928 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1929     if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   1930         return bcmi_td2p_mpls_tunnel_stat_detach(unit, intf_id, 0);
   1931     }
   1932 #endif
   1933 #endif
   1934     return BCM_E_UNAVAIL;
   1935 }
   1936 
   1937 /*
   1938  * Function:
   1939  *      bcm_esw_mpls_tunnel_stat_counter_get
   1940  *
   1941  * Description:
   1942  *      Get the specified counter statistic for a mpls tunnel derived from the
   1943  *      given L3 Egress interface
   1944  *
   1945  * Parameters:
   1946  *      unit             - (IN) unit number
   1947  *      intf_id          - (IN) Interface id of a egress L3 object.
   1948  *      stat             - (IN) Type of the counter to retrieve
   1949  *                              I.e. ingress/egress byte/packet)
   1950  *      num_entries      - (IN) Number of counter Entries
   1951  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   1952  *      counter_values   - (OUT) Pointer to counter values
   1953  *
   1954  *  Return Value:
   1955  *      BCM_E_XXX
   1956  */
   1957 int bcm_esw_mpls_tunnel_stat_counter_get(
   1958             int              unit,
   1959             bcm_if_t         intf_id,
   1960             bcm_mpls_stat_t    stat,
   1961             uint32           num_entries,
   1962             uint32           *counter_indexes,
   1963             bcm_stat_value_t *counter_values)
   1964 {
   1965 #ifdef BCM_MPLS_SUPPORT
   1966 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1967     return bcmi_td2p_mpls_tunnel_stat_counter_get(unit, 0, intf_id, 0, stat,
   1968                                         num_entries,
   1969                                         counter_indexes,
   1970                                         counter_values);
   1971 #endif
   1972 #endif
   1973 
   1974     return BCM_E_UNAVAIL;
   1975 }
   1976 
   1977 /*
   1978  * Function:
   1979  *      bcm_esw_mpls_tunnel_stat_counter_sync_get
   1980  *
   1981  * Description:
   1982  *      Retrieve set of counter statistics for a mpls tunnel derived from the
   1983  *      given L3 Egress interface
   1984  *      sw accumulated counters synced with hw count.
   1985  *
   1986  * Parameters:
   1987  *      unit             - (IN) unit number
   1988  *      intf_id          - (IN) Interface id of a egress L3 object.
   1989  *      stat             - (IN) Type of the counter to retrieve
   1990  *                              I.e. ingress/egress byte/packet)
   1991  *      num_entries      - (IN) Number of counter Entries
   1992  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   1993  *      counter_values   - (OUT) Pointer to counter values
   1994  *
   1995  *  Return Value:
   1996  *      BCM_E_XXX
   1997  */
   1998 int bcm_esw_mpls_tunnel_stat_counter_sync_get(
   1999             int              unit,
   2000             bcm_if_t         intf_id,
   2001             bcm_mpls_stat_t    stat,
   2002             uint32           num_entries,
   2003             uint32           *counter_indexes,
   2004             bcm_stat_value_t *counter_values)
   2005 {
   2006 #ifdef BCM_MPLS_SUPPORT
   2007 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2008     return bcmi_td2p_mpls_tunnel_stat_counter_get(unit, 1, intf_id, 0, stat,
   2009                                           num_entries, counter_indexes,
   2010                                           counter_values);
   2011 #endif
   2012 #endif
   2013     return BCM_E_UNAVAIL;
   2014 }
   2015 /*
   2016  * Function:
   2017  *      bcm_esw_mpls_tunnel_stat_counter_set
   2018  *
   2019  * Description:
   2020  *      Set the specified counter statistic for a mpls tunnel derived from the
   2021  *      given L3 Egress interface
   2022  *
   2023  * Parameters:
   2024  *      unit             - (IN) unit number
   2025  *      intf_id          - (IN) Interface id of a egress L3 object.
   2026  *      stat             - (IN) Type of the counter to retrieve
   2027  *                              I.e. ingress/egress byte/packet)
   2028  *      num_entries      - (IN) Number of counter Entries
   2029  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   2030  *      counter_values   - (IN) Pointer to counter values
   2031  *
   2032  * Return Value:
   2033  *      BCM_E_XXX
   2034  */
   2035 int bcm_esw_mpls_tunnel_stat_counter_set(
   2036             int              unit,
   2037             bcm_if_t         intf_id,
   2038             bcm_mpls_stat_t  stat,
   2039             uint32           num_entries,
   2040             uint32           *counter_indexes,
   2041             bcm_stat_value_t *counter_values)
   2042 {
   2043 #ifdef BCM_MPLS_SUPPORT
   2044 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2045     if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   2046         return bcmi_td2p_mpls_tunnel_stat_counter_set(unit, intf_id, 0, stat,
   2047                       num_entries, counter_indexes, counter_values);
   2048     }
   2049 #endif
   2050 #endif
   2051     return BCM_E_UNAVAIL;
   2052 }
   2053 
   2054 /*
   2055  * Function:
   2056  *      bcm_esw_mpls_tunnel_stat_id_get
   2057  *
   2058  * Description:
   2059  *      Get stat counter id associated with given egress interface id
   2060  *
   2061  * Parameters:
   2062  *      unit             - (IN) unit number
   2063  *      intf_id          - (IN) Interface id of a egress L3 object.
   2064  *      stat             - (IN) Type of the counter to retrieve
   2065  *                              I.e. ingress/egress byte/packet)
   2066  *      Stat_counter_id  - (OUT) Stat Counter ID
   2067  *
   2068  * Return Value:
   2069  *      BCM_E_XXX
   2070  */
   2071 int bcm_esw_mpls_tunnel_stat_id_get(
   2072             int             unit,
   2073             bcm_if_t        intf_id,
   2074             bcm_mpls_stat_t   stat,
   2075             uint32          *stat_counter_id)
   2076 {
   2077 #ifdef BCM_MPLS_SUPPORT
   2078 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2079     if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   2080         return bcmi_td2p_mpls_tunnel_stat_id_get(unit, intf_id, stat,
   2081                                 stat_counter_id);
   2082     }
   2083 #endif
   2084 #endif
   2085     return BCM_E_UNAVAIL;
   2086 }
   2087 
   2088 /*
   2089  * Function:
   2090  *      bcm_esw_mpls_tunnel_label_counter_id_detach
   2091  *
   2092  * Description:
   2093  *      Detach  counter entry of the specific mpls tunnel label pointed
   2094  *      to by the given stat counter id.
   2095  *
   2096  * Parameters:
   2097  *      unit             - (IN) unit number
   2098  *      intf_id          - (IN) Interface id of a egress L3 object.
   2099  *      stat_counter_id  - (IN) Stat Counter ID.
   2100  *
   2101  * Return Value:
   2102  *      BCM_E_XXX
   2103  */
   2104 int bcm_esw_mpls_tunnel_label_counter_id_detach(
   2105             int      unit,
   2106             bcm_if_t intf_id,
   2107             uint32 stat_counter_id)
   2108 {
   2109 #ifdef BCM_MPLS_SUPPORT
   2110 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2111     if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   2112         return bcmi_td2p_mpls_tunnel_stat_detach(unit, intf_id, stat_counter_id);
   2113     }
   2114 #endif
   2115 #endif
   2116     return BCM_E_UNAVAIL;
   2117 }
   2118 
   2119 /*
   2120  * Function:
   2121  *      bcm_esw_mpls_tunnel_label_counter_id_stat_get
   2122  *
   2123  * Description:
   2124  *      Get the specified counter statistic for the given mpls tunnel
   2125  *      label and counter id associated with it
   2126  *
   2127  * Parameters:
   2128  *      unit             - (IN) unit number
   2129  *      intf_id          - (IN) Interface id of a egress L3 object.
   2130  *      stat_counter_id  - (IN) Stat Counter Id
   2131  *      stat_info        - (IN/OUT) Mpls Stat Info Structure
   2132  *
   2133  *  Return Value:
   2134  *      BCM_E_XXX
   2135  */
   2136 int bcm_esw_mpls_tunnel_label_counter_id_stat_get(
   2137             int              unit,
   2138             bcm_if_t         intf_id,
   2139             uint32           stat_counter_id,
   2140             bcm_mpls_stat_info_t *stat_info)
   2141 {
   2142 #ifdef BCM_MPLS_SUPPORT
   2143 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2144     return bcmi_td2p_mpls_tunnel_stat_counter_get(unit, 0, intf_id, stat_counter_id,
   2145                                         stat_info->stat,stat_info->num_entries,
   2146                                         stat_info->counter_indexes,
   2147                                         stat_info->counter_values);
   2148 #endif
   2149 #endif
   2150 
   2151     return BCM_E_UNAVAIL;
   2152 }
   2153 
   2154 /*
   2155  * Function:
   2156  *      bcm_esw_mpls_tunnel_label_counter_id_stat_sync_get
   2157  *
   2158  * Description:
   2159  *      Get the specified counter statistic for the given mpls tunnel
   2160  *      label and counter id associated with it
   2161  *      sw accumulated counters synced with hw count.
   2162  *
   2163  * Parameters:
   2164  *      unit             - (IN) unit number
   2165  *      intf_id          - (IN) Interface id of a egress L3 object.
   2166  *      stat_counter_id  - (IN) Stat Counter Id
   2167  *      stat_info        - (IN/OUT) Mpls Stat Info Structure
   2168  *
   2169  *  Return Value:
   2170  *      BCM_E_XXX
   2171  */
   2172 int bcm_esw_mpls_tunnel_label_counter_id_stat_sync_get(
   2173             int              unit,
   2174             bcm_if_t         intf_id,
   2175             uint32           stat_counter_id,
   2176             bcm_mpls_stat_info_t *stat_info)
   2177 {
   2178 #ifdef BCM_MPLS_SUPPORT
   2179 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2180     return bcmi_td2p_mpls_tunnel_stat_counter_get(unit, 1, intf_id, stat_counter_id,
   2181                                           stat_info->stat,stat_info->num_entries,
   2182                                           stat_info->counter_indexes,
   2183                                           stat_info->counter_values);
   2184 #endif
   2185 #endif
   2186     return BCM_E_UNAVAIL;
   2187 }
   2188 
   2189 /*
   2190  * Function:
   2191  *      bcm_esw_mpls_tunnel_label_counter_id_stat_set
   2192  *
   2193  * Description:
   2194  *      Set the specified counter statistic for the given mpls tunnel
   2195  *      label and counter id associated with it
   2196  *
   2197  * Parameters:
   2198  *      unit             - (IN) unit number
   2199  *      intf_id          - (IN) Interface id of a egress L3 object.
   2200  *      stat_counter_id  - (IN) Stat Counter Id
   2201  *      stat_info        - (IN) Mpls Stat Info Structure
   2202  *
   2203  *  Return Value:
   2204  *      BCM_E_XXX
   2205  */
   2206 int bcm_esw_mpls_tunnel_label_counter_id_stat_set(
   2207             int              unit,
   2208             bcm_if_t         intf_id,
   2209             uint32           stat_counter_id,
   2210             bcm_mpls_stat_info_t *stat_info)
   2211 {
   2212 #ifdef BCM_MPLS_SUPPORT
   2213 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2214     if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   2215         return bcmi_td2p_mpls_tunnel_stat_counter_set(unit, intf_id,
   2216                       stat_counter_id,stat_info->stat, stat_info->num_entries,
   2217                       stat_info->counter_indexes,stat_info->counter_values);
   2218     }
   2219 #endif
   2220 #endif
   2221     return BCM_E_UNAVAIL;
   2222 }
   2223 
   2224 /*
   2225  * Function:
   2226  *      bcm_esw_mpls_tunnel_label_counter_id_num_get
   2227  *
   2228  * Description:
   2229  *      Get stat counter id associated with given egress interface id
   2230  *
   2231  * Parameters:
   2232  *      unit             - (IN)  unit number
   2233  *      intf_id          - (IN)  Interface id of a egress L3 object.
   2234  *      num_counters     - (IN/OUT) Number of counters attached
   2235  *                               to the interface id
   2236  *      Stat_counter_id  - (OUT) Array of stat counter ids
   2237  *                               associated with the interface id
   2238  *
   2239  * Return Value:
   2240  *      BCM_E_XXX
   2241  */
   2242 int bcm_esw_mpls_tunnel_label_counter_id_num_get(
   2243             int             unit,
   2244             bcm_if_t        intf_id,
   2245             int             *num_counters,
   2246             uint32          *stat_counter_id)
   2247 {
   2248 #ifdef BCM_MPLS_SUPPORT
   2249 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2250     if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   2251         return bcmi_td2p_mpls_tunnel_label_counter_id_num_get(unit, intf_id,
   2252                 num_counters,stat_counter_id);
   2253     }
   2254 #endif
   2255 #endif
   2256     return BCM_E_UNAVAIL;
   2257 }
   2258 #if defined(BCM_TRIDENT2_SUPPORT)
   2259 
   2260 /* Duplicated from Katana code 
   2261  * This should also serve as default MPLS flex stat counter support. 
   2262  */
   2263  
   2264 /*
   2265  * Function:
   2266  *      td2_mpls_port_stat_get_table_info
   2267  * Description:
   2268  *      Provides relevant flex table information(table-name,index with
   2269  *      direction)  for specific vpn and gport
   2270  *
   2271  * Parameters:
   2272  *      unit             - (IN) unit number
   2273  *      vpn              - (IN) VPN Id
   2274  *      port             - (IN) MPLS GPORT ID
   2275  *      num_of_tables    - (OUT) Number of flex counter tables
   2276  *      table_info       - (OUT) Flex counter tables information
   2277  *
   2278  * Return Value:
   2279  *      BCM_E_XXX
   2280  * Notes:
   2281  */
   2282 STATIC
   2283 bcm_error_t td2_mpls_port_stat_get_table_info(
   2284             int                        unit,
   2285             bcm_vpn_t                  vpn,
   2286             bcm_gport_t                port,
   2287             uint32                     *num_of_tables,
   2288             bcm_stat_flex_table_info_t *table_info)
   2289 {
   2290     int                   vp=0;
   2291     ing_dvp_table_entry_t dvp={{0}};
   2292     int                   nh_index=0;
   2293     initial_prot_nhi_table_entry_t prot_entry;
   2294     int vpless_failover_port = FALSE;
   2295     int rv;
   2296 
   2297     if (_BCM_MPLS_GPORT_FAILOVER_VPLESS_GET(port)) {
   2298         vpless_failover_port = TRUE;
   2299         port = _BCM_MPLS_GPORT_FAILOVER_VPLESS_CLEAR(port);
   2300     }
   2301 
   2302     (*num_of_tables)=0;
   2303     if (!soc_feature(unit,soc_feature_advanced_flex_counter)) {
   2304         return BCM_E_UNAVAIL;
   2305     }
   2306     if (soc_feature(unit, soc_feature_mpls)) {
   2307         BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit));
   2308         if (!_BCM_MPLS_VPN_IS_VPLS(vpn) &&
   2309             !_BCM_MPLS_VPN_IS_VPWS(vpn)) {
   2310             bcm_tr_mpls_unlock (unit);
   2311             return BCM_E_PARAM;
   2312         }
   2313         vp = BCM_GPORT_MPLS_PORT_ID_GET(port);
   2314         if (vp == -1) {
   2315             bcm_tr_mpls_unlock (unit);
   2316             return BCM_E_PARAM;
   2317         }
   2318         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) {
   2319             bcm_tr_mpls_unlock (unit);
   2320             return BCM_E_NOT_FOUND;
   2321         }
   2322         table_info[*num_of_tables].table= SOURCE_VPm;
   2323         table_info[*num_of_tables].index=vp;
   2324         table_info[*num_of_tables].direction=bcmStatFlexDirectionIngress;
   2325         (*num_of_tables)++;
   2326         if(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp) == BCM_E_NONE) {
   2327            nh_index=soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
   2328            rv = BCM_E_NONE;
   2329            if (vpless_failover_port == TRUE) {
   2330                rv = READ_INITIAL_PROT_NHI_TABLEm(unit,MEM_BLOCK_ANY, nh_index, &prot_entry);
   2331                if (BCM_SUCCESS(rv)) {
   2332                    nh_index = soc_INITIAL_PROT_NHI_TABLEm_field32_get(unit,&prot_entry,
   2333                               PROT_NEXT_HOP_INDEXf);
   2334                }
   2335            }
   2336            if (BCM_SUCCESS(rv)) {
   2337                table_info[*num_of_tables].table= EGR_L3_NEXT_HOPm;
   2338                table_info[*num_of_tables].index=nh_index;
   2339                table_info[*num_of_tables].direction=bcmStatFlexDirectionEgress;
   2340                (*num_of_tables)++;
   2341            }
   2342         }
   2343         bcm_tr_mpls_unlock (unit);
   2344         return BCM_E_NONE;
   2345     }
   2346     return BCM_E_UNAVAIL;
   2347 }
   2348 
   2349 #ifdef BCM_TOMAHAWK3_SUPPORT
   2350 /* Convert key part of application format to HW entry. */
   2351 STATIC int
   2352 th3_mpls_entry_set_key(int unit, bcm_mpls_tunnel_switch_t *info,
   2353                            mpls_entry_entry_t *ment)
   2354 {
   2355     bcm_module_t mod_out;
   2356     bcm_port_t port_out;
   2357     bcm_trunk_t trunk_id;
   2358     int rv, gport_id;
   2359     soc_mem_t mem = MPLS_ENTRY_SINGLEm;
   2360     sal_memset(ment, 0, sizeof(mpls_entry_entry_t));
   2361 
   2362     if (info->port == BCM_GPORT_INVALID) {
   2363         /* Global label, mod/port not part of lookup key */
   2364         soc_mem_field32_set(unit, mem,  ment, PORT_NUMf, 0);
   2365         if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) {
   2366             soc_mem_field32_set(unit, mem,  ment, MPLS__MPLS_LABELf, info->label);
   2367         } else {
   2368             return BCM_E_PARAM;
   2369         }
   2370 
   2371         soc_mem_field32_set(unit, mem, ment, BASE_VALIDf, 1);
   2372         return BCM_E_NONE;
   2373     }
   2374 
   2375     rv = _bcm_esw_gport_resolve(unit, info->port, &mod_out,
   2376                                 &port_out, &trunk_id, &gport_id);
   2377     BCM_IF_ERROR_RETURN(rv);
   2378 
   2379     if (BCM_GPORT_IS_TRUNK(info->port)) {
   2380         soc_mem_field32_set(unit, mem, ment, Tf, 1);
   2381         soc_mem_field32_set(unit, mem, ment, TGIDf, trunk_id);
   2382     } else {
   2383         soc_mem_field32_set(unit, mem, ment, PORT_NUMf, port_out);
   2384     }
   2385     if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) {
   2386         soc_mem_field32_set(unit, mem, ment, MPLS__MPLS_LABELf, info->label);
   2387     } else {
   2388         return BCM_E_PARAM;
   2389     }
   2390 
   2391     soc_mem_field32_set(unit, mem, ment, BASE_VALIDf, 1);
   2392 
   2393     return BCM_E_NONE;
   2394 }
   2395 #endif
   2396 
   2397 /* Convert key part of application format to HW entry. */
   2398 STATIC int
   2399 td2_mpls_entry_set_key(int unit, bcm_mpls_tunnel_switch_t *info,
   2400                            mpls_entry_entry_t *ment)
   2401 {
   2402     bcm_module_t mod_out;
   2403     bcm_port_t port_out;
   2404     bcm_trunk_t trunk_id;
   2405     int rv, gport_id;
   2406 
   2407     sal_memset(ment, 0, sizeof(mpls_entry_entry_t));
   2408 
   2409     if (info->port == BCM_GPORT_INVALID) {
   2410         /* Global label, mod/port not part of lookup key */
   2411         soc_MPLS_ENTRYm_field32_set(unit, ment, MODULE_IDf, 0);
   2412         soc_MPLS_ENTRYm_field32_set(unit, ment, PORT_NUMf, 0);
   2413         if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) {
   2414             soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_LABELf, info->label);
   2415         } else {
   2416             return BCM_E_PARAM;
   2417         }
   2418 
   2419         if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   2420             soc_MPLS_ENTRYm_field32_set(unit, ment, BASE_VALID_0f, 3);
   2421             soc_MPLS_ENTRYm_field32_set(unit, ment, BASE_VALID_1f, 7);
   2422         } else {
   2423         soc_MPLS_ENTRYm_field32_set(unit, ment, VALIDf, 1);
   2424         }
   2425         return BCM_E_NONE;
   2426     }
   2427 
   2428     rv = _bcm_esw_gport_resolve(unit, info->port, &mod_out,
   2429                                 &port_out, &trunk_id, &gport_id);
   2430     BCM_IF_ERROR_RETURN(rv);
   2431 
   2432     if (BCM_GPORT_IS_TRUNK(info->port)) {
   2433         soc_MPLS_ENTRYm_field32_set(unit, ment, Tf, 1);
   2434         soc_MPLS_ENTRYm_field32_set(unit, ment, TGIDf, trunk_id);
   2435     } else {
   2436         soc_MPLS_ENTRYm_field32_set(unit, ment, MODULE_IDf, mod_out);
   2437         soc_MPLS_ENTRYm_field32_set(unit, ment, PORT_NUMf, port_out);
   2438     }
   2439     if (BCM_XGS3_L3_MPLS_LBL_VALID(info->label)) {
   2440         soc_MPLS_ENTRYm_field32_set(unit, ment, MPLS_LABELf, info->label);
   2441     } else {
   2442         return BCM_E_PARAM;
   2443     }
   2444 
   2445     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   2446         soc_MPLS_ENTRYm_field32_set(unit, ment, BASE_VALID_0f, 3);
   2447         soc_MPLS_ENTRYm_field32_set(unit, ment, BASE_VALID_1f, 7);
   2448     } else {
   2449     soc_MPLS_ENTRYm_field32_set(unit, ment, VALIDf, 1);
   2450     }
   2451 
   2452     return BCM_E_NONE;
   2453 }
   2454 
   2455 /*
   2456  * Function:
   2457  *      td2_mpls_label_stat_get_table_info
   2458  * Description:
   2459  *      Provides relevant flex table information(table-name,index with
   2460  *      direction)  for given mpls label and gport
   2461  *
   2462  * Parameters:
   2463  *      unit             - (IN) unit number
   2464  *      label            - (IN) MPLS Label
   2465  *      port             - (IN) MPLS Gport
   2466  *      object           - (IN) Stat Object
   2467  *      num_of_tables    - (OUT) Number of flex counter tables
   2468  *      table_info       - (OUT) Flex counter tables information
   2469  *
   2470  * Return Value:
   2471  *      BCM_E_XXX
   2472  * Notes:
   2473  */
   2474 
   2475 STATIC
   2476 bcm_error_t td2_mpls_label_stat_get_table_info(
   2477             int                        unit,
   2478             bcm_mpls_label_t           label,
   2479             bcm_gport_t                port,
   2480             bcm_stat_object_t          object,
   2481             uint32                     *num_of_tables,
   2482             bcm_stat_flex_table_info_t *table_info)
   2483 {
   2484     bcm_error_t              rv=BCM_E_NOT_FOUND;
   2485     bcm_mpls_tunnel_switch_t mpls_tunnel_switch={0};
   2486     mpls_entry_entry_t       ment={{0}};
   2487     int                      index=0;
   2488     soc_mem_t                mem = MPLS_ENTRYm;
   2489     int                      found = -1;
   2490 
   2491     (*num_of_tables)=0;
   2492     if (!soc_feature(unit,soc_feature_advanced_flex_counter)) {
   2493         return BCM_E_UNAVAIL;
   2494     }
   2495     if (!soc_feature(unit, soc_feature_mpls)) {
   2496         return BCM_E_UNAVAIL;
   2497     }
   2498     
   2499 #ifdef BCM_TOMAHAWK3_SUPPORT
   2500     if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
   2501         mem = MPLS_ENTRY_SINGLEm;
   2502     }
   2503 #endif
   2504     sal_memset(&ment, 0, sizeof(mpls_entry_entry_t));
   2505 
   2506     mpls_tunnel_switch.port = port;
   2507     if (BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   2508        mpls_tunnel_switch.label = label;
   2509     } else {
   2510         return BCM_E_PARAM;
   2511     }
   2512     if ((object == bcmStatObjectIngMplsSwitchLabel) ||
   2513         (object == bcmStatObjectIngMplsSwitchSecondLabel)) {
   2514     if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
   2515         BCM_IF_ERROR_RETURN(td2_mpls_entry_set_key(unit,
   2516                     &mpls_tunnel_switch,&ment));
   2517     }
   2518 #ifdef BCM_TOMAHAWK3_SUPPORT
   2519     else {
   2520         BCM_IF_ERROR_RETURN(th3_mpls_entry_set_key(unit,
   2521                     &mpls_tunnel_switch,&ment));
   2522     }
   2523 #endif
   2524         if ((rv=soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index,
   2525                         &ment, &ment, 0)) == BCM_E_NONE) {
   2526             found = 1;
   2527         }
   2528     } else if ((object == bcmStatObjectIngMplsFrrLabel) &&
   2529             (soc_feature(unit, soc_feature_mpls_frr_lookup))){
   2530         mem = L3_TUNNELm;
   2531         rv =  _bcm_tr3_mpls_tunnel_switch_frr_get(unit, &mpls_tunnel_switch, &index);
   2532         if (rv == BCM_E_NONE) {
   2533             found = 1;
   2534         }
   2535     } else if (object == bcmStatObjectMaxValue) {
   2536         if (!soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
   2537             BCM_IF_ERROR_RETURN(td2_mpls_entry_set_key(unit,
   2538                         &mpls_tunnel_switch,&ment));
   2539         }
   2540 #ifdef BCM_TOMAHAWK3_SUPPORT
   2541         else {
   2542             BCM_IF_ERROR_RETURN(th3_mpls_entry_set_key(unit,
   2543                         &mpls_tunnel_switch,&ment));
   2544         }
   2545 #endif
   2546         if ((rv=soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index,
   2547                         &ment, &ment, 0)) == BCM_E_NONE) {
   2548             mem = MPLS_ENTRYm;
   2549 #ifdef BCM_TOMAHAWK3_SUPPORT
   2550             if (soc_feature(unit, soc_feature_th3_style_simple_mpls)) {
   2551                 mem = MPLS_ENTRY_SINGLEm;
   2552             }
   2553 #endif
   2554         } else if (soc_feature(unit, soc_feature_mpls_frr_lookup)) {
   2555             if ((rv= _bcm_tr3_mpls_tunnel_switch_frr_get(unit,
   2556                             &mpls_tunnel_switch, &index)) == BCM_E_NONE) {
   2557                 mem = L3_TUNNELm;
   2558             } else {
   2559                 return rv;
   2560             }
   2561         } else {
   2562             return rv;
   2563         }
   2564         found = 1;
   2565     }
   2566 
   2567     if (found == 1) {
   2568         table_info[*num_of_tables].table= mem;
   2569         table_info[*num_of_tables].index=index;
   2570         table_info[*num_of_tables].direction=bcmStatFlexDirectionIngress;
   2571         (*num_of_tables)++;
   2572     }
   2573     return rv;
   2574 }
   2575 
   2576 
   2577 /*
   2578  * Function:
   2579  *      td2_mpls_port_stat_attach
   2580  * Description:
   2581  *      Attach counters entries to the given mpls gport and vpn
   2582  *
   2583  * Parameters:
   2584  *      unit             - (IN) unit number
   2585  *      vpn              - (IN) VPN Id
   2586  *      port             - (IN) MPLS GPORT ID
   2587  *      stat_counter_id  - (IN) Stat Counter ID.
   2588  *
   2589  * Return Value:
   2590  *      BCM_E_XXX
   2591  * Notes:
   2592  */
   2593 STATIC
   2594 bcm_error_t td2_mpls_port_stat_attach(
   2595                    int         unit,
   2596                    bcm_vpn_t   vpn,
   2597                    bcm_gport_t port,
   2598                    uint32      stat_counter_id)
   2599 {
   2600     soc_mem_t                 table=0;
   2601     bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress;
   2602     uint32                    pool_number=0;
   2603     uint32                    base_index=0;
   2604     bcm_stat_flex_mode_t      offset_mode=0;
   2605     bcm_stat_object_t         object=bcmStatObjectIngPort;
   2606     bcm_stat_group_mode_t     group_mode= bcmStatGroupModeSingle;
   2607     uint32                    count=0;
   2608     uint32                     actual_num_tables=0;
   2609     uint32                     num_of_tables=0;
   2610     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   2611 
   2612     _bcm_esw_stat_get_counter_id_info(
   2613                   unit, stat_counter_id,
   2614                   &group_mode,&object,&offset_mode,&pool_number,&base_index);
   2615     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_object(unit,object,&direction));
   2616     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit,group_mode));
   2617     BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info(
   2618                         unit,object,1,&actual_num_tables,&table,&direction));
   2619 
   2620     BCM_IF_ERROR_RETURN(td2_mpls_port_stat_get_table_info(
   2621                    unit, vpn,port,&num_of_tables,&table_info[0]));
   2622     for (count=0; count < num_of_tables ; count++) {
   2623          if ((table_info[count].direction == direction) &&
   2624            (table_info[count].table == table) ) {
   2625               if (direction == bcmStatFlexDirectionIngress) {
   2626               return _bcm_esw_stat_flex_attach_ingress_table_counters(
   2627                      unit,
   2628                      table_info[count].table,
   2629                      table_info[count].index,
   2630                      offset_mode,
   2631                      base_index,
   2632                      pool_number);
   2633            } else {
   2634               return _bcm_esw_stat_flex_attach_egress_table_counters(
   2635                      unit,
   2636                      table_info[count].table,
   2637                      table_info[count].index,
   2638                      0,
   2639                      offset_mode,
   2640                      base_index,
   2641                      pool_number);
   2642            } 
   2643       }
   2644     }
   2645     return BCM_E_UNAVAIL;
   2646 }
   2647 /*
   2648  * Function:
   2649  *      td2_mpls_port_stat_detach
   2650  * Description:
   2651  *      Detach counters entries to the given mpls port and vpn
   2652  *
   2653  * Parameters:
   2654  *      unit             - (IN) unit number
   2655  *      vpn              - (IN) VPN Id
   2656  *      port             - (IN) MPLS GPORT ID
   2657  *
   2658  * Return Value:
   2659  *      BCM_E_XXX
   2660  * Notes:
   2661  */
   2662 STATIC
   2663 bcm_error_t td2_mpls_port_stat_detach(
   2664                    int         unit,
   2665                    bcm_vpn_t   vpn,
   2666                    bcm_gport_t port)
   2667 {
   2668     uint32                     count=0;
   2669     uint32                     num_of_tables=0;
   2670     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   2671     bcm_error_t                rv = BCM_E_NONE;
   2672     bcm_error_t                err_code[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {BCM_E_NONE};
   2673 
   2674     BCM_IF_ERROR_RETURN(td2_mpls_port_stat_get_table_info(
   2675                    unit, vpn,port,&num_of_tables,&table_info[0]));
   2676 
   2677     for (count=0; count < num_of_tables ; count++) {
   2678       if (table_info[count].direction == bcmStatFlexDirectionIngress) {
   2679            rv = _bcm_esw_stat_flex_detach_ingress_table_counters(
   2680                         unit, table_info[count].table, table_info[count].index);
   2681            if (BCM_E_NONE != rv &&
   2682                 BCM_E_NONE == err_code[bcmStatFlexDirectionIngress]) {
   2683                 err_code[bcmStatFlexDirectionIngress] = rv;
   2684            }
   2685       } else {
   2686            rv = _bcm_esw_stat_flex_detach_egress_table_counters(
   2687                         unit, 0, table_info[count].table, table_info[count].index);
   2688            if (BCM_E_NONE != rv &&
   2689                 BCM_E_NONE == err_code[bcmStatFlexDirectionEgress]) {
   2690                 err_code[bcmStatFlexDirectionEgress] = rv;
   2691            }
   2692       }
   2693     }
   2694 
   2695     BCM_STAT_FLEX_DETACH_RETURN(err_code)
   2696 }
   2697 /*
   2698  * Function:
   2699  *      td2_mpls_port_stat_counter_get
   2700  * Description:
   2701  *      Get counter statistic values for specific vpn and gport
   2702  *      if sync_mode is set, sync the sw accumulated count
   2703  *      with hw count value first, else return sw count.  
   2704  *
   2705  * Parameters:
   2706  *      unit             - (IN) unit number
   2707  *      sync_mode        - (IN) hwcount is to be synced to sw count 
   2708  *      vpn              - (IN) VPN Id
   2709  *      port             - (IN) MPLS GPORT ID
   2710  *      stat             - (IN) Type of the counter to retrieve
   2711  *                              I.e. ingress/egress byte/packet)
   2712  *      num_entries      - (IN) Number of counter Entries
   2713  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   2714  *      counter_values   - (OUT) Pointer to counter values
   2715  *
   2716  * Return Value:
   2717  *      BCM_E_XXX
   2718  * Notes:
   2719  */
   2720 STATIC
   2721 bcm_error_t td2_mpls_port_stat_counter_get(
   2722                    int                  unit,
   2723                    int                  sync_mode,
   2724                    bcm_vpn_t            vpn,
   2725                    bcm_gport_t          port,
   2726                    bcm_mpls_stat_t      stat,
   2727                    uint32               num_entries,
   2728                    uint32               *counter_indexes,
   2729                    bcm_stat_value_t     *counter_values)
   2730 {
   2731     uint32                          table_count=0;
   2732     uint32                          index_count=0;
   2733     uint32                          num_of_tables=0;
   2734     bcm_stat_flex_direction_t       direction=bcmStatFlexDirectionIngress;
   2735     uint32                          byte_flag=0;
   2736     bcm_stat_flex_table_info_t      table_info[
   2737                                     BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   2738 
   2739     if ((stat == bcmMplsInBytes) ||
   2740         (stat == bcmMplsInPkts)) {
   2741          direction = bcmStatFlexDirectionIngress;
   2742     } else {
   2743          direction = bcmStatFlexDirectionEgress;
   2744     }
   2745     if ((stat == bcmMplsInPkts) ||
   2746         (stat == bcmMplsOutPkts)) {
   2747         byte_flag=0;
   2748     } else {
   2749         byte_flag=1;
   2750     }
   2751     
   2752     BCM_IF_ERROR_RETURN(td2_mpls_port_stat_get_table_info(
   2753                    unit, vpn,port,&num_of_tables,&table_info[0]));
   2754 
   2755     for (table_count=0; table_count < num_of_tables ; table_count++) {
   2756       if (table_info[table_count].direction == direction) {
   2757           for (index_count=0; index_count < num_entries ; index_count++) {
   2758             BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get(
   2759                          unit, sync_mode,
   2760                          table_info[table_count].index,
   2761                          table_info[table_count].table,
   2762                          0, byte_flag,
   2763                          counter_indexes[index_count],
   2764                          &counter_values[index_count]));
   2765           }
   2766       }
   2767     }
   2768     return BCM_E_NONE;
   2769 }
   2770 /*
   2771  * Function:
   2772  *      td2_mpls_port_stat_counter_set
   2773  * Description:
   2774  *      Set counter statistic values for specific vpn and gport
   2775  *
   2776  * Parameters:
   2777  *      unit             - (IN) unit number
   2778  *      vpn              - (IN) VPN Id
   2779  *      port             - (IN) MPLS GPORT ID
   2780  *      stat             - (IN) Type of the counter to retrieve
   2781  *                              I.e. ingress/egress byte/packet)
   2782  *      num_entries      - (IN) Number of counter Entries
   2783  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   2784  *      counter_values   - (OUT) Pointer to counter values
   2785  *
   2786  * Return Value:
   2787  *      BCM_E_XXX
   2788  * Notes:
   2789  */
   2790 STATIC
   2791 bcm_error_t td2_mpls_port_stat_counter_set(
   2792                    int                  unit,
   2793                    bcm_vpn_t            vpn,
   2794                    bcm_gport_t          port,
   2795                    bcm_mpls_stat_t      stat,
   2796                    uint32               num_entries,
   2797                    uint32               *counter_indexes,
   2798                    bcm_stat_value_t     *counter_values)
   2799 {
   2800     uint32                          table_count=0;
   2801     uint32                          index_count=0;
   2802     uint32                          num_of_tables=0;
   2803     bcm_stat_flex_direction_t       direction=bcmStatFlexDirectionIngress;
   2804     uint32                          byte_flag=0;
   2805     bcm_stat_flex_table_info_t      table_info[
   2806                                     BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   2807 
   2808     if ((stat == bcmMplsInBytes) ||
   2809         (stat == bcmMplsInPkts)) {
   2810          direction = bcmStatFlexDirectionIngress;
   2811     } else {
   2812          direction = bcmStatFlexDirectionEgress;
   2813     }
   2814     if ((stat == bcmMplsInPkts) ||
   2815         (stat == bcmMplsOutPkts)) {
   2816         byte_flag=0;
   2817     } else {
   2818         byte_flag=1;
   2819     }
   2820     
   2821     BCM_IF_ERROR_RETURN(td2_mpls_port_stat_get_table_info(
   2822                    unit, vpn,port,&num_of_tables,&table_info[0]));
   2823 
   2824     for (table_count=0; table_count < num_of_tables ; table_count++) {
   2825       if (table_info[table_count].direction == direction) {
   2826           for (index_count=0; index_count < num_entries ; index_count++) {
   2827             BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set(
   2828                          unit,
   2829                          table_info[table_count].index,
   2830                          table_info[table_count].table,
   2831                          0, byte_flag,
   2832                          counter_indexes[index_count],
   2833                          &counter_values[index_count]));
   2834           }
   2835       }
   2836     }
   2837     return BCM_E_NONE;
   2838 }
   2839 /*
   2840  * Function:
   2841  *      td2_mpls_port_stat_id_get
   2842  * Description:
   2843  *      Get stat counter id associated with specific vpn and gport
   2844  *
   2845  * Parameters:
   2846  *      unit             - (IN) unit number
   2847  *      vpn              - (IN) VPN Id
   2848  *      port             - (IN) MPLS GPORT ID
   2849  *      stat             - (IN) Type of the counter to retrieve
   2850  *                              I.e. ingress/egress byte/packet)
   2851  *      Stat_counter_id  - (OUT) Stat Counter ID
   2852  *
   2853  * Return Value:
   2854  *      BCM_E_XXX
   2855  * Notes:
   2856  */
   2857 STATIC
   2858 bcm_error_t td2_mpls_port_stat_id_get(
   2859                    int             unit,
   2860                    bcm_vpn_t       vpn,
   2861                    bcm_gport_t     port,
   2862                    bcm_mpls_stat_t stat,
   2863                    uint32          *stat_counter_id)
   2864 {
   2865     bcm_stat_flex_direction_t  direction=bcmStatFlexDirectionIngress;
   2866     uint32                     num_of_tables=0;
   2867     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   2868     uint32                     index=0;
   2869     uint32                     num_stat_counter_ids=0;
   2870 
   2871     if ((stat == bcmMplsInBytes) ||
   2872         (stat == bcmMplsInPkts)) {
   2873          direction = bcmStatFlexDirectionIngress;
   2874     } else {
   2875          direction = bcmStatFlexDirectionEgress;
   2876       }
   2877     BCM_IF_ERROR_RETURN(td2_mpls_port_stat_get_table_info(
   2878                         unit,vpn,port,&num_of_tables,&table_info[0]));
   2879     for (index=0; index < num_of_tables ; index++) {
   2880          if (table_info[index].direction == direction)
   2881              return _bcm_esw_stat_flex_get_counter_id(
   2882                                   unit, 1, &table_info[index],
   2883                                   &num_stat_counter_ids,stat_counter_id);
   2884   }
   2885     return BCM_E_NOT_FOUND;
   2886 }
   2887 /*
   2888  * Function:
   2889  *      td2_mpls_label_stat_attach
   2890  * Description:
   2891  *      Attach counters entries to the given mpls label and gport
   2892  *
   2893  * Parameters:
   2894  *      unit             - (IN) unit number
   2895  *      label            - (IN) MPLS Label
   2896  *      port             - (IN) MPLS Gport
   2897  *      stat_counter_id  - (IN) Stat Counter ID.
   2898  *
   2899  * Return Value:
   2900  *      BCM_E_XXX
   2901  * Notes:
   2902  */
   2903 STATIC
   2904 bcm_error_t td2_mpls_label_stat_attach(
   2905                    int              unit,
   2906                    bcm_mpls_label_t label,
   2907                    bcm_gport_t      port,
   2908                    uint32           stat_counter_id)
   2909 {
   2910     soc_mem_t                 table=0;
   2911     bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress;
   2912     uint32                    pool_number=0;
   2913     uint32                    base_index=0;
   2914     bcm_stat_flex_mode_t      offset_mode=0;
   2915     bcm_stat_object_t         object=bcmStatObjectIngPort;
   2916     bcm_stat_group_mode_t     group_mode= bcmStatGroupModeSingle;
   2917     uint32                    count=0;
   2918     uint32                     actual_num_tables=0;
   2919     uint32                     num_of_tables=0;
   2920     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   2921 
   2922     _bcm_esw_stat_get_counter_id_info(
   2923                   unit, stat_counter_id,
   2924                   &group_mode,&object,&offset_mode,&pool_number,&base_index);
   2925     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_object(unit,object,&direction));
   2926     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit,group_mode));
   2927     BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info(
   2928                         unit,object,1,&actual_num_tables,&table,&direction));
   2929 
   2930     if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   2931         return BCM_E_PARAM;
   2932     }
   2933 
   2934     BCM_IF_ERROR_RETURN(td2_mpls_label_stat_get_table_info(
   2935                    unit, label,port, object, &num_of_tables,&table_info[0]));
   2936     for (count=0; count < num_of_tables ; count++) {
   2937          if ((table_info[count].direction == direction) &&
   2938            (table_info[count].table == table) ) {
   2939               if (direction == bcmStatFlexDirectionIngress) {
   2940               return _bcm_esw_stat_flex_attach_ingress_table_counters(
   2941                      unit,
   2942                      table_info[count].table,
   2943                      table_info[count].index,
   2944                      offset_mode,
   2945                      base_index,
   2946                      pool_number);
   2947            } else {
   2948               return _bcm_esw_stat_flex_attach_egress_table_counters(
   2949                      unit,
   2950                      table_info[count].table,
   2951                      table_info[count].index,
   2952                      0,
   2953                      offset_mode,
   2954                      base_index,
   2955                      pool_number);
   2956            } 
   2957       }
   2958     }
   2959     return BCM_E_NOT_FOUND;
   2960 }
   2961 /*
   2962  * Function:
   2963  *      td2_mpls_label_stat_detach
   2964  * Description:
   2965  *      Detach counters entries to the given mpls label and gport
   2966  *
   2967  * Parameters:
   2968  *      unit             - (IN) unit number
   2969  *      label            - (IN) MPLS Label
   2970  *      port             - (IN) MPLS Gport
   2971  *
   2972  * Return Value:
   2973  *      BCM_E_XXX
   2974  * Notes:
   2975  */
   2976 STATIC
   2977 bcm_error_t td2_mpls_label_stat_detach(
   2978                    int              unit,
   2979                    bcm_mpls_label_t label,
   2980                    bcm_gport_t      port)
   2981 {
   2982     uint32                     count=0;
   2983     uint32                     num_of_tables=0;
   2984     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   2985     bcm_error_t                rv = BCM_E_NONE;
   2986     bcm_error_t                err_code[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {BCM_E_NONE};
   2987 
   2988     if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   2989         return BCM_E_PARAM;
   2990     }
   2991 
   2992     BCM_IF_ERROR_RETURN(td2_mpls_label_stat_get_table_info(
   2993                    unit, label,port, bcmStatObjectMaxValue, &num_of_tables,&table_info[0]));
   2994 
   2995     for (count=0; count < num_of_tables ; count++) {
   2996       if (table_info[count].direction == bcmStatFlexDirectionIngress) {
   2997            rv = _bcm_esw_stat_flex_detach_ingress_table_counters(
   2998                         unit, table_info[count].table, table_info[count].index);
   2999            if (BCM_E_NONE != rv &&
   3000                 BCM_E_NONE == err_code[bcmStatFlexDirectionIngress]) {
   3001                 err_code[bcmStatFlexDirectionIngress] = rv;
   3002            }
   3003       } else {
   3004            rv = _bcm_esw_stat_flex_detach_egress_table_counters(
   3005                         unit, 0, table_info[count].table, table_info[count].index);
   3006            if (BCM_E_NONE != rv &&
   3007                 BCM_E_NONE == err_code[bcmStatFlexDirectionEgress]) {
   3008                 err_code[bcmStatFlexDirectionEgress] = rv;
   3009            }
   3010       }
   3011     }
   3012 
   3013     BCM_STAT_FLEX_DETACH_RETURN(err_code)
   3014 }
   3015 /*
   3016  * Function:
   3017  *      td2_mpls_label_stat_counter_get
   3018  * Description:
   3019  *      Get counter statistic values for specific MPLS label and gport
   3020  *      Get counter statistic values for specific vpn and gport
   3021  *      if sync_mode is set, sync the sw accumulated count
   3022  *
   3023  * Parameters:
   3024  *      unit             - (IN) unit number
   3025  *      sync_mode        - (IN) hwcount is to be synced to sw count 
   3026  *      label            - (IN) MPLS Label
   3027  *      port             - (IN) MPLS Gport
   3028  *      stat             - (IN) Type of the counter to retrieve
   3029  *                              I.e. ingress/egress byte/packet)
   3030  *      num_entries      - (IN) Number of counter Entries
   3031  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   3032  *      counter_values   - (OUT) Pointer to counter values
   3033  *
   3034  * Return Value:
   3035  *      BCM_E_XXX
   3036  * Notes:
   3037  */
   3038 STATIC
   3039 bcm_error_t td2_mpls_label_stat_counter_get(
   3040                    int                  unit,
   3041                    int                  sync_mode,
   3042                    bcm_mpls_label_t     label,
   3043                    bcm_gport_t          port,
   3044                    bcm_mpls_stat_t      stat,
   3045                    uint32               num_entries,
   3046                    uint32               *counter_indexes,
   3047                    bcm_stat_value_t     *counter_values)
   3048 {
   3049     uint32                          table_count=0;
   3050     uint32                          index_count=0;
   3051     uint32                          num_of_tables=0;
   3052     bcm_stat_flex_direction_t       direction=bcmStatFlexDirectionIngress;
   3053     uint32                          byte_flag=0;
   3054     bcm_stat_flex_table_info_t      table_info[
   3055                                     BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   3056 
   3057     if ((stat == bcmMplsInBytes) ||
   3058         (stat == bcmMplsInPkts)) {
   3059          direction = bcmStatFlexDirectionIngress;
   3060     } else {
   3061          direction = bcmStatFlexDirectionEgress;
   3062     }
   3063     if ((stat == bcmMplsInPkts) ||
   3064         (stat == bcmMplsOutPkts)) {
   3065         byte_flag=0;
   3066     } else {
   3067         byte_flag=1;
   3068     }
   3069 
   3070     if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   3071         return BCM_E_PARAM;
   3072     }
   3073 
   3074     BCM_IF_ERROR_RETURN(td2_mpls_label_stat_get_table_info(
   3075                    unit, label,port,bcmStatObjectMaxValue,&num_of_tables,&table_info[0]));
   3076 
   3077     for (table_count=0; table_count < num_of_tables ; table_count++) {
   3078       if (table_info[table_count].direction == direction) {
   3079           for (index_count=0; index_count < num_entries ; index_count++) {
   3080             BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get(
   3081                          unit, sync_mode,
   3082                          table_info[table_count].index,
   3083                          table_info[table_count].table,
   3084                          0, byte_flag,
   3085                          counter_indexes[index_count],
   3086                          &counter_values[index_count]));
   3087           }
   3088       }
   3089     }
   3090     return BCM_E_NONE;
   3091 }
   3092 /*
   3093  * Function:
   3094  *      td2_mpls_label_stat_counter_set
   3095  * Description:
   3096  *      Set counter statistic values for specific MPLS label and gport
   3097  *
   3098  * Parameters:
   3099  *      unit             - (IN) unit number
   3100  *      label            - (IN) MPLS Label
   3101  *      port             - (IN) MPLS Gport
   3102  *      stat             - (IN) Type of the counter to retrieve
   3103  *                              I.e. ingress/egress byte/packet)
   3104  *      num_entries      - (IN) Number of counter Entries
   3105  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   3106  *      counter_values   - (IN) Pointer to counter values
   3107  *
   3108  * Return Value:
   3109  *      BCM_E_XXX
   3110  * Notes:
   3111  */
   3112 STATIC
   3113 bcm_error_t td2_mpls_label_stat_counter_set(
   3114                    int                  unit,
   3115                    bcm_mpls_label_t     label,
   3116                    bcm_gport_t          port,
   3117                    bcm_mpls_stat_t      stat,
   3118                    uint32               num_entries,
   3119                    uint32               *counter_indexes,
   3120                    bcm_stat_value_t     *counter_values)
   3121 {
   3122     uint32                          table_count=0;
   3123     uint32                          index_count=0;
   3124     uint32                          num_of_tables=0;
   3125     bcm_stat_flex_direction_t       direction=bcmStatFlexDirectionIngress;
   3126     uint32                          byte_flag=0;
   3127     bcm_stat_flex_table_info_t      table_info[
   3128                                     BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   3129     bcm_vpn_t                       vpn = 0;
   3130 
   3131     if ((stat == bcmMplsInBytes) ||
   3132         (stat == bcmMplsInPkts)) {
   3133          direction = bcmStatFlexDirectionIngress;
   3134     } else {
   3135          direction = bcmStatFlexDirectionEgress;
   3136     }
   3137     if ((stat == bcmMplsInPkts) ||
   3138         (stat == bcmMplsOutPkts)) {
   3139         byte_flag=0;
   3140     } else {
   3141         byte_flag=1;
   3142     }
   3143 
   3144     if (BCM_GPORT_IS_MPLS_PORT(port)) {
   3145         /* Just create a valid vpn id to pass the check */
   3146         _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1);
   3147         BCM_IF_ERROR_RETURN(td2_mpls_port_stat_get_table_info(
   3148             unit, vpn, port, &num_of_tables, &table_info[0]));
   3149     } else {
   3150         if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   3151             return BCM_E_PARAM;
   3152         }
   3153         BCM_IF_ERROR_RETURN(td2_mpls_label_stat_get_table_info(
   3154             unit, label, port, bcmStatObjectMaxValue, &num_of_tables, &table_info[0]));
   3155     }
   3156 
   3157     for (table_count=0; table_count < num_of_tables ; table_count++) {
   3158       if (table_info[table_count].direction == direction) {
   3159           for (index_count=0; index_count < num_entries ; index_count++) {
   3160             BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set(
   3161                          unit,
   3162                          table_info[table_count].index,
   3163                          table_info[table_count].table,
   3164                          0, byte_flag,
   3165                          counter_indexes[index_count],
   3166                          &counter_values[index_count]));
   3167           }
   3168       }
   3169     }
   3170     return BCM_E_NONE;
   3171 }
   3172 /*
   3173  * Function:
   3174  *      td2_mpls_label_stat_id_get
   3175  * Description:
   3176  *      Get stat counter id associated with given vlan
   3177  *
   3178  * Parameters:
   3179  *      unit             - (IN) unit number
   3180  *      label            - (IN) MPLS Label
   3181  *      port             - (IN) MPLS Gport
   3182  *      stat             - (IN) Type of the counter to retrieve
   3183  *                              I.e. ingress/egress byte/packet)
   3184  *      Stat_counter_id  - (OUT) Stat Counter ID
   3185  *
   3186  * Return Value:
   3187  *      BCM_E_XXX
   3188  * Notes:
   3189  */
   3190 STATIC
   3191 bcm_error_t td2_mpls_label_stat_id_get(
   3192             int                  unit,
   3193             bcm_mpls_label_t     label,
   3194             bcm_gport_t          port,
   3195             bcm_mpls_stat_t      stat,
   3196             uint32               *stat_counter_id)
   3197 {
   3198     bcm_stat_flex_direction_t  direction=bcmStatFlexDirectionIngress;
   3199     uint32                     num_of_tables=0;
   3200     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   3201     uint32                     index=0;
   3202     uint32                     num_stat_counter_ids=0;
   3203 
   3204     if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   3205         return BCM_E_PARAM;
   3206     }
   3207 
   3208     if ((stat == bcmMplsInBytes) ||
   3209         (stat == bcmMplsInPkts)) {
   3210          direction = bcmStatFlexDirectionIngress;
   3211     } else {
   3212          direction = bcmStatFlexDirectionEgress;
   3213     }
   3214     BCM_IF_ERROR_RETURN(td2_mpls_label_stat_get_table_info(
   3215                         unit,label,port,bcmStatObjectMaxValue,&num_of_tables,&table_info[0]));
   3216     for (index=0; index < num_of_tables ; index++) {
   3217          if (table_info[index].direction == direction)
   3218              return _bcm_esw_stat_flex_get_counter_id(
   3219                                   unit, 1, &table_info[index],
   3220                                   &num_stat_counter_ids,stat_counter_id);
   3221     }
   3222     return BCM_E_NOT_FOUND;
   3223 }
   3224 /*
   3225  * Function:
   3226  *      td2_mpls_label_stat_enable_set
   3227  * Purpose:
   3228  *      Enable statistics collection for MPLS label or MPLS gport
   3229  * Parameters:
   3230  *      unit - (IN) Unit number.
   3231  *      label - (IN) MPLS label
   3232  *      port - (IN) MPLS gport
   3233  *      enable - (IN) Non-zero to enable counter collection, zero to disable.
   3234  * Returns:
   3235  *      BCM_E_xxx
   3236  * Notes:
   3237  */
   3238 STATIC
   3239 int td2_mpls_label_stat_enable_set(
   3240     int              unit, 
   3241     bcm_mpls_label_t label,
   3242     bcm_gport_t      port, 
   3243     int              enable)
   3244 {
   3245     uint32                     num_of_tables=0;
   3246     uint32                     num_stat_counter_ids=0;
   3247     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   3248     bcm_stat_object_t          object=bcmStatObjectIngPort;
   3249     uint32                     stat_counter_id[
   3250                                        BCM_STAT_FLEX_COUNTER_MAX_DIRECTION]={0};
   3251     uint32                     num_entries=0;
   3252     int                        index=0;
   3253 
   3254     if (BCM_GPORT_IS_MPLS_PORT(port)) {
   3255         /* When the gport is an MPLS port, we'll turn on the
   3256          * port-based tracking to comply with API definition.
   3257          */
   3258 
   3259         int vpn;
   3260 
   3261         /* just create a valid vpn id to pass the check */
   3262         _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1);
   3263         BCM_IF_ERROR_RETURN(td2_mpls_port_stat_get_table_info(
   3264                         unit,vpn,port,&num_of_tables,&table_info[0]));
   3265         if (enable ) {
   3266             for(index=0;index < num_of_tables ;index++) {
   3267                 if (table_info[index].direction == bcmStatFlexDirectionIngress) {
   3268                     BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_ingress_object(
   3269                                         unit,table_info[index].table,
   3270                                         table_info[index].index,NULL,&object));
   3271                 } else {
   3272                     BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_egress_object(
   3273                                         unit,table_info[index].table,
   3274                                         table_info[index].table,NULL,&object));
   3275                 }
   3276                 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_create(
   3277                                     unit,object,bcmStatGroupModeSingle,
   3278                                 &stat_counter_id[table_info[index].direction],
   3279                                 &num_entries));
   3280                 BCM_IF_ERROR_RETURN(td2_mpls_port_stat_attach(
   3281                                 unit,vpn,port,
   3282                                 stat_counter_id[table_info[index].direction]));
   3283             }
   3284             return BCM_E_NONE;
   3285         } else {
   3286             BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_counter_id(
   3287                             unit, num_of_tables,&table_info[0],
   3288                             &num_stat_counter_ids,&stat_counter_id[0]));
   3289             if ((stat_counter_id[bcmStatFlexDirectionIngress] == 0) &&
   3290                 (stat_counter_id[bcmStatFlexDirectionEgress] == 0)) {
   3291                  return BCM_E_PARAM;
   3292             }
   3293             BCM_IF_ERROR_RETURN(td2_mpls_port_stat_detach(unit,vpn,port));
   3294             if (stat_counter_id[bcmStatFlexDirectionIngress] != 0) {
   3295                 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy(
   3296                                 unit,
   3297                                 stat_counter_id[bcmStatFlexDirectionIngress]));
   3298             }
   3299             if (stat_counter_id[bcmStatFlexDirectionEgress] != 0) {
   3300                 BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy(
   3301                                 unit,
   3302                                 stat_counter_id[bcmStatFlexDirectionEgress]));
   3303             }
   3304             return BCM_E_NONE;
   3305         }
   3306 
   3307     }
   3308 
   3309     if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   3310         return BCM_E_PARAM;
   3311     }
   3312 
   3313     BCM_IF_ERROR_RETURN(td2_mpls_label_stat_get_table_info(
   3314                         unit,label,port,bcmStatObjectMaxValue,&num_of_tables,&table_info[0]));
   3315     if (enable ) {
   3316         for(index=0;index < num_of_tables ;index++) {
   3317             if (table_info[index].direction == bcmStatFlexDirectionIngress) {
   3318                 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_ingress_object(
   3319                                     unit,table_info[index].table,
   3320                                     table_info[index].index,NULL,&object));
   3321             } else {
   3322                 BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_egress_object(
   3323                                     unit,table_info[index].table,
   3324                                     table_info[index].table,NULL,&object));
   3325             }
   3326             BCM_IF_ERROR_RETURN(bcm_esw_stat_group_create(
   3327                                 unit,object,bcmStatGroupModeSingle,
   3328                                 &stat_counter_id[table_info[index].direction],
   3329                                 &num_entries));
   3330             BCM_IF_ERROR_RETURN(bcm_esw_mpls_label_stat_attach(
   3331                                 unit,label,port,
   3332                                 stat_counter_id[table_info[index].direction]));
   3333         }
   3334         return BCM_E_NONE;
   3335     } else {
   3336         BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_counter_id(
   3337                             unit, num_of_tables,&table_info[0],
   3338                             &num_stat_counter_ids,&stat_counter_id[0]));
   3339         if ((stat_counter_id[bcmStatFlexDirectionIngress] == 0) &&
   3340             (stat_counter_id[bcmStatFlexDirectionEgress] == 0)) {
   3341              return BCM_E_PARAM;
   3342         }
   3343         BCM_IF_ERROR_RETURN(bcm_esw_mpls_label_stat_detach(unit,label,port));
   3344         if (stat_counter_id[bcmStatFlexDirectionIngress] != 0) {
   3345             BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy(
   3346                                 unit,
   3347                                 stat_counter_id[bcmStatFlexDirectionIngress]));
   3348         }
   3349         if (stat_counter_id[bcmStatFlexDirectionEgress] != 0) {
   3350             BCM_IF_ERROR_RETURN(bcm_esw_stat_group_destroy(
   3351                                 unit,
   3352                                 stat_counter_id[bcmStatFlexDirectionEgress]));
   3353         }
   3354         return BCM_E_NONE;
   3355     }
   3356 
   3357 }
   3358 /*
   3359  * Function:
   3360  *      td2_mpls_label_stat_get
   3361  * Purpose:
   3362  *      Get L2 MPLS PW Stats
   3363  * Parameters:
   3364  *      unit   - (IN) SOC unit #
   3365  *      label  - (IN) MPLS label
   3366  *      port   - (IN) MPLS gport
   3367  *      stat   - (IN)  specify the Stat type
   3368  *      val    - (OUT) 64-bit Stats value
   3369  * Returns:
   3370  *      BCM_E_XXX
   3371  */
   3372 
   3373 STATIC
   3374 int td2_mpls_label_stat_get(
   3375                             int              unit, 
   3376                             int              sync_mode,
   3377                             bcm_mpls_label_t label, 
   3378                             bcm_gport_t      port,
   3379                             bcm_mpls_stat_t  stat, 
   3380                             uint64           *val)
   3381 {
   3382     uint32           counter_indexes=0   ;
   3383     bcm_stat_value_t counter_values={0};
   3384 
   3385     if (BCM_GPORT_IS_MPLS_PORT(port)) {
   3386         int vpn;
   3387 
   3388         /* just create a valid vpn id to pass the check */
   3389         _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1);
   3390 
   3391         BCM_IF_ERROR_RETURN(td2_mpls_port_stat_counter_get(unit, sync_mode, 
   3392                                                            vpn, port, stat, 
   3393                                                            1, &counter_indexes,
   3394                                                            &counter_values));
   3395     } else {
   3396         if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   3397             return BCM_E_PARAM;
   3398         }
   3399 
   3400         BCM_IF_ERROR_RETURN(td2_mpls_label_stat_counter_get(
   3401                         unit, sync_mode, label, port, stat, 1,
   3402                         &counter_indexes, &counter_values));
   3403     }
   3404 
   3405     if ((stat == bcmMplsInPkts) ||
   3406         (stat == bcmMplsOutPkts)) {
   3407          COMPILER_64_SET(*val,
   3408                          COMPILER_64_HI(counter_values.packets64),
   3409                          COMPILER_64_LO(counter_values.packets64));
   3410     } else {
   3411          COMPILER_64_SET(*val,
   3412                          COMPILER_64_HI(counter_values.bytes),
   3413                          COMPILER_64_LO(counter_values.bytes));
   3414     }
   3415     return BCM_E_NONE;
   3416 }
   3417 
   3418 /*
   3419  * Function:
   3420  *      td2_mpls_label_stat_get32
   3421  * Purpose:
   3422  *      Get L2 MPLS PW Stats
   3423  *      if sync_mode is set, sync the sw accumulated count
   3424  *      with hw count value first, else return sw count.
   3425  * Parameters:
   3426  *      unit      - (IN) SOC unit #
   3427  *      sync_mode - (IN) hwcount is to be synced to sw count 
   3428  *      label     - (IN) MPLS label
   3429  *      port      - (IN) MPLS gport
   3430  *      stat      - (IN)  specify the Stat type
   3431  *      val       - (OUT) 32-bit Stats value
   3432  * Returns:
   3433  *      BCM_E_XXX
   3434  */
   3435 
   3436 STATIC
   3437 int td2_mpls_label_stat_get32(
   3438                               int              unit,
   3439                               int              sync_mode,
   3440                               bcm_mpls_label_t label, 
   3441                               bcm_gport_t      port, 
   3442                               bcm_mpls_stat_t  stat, 
   3443                               uint32           *val)
   3444 {
   3445     uint32           counter_indexes=0;
   3446     bcm_stat_value_t counter_values={0};
   3447 
   3448     if (BCM_GPORT_IS_MPLS_PORT(port)) {
   3449         int vpn;
   3450 
   3451         /* just create a valid vpn id to pass the check */
   3452         _BCM_MPLS_VPN_SET(vpn, _BCM_MPLS_VPN_TYPE_VPWS, 1);
   3453 
   3454         BCM_IF_ERROR_RETURN(td2_mpls_port_stat_counter_get(
   3455                unit, sync_mode, vpn, port, stat, 1,
   3456                &counter_indexes, &counter_values));
   3457     } else {
   3458 
   3459         if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   3460             return BCM_E_PARAM;
   3461         }
   3462 
   3463         BCM_IF_ERROR_RETURN(td2_mpls_label_stat_counter_get(
   3464                         unit, sync_mode, label, port, stat, 1,
   3465                         &counter_indexes, &counter_values));
   3466     }
   3467 
   3468     if ((stat == bcmMplsInPkts) ||
   3469         (stat == bcmMplsOutPkts)) {
   3470          *val = counter_values.packets;
   3471     } else {
   3472          /* Ignoring Hi bytes value */
   3473          *val = COMPILER_64_LO(counter_values.bytes);
   3474     }
   3475     return BCM_E_NONE;
   3476 }
   3477 
   3478 /*
   3479  * Function:
   3480  *      td2_mpls_label_stat_clear
   3481  * Purpose:
   3482  *      Clear L2 MPLS PW Stats
   3483  * Parameters:
   3484  *      unit   - (IN) SOC unit #
   3485  *      label  - (IN) MPLS label
   3486  *      port   - (IN) MPLS gport
   3487  *      stat   - (IN)  specify the Stat type
   3488  * Returns:
   3489  *      BCM_E_XXX
   3490  */
   3491 
   3492 STATIC
   3493 int td2_mpls_label_stat_clear(
   3494     int              unit, 
   3495     bcm_mpls_label_t label, 
   3496     bcm_gport_t      port, 
   3497     bcm_mpls_stat_t  stat)
   3498 {
   3499     uint32           counter_indexes=0   ;
   3500     bcm_stat_value_t counter_values={0};
   3501 
   3502     if (!BCM_XGS3_L3_MPLS_LBL_VALID(label)) {
   3503         return BCM_E_PARAM;
   3504     }
   3505 
   3506     BCM_IF_ERROR_RETURN(bcm_esw_mpls_label_stat_counter_set(
   3507                         unit,label,port,stat,1,
   3508                         &counter_indexes,&counter_values));
   3509     return BCM_E_NONE;
   3510 }
   3511 
   3512 
   3513 #endif /* BCM_TRIDENT2_SUPPORT */
   3514 
   3515 /*
   3516  * Function:
   3517  *      bcm_esw_mpls_label_stat_enable_set
   3518  * Purpose:
   3519  *      Enable statistics collection for MPLS label or MPLS gport
   3520  * Parameters:
   3521  *      unit - (IN) Unit number.
   3522  *      label - (IN) MPLS label
   3523  *      port - (IN) MPLS gport
   3524  *      enable - (IN) Non-zero to enable counter collection, zero to disable.
   3525  * Returns:
   3526  *      BCM_E_xxx
   3527  * Notes:
   3528  */
   3529 int 
   3530 bcm_esw_mpls_label_stat_enable_set(int unit, bcm_mpls_label_t label, 
   3531                                    bcm_gport_t port, int enable)
   3532 {
   3533     int rv = BCM_E_UNAVAIL;
   3534 #ifdef BCM_MPLS_SUPPORT
   3535 #ifdef BCM_TRIUMPH2_SUPPORT
   3536     if (soc_feature(unit, soc_feature_gport_service_counters) &&
   3537         soc_feature(unit, soc_feature_mpls)) {
   3538         rv = bcm_tr_mpls_lock(unit);
   3539         if (BCM_E_NONE == rv) {
   3540             rv = bcm_tr2_mpls_label_stat_enable_set(unit, label,
   3541                                                     port, enable,0);
   3542             bcm_tr_mpls_unlock(unit);
   3543         }
   3544     }
   3545 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
   3546     defined(BCM_TRIDENT2_SUPPORT)
   3547       else if (soc_feature(unit,soc_feature_advanced_flex_counter) &&
   3548                soc_feature(unit, soc_feature_mpls)) {
   3549                BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit));
   3550 #if defined(BCM_KATANA_SUPPORT) 
   3551                if (SOC_IS_KATANAX(unit)) {
   3552                    rv = bcm_kt_mpls_label_stat_enable_set(unit, label,
   3553                                                           port, enable);
   3554                } else
   3555 #endif
   3556 #if defined(BCM_TRIUMPH3_SUPPORT) 
   3557                if (SOC_IS_TRIUMPH3(unit)) {
   3558                    rv = bcm_tr3_mpls_label_stat_enable_set(unit, label,
   3559                                                            port, enable);
   3560                } else
   3561 #endif
   3562                {
   3563 #if defined(BCM_TRIDENT2_SUPPORT) 
   3564                    rv = td2_mpls_label_stat_enable_set(unit, label,
   3565                                                            port, enable);
   3566 #endif
   3567                }
   3568                bcm_tr_mpls_unlock(unit);
   3569     }
   3570 #endif
   3571 #if defined(BCM_MONTEREY_SUPPORT)
   3572       else if(SOC_IS_MONTEREY(unit)) {
   3573         /* Flex counters not supported in Monterey */
   3574         return rv;
   3575       }
   3576 #endif
   3577 #endif
   3578 #endif
   3579     return rv;
   3580 }
   3581 
   3582 /*
   3583  * Function:
   3584  *      _bcm_esw_mpls_label_stat_get
   3585  * Purpose:
   3586  *      Get L2 MPLS PW Stats
   3587  *      if sync_mode is set, sync the sw accumulated count
   3588  *      with hw count value first, else return sw count.  
   3589  * Parameters:
   3590  *      unit   - (IN) SOC unit #
   3591  *      sync_mode        - (IN) hwcount is to be synced to sw count 
   3592  *      label  - (IN) MPLS label
   3593  *      port   - (IN) MPLS gport
   3594  *      stat   - (IN)  specify the Stat type
   3595  *      val    - (OUT) 64-bit Stats value
   3596  * Returns:
   3597  *      BCM_E_XXX
   3598  */     
   3599 
   3600 int
   3601 _bcm_esw_mpls_label_stat_get(int unit, int sync_mode, 
   3602                              bcm_mpls_label_t label, 
   3603                              bcm_gport_t port, 
   3604                              bcm_mpls_stat_t stat, 
   3605                              uint64 *val)
   3606 {
   3607 int rv = BCM_E_UNAVAIL;
   3608 #ifdef BCM_MPLS_SUPPORT
   3609 #ifdef BCM_TRIUMPH_SUPPORT
   3610 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
   3611     defined(BCM_TRIDENT2_SUPPORT)
   3612     if (soc_feature(unit,soc_feature_advanced_flex_counter) &&
   3613                soc_feature(unit, soc_feature_mpls)) {
   3614                BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit));
   3615 #if defined(BCM_KATANA_SUPPORT) 
   3616                if (SOC_IS_KATANAX(unit)) {
   3617                    rv = bcm_kt_mpls_label_stat_get(unit, sync_mode, 
   3618                                                    label, port, 
   3619                                                    stat, val);
   3620                } else
   3621 #endif
   3622 #if defined(BCM_TRIUMPH3_SUPPORT)
   3623                if (SOC_IS_TRIUMPH3(unit)) {
   3624                    rv = bcm_tr3_mpls_label_stat_get(unit, sync_mode, 
   3625                                                     label, port,
   3626                                                     stat, val);
   3627                } else
   3628 #endif
   3629                {
   3630 #if defined(BCM_TRIDENT2_SUPPORT)
   3631                    rv = td2_mpls_label_stat_get(unit, sync_mode, 
   3632                                                 label, port,
   3633                                                 stat, val);
   3634 #endif
   3635                }
   3636                bcm_tr_mpls_unlock(unit);
   3637     } else
   3638 #endif
   3639 #if defined(BCM_MONTEREY_SUPPORT)
   3640     if(SOC_IS_MONTEREY(unit)) {
   3641         /* Flex counters not supported in Monterey */
   3642         return rv;
   3643     } else
   3644 #endif
   3645     if ((SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) ||
   3646         (soc_feature(unit, soc_feature_mpls) &&
   3647          soc_feature(unit, soc_feature_gport_service_counters))) {
   3648               rv = bcm_tr_mpls_lock(unit);
   3649          if ( rv == BCM_E_NONE ) {
   3650               rv = bcm_tr_mpls_label_stat_get(unit, sync_mode, 
   3651                                                label, port, 
   3652                                                stat, val);
   3653               bcm_tr_mpls_unlock (unit);
   3654          }
   3655         return rv;
   3656     }
   3657 #endif
   3658 #endif
   3659     return rv;
   3660 }
   3661 
   3662 
   3663 /*
   3664  * Function:
   3665  *      bcm_esw_mpls_label_stat_get
   3666  * Purpose:
   3667  *      Get L2 MPLS PW Stats
   3668  * Parameters:
   3669  *      unit   - (IN) SOC unit #
   3670  *      label  - (IN) MPLS label
   3671  *      port   - (IN) MPLS gport
   3672  *      stat   - (IN)  specify the Stat type
   3673  *      val    - (OUT) 64-bit Stats value
   3674  * Returns:
   3675  *      BCM_E_XXX
   3676  */     
   3677 int
   3678 bcm_esw_mpls_label_stat_get(int unit, bcm_mpls_label_t label, 
   3679                             bcm_gport_t port, bcm_mpls_stat_t stat, 
   3680                             uint64 *val)
   3681 {
   3682     int rv = BCM_E_UNAVAIL;
   3683 
   3684     rv = _bcm_esw_mpls_label_stat_get(unit, 0, label, port, stat, val);
   3685 
   3686     return rv;
   3687 }
   3688 
   3689 
   3690 /*
   3691  * Function:
   3692  *      bcm_esw_mpls_label_stat_sync_get
   3693  * Purpose:
   3694  *      Get L2 MPLS PW Stats
   3695  *      sw accumulated counters synced with hw count.
   3696  * Parameters:
   3697  *      unit   - (IN) SOC unit #
   3698  *      label  - (IN) MPLS label
   3699  *      port   - (IN) MPLS gport
   3700  *      stat   - (IN)  specify the Stat type
   3701  *      val    - (OUT) 64-bit Stats value
   3702  * Returns:
   3703  *      BCM_E_XXX
   3704  */     
   3705 int
   3706 bcm_esw_mpls_label_stat_sync_get(int unit, bcm_mpls_label_t label, 
   3707                                  bcm_gport_t port, bcm_mpls_stat_t stat, 
   3708                                  uint64 *val)
   3709 {
   3710     int rv = BCM_E_UNAVAIL;
   3711 
   3712     rv = _bcm_esw_mpls_label_stat_get(unit, 1, label, port, stat, val);
   3713 
   3714     return rv;
   3715 }
   3716 
   3717 
   3718 /*
   3719  * Function:
   3720  *      bcm_esw_mpls_label_stat_get32
   3721  * Purpose:
   3722  *      Get L2 MPLS PW Stats
   3723  * Parameters:
   3724  *      unit      - (IN) SOC unit #
   3725  *      sync_mode - (IN) hwcount is to be synced to sw count 
   3726  *      label     - (IN) MPLS label
   3727  *      port      - (IN) MPLS gport
   3728  *      stat      - (IN)  specify the Stat type
   3729  *      val       - (OUT) 64-bit Stats value
   3730  * Returns:
   3731  *      BCM_E_XXX
   3732  */     
   3733 int
   3734 _bcm_esw_mpls_label_stat_get32(int unit, int sync_mode, 
   3735                                bcm_mpls_label_t label, 
   3736                                bcm_gport_t port,
   3737                                bcm_mpls_stat_t stat, 
   3738                                uint32 *val)
   3739 {
   3740 int rv = BCM_E_UNAVAIL;
   3741 #ifdef BCM_MPLS_SUPPORT
   3742 #ifdef BCM_TRIUMPH_SUPPORT
   3743     
   3744 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
   3745     defined(BCM_TRIDENT2_SUPPORT)
   3746     if (soc_feature(unit,soc_feature_advanced_flex_counter) &&
   3747                soc_feature(unit, soc_feature_mpls)) {
   3748                BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit));
   3749 #if defined(BCM_KATANA_SUPPORT) 
   3750                if (SOC_IS_KATANAX(unit)) {
   3751                    rv = bcm_kt_mpls_label_stat_get32(unit, sync_mode, 
   3752                                                      label, port,
   3753                                                      stat, val);
   3754                } else
   3755 #endif
   3756 #if defined(BCM_TRIUMPH3_SUPPORT)
   3757                if (SOC_IS_TRIUMPH3(unit)) {
   3758                    rv = bcm_tr3_mpls_label_stat_get32(unit, sync_mode, 
   3759                                                       label, port,
   3760                                                       stat, val);
   3761                } else
   3762 #endif
   3763                {
   3764 #if defined(BCM_TRIDENT2_SUPPORT)
   3765                    rv = td2_mpls_label_stat_get32(unit, sync_mode, 
   3766                                                   label, port,
   3767                                                   stat, val);
   3768 #endif
   3769                }
   3770                bcm_tr_mpls_unlock(unit);
   3771     } else
   3772 #endif
   3773 #if defined(BCM_MONTEREY_SUPPORT)
   3774     if(SOC_IS_MONTEREY(unit)) {
   3775         /* Flex counters not supported in Monterey */
   3776         return rv;
   3777     } else
   3778 #endif
   3779     if ((SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) ||
   3780         (soc_feature(unit, soc_feature_mpls) &&
   3781          soc_feature(unit, soc_feature_gport_service_counters))) {
   3782               rv = bcm_tr_mpls_lock(unit);
   3783          if ( rv == BCM_E_NONE ) {
   3784               rv = bcm_tr_mpls_label_stat_get32(unit, sync_mode, 
   3785                                                label, port, 
   3786                                                stat, val);
   3787               bcm_tr_mpls_unlock (unit);
   3788          }
   3789          return rv;
   3790     }
   3791 #endif
   3792 #endif
   3793     return rv;
   3794 }
   3795 
   3796 
   3797 int
   3798 bcm_esw_mpls_label_stat_get32(int unit, bcm_mpls_label_t label, 
   3799                               bcm_gport_t port, 
   3800                               bcm_mpls_stat_t stat, 
   3801                               uint32 *val)
   3802 {
   3803     int rv = BCM_E_UNAVAIL;
   3804 
   3805     rv = _bcm_esw_mpls_label_stat_get32(unit, 0, label, port, stat, val);
   3806 
   3807     return rv;
   3808 }
   3809 
   3810 
   3811 int
   3812 bcm_esw_mpls_label_stat_sync_get32(int unit, bcm_mpls_label_t label, 
   3813                                    bcm_gport_t port, 
   3814                                    bcm_mpls_stat_t stat, 
   3815                                    uint32 *val)
   3816 {
   3817     int rv = BCM_E_UNAVAIL;
   3818 
   3819     rv = _bcm_esw_mpls_label_stat_get32(unit, 1, label, port, stat, val);
   3820 
   3821     return rv;
   3822 }    
   3823 
   3824 /*
   3825  * Function:
   3826  *      bcm_esw_mpls_label_stat_clear
   3827  * Purpose:
   3828  *      Clear L2 MPLS PW Stats
   3829  * Parameters:
   3830  *      unit   - (IN) SOC unit #
   3831  *      label  - (IN) MPLS label
   3832  *      port   - (IN) MPLS gport
   3833  *      stat   - (IN)  specify the Stat type
   3834  * Returns:
   3835  *      BCM_E_XXX
   3836  */     
   3837 
   3838 int
   3839 bcm_esw_mpls_label_stat_clear(int unit, bcm_mpls_label_t label, bcm_gport_t port,
   3840                             bcm_mpls_stat_t stat)
   3841 {
   3842 int rv = BCM_E_UNAVAIL;
   3843 #ifdef BCM_MPLS_SUPPORT
   3844 #ifdef BCM_TRIUMPH_SUPPORT
   3845 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
   3846     defined(BCM_TRIDENT2_SUPPORT)
   3847     if (soc_feature(unit,soc_feature_advanced_flex_counter) &&
   3848                soc_feature(unit, soc_feature_mpls)) {
   3849                BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit));
   3850 #if defined(BCM_KATANA_SUPPORT) 
   3851                if (SOC_IS_KATANAX(unit)) {
   3852                    rv = bcm_kt_mpls_label_stat_clear(unit,label,port, stat);
   3853                } else
   3854 #endif
   3855 #if defined(BCM_TRIUMPH3_SUPPORT)
   3856               if (SOC_IS_TRIUMPH3(unit)) {
   3857                   rv = bcm_tr3_mpls_label_stat_clear(unit,label,port,stat);
   3858               } else
   3859 #endif
   3860               {
   3861 #if defined(BCM_TRIDENT2_SUPPORT)
   3862                   rv = td2_mpls_label_stat_clear(unit,label,port,stat);
   3863 #endif
   3864               }
   3865               bcm_tr_mpls_unlock(unit);
   3866     } else
   3867 #endif
   3868 #if defined(BCM_MONTEREY_SUPPORT)
   3869     if(SOC_IS_MONTEREY(unit)) {
   3870         /* Flex counters not supported in Monterey */
   3871         return rv;
   3872     } else
   3873 #endif
   3874     if ((SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) ||
   3875         (soc_feature(unit, soc_feature_mpls) &&
   3876          soc_feature(unit, soc_feature_gport_service_counters))) {
   3877               rv = bcm_tr_mpls_lock(unit);
   3878          if ( rv == BCM_E_NONE ) {
   3879               rv = bcm_tr_mpls_label_stat_clear(unit, label, port, stat);
   3880               bcm_tr_mpls_unlock (unit);
   3881          }
   3882          return rv;
   3883     }
   3884 #endif
   3885 #endif
   3886     return rv;
   3887 }
   3888 
   3889 /*
   3890  * Function:
   3891  *      _bcm_esw_mpls_trunk_member_add
   3892  * Purpose:
   3893  *      Set Mpls state for trunk members joining a trunk group.
   3894  * Parameters:
   3895  *     unit  - (IN) Device Number
   3896  *     trunk_id - (IN)  Trunk Group ID
   3897  *     trunk_member_count - (IN) Count of Trunk members to be added
   3898  *     trunk_member_array - (IN) Trunk member ports to be added
   3899  * Returns:
   3900  *      BCM_E_XXX
   3901  */     
   3902 int
   3903 _bcm_esw_mpls_trunk_member_add(int unit, bcm_trunk_t trunk_id, 
   3904         int trunk_member_count, bcm_port_t *trunk_member_array)
   3905 {
   3906     int rv = BCM_E_UNAVAIL;
   3907 #ifdef BCM_MPLS_SUPPORT
   3908 #ifdef BCM_TRIUMPH_SUPPORT
   3909     if (soc_feature(unit, soc_feature_mpls)) {
   3910         rv = bcm_tr_mpls_trunk_member_add(unit, trunk_id,
   3911                  trunk_member_count, trunk_member_array);
   3912     }
   3913 #endif
   3914 #endif
   3915     return rv;
   3916 }
   3917 
   3918 /*
   3919  * Function:
   3920  *      _bcm_esw_mpls_trunk_member_delete
   3921  * Purpose:
   3922  *      Clear Mpls state for trunk members leaving a trunk group.
   3923  * Parameters:
   3924  *     unit  - (IN) Device Number
   3925  *     trunk_id - (IN)  Trunk Group ID
   3926  *     trunk_member_count - (IN) Count of Trunk members to be deleted
   3927  *     trunk_member_array - (IN) Trunk member ports to be deleted
   3928  * Returns:
   3929  *      BCM_E_XXX
   3930  */     
   3931 int
   3932 _bcm_esw_mpls_trunk_member_delete(int unit, bcm_trunk_t trunk_id, 
   3933         int trunk_member_count, bcm_port_t *trunk_member_array)
   3934 {
   3935     int rv = BCM_E_UNAVAIL;
   3936 #ifdef BCM_MPLS_SUPPORT
   3937 #ifdef BCM_TRIUMPH_SUPPORT
   3938     if (soc_feature(unit, soc_feature_mpls)) {
   3939         rv = bcm_tr_mpls_trunk_member_delete(unit, trunk_id,
   3940                  trunk_member_count, trunk_member_array);
   3941     }
   3942 #endif
   3943 #endif
   3944     return rv;
   3945 }
   3946 
   3947 /*
   3948  * Function:
   3949  *      _bcm_esw_mpls_match_add
   3950  * Purpose:
   3951  *      Assign match criteria of an MPLS port
   3952  * Parameters:
   3953  *      unit    - (IN) Device Number
   3954  *      mpls_port - (IN) mpls port information
   3955  *      vp  - (IN) Source Virtual Port
   3956  *      vpn - (IN) VPN
   3957  * Returns:
   3958  *      BCM_E_XXX
   3959  */
   3960 
   3961 int
   3962 _bcm_esw_mpls_match_add(int unit, bcm_mpls_port_t *mpls_port, int vp, int vpn,
   3963                         int hw_update)
   3964 {
   3965 int rv = BCM_E_UNAVAIL;
   3966 
   3967 #ifdef BCM_MPLS_SUPPORT
   3968 #ifdef BCM_TRIUMPH3_SUPPORT
   3969     if (SOC_IS_TRIUMPH3(unit)) {
   3970          rv = _bcm_tr3_mpls_match_add(unit, mpls_port, vp, hw_update);
   3971          return rv;
   3972     }
   3973 #endif
   3974 #ifdef BCM_TRIUMPH_SUPPORT
   3975     if (SOC_IS_TR_VL(unit)) {
   3976          rv = _bcm_tr_mpls_match_add(unit, mpls_port, vp, vpn, hw_update);
   3977          return rv;
   3978     }
   3979 #endif
   3980 #endif
   3981     return rv;
   3982 
   3983 }
   3984 
   3985 /*
   3986  * Function:
   3987  *      _bcm_esw_mpls_match_delete
   3988  * Purpose:
   3989  *      Delete match criteria of an MPLS port
   3990  * Parameters:
   3991  *      unit    - (IN) Device Number
   3992  *      vp  - (IN) Source Virtual Port
   3993  * Returns:
   3994  *      BCM_E_XXX
   3995  */
   3996 
   3997 int
   3998 _bcm_esw_mpls_match_delete(int unit, int vp, int sw_clear)
   3999 {
   4000 int rv = BCM_E_UNAVAIL;
   4001 
   4002 #ifdef BCM_MPLS_SUPPORT
   4003 #ifdef BCM_TRIUMPH3_SUPPORT
   4004     if (SOC_IS_TRIUMPH3(unit)) {
   4005          rv = _bcm_tr3_mpls_match_delete(unit, vp, sw_clear);
   4006          return rv;
   4007     }
   4008 #endif
   4009 #ifdef BCM_TRIUMPH_SUPPORT
   4010     if (SOC_IS_TR_VL(unit)) {
   4011          rv = _bcm_tr_mpls_match_delete(unit, vp, NULL, sw_clear);
   4012          return rv;
   4013     }
   4014 #endif
   4015 #endif
   4016     return rv;
   4017 
   4018 }
   4019 
   4020 /*
   4021  * Function:
   4022  *  _bcm_esw_mpls_match_failover_update
   4023  * Purpose:
   4024  *  Search mpls entry with provided source vp
   4025  *  and replace with failover vp
   4026  * Parameters:
   4027  *  unit    - (IN) Device Number
   4028  *  vp      - (IN) Source Virtual Port
   4029  *  fo_vp   - (IN) Failover Virtual Port
   4030  * Returns:
   4031  *  BCM_E_XXX
   4032  */
   4033 
   4034 int
   4035 _bcm_esw_mpls_match_failover_update(int unit, int vp, int fo_vp)
   4036 {
   4037     int rv = BCM_E_NONE;
   4038 #ifdef BCM_MPLS_SUPPORT
   4039 #if defined(BCM_TRIUMPH3_SUPPORT)
   4040     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_METROLITE(unit)) {
   4041         rv = _bcm_tr3_mpls_match_failover_update(unit, vp, fo_vp);
   4042         return rv;
   4043     }
   4044 #endif
   4045 #endif
   4046     return rv;
   4047 }
   4048 
   4049 /*
   4050  * Function:
   4051  *      _bcm_esw_mpls_failover_nw_port_match_get
   4052  * Purpose:
   4053  *      Get match criteria of an MPLS port
   4054  * Parameters:
   4055  *      unit        - (IN) Device Number
   4056  *      mpls_port   - (IN) mpls port
   4057  *      vp          - (IN) Source Virtual Port
   4058  *      return_ment - (OUT) matched mpls entry.
   4059  * Returns:
   4060  *      BCM_E_XXX
   4061  */
   4062 
   4063 int
   4064 _bcm_esw_mpls_failover_nw_port_match_get(int unit, bcm_mpls_port_t *mpls_port,
   4065                                     int vp, mpls_entry_entry_t *return_ment)
   4066 
   4067 {
   4068 int rv = BCM_E_NOT_FOUND;
   4069 
   4070 #ifdef BCM_MPLS_SUPPORT
   4071 #ifdef BCM_TRIUMPH3_SUPPORT
   4072     if (SOC_IS_TRIUMPH3(unit)) {
   4073          rv = _bcm_tr3_mpls_failover_nw_port_match_get(unit, mpls_port, vp,
   4074                   return_ment);
   4075          return rv;
   4076     }
   4077 #endif
   4078 #if defined(BCM_APACHE_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT)
   4079     if (soc_feature(unit, soc_feature_mpls_xgs5_nw_port_match)) {
   4080         rv = bcmi_xgs5_mpls_failover_nw_port_match_get(unit, mpls_port, vp,
   4081                   return_ment);
   4082         return rv;
   4083     }
   4084 #endif
   4085 #ifdef BCM_TRIUMPH_SUPPORT
   4086 if (SOC_IS_TR_VL(unit)) {
   4087     rv = _bcm_tr_mpls_failover_nw_port_match_get(unit, mpls_port, vp,
   4088                     return_ment);
   4089         return rv;
   4090     }
   4091 #endif
   4092 #endif
   4093 
   4094     return rv;
   4095 }
   4096 
   4097 /*
   4098  * Function:
   4099  *      _bcm_esw_mpls_match_get
   4100  * Purpose:
   4101  *      Get match criteria of an MPLS port
   4102  * Parameters:
   4103  *      unit    - (IN) Device Number
   4104  *      vp  - (IN) Source Virtual Port
   4105  * Returns:
   4106  *      BCM_E_XXX
   4107  */
   4108 
   4109 int
   4110 _bcm_esw_mpls_match_get(int unit, bcm_mpls_port_t *mpls_port, int vp)
   4111 {
   4112 int rv = BCM_E_UNAVAIL;
   4113 
   4114 #ifdef BCM_MPLS_SUPPORT
   4115 #ifdef BCM_TRIUMPH3_SUPPORT
   4116     if (SOC_IS_TRIUMPH3(unit)) {
   4117          rv = _bcm_tr3_mpls_match_get(unit, mpls_port, vp);
   4118          return rv;
   4119     }
   4120 #endif
   4121 #ifdef BCM_TRIUMPH_SUPPORT
   4122     if (SOC_IS_TR_VL(unit)) {
   4123          rv = _bcm_tr_mpls_match_get(unit, mpls_port, vp);
   4124          return rv;
   4125     }
   4126 #endif
   4127 #endif
   4128     return rv;
   4129 
   4130 }
   4131 
   4132 /*
   4133  * Function:
   4134  *      _bcm_mpls_tunnel_switch_delete_all
   4135  * Purpose:
   4136  *      Delete all MPLS label entries.
   4137  * Parameters:
   4138  *      unit   - Device Number
   4139  * Returns:
   4140  *      BCM_E_XXX
   4141  */
   4142 int
   4143 _bcm_esw_mpls_tunnel_switch_delete_all (int unit)
   4144 {
   4145 int rv = BCM_E_UNAVAIL;
   4146 #ifdef BCM_MPLS_SUPPORT
   4147 #ifdef BCM_TRIUMPH3_SUPPORT
   4148     if (SOC_IS_TRIUMPH3(unit) && soc_feature(unit, soc_feature_mpls)) {
   4149          rv = bcm_tr3_mpls_tunnel_switch_delete_all(unit);
   4150          return rv;
   4151     }
   4152 #endif
   4153 #ifdef BCM_KATANA_SUPPORT
   4154     if (SOC_IS_KATANAX(unit) && soc_feature(unit, soc_feature_mpls)) {
   4155          rv = bcm_kt_mpls_tunnel_switch_delete_all(unit);
   4156          return rv;
   4157     }
   4158 #endif
   4159 #ifdef BCM_TRIUMPH_SUPPORT
   4160     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls)) {
   4161 #if (defined(BCM_TOMAHAWK3_SUPPORT))
   4162                   if (SOC_IS_TOMAHAWK3(unit)) {
   4163                       rv = bcmi_xgs5_mpls_tunnel_switch_delete_all(unit);
   4164                   } else
   4165 #endif
   4166                   {
   4167                       rv = bcm_tr_mpls_tunnel_switch_delete_all(unit);
   4168                   }
   4169          return rv;
   4170     }
   4171 #endif
   4172 #endif
   4173     return rv;
   4174 }
   4175 
   4176 /*
   4177  * Function:
   4178  *      bcm_esw_mpls_port_stat_attach
   4179  * Description:
   4180  *      Attach counters entries to the given mpls gport and vpn 
   4181  *
   4182  * Parameters:
   4183  *      unit             - (IN) unit number
   4184  *      vpn              - (IN) VPN Id
   4185  *      port             - (IN) MPLS GPORT ID
   4186  *      stat_counter_id  - (IN) Stat Counter ID.
   4187  *
   4188  * Return Value:
   4189  *      BCM_E_XXX
   4190  * Notes:
   4191  */
   4192 int bcm_esw_mpls_port_stat_attach(
   4193             int         unit, 
   4194             bcm_vpn_t   vpn, 
   4195             bcm_gport_t port, 
   4196             uint32      stat_counter_id)
   4197 {
   4198 #ifdef BCM_KATANA_SUPPORT
   4199     if (SOC_IS_KATANAX(unit)) {
   4200         return bcm_kt_mpls_port_stat_attach(
   4201                unit,vpn,port,stat_counter_id);
   4202     } else 
   4203 #endif
   4204 #ifdef BCM_TRIUMPH3_SUPPORT
   4205     if (SOC_IS_TRIUMPH3(unit)) {
   4206         return bcm_tr3_mpls_port_stat_attach(
   4207                unit,vpn,port,stat_counter_id);
   4208     }  else
   4209 #endif
   4210     {
   4211 #ifdef BCM_TRIDENT2_SUPPORT
   4212         if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   4213             return td2_mpls_port_stat_attach(
   4214                    unit,vpn,port,stat_counter_id);
   4215         }
   4216 #endif
   4217     }
   4218 #if defined(BCM_MPLS_SUPPORT)
   4219 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   4220     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_TRIDENT(unit)) {
   4221         if (soc_feature(unit, soc_feature_gport_service_counters) &&
   4222             soc_feature(unit, soc_feature_mpls)) {
   4223             _bcm_flex_stat_type_t fs_type;
   4224             uint32 fs_inx;
   4225             uint32 flag;
   4226             int rv;
   4227 
   4228             fs_type = _BCM_FLEX_STAT_TYPE(stat_counter_id);
   4229             fs_inx  = _BCM_FLEX_STAT_COUNT_INX(stat_counter_id);
   4230             if (((fs_type != _bcmFlexStatTypeEgressGport) && 
   4231                  (fs_type != _bcmFlexStatTypeGport)) || (!fs_inx)) {
   4232                 return BCM_E_PARAM;
   4233             }
   4234             flag = fs_type==_bcmFlexStatTypeGport? _BCM_FLEX_STAT_HW_INGRESS:
   4235                          _BCM_FLEX_STAT_HW_EGRESS;
   4236 
   4237             rv = _bcm_esw_flex_stat_enable_set(unit, fs_type,
   4238                              _bcm_esw_port_flex_stat_hw_index_set,
   4239                                       INT_TO_PTR(flag),
   4240                                       port, TRUE,fs_inx);
   4241             return rv;
   4242         }
   4243     }
   4244 #endif
   4245 #endif
   4246     return BCM_E_UNAVAIL;
   4247 }
   4248 
   4249 /*
   4250  * Function:
   4251  *      bcm_esw_mpls_port_stat_detach
   4252  * Description:
   4253  *      Detach counters entries to the given mpls port and vpn 
   4254  *
   4255  * Parameters:
   4256  *      unit             - (IN) unit number
   4257  *      vpn              - (IN) VPN Id
   4258  *      port             - (IN) MPLS GPORT ID
   4259  *
   4260  * Return Value:
   4261  *      BCM_E_XXX
   4262  * Notes:
   4263  */
   4264 int bcm_esw_mpls_port_stat_detach(
   4265             int         unit, 
   4266             bcm_vpn_t   vpn, 
   4267             bcm_gport_t port)
   4268 {
   4269 #ifdef BCM_KATANA_SUPPORT
   4270     if (SOC_IS_KATANAX(unit)) {
   4271         return bcm_kt_mpls_port_stat_detach(unit,vpn,port);
   4272     } else
   4273 #endif
   4274 #ifdef BCM_TRIUMPH3_SUPPORT
   4275     if (SOC_IS_TRIUMPH3(unit)) {
   4276         return bcm_tr3_mpls_port_stat_detach(unit,vpn,port);
   4277     } else
   4278 #endif
   4279     {
   4280 #ifdef BCM_TRIDENT2_SUPPORT
   4281         if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   4282             return td2_mpls_port_stat_detach(unit,vpn,port);
   4283         }
   4284 #endif
   4285     }
   4286 #if defined(BCM_MPLS_SUPPORT)
   4287 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   4288     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_TRIDENT(unit)) {
   4289         if (soc_feature(unit, soc_feature_gport_service_counters) &&
   4290             soc_feature(unit, soc_feature_mpls)) {
   4291             uint32 flag;
   4292             int rv;
   4293             int rv1;
   4294 
   4295             flag= _BCM_FLEX_STAT_HW_INGRESS;
   4296             rv = _bcm_esw_flex_stat_enable_set(unit, _bcmFlexStatTypeGport,
   4297                              _bcm_esw_port_flex_stat_hw_index_set,
   4298                                       INT_TO_PTR(flag),
   4299                                       port, FALSE,1);
   4300             flag= _BCM_FLEX_STAT_HW_EGRESS;
   4301             rv1 = _bcm_esw_flex_stat_enable_set(unit,
   4302                          _bcmFlexStatTypeEgressGport,
   4303                          _bcm_esw_port_flex_stat_hw_index_set,
   4304                                   INT_TO_PTR(flag),
   4305                                   port, FALSE,1);
   4306             if (BCM_SUCCESS(rv) && BCM_SUCCESS(rv1)) {
   4307                 return BCM_E_NONE;
   4308             } else {
   4309                 return BCM_E_NOT_FOUND;
   4310             }
   4311         }
   4312     }
   4313 #endif
   4314 #endif
   4315     return BCM_E_UNAVAIL;
   4316 }
   4317 
   4318 /*
   4319  * Function:
   4320  *      _bcm_esw_mpls_port_stat_counter_get
   4321  * Description:
   4322  *      Get counter statistic values for specific vpn and gport 
   4323  *      if sync_mode is set, sync the sw accumulated count
   4324  *      with hw count value first, else return sw count.  
   4325  *
   4326  * Parameters:
   4327  *      unit             - (IN) unit number
   4328  *      sync_mode        - (IN) hwcount is to be synced to sw count 
   4329  *      vpn              - (IN) VPN Id
   4330  *      port             - (IN) MPLS GPORT ID
   4331  *      stat             - (IN) Type of the counter to retrieve
   4332  *                              I.e. ingress/egress byte/packet)
   4333  *      num_entries      - (IN) Number of counter Entries
   4334  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   4335  *      counter_values   - (OUT) Pointer to counter values
   4336  *
   4337  * Return Value:
   4338  *      BCM_E_XXX
   4339  * Notes:
   4340  */
   4341 
   4342 int 
   4343 _bcm_esw_mpls_port_stat_counter_get(
   4344             int                  unit, 
   4345             int                  sync_mode, 
   4346             bcm_vpn_t            vpn, 
   4347             bcm_gport_t          port, 
   4348             bcm_mpls_stat_t      stat, 
   4349             uint32               num_entries, 
   4350             uint32               *counter_indexes, 
   4351             bcm_stat_value_t     *counter_values)
   4352 {
   4353 #ifdef BCM_KATANA_SUPPORT
   4354     if (SOC_IS_KATANAX(unit)) {
   4355         return bcm_kt_mpls_port_stat_counter_get(
   4356                unit, sync_mode, vpn, port, stat, num_entries,
   4357                counter_indexes,counter_values);
   4358     } else
   4359 #endif
   4360 #ifdef BCM_TRIUMPH3_SUPPORT
   4361     if (SOC_IS_TRIUMPH3(unit)) {
   4362         return bcm_tr3_mpls_port_stat_counter_get(
   4363                unit, sync_mode, vpn, port, stat, num_entries, 
   4364                counter_indexes,counter_values);
   4365     } else
   4366 #endif
   4367     {
   4368 #ifdef BCM_TRIDENT2_SUPPORT
   4369         if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   4370             return td2_mpls_port_stat_counter_get(
   4371                unit, sync_mode, vpn, port, stat, num_entries, 
   4372                counter_indexes,counter_values);
   4373         }
   4374 #endif
   4375     }
   4376 #if defined(BCM_MPLS_SUPPORT)
   4377 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   4378     if ((SOC_IS_TRIUMPH2(unit) || SOC_IS_TRIDENT(unit)) &&
   4379         soc_feature(unit, soc_feature_mpls) &&
   4380         soc_feature(unit, soc_feature_gport_service_counters)) {
   4381         uint64 val;
   4382         int rv = BCM_E_NONE;
   4383         bcm_port_stat_t flex_stat=0;
   4384 
   4385         switch (stat) {
   4386             case bcmMplsInPkts:
   4387                 flex_stat = bcmPortStatIngressPackets;
   4388                 break;
   4389             case bcmMplsInBytes:
   4390                 flex_stat = bcmPortStatIngressBytes;
   4391                 break;
   4392             case bcmMplsOutPkts:
   4393                 flex_stat = bcmPortStatEgressPackets;
   4394                 break;
   4395             case bcmMplsOutBytes:
   4396                 flex_stat = bcmPortStatEgressBytes;
   4397                 break;
   4398             default:
   4399                 return BCM_E_PARAM;
   4400                 break;
   4401             }
   4402 
   4403         rv =  _bcm_esw_flex_stat_get(unit, 0,
   4404                ((flex_stat == bcmPortStatIngressPackets) ||
   4405                 (flex_stat == bcmPortStatIngressBytes)) ?
   4406                  _bcmFlexStatTypeGport:_bcmFlexStatTypeEgressGport,
   4407                 port, (_bcm_flex_stat_t)flex_stat, &val);
   4408 
   4409         if ((flex_stat == bcmPortStatIngressPackets) ||
   4410             (flex_stat == bcmPortStatEgressPackets)) {
   4411             counter_values->packets = COMPILER_64_LO(val);
   4412         } else {
   4413             COMPILER_64_SET(counter_values->bytes,
   4414                       COMPILER_64_HI(val),
   4415                       COMPILER_64_LO(val));
   4416         }
   4417         return rv;
   4418     }
   4419 #endif
   4420 #endif
   4421     return BCM_E_UNAVAIL;
   4422 }
   4423 
   4424 /*
   4425  * Function:
   4426  *      bcm_esw_mpls_port_stat_counter_get
   4427  * Description:
   4428  *      Get counter statistic values for specific vpn and gport 
   4429  *
   4430  * Parameters:
   4431  *      unit             - (IN) unit number
   4432  *      vpn              - (IN) VPN Id
   4433  *      port             - (IN) MPLS GPORT ID
   4434  *      stat             - (IN) Type of the counter to retrieve
   4435  *                              I.e. ingress/egress byte/packet)
   4436  *      num_entries      - (IN) Number of counter Entries
   4437  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   4438  *      counter_values   - (OUT) Pointer to counter values
   4439  *
   4440  * Return Value:
   4441  *      BCM_E_XXX
   4442  * Notes:
   4443  */
   4444 
   4445 int 
   4446 bcm_esw_mpls_port_stat_counter_get(int                  unit, 
   4447                                    bcm_vpn_t            vpn, 
   4448                                    bcm_gport_t          port, 
   4449                                    bcm_mpls_stat_t      stat, 
   4450                                    uint32               num_entries, 
   4451                                    uint32               *counter_indexes, 
   4452                                    bcm_stat_value_t     *counter_values)
   4453 {
   4454     return _bcm_esw_mpls_port_stat_counter_get(unit, 0,  vpn, port, stat, 
   4455                                                num_entries, 
   4456                                                counter_indexes, 
   4457                                                counter_values);
   4458 }
   4459 
   4460 /*
   4461  * Function:
   4462  *      bcm_esw_mpls_port_stat_counter_sync_get
   4463  * Description:
   4464  *      Get counter statistic values for specific vpn and gport 
   4465  *      sync the sw accumulated count with hw count value 
   4466  *
   4467  * Parameters:
   4468  *      unit             - (IN) unit number
   4469  *      vpn              - (IN) VPN Id
   4470  *      port             - (IN) MPLS GPORT ID
   4471  *      stat             - (IN) Type of the counter to retrieve
   4472  *                              I.e. ingress/egress byte/packet)
   4473  *      num_entries      - (IN) Number of counter Entries
   4474  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   4475  *      counter_values   - (OUT) Pointer to counter values
   4476  *
   4477  * Return Value:
   4478  *      BCM_E_XXX
   4479  * Notes:
   4480  */
   4481 
   4482 
   4483 int 
   4484 bcm_esw_mpls_port_stat_counter_sync_get(int                  unit, 
   4485                                         bcm_vpn_t            vpn, 
   4486                                         bcm_gport_t          port, 
   4487                                         bcm_mpls_stat_t      stat, 
   4488                                         uint32               num_entries, 
   4489                                         uint32               *counter_indexes, 
   4490                                         bcm_stat_value_t     *counter_values)
   4491 {
   4492     return _bcm_esw_mpls_port_stat_counter_get(unit, 1,  vpn, port, stat, 
   4493                                                num_entries, 
   4494                                                counter_indexes, 
   4495                                               counter_values);
   4496 }
   4497 
   4498 
   4499 /*
   4500  * Function:
   4501  *      bcm_esw_mpls_port_stat_counter_set
   4502  * Description:
   4503  *      Set counter statistic values for specific vpn and gport 
   4504  *
   4505  * Parameters:
   4506  *      unit             - (IN) unit number
   4507  *      vpn              - (IN) VPN Id
   4508  *      port             - (IN) MPLS GPORT ID
   4509  *      stat             - (IN) Type of the counter to retrieve
   4510  *                              I.e. ingress/egress byte/packet)
   4511  *      num_entries      - (IN) Number of counter Entries
   4512  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   4513  *      counter_values   - (OUT) Pointer to counter values
   4514  *
   4515  * Return Value:
   4516  *      BCM_E_XXX
   4517  * Notes:
   4518  */
   4519 int bcm_esw_mpls_port_stat_counter_set(
   4520             int                  unit, 
   4521             bcm_vpn_t            vpn, 
   4522             bcm_gport_t          port, 
   4523             bcm_mpls_stat_t      stat, 
   4524             uint32               num_entries, 
   4525             uint32               *counter_indexes, 
   4526             bcm_stat_value_t     *counter_values)
   4527 {
   4528 #ifdef BCM_KATANA_SUPPORT
   4529     if (SOC_IS_KATANAX(unit)) {
   4530         return bcm_kt_mpls_port_stat_counter_set(
   4531                unit,vpn,port,stat,num_entries,counter_indexes,counter_values);
   4532     } else
   4533 #endif
   4534 #ifdef BCM_TRIUMPH3_SUPPORT
   4535     if (SOC_IS_TRIUMPH3(unit)) {
   4536         return bcm_tr3_mpls_port_stat_counter_set(
   4537                unit,vpn,port,stat,num_entries,counter_indexes,counter_values);
   4538     } else
   4539 #endif
   4540     {
   4541 #ifdef BCM_TRIDENT2_SUPPORT
   4542         if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   4543             return td2_mpls_port_stat_counter_set(
   4544                unit,vpn,port,stat,num_entries,counter_indexes,counter_values);
   4545         }
   4546 #endif
   4547     }
   4548 #if defined(BCM_MPLS_SUPPORT)
   4549 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   4550     if ((SOC_IS_TRIUMPH2(unit) || SOC_IS_TRIDENT(unit)) &&
   4551         soc_feature(unit, soc_feature_mpls) &&
   4552         soc_feature(unit, soc_feature_gport_service_counters)) {
   4553         uint64 val;
   4554         int rv = BCM_E_NONE;
   4555         bcm_port_stat_t flex_stat=0;
   4556 
   4557         switch (stat) {
   4558             case bcmMplsInPkts:
   4559                 flex_stat = bcmPortStatIngressPackets;
   4560                 break;
   4561             case bcmMplsInBytes:
   4562                 flex_stat = bcmPortStatIngressBytes;
   4563                 break;
   4564             case bcmMplsOutPkts:
   4565                 flex_stat = bcmPortStatEgressPackets;
   4566                 break;
   4567             case bcmMplsOutBytes:
   4568                 flex_stat = bcmPortStatEgressBytes;
   4569                 break;
   4570             default:
   4571                 return BCM_E_PARAM;
   4572                 break;
   4573             }
   4574 
   4575         if ((flex_stat == bcmPortStatIngressPackets) ||
   4576             (flex_stat == bcmPortStatEgressPackets)) {
   4577             COMPILER_64_SET(val,0,counter_values->packets);
   4578         } else {
   4579             COMPILER_64_SET(val,
   4580                       COMPILER_64_HI(counter_values->bytes),
   4581                       COMPILER_64_LO(counter_values->bytes));
   4582         }
   4583         rv =  _bcm_esw_flex_stat_set(unit,
   4584                ((flex_stat == bcmPortStatIngressPackets) ||
   4585                 (flex_stat == bcmPortStatIngressBytes)) ?
   4586                  _bcmFlexStatTypeGport:_bcmFlexStatTypeEgressGport,
   4587                 port, (_bcm_flex_stat_t) flex_stat, val);
   4588         return rv;
   4589     }
   4590 #endif
   4591 #endif 
   4592     return BCM_E_UNAVAIL;
   4593 }
   4594 /*
   4595  * Function:
   4596  *      bcm_esw_mpls_port_stat_id_get
   4597  * Description:
   4598  *      Get stat counter id associated with specific vpn and gport
   4599  *
   4600  * Parameters:
   4601  *      unit             - (IN) unit number
   4602  *      vpn              - (IN) VPN Id
   4603  *      port             - (IN) MPLS GPORT ID
   4604  *      stat             - (IN) Type of the counter to retrieve
   4605  *                              I.e. ingress/egress byte/packet)
   4606  *      Stat_counter_id  - (OUT) Stat Counter ID
   4607  * Return Value:
   4608  *      BCM_E_XXX
   4609  * Notes:
   4610  */
   4611 int bcm_esw_mpls_port_stat_id_get(
   4612             int                  unit,
   4613             bcm_vpn_t            vpn, 
   4614             bcm_gport_t          port, 
   4615             bcm_mpls_stat_t      stat, 
   4616             uint32               *stat_counter_id)
   4617 {
   4618 #ifdef BCM_KATANA_SUPPORT
   4619     if (SOC_IS_KATANAX(unit)) {
   4620         return bcm_kt_mpls_port_stat_id_get(
   4621                unit,vpn,port,stat,stat_counter_id);
   4622     } else
   4623 #endif
   4624 #ifdef BCM_TRIUMPH3_SUPPORT
   4625     if (SOC_IS_TRIUMPH3(unit)) {
   4626         return bcm_tr3_mpls_port_stat_id_get(
   4627                unit,vpn,port,stat,stat_counter_id);
   4628     } else
   4629 #endif
   4630     {
   4631 #ifdef BCM_TRIDENT2_SUPPORT
   4632         if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   4633             return td2_mpls_port_stat_id_get(
   4634                unit,vpn,port,stat,stat_counter_id);
   4635         }
   4636 #endif
   4637     }
   4638     return BCM_E_UNAVAIL;
   4639 }
   4640 
   4641 /*
   4642  * Function:
   4643  *      bcm_esw_mpls_label_stat_attach
   4644  * Description:
   4645  *      Attach counters entries to the given mpls label and gport 
   4646  *
   4647  * Parameters:
   4648  *      unit             - (IN) unit number
   4649  *      label            - (IN) MPLS Label  
   4650  *      port             - (IN) MPLS Gport  
   4651  *      stat_counter_id  - (IN) Stat Counter ID.
   4652  *
   4653  * Return Value:
   4654  *      BCM_E_XXX
   4655  * Notes:
   4656  */
   4657 int bcm_esw_mpls_label_stat_attach(
   4658             int              unit, 
   4659             bcm_mpls_label_t label, 
   4660             bcm_gport_t      port, 
   4661             uint32           stat_counter_id)
   4662 {
   4663 #if defined(BCM_KATANA_SUPPORT)
   4664     if (SOC_IS_KATANAX(unit)) {
   4665         return bcm_kt_mpls_label_stat_attach(
   4666                unit,label,port,stat_counter_id);
   4667     } else 
   4668 #endif
   4669 #if defined(BCM_TRIUMPH3_SUPPORT)
   4670     if (SOC_IS_TRIUMPH3(unit)) {
   4671         return bcm_tr3_mpls_label_stat_attach(
   4672                unit,label,port,stat_counter_id);
   4673     } else
   4674 #endif
   4675     {
   4676 #if defined(BCM_TRIDENT2_SUPPORT)
   4677         if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   4678             return td2_mpls_label_stat_attach(
   4679                unit,label,port,stat_counter_id);
   4680         }
   4681 #endif
   4682     } 
   4683 #if defined(BCM_MPLS_SUPPORT)
   4684 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   4685     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_TRIDENT(unit)) {
   4686         if (soc_feature(unit, soc_feature_gport_service_counters) &&
   4687             soc_feature(unit, soc_feature_mpls)) {
   4688             _bcm_flex_stat_type_t fs_type;
   4689             uint32 fs_inx;
   4690             int rv;
   4691 
   4692             fs_type = _BCM_FLEX_STAT_TYPE(stat_counter_id);
   4693             fs_inx  = _BCM_FLEX_STAT_COUNT_INX(stat_counter_id);
   4694             if ((fs_type != _bcmFlexStatTypeMplsLabel) || (!fs_inx)) {
   4695                 return BCM_E_PARAM;
   4696             }
   4697 
   4698             rv = bcm_tr_mpls_lock(unit);
   4699             if (BCM_E_NONE == rv) {
   4700                 rv = bcm_tr2_mpls_label_stat_enable_set(unit, label,
   4701                                                     port, TRUE, fs_inx);
   4702                 bcm_tr_mpls_unlock(unit);
   4703             }
   4704             return rv;
   4705         }
   4706     }
   4707 #endif
   4708 #endif
   4709     return BCM_E_UNAVAIL;
   4710 }
   4711 /*
   4712  * Function:
   4713  *      bcm_esw_mpls_label_stat_detach
   4714  * Description:
   4715  *      Detach counters entries to the given mpls label and gport 
   4716  *
   4717  * Parameters:
   4718  *      unit             - (IN) unit number
   4719  *      label            - (IN) MPLS Label  
   4720  *      port             - (IN) MPLS Gport  
   4721  *
   4722  * Return Value:
   4723  *      BCM_E_XXX
   4724  * Notes:
   4725  */
   4726 int bcm_esw_mpls_label_stat_detach(
   4727             int              unit, 
   4728             bcm_mpls_label_t label, 
   4729             bcm_gport_t      port)
   4730 {
   4731 #if defined(BCM_KATANA_SUPPORT) 
   4732     if (SOC_IS_KATANAX(unit)) {
   4733         return bcm_kt_mpls_label_stat_detach(
   4734                unit,label,port);
   4735     } else
   4736 #endif
   4737 #if defined(BCM_TRIUMPH3_SUPPORT)
   4738     if (SOC_IS_TRIUMPH3(unit)) {
   4739         return bcm_tr3_mpls_label_stat_detach(
   4740                unit,label,port);
   4741     } else
   4742 #endif
   4743     {
   4744 #if defined(BCM_TRIDENT2_SUPPORT)
   4745         if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   4746             return td2_mpls_label_stat_detach(
   4747                    unit,label,port);
   4748         } 
   4749 #endif
   4750     }
   4751 #if defined(BCM_MPLS_SUPPORT)
   4752 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   4753     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_TRIDENT(unit)) {
   4754         if (soc_feature(unit, soc_feature_gport_service_counters) &&
   4755             soc_feature(unit, soc_feature_mpls)) {
   4756             int rv;
   4757 
   4758             rv = bcm_tr_mpls_lock(unit);
   4759             if (BCM_E_NONE == rv) {
   4760                 rv = bcm_tr2_mpls_label_stat_enable_set(unit, label,
   4761                                                     port, FALSE, 1);
   4762                 bcm_tr_mpls_unlock(unit);
   4763             }
   4764             return rv;
   4765         }
   4766     }
   4767 #endif
   4768 #endif
   4769     return BCM_E_UNAVAIL;
   4770 }
   4771 
   4772 /*
   4773  * Function:
   4774  *      _bcm_esw_mpls_label_stat_counter_get
   4775  * Description:
   4776  *      Get counter statistic values for specific MPLS label and gport 
   4777  *      if sync_mode is set, sync the sw accumulated count
   4778  *      with hw count value first, else return sw count.  
   4779  *
   4780  * Parameters:
   4781  *      unit             - (IN) unit number
   4782  *      sync_mode        - (IN) hwcount is to be synced to sw count 
   4783  *      label            - (IN) MPLS Label  
   4784  *      port             - (IN) MPLS Gport  
   4785  *      stat             - (IN) Type of the counter to retrieve
   4786  *                              I.e. ingress/egress byte/packet)
   4787  *      num_entries      - (IN) Number of counter Entries
   4788  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   4789  *      counter_values   - (OUT) Pointer to counter values
   4790  *
   4791  * Return Value:
   4792  *      BCM_E_XXX
   4793  * Notes:
   4794  */
   4795 int 
   4796 _bcm_esw_mpls_label_stat_counter_get(int                  unit, 
   4797                                      int                  sync_mode, 
   4798                                      bcm_mpls_label_t     label, 
   4799                                      bcm_gport_t          port, 
   4800                                      bcm_mpls_stat_t      stat, 
   4801                                      uint32               num_entries, 
   4802                                      uint32               *counter_indexes, 
   4803                                      bcm_stat_value_t     *counter_values)
   4804 {
   4805 #if defined(BCM_KATANA_SUPPORT) 
   4806     if (SOC_IS_KATANAX(unit)) {
   4807         return bcm_kt_mpls_label_stat_counter_get(
   4808                unit, sync_mode, label, port, stat, num_entries,
   4809                counter_indexes,counter_values);
   4810     } else
   4811 #endif
   4812 #if defined(BCM_TRIUMPH3_SUPPORT)
   4813     if (SOC_IS_TRIUMPH3(unit)) {
   4814         return bcm_tr3_mpls_label_stat_counter_get(
   4815                unit, sync_mode, label, port, stat,
   4816                num_entries, counter_indexes, counter_values);
   4817     } else
   4818 #endif
   4819     {
   4820 #if defined(BCM_TRIDENT2_SUPPORT)
   4821         if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   4822             return td2_mpls_label_stat_counter_get(
   4823                unit, sync_mode, label, port, stat, 
   4824                num_entries, counter_indexes, counter_values);
   4825         }
   4826 #endif
   4827     }
   4828 #ifdef BCM_MPLS_SUPPORT
   4829 #ifdef BCM_TRIUMPH_SUPPORT
   4830     if (SOC_IS_TR_VL(unit) && soc_feature(unit, soc_feature_mpls) &&
   4831         soc_feature(unit, soc_feature_gport_service_counters)) {
   4832         uint64 val;
   4833         int rv;
   4834 
   4835         rv = bcm_tr_mpls_lock(unit);
   4836         if (rv == BCM_E_NONE ) {
   4837             rv = bcm_tr_mpls_label_stat_get(unit, sync_mode, label, 
   4838                                             port, stat, &val);
   4839             bcm_tr_mpls_unlock (unit);
   4840             if ((stat == bcmMplsInPkts) || (stat == bcmMplsOutPkts)) {
   4841                  counter_values->packets = COMPILER_64_LO(val);
   4842             } else {
   4843                  COMPILER_64_SET(counter_values->bytes,
   4844                            COMPILER_64_HI(val),
   4845                            COMPILER_64_LO(val));
   4846             }
   4847         }
   4848         return rv;
   4849     }
   4850 #endif
   4851 #endif
   4852 
   4853     return BCM_E_UNAVAIL;
   4854 }
   4855 
   4856 /*
   4857  * Function:
   4858  *      bcm_esw_mpls_label_stat_counter_get
   4859  * Description:
   4860  *      Get counter statistic values for specific MPLS label and gport 
   4861  *
   4862  * Parameters:
   4863  *      unit             - (IN) unit number
   4864  *      label            - (IN) MPLS Label  
   4865  *      port             - (IN) MPLS Gport  
   4866  *      stat             - (IN) Type of the counter to retrieve
   4867  *                              I.e. ingress/egress byte/packet)
   4868  *      num_entries      - (IN) Number of counter Entries
   4869  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   4870  *      counter_values   - (OUT) Pointer to counter values
   4871  *
   4872  * Return Value:
   4873  *      BCM_E_XXX
   4874  * Notes:
   4875  */
   4876 int 
   4877 bcm_esw_mpls_label_stat_counter_get(int                  unit, 
   4878                                     bcm_mpls_label_t     label, 
   4879                                     bcm_gport_t          port, 
   4880                                     bcm_mpls_stat_t      stat, 
   4881                                     uint32               num_entries, 
   4882                                     uint32               *counter_indexes, 
   4883                                     bcm_stat_value_t     *counter_values)
   4884 {
   4885     return _bcm_esw_mpls_label_stat_counter_get(unit, 0, label, port, stat,
   4886                                                 num_entries, counter_indexes,
   4887                                                 counter_values);    
   4888 }
   4889 
   4890 /*
   4891  * Function:
   4892  *      bcm_esw_mpls_label_stat_counter_sync_get
   4893  * Description:
   4894  *      Get counter statistic values for specific MPLS label and gport 
   4895  *      sync the sw accumulated count with hw count value 
   4896  *
   4897  * Parameters:
   4898  *      unit             - (IN) unit number
   4899  *      label            - (IN) MPLS Label  
   4900  *      port             - (IN) MPLS Gport  
   4901  *      stat             - (IN) Type of the counter to retrieve
   4902  *                              I.e. ingress/egress byte/packet)
   4903  *      num_entries      - (IN) Number of counter Entries
   4904  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   4905  *      counter_values   - (OUT) Pointer to counter values
   4906  *
   4907  * Return Value:
   4908  *      BCM_E_XXX
   4909  * Notes:
   4910  */
   4911 int 
   4912 bcm_esw_mpls_label_stat_counter_sync_get(int                  unit, 
   4913                                          bcm_mpls_label_t     label, 
   4914                                          bcm_gport_t          port, 
   4915                                          bcm_mpls_stat_t      stat, 
   4916                                          uint32               num_entries, 
   4917                                          uint32               *counter_indexes,
   4918                                          bcm_stat_value_t     *counter_values)
   4919 {
   4920     return _bcm_esw_mpls_label_stat_counter_get(unit, 1, label, port, stat,
   4921                                                 num_entries, counter_indexes,
   4922                                                 counter_values);    
   4923 }
   4924 /*
   4925  * Function:
   4926  *      bcm_esw_mpls_label_stat_counter_set
   4927  * Description:
   4928  *      Set counter statistic values for specific MPLS label and gport 
   4929  *
   4930  * Parameters:
   4931  *      unit             - (IN) unit number
   4932  *      label            - (IN) MPLS Label  
   4933  *      port             - (IN) MPLS Gport  
   4934  *      stat             - (IN) Type of the counter to retrieve
   4935  *                              I.e. ingress/egress byte/packet)
   4936  *      num_entries      - (IN) Number of counter Entries
   4937  *      counter_indexes  - (IN) Pointer to Counter indexes entries
   4938  *      counter_values   - (IN) Pointer to counter values
   4939  *
   4940  * Return Value:
   4941  *      BCM_E_XXX
   4942  * Notes:
   4943  */
   4944 int bcm_esw_mpls_label_stat_counter_set(
   4945             int                  unit, 
   4946             bcm_mpls_label_t     label, 
   4947             bcm_gport_t          port, 
   4948             bcm_mpls_stat_t      stat, 
   4949             uint32               num_entries, 
   4950             uint32               *counter_indexes, 
   4951             bcm_stat_value_t     *counter_values)
   4952 {
   4953 #if defined(BCM_KATANA_SUPPORT) 
   4954     if (SOC_IS_KATANAX(unit)) {
   4955         return bcm_kt_mpls_label_stat_counter_set(
   4956                unit,label,port,stat,num_entries,counter_indexes,counter_values);
   4957     } else
   4958 #endif
   4959 #if defined(BCM_TRIUMPH3_SUPPORT)
   4960     if (SOC_IS_TRIUMPH3(unit)) {
   4961         return bcm_tr3_mpls_label_stat_counter_set(
   4962                unit,label,port,stat,num_entries,counter_indexes,counter_values);
   4963     } else
   4964 #endif
   4965     {
   4966 #if defined(BCM_TRIDENT2_SUPPORT)
   4967         if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   4968             return td2_mpls_label_stat_counter_set(
   4969                unit,label,port,stat,num_entries,counter_indexes,counter_values);
   4970         }
   4971 #endif
   4972     }
   4973     return BCM_E_UNAVAIL;
   4974 }
   4975 /*
   4976  * Function:
   4977  *      bcm_esw_mpls_label_stat_id_get
   4978  * Description:
   4979  *      Get stat counter id associated with specific MPLS label and gport
   4980  *
   4981  * Parameters:
   4982  *      unit             - (IN) unit number
   4983  *      label            - (IN) MPLS Label  
   4984  *      port             - (IN) MPLS Gport  
   4985  *      stat             - (IN) Type of the counter to retrieve
   4986  *                              I.e. ingress/egress byte/packet)
   4987  *      Stat_counter_id  - (OUT) Stat Counter ID
   4988  * Return Value:
   4989  *      BCM_E_XXX
   4990  * Notes:
   4991  */
   4992 int bcm_esw_mpls_label_stat_id_get(
   4993             int                  unit,
   4994             bcm_mpls_label_t     label, 
   4995             bcm_gport_t          port, 
   4996             bcm_mpls_stat_t      stat, 
   4997             uint32               *stat_counter_id)
   4998 {
   4999 #if defined(BCM_KATANA_SUPPORT) 
   5000     if (SOC_IS_KATANAX(unit)) {
   5001         return bcm_kt_mpls_label_stat_id_get(
   5002                unit,label,port,stat,stat_counter_id);
   5003     } else
   5004 #endif
   5005 #if defined(BCM_TRIUMPH3_SUPPORT)
   5006     if (SOC_IS_TRIUMPH3(unit)) {
   5007         return bcm_tr3_mpls_label_stat_id_get(
   5008                unit,label,port,stat,stat_counter_id);
   5009     } else
   5010 #endif
   5011     {
   5012 #if defined(BCM_TRIDENT2_SUPPORT)
   5013         if (soc_feature(unit,soc_feature_advanced_flex_counter)) {
   5014             return td2_mpls_label_stat_id_get(
   5015                unit,label,port,stat,stat_counter_id);
   5016         }
   5017 #endif
   5018     }
   5019     return BCM_E_UNAVAIL;
   5020 }
   5021 
   5022 
   5023 /*
   5024  * Function:
   5025  *      bcm_esw_mpls_special_label_identifier_add
   5026  * Description:
   5027  *      Add identifier entry of special label.
   5028  *
   5029  * Parameters:
   5030  *      unit                - (IN) unit number
   5031  *      label_type          - (IN) MPLS Label
   5032  *      label_info          - (IN) MPLS Gport
   5033  * Return Value:
   5034  *      BCM_E_XXX
   5035  * Notes:
   5036  */
   5037 int
   5038 bcm_esw_mpls_special_label_identifier_add(int unit,
   5039             bcm_mpls_special_label_type_t label_type,
   5040             bcm_mpls_special_label_t label_info)
   5041 {
   5042     int rv = BCM_E_NONE;
   5043 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   5044 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   5045 
   5046     if ((!soc_feature(unit, soc_feature_mpls)) ||
   5047        (!(soc_feature(unit, soc_feature_mpls_special_label)))) {
   5048         return BCM_E_UNAVAIL;
   5049     }
   5050     rv = bcm_tr_mpls_lock(unit);
   5051     if (BCM_E_NONE == rv) {
   5052         rv = bcmi_mpls_special_label_identifier_add(unit, label_type,
   5053                 label_info);
   5054     }
   5055     bcm_tr_mpls_unlock(unit);
   5056 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_TRIDENT_SUPPORT */
   5057 #endif /*BCM_SPECIAL_LABEL_SUPPORT*/
   5058 
   5059     return rv;
   5060 }
   5061 
   5062 /*
   5063  * Function:
   5064  *      bcm_esw_mpls_special_label_identifier_get
   5065  * Description:
   5066  *      Get identifier entry of special label.
   5067  *
   5068  * Parameters:
   5069  *      unit                - (IN) unit number
   5070  *      label_type          - (IN) MPLS Label
   5071  *      label_info          - (IN) MPLS Gport
   5072  * Return Value:
   5073  *      BCM_E_XXX
   5074  * Notes:
   5075  */
   5076 int
   5077 bcm_esw_mpls_special_label_identifier_get(int unit,
   5078             bcm_mpls_special_label_type_t label_type,
   5079             bcm_mpls_special_label_t *label_info)
   5080 {
   5081     int rv = BCM_E_NONE;
   5082 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   5083 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   5084 
   5085     if ((!soc_feature(unit, soc_feature_mpls)) ||
   5086        (!(soc_feature(unit, soc_feature_mpls_special_label)))) {
   5087         return BCM_E_UNAVAIL;
   5088     }
   5089     rv = bcm_tr_mpls_lock(unit);
   5090     if (BCM_E_NONE == rv) {
   5091         rv = bcmi_mpls_special_label_identifier_get(unit, label_type,
   5092                 label_info);
   5093     }
   5094     bcm_tr_mpls_unlock(unit);
   5095 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_TRIDENT_SUPPORT */
   5096 #endif /*BCM_SPECIAL_LABEL_SUPPORT*/
   5097 
   5098     return rv;
   5099 }
   5100 
   5101 /*
   5102  * Function:
   5103  *      bcm_esw_mpls_special_label_identifier_delete
   5104  * Description:
   5105  *      Delete identifiers of special label.
   5106  *
   5107  * Parameters:
   5108  *      unit                - (IN) unit number
   5109  *      label_type          - (IN) MPLS Label
   5110  *      label_info          - (IN) MPLS Gport
   5111  * Return Value:
   5112  *      BCM_E_XXX
   5113  * Notes:
   5114  */
   5115 int
   5116 bcm_esw_mpls_special_label_identifier_delete(int unit,
   5117             bcm_mpls_special_label_type_t label_type,
   5118             bcm_mpls_special_label_t label_info)
   5119 {
   5120     int rv = BCM_E_NONE;
   5121 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   5122 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   5123 
   5124     if ((!soc_feature(unit, soc_feature_mpls)) ||
   5125        (!(soc_feature(unit, soc_feature_mpls_special_label)))) {
   5126         return BCM_E_UNAVAIL;
   5127     }
   5128     rv = bcm_tr_mpls_lock(unit);
   5129     if (BCM_E_NONE == rv) {
   5130         rv = bcmi_mpls_special_label_identifier_delete(unit, label_type,
   5131                 label_info);
   5132     }
   5133     bcm_tr_mpls_unlock(unit);
   5134 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_TRIDENT_SUPPORT */
   5135 #endif /*BCM_SPECIAL_LABEL_SUPPORT*/
   5136 
   5137     return rv;
   5138 
   5139 }
   5140 
   5141 /*
   5142  * Function:
   5143  *      bcm_esw_mpls_special_label_identifier_delete_all
   5144  * Description:
   5145  *      Delete all identifiers ofs pecial labels.
   5146  *
   5147  * Parameters:
   5148  *      unit                - (IN) unit number
   5149  *      label_type          - (IN) MPLS Label
   5150  *      label_info          - (IN) MPLS Gport
   5151  * Return Value:
   5152  *      BCM_E_XXX
   5153  * Notes:
   5154  */
   5155 int
   5156 bcm_esw_mpls_special_label_identifier_delete_all(int unit)
   5157 {
   5158     int rv = BCM_E_NONE;
   5159 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   5160 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   5161 
   5162     if ((!soc_feature(unit, soc_feature_mpls)) ||
   5163        (!(soc_feature(unit, soc_feature_mpls_special_label)))) {
   5164         return BCM_E_UNAVAIL;
   5165     }
   5166     rv = bcm_tr_mpls_lock(unit);
   5167     if (BCM_E_NONE == rv) {
   5168         rv = bcmi_mpls_special_label_identifier_delete_all(unit);
   5169     }
   5170     bcm_tr_mpls_unlock(unit);
   5171 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_TRIDENT_SUPPORT */
   5172 #endif /*BCM_SPECIAL_LABEL_SUPPORT*/
   5173 
   5174     return rv;
   5175 }
   5176 
   5177 /*
   5178  * Function:
   5179  *      bcm_esw_mpls_special_label_identifier_traverse
   5180  * Description:
   5181  *      Traverse and call user call back for all special labels identifiers.
   5182  *
   5183  * Parameters:
   5184  *      unit                - (IN) unit number
   5185  *      cb                  - (IN) user callback
   5186  *      user data           - (IN) option user data
   5187  * Return Value:
   5188  *      BCM_E_XXX
   5189  * Notes:
   5190  */
   5191 int bcm_esw_mpls_special_label_identifier_traverse(int unit,
   5192             bcm_mpls_special_label_identifier_traverse_cb cb, void *user_data)
   5193 {
   5194     int rv = BCM_E_NONE;
   5195 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   5196 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   5197 
   5198     if ((!soc_feature(unit, soc_feature_mpls)) ||
   5199        (!(soc_feature(unit, soc_feature_mpls_special_label)))) {
   5200         return BCM_E_UNAVAIL;
   5201     }
   5202     rv = bcm_tr_mpls_lock(unit);
   5203     if (BCM_E_NONE == rv) {
   5204         rv = bcmi_mpls_special_label_identifier_traverse(unit, cb, user_data);
   5205     }
   5206     bcm_tr_mpls_unlock(unit);
   5207 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_TRIDENT_SUPPORT */
   5208 #endif /*BCM_SPECIAL_LABEL_SUPPORT*/
   5209 
   5210     return rv;
   5211 }
   5212 /*
   5213  * Function:
   5214  *      bcm_esw_mpls_special_label_egress_add
   5215  * Description:
   5216  *      Add special label in MPLS stack for packets
   5217  *      going into MPLS tunnel.
   5218  *
   5219  * Parameters:
   5220  *      unit                - (IN) unit number
   5221  *      label_type          - (IN) MPLS Label
   5222  *      label_info          - (IN) MPLS Gport
   5223  * Return Value:
   5224  *      BCM_E_XXX
   5225  * Notes:
   5226  */
   5227 int
   5228 bcm_esw_mpls_special_label_egress_add(int unit,
   5229             bcm_mpls_special_label_type_t label_type,
   5230             bcm_mpls_special_label_t label_info)
   5231 {
   5232     int rv = BCM_E_NONE;
   5233 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   5234 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   5235 
   5236     if ((!soc_feature(unit, soc_feature_mpls)) ||
   5237        (!(soc_feature(unit, soc_feature_mpls_special_label)))) {
   5238         return BCM_E_UNAVAIL;
   5239     }
   5240     rv = bcm_tr_mpls_lock(unit);
   5241     if (BCM_E_NONE == rv) {
   5242         rv = bcmi_mpls_special_label_egress_add(unit, label_type, label_info);
   5243     }
   5244     bcm_tr_mpls_unlock(unit);
   5245 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_TRIDENT_SUPPORT */
   5246 #endif /*BCM_SPECIAL_LABEL_SUPPORT*/
   5247 
   5248     return rv;
   5249 }
   5250 
   5251 /*
   5252  * Function:
   5253  *      bcm_esw_mpls_special_label_egress_get
   5254  * Description:
   5255  *      Get special label in MPLS stack for packets
   5256  *      going into MPLS tunnel.
   5257  *
   5258  * Parameters:
   5259  *      unit                - (IN) unit number
   5260  *      label_type          - (IN) MPLS Label
   5261  *      label_info          - (IN) MPLS Gport
   5262  * Return Value:
   5263  *      BCM_E_XXX
   5264  * Notes:
   5265  */
   5266 int
   5267 bcm_esw_mpls_special_label_egress_get(int unit,
   5268             bcm_mpls_special_label_type_t label_type,
   5269             bcm_mpls_special_label_t *label_info)
   5270 {
   5271     int rv = BCM_E_NONE;
   5272 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   5273 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   5274 
   5275     if ((!soc_feature(unit, soc_feature_mpls)) ||
   5276        (!(soc_feature(unit, soc_feature_mpls_special_label)))) {
   5277         return BCM_E_UNAVAIL;
   5278     }
   5279     rv = bcm_tr_mpls_lock(unit);
   5280     if (BCM_E_NONE == rv) {
   5281         rv = bcmi_mpls_special_label_egress_get(unit, label_type, label_info);
   5282     }
   5283     bcm_tr_mpls_unlock(unit);
   5284 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_TRIDENT_SUPPORT */
   5285 #endif /*BCM_SPECIAL_LABEL_SUPPORT*/
   5286     return rv;
   5287 }
   5288 
   5289 /*
   5290  * Function:
   5291  *      bcm_esw_mpls_special_label_egress_delete
   5292  * Description:
   5293  *      Delete special label in MPLS stack for packets
   5294  *      going into MPLS tunnel.
   5295  *
   5296  * Parameters:
   5297  *      unit                - (IN) unit number
   5298  *      label_type          - (IN) MPLS Label
   5299  *      label_info          - (IN) MPLS Gport
   5300  * Return Value:
   5301  *      BCM_E_XXX
   5302  * Notes:
   5303  */
   5304 int
   5305 bcm_esw_mpls_special_label_egress_delete(int unit,
   5306             bcm_mpls_special_label_type_t label_type,
   5307             bcm_mpls_special_label_t label_info)
   5308 {
   5309     int rv = BCM_E_NONE;
   5310 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   5311 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   5312 
   5313     if ((!soc_feature(unit, soc_feature_mpls)) ||
   5314        (!(soc_feature(unit, soc_feature_mpls_special_label)))) {
   5315         return BCM_E_UNAVAIL;
   5316     }
   5317     rv = bcm_tr_mpls_lock(unit);
   5318     if (BCM_E_NONE == rv) {
   5319         rv = bcmi_mpls_special_label_egress_delete(unit, label_type, label_info);
   5320     }
   5321     bcm_tr_mpls_unlock(unit);
   5322 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_TRIDENT_SUPPORT */
   5323 #endif /*BCM_SPECIAL_LABEL_SUPPORT*/
   5324 
   5325     return rv;
   5326 }
   5327 
   5328 /*
   5329  * Function:
   5330  *      bcm_esw_mpls_special_label_egress_delete_all
   5331  * Description:
   5332  *      Delete all special labels in MPLS stack for packets
   5333  *      going into MPLS tunnel.
   5334  *
   5335  * Parameters:
   5336  *      unit                - (IN) unit number
   5337  *      label_type          - (IN) MPLS Label
   5338  *      label_info          - (IN) MPLS Gport
   5339  * Return Value:
   5340  *      BCM_E_XXX
   5341  * Notes:
   5342  */
   5343 int
   5344 bcm_esw_mpls_special_label_egress_delete_all(int unit)
   5345 {
   5346     int rv = BCM_E_NONE;
   5347 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   5348 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   5349 
   5350     if ((!soc_feature(unit, soc_feature_mpls)) ||
   5351        (!(soc_feature(unit, soc_feature_mpls_special_label)))) {
   5352         return BCM_E_UNAVAIL;
   5353     }
   5354     rv = bcm_tr_mpls_lock(unit);
   5355     if (BCM_E_NONE == rv) {
   5356         rv = bcmi_mpls_special_label_egress_delete_all(unit);
   5357     }
   5358     bcm_tr_mpls_unlock(unit);
   5359 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_TRIDENT_SUPPORT */
   5360 #endif /*BCM_SPECIAL_LABEL_SUPPORT*/
   5361 
   5362     return rv;
   5363 }
   5364 
   5365 /*
   5366  * Function:
   5367  *      bcm_esw_mpls_special_label_egress_traverse
   5368  * Description:
   5369  *      Traverse and call user call back for all special labels
   5370  *      going into MPLS tunnel.
   5371  *
   5372  * Parameters:
   5373  *      unit                - (IN) unit number
   5374  *      cb                  - (IN) user callback
   5375  *      user data           - (IN) option user data
   5376  * Return Value:
   5377  *      BCM_E_XXX
   5378  * Notes:
   5379  */
   5380 int bcm_esw_mpls_special_label_egress_traverse(int unit,
   5381             bcm_mpls_special_label_egress_traverse_cb cb,void *user_data)
   5382 {
   5383     int rv = BCM_E_NONE;
   5384 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   5385 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   5386 
   5387     if ((!soc_feature(unit, soc_feature_mpls)) ||
   5388        (!(soc_feature(unit, soc_feature_mpls_special_label)))) {
   5389         return BCM_E_UNAVAIL;
   5390     }
   5391     rv = bcm_tr_mpls_lock(unit);
   5392     if (BCM_E_NONE == rv) {
   5393         rv = bcmi_mpls_special_label_egress_traverse(unit, cb, user_data);
   5394     }
   5395     bcm_tr_mpls_unlock(unit);
   5396 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_TRIDENT_SUPPORT */
   5397 #endif /*BCM_SPECIAL_LABEL_SUPPORT*/
   5398 
   5399     return rv;
   5400 }
   5401 /*
   5402  * Function:
   5403  *      bcm_esw_mpls_special_label_push_action_set
   5404  * Description:
   5405  *      Set mpls push action in MPLS objects.
   5406  *      going into MPLS tunnel.
   5407  *
   5408  * Parameters:
   5409  *      unit                - (IN) unit number
   5410  *      element             - (IN) MPLS object
   5411  *      push_type           - (IN) push action
   5412  * Return Value:
   5413  *      BCM_E_XXX
   5414  * Notes:
   5415  */
   5416 int
   5417 bcm_esw_mpls_special_label_push_action_set(int unit,
   5418             bcm_mpls_special_label_push_element_t *element,
   5419             int push_type)
   5420 {
   5421     int rv = BCM_E_NONE;
   5422 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   5423 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   5424 
   5425     if ((!soc_feature(unit, soc_feature_mpls)) ||
   5426        (!(soc_feature(unit, soc_feature_mpls_special_label)))) {
   5427         return BCM_E_UNAVAIL;
   5428     }
   5429     rv = bcm_tr_mpls_lock(unit);
   5430     if (BCM_E_NONE == rv) {
   5431 
   5432         rv = bcmi_mpls_special_label_push_action_set(
   5433                 unit, element, (bcm_mpls_special_label_push_type_t)push_type);
   5434     }
   5435     bcm_tr_mpls_unlock(unit);
   5436 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_TRIDENT_SUPPORT */
   5437 #endif /*BCM_SPECIAL_LABEL_SUPPORT*/
   5438     return rv;
   5439 }
   5440 /*
   5441  * Function:
   5442  *      bcm_esw_mpls_special_label_push_action_get
   5443  * Description:
   5444  *      Get mpls push action in MPLS objects.
   5445  *      going into MPLS tunnel.
   5446  *
   5447  * Parameters:
   5448  *      unit                - (IN) unit number
   5449  *      element             - (IN) MPLS object
   5450  *      push_type           - (OUT) push action
   5451  * Return Value:
   5452  *      BCM_E_XXX
   5453  * Notes:
   5454  */
   5455 int
   5456 bcm_esw_mpls_special_label_push_action_get(int unit,
   5457             bcm_mpls_special_label_push_element_t *element,
   5458             int *push_type)
   5459 {
   5460     int rv = BCM_E_NONE;
   5461 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   5462 #ifdef BCM_SPECIAL_LABEL_SUPPORT
   5463 
   5464     if ((!soc_feature(unit, soc_feature_mpls)) ||
   5465        (!(soc_feature(unit, soc_feature_mpls_special_label)))) {
   5466         return BCM_E_UNAVAIL;
   5467     }
   5468     if (push_type == NULL) {
   5469         return BCM_E_PARAM;
   5470     }
   5471 
   5472     rv = bcm_tr_mpls_lock(unit);
   5473     if (BCM_E_NONE == rv) {
   5474 
   5475         rv = bcmi_mpls_special_label_push_action_get(
   5476                 unit, element, (bcm_mpls_special_label_push_type_t *)push_type);
   5477     }
   5478     bcm_tr_mpls_unlock(unit);
   5479 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_TRIDENT_SUPPORT */
   5480 #endif /*BCM_SPECIAL_LABEL_SUPPORT*/
   5481     return rv;
   5482 }
   5483 
   5484 #else   /* INCLUDE_L3 */
   5485 int bcm_esw_mpls_not_empty;
   5486 #endif  /* INCLUDE_L3 */
   5487