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


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