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

l2gre.c (307244B)


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