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

vxlan.c (556089B)


      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  * VXLAN API
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <soc/defs.h>
     14 #include <sal/core/libc.h>
     15 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
     16 #include <soc/drv.h>
     17 #include <soc/scache.h>
     18 #include <soc/util.h>
     19 #include <soc/hash.h>
     20 #include <soc/debug.h>
     21 #include <bcm/types.h>
     22 #include <bcm/error.h>
     23 
     24 #include <bcm/types.h>
     25 #include <bcm/l3.h>
     26 #include <soc/ism_hash.h>
     27 
     28 #include <bcm_int/esw/mbcm.h>
     29 #include <bcm_int/api_xlate_port.h>
     30 #include <bcm_int/esw_dispatch.h>
     31 #include <bcm_int/esw/virtual.h>
     32 #include <bcm_int/esw/trx.h>
     33 #include <bcm_int/esw/triumph2.h>
     34 #include <bcm_int/esw/trident2.h>
     35 #include <bcm_int/esw/vxlan.h>
     36 #include <bcm_int/esw/stack.h>
     37 #include <bcm_int/common/multicast.h>
     38 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
     39 #include <bcm_int/esw/trident2plus.h>
     40 #include <bcm_int/esw/xgs5.h>
     41 #include <bcm_int/esw/port.h>
     42 #include <soc/td2_td2p.h>
     43 #endif /* BCM_TRIDENT2PLUS_SUPPORT*/
     44 
     45 #if defined(BCM_TRIDENT3_SUPPORT)
     46 #include <bcm_int/esw/trident3.h>
     47 #include <bcm_int/esw/flow.h>
     48 #include <soc/esw/cancun.h>
     49 #endif
     50 _bcm_td2_vxlan_bookkeeping_t   *_bcm_td2_vxlan_bk_info[BCM_MAX_NUM_UNITS] = { 0 };
     51 
     52 #define VXLAN_INFO(_unit_)      (_bcm_td2_vxlan_bk_info[_unit_])
     53 #define L3_INFO(_unit_)         (&_bcm_l3_bk_info[_unit_])
     54 #define VIRTUAL_INFO(_unit_)    (&_bcm_virtual_bk_info[_unit_])
     55 
     56 /*
     57  * EGR_IP_TUNNEL table usage bitmap operations
     58  */
     59 #define _BCM_VXLAN_IP_TNL_USED_GET(_u_, _tnl_) \
     60         SHR_BITGET(VXLAN_INFO(_u_)->vxlan_ip_tnl_bitmap, (_tnl_))
     61 #define _BCM_VXLAN_IP_TNL_USED_SET(_u_, _tnl_) \
     62         SHR_BITSET(VXLAN_INFO((_u_))->vxlan_ip_tnl_bitmap, (_tnl_))
     63 #define _BCM_VXLAN_IP_TNL_USED_CLR(_u_, _tnl_) \
     64         SHR_BITCLR(VXLAN_INFO((_u_))->vxlan_ip_tnl_bitmap, (_tnl_))
     65 
     66 #define _BCM_VXLAN_CLEANUP(_rv_) \
     67        if ( (_rv_) < 0) { \
     68            goto cleanup; \
     69        }
     70 
     71 STATIC int _bcm_td2_vxlan_match_vnid_entry_reset(int unit, uint32 vnid,
     72                                                             bcm_vlan_t ovid);
     73 STATIC int _bcm_td2_vxlan_bud_loopback_disable(int unit);
     74 STATIC int _bcm_td2_vxlan_sd_tag_set( int unit, bcm_vxlan_vpn_config_t *vxlan_vpn_info, 
     75                          bcm_vxlan_port_t *vxlan_port, 
     76                          _bcm_td2_vxlan_nh_info_t  *egr_nh_info, 
     77                          uint32   *vxlate_entry,
     78                          int *tpid_index );
     79 STATIC int _bcm_td2_vxlan_egr_xlate_entry_reset(int unit, bcm_vpn_t vpn);
     80 STATIC int
     81 _bcm_td2_vxlan_egr_xlate_entry_get(int unit, int vfi, int vp, uint32 *vxlate_entry);
     82 STATIC void _bcm_td2_vxlan_sd_tag_get( int unit, bcm_vxlan_vpn_config_t *vxlan_vpn_info, 
     83                          bcm_vxlan_port_t *vxlan_port, 
     84                          egr_l3_next_hop_entry_t *egr_nh, 
     85                          uint32   *vxlate_entry,
     86                          int network_port_flag );
     87 STATIC int _bcm_td2_vxlan_tunnel_initiator_idx_translate(int unit, 
     88                                                          int soft_idx, 
     89                                                          int *hw_idx);
     90 #if defined(BCM_TRIDENT3_SUPPORT)
     91 STATIC void
     92 _bcm_td3_vxlan_vxlate_entry_assemble(int unit, _bcm_td3_vxlan_vxlate_entry_t info, uint32* ment);
     93 STATIC int
     94 _bcm_td3_vxlan_tpid_delete(int unit, uint32* vxlate, uint32* egr_nh);
     95 #endif
     96 
     97 void bcm_td2_vxlan_match_clear (int unit, int vp);
     98 int _bcm_td2_vxlan_vpn_is_tunnel_based_vnid( int unit, bcm_vpn_t l2vpn, uint8 *vxlan_vpn_type);
     99 STATIC int _bcm_td2_vxlan_vp_based_vnid_delete_all(int unit);
    100 
    101 /*
    102  * Function:
    103  *      _bcm_vxlan_check_init
    104  * Purpose:
    105  *      Check if VXLAN is initialized
    106  * Parameters:
    107  *      unit     - Device Number
    108  * Returns:
    109  *      BCM_E_XXX
    110  */
    111 
    112 
    113 STATIC int 
    114 _bcm_vxlan_check_init(int unit)
    115 {
    116     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
    117 
    118     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
    119          return BCM_E_UNIT;
    120     }
    121 
    122     vxlan_info = VXLAN_INFO(unit);
    123 
    124     if ((vxlan_info == NULL) || (vxlan_info->initialized == FALSE)) { 
    125          return BCM_E_INIT;
    126     } else {
    127          return BCM_E_NONE;
    128     }
    129 }
    130 
    131 /*
    132  * Function:
    133  *      bcm_td2_vxlan_lock
    134  * Purpose:
    135  *      Take VXLAN Lock Sempahore
    136  * Parameters:
    137  *      unit     - Device Number
    138  * Returns:
    139  *      BCM_E_XXX
    140  */
    141 
    142 
    143  int 
    144  bcm_td2_vxlan_lock(int unit)
    145 {
    146    int rv=BCM_E_NONE;
    147 
    148    rv = _bcm_vxlan_check_init(unit);
    149    
    150    if ( rv == BCM_E_NONE ) {
    151            sal_mutex_take(VXLAN_INFO((unit))->vxlan_mutex, sal_mutex_FOREVER);
    152    }
    153    return rv; 
    154 }
    155 
    156 
    157 
    158 /*
    159  * Function:
    160  *      bcm_td2_vxlan_unlock
    161  * Purpose:
    162  *      Release  VXLAN Lock Semaphore
    163  * Parameters:
    164  *      unit     - Device Number
    165  * Returns:
    166  *      BCM_E_XXX
    167  */
    168 
    169 
    170 void
    171 bcm_td2_vxlan_unlock(int unit)
    172 {
    173    int rv=BCM_E_NONE;
    174 
    175    rv = _bcm_vxlan_check_init(unit);
    176     if ( rv == BCM_E_NONE ) {
    177          sal_mutex_give(VXLAN_INFO((unit))->vxlan_mutex);
    178     }
    179 }
    180 
    181 /*
    182  * Function:
    183  *      bcm_td2_vxlan_udpDestPort_set
    184  * Purpose:
    185  *      Set UDP Dest port for VXLAN
    186  * Parameters:
    187  *      unit - SOC unit number.
    188  *      UDP Dest port  -  Non-zero value
    189  * Returns:
    190  *      BCM_E_XXX.
    191  */
    192 int
    193 bcm_td2_vxlan_udpDestPort_set(int unit, int udpDestPort)
    194 {
    195     int rv = BCM_E_NONE;
    196     uint64 reg64;
    197 
    198     COMPILER_64_ZERO(reg64);
    199 
    200     if ((udpDestPort < 0) || (udpDestPort > 0xFFFF) ) {
    201          return BCM_E_PARAM;
    202     }
    203 
    204     if (SOC_REG_FIELD_VALID(unit, VXLAN_CONTROLr, UDP_DEST_PORTf)){
    205         SOC_IF_ERROR_RETURN(READ_VXLAN_CONTROLr(unit, &reg64));
    206         soc_reg64_field32_set(unit, VXLAN_CONTROLr, &reg64,
    207                               UDP_DEST_PORTf, udpDestPort);
    208         SOC_IF_ERROR_RETURN(WRITE_VXLAN_CONTROLr(unit, reg64));
    209     } else {
    210         rv = BCM_E_UNAVAIL;
    211     }
    212 
    213     return rv;
    214 }
    215 
    216 /*
    217  * Function:
    218  *      bcm_td2_vxlan_udpSourcePort_set
    219  * Purpose:
    220  *      Enable UDP Source port based HASH for VXLAN
    221  * Parameters:
    222  *      unit - SOC unit number.
    223  *      hashEnable - Enable Hash for UDP SourcePort
    224  * Returns:
    225  *      BCM_E_XXX.
    226  */
    227 int
    228 bcm_td2_vxlan_udpSourcePort_set(int unit, int hashEnable)
    229 {
    230     int rv = BCM_E_NONE;
    231     uint64 reg64;
    232 
    233     COMPILER_64_ZERO(reg64);
    234 
    235     if ((hashEnable < 0) || (hashEnable > 1) ) {
    236          return BCM_E_PARAM;
    237     }
    238 
    239     if (!SOC_REG_IS_VALID(unit, EGR_VXLAN_CONTROLr)) {
    240         return rv;
    241     }
    242 
    243     if (SOC_REG_FIELD_VALID(unit, EGR_VXLAN_CONTROLr, USE_SOURCE_PORT_SELf)){
    244          soc_reg64_field32_set(unit, EGR_VXLAN_CONTROLr, &reg64,
    245                       USE_SOURCE_PORT_SELf, hashEnable);
    246     }
    247 
    248 #if defined(BCM_TRIDENT3_SUPPORT)
    249     if (SOC_REG_IS_VALID(unit,FLEX_EDITOR_VXLAN_CONTROL_64r)) {
    250         SOC_IF_ERROR_RETURN(
    251             soc_reg_field32_modify(unit, FLEX_EDITOR_VXLAN_CONTROL_64r,
    252             REG_PORT_ANY, VXLAN_FLAGSf, 0x8));
    253     } else
    254 #endif
    255     {
    256         soc_reg64_field32_set(unit, EGR_VXLAN_CONTROLr, &reg64,
    257                       VXLAN_FLAGSf, 0x8);
    258     }
    259 
    260     SOC_IF_ERROR_RETURN(WRITE_EGR_VXLAN_CONTROLr(unit, reg64));
    261     return rv;
    262 }
    263 
    264 /*
    265  * Function:
    266  *      bcm_td2_vxlan_udpDestPort_get
    267  * Purpose:
    268  *      Get UDP Dest port for VXLAN
    269  * Parameters:
    270  *      unit - SOC unit number.
    271  *      UDP Dest port  -  Non-zero value
    272  * Returns:
    273  *      BCM_E_XXX.
    274  */
    275 int
    276 bcm_td2_vxlan_udpDestPort_get(int unit, int *udpDestPort)
    277 {
    278     int rv = BCM_E_NONE;
    279     uint64 reg64;
    280 
    281     COMPILER_64_ZERO(reg64);
    282 
    283     if (SOC_REG_FIELD_VALID(unit, VXLAN_CONTROLr, UDP_DEST_PORTf)) {
    284         SOC_IF_ERROR_RETURN(READ_VXLAN_CONTROLr(unit, &reg64));
    285         *udpDestPort = soc_reg64_field32_get(unit, VXLAN_CONTROLr,
    286                                                   reg64, UDP_DEST_PORTf);
    287     } else {
    288         rv = BCM_E_UNAVAIL;
    289     }
    290 
    291     return rv;
    292 }
    293 
    294 /*
    295  * Function:
    296  *      bcm_td2_vxlan_udpSourcePort_get
    297  * Purpose:
    298  *      Get UDP Source port based HASH for VXLAN
    299  * Parameters:
    300  *      unit - SOC unit number.
    301  *      hashEnable - Enable Hash for UDP SourcePort
    302  * Returns:
    303  *      BCM_E_XXX.
    304  */
    305 int
    306 bcm_td2_vxlan_udpSourcePort_get(int unit, int *hashEnable)
    307 {
    308     int rv = BCM_E_NONE;
    309     uint64 reg64;
    310 
    311     COMPILER_64_ZERO(reg64);
    312 
    313     SOC_IF_ERROR_RETURN(READ_EGR_VXLAN_CONTROLr(unit, &reg64));
    314     *hashEnable = soc_reg64_field32_get(unit, EGR_VXLAN_CONTROLr, 
    315                                               reg64, USE_SOURCE_PORT_SELf);
    316     return rv;
    317 }
    318 
    319 
    320 /*
    321  * Function:
    322  *      _bcm_td2_vxlan_free_resource
    323  * Purpose:
    324  *      Free all allocated software resources 
    325  * Parameters:
    326  *      unit - SOC unit number
    327  * Returns:
    328  *      Nothing
    329  */
    330 
    331 
    332 STATIC void
    333 _bcm_td2_vxlan_free_resource(int unit)
    334 {
    335     _bcm_td2_vxlan_bookkeeping_t *vxlan_info = VXLAN_INFO(unit);
    336 
    337     /* If software tables were not allocated we are done. */ 
    338     if (NULL == VXLAN_INFO(unit)) {
    339         return;
    340     }
    341 
    342     /* Destroy EGR_IP_TUNNEL usage bitmap */
    343     if (vxlan_info->vxlan_ip_tnl_bitmap) {
    344         sal_free(vxlan_info->vxlan_ip_tnl_bitmap);
    345         vxlan_info->vxlan_ip_tnl_bitmap = NULL;
    346     }
    347 
    348     if (vxlan_info->match_key) {
    349         sal_free(vxlan_info->match_key);
    350         vxlan_info->match_key = NULL;
    351     }
    352 
    353     if (vxlan_info->vxlan_tunnel_init) {
    354         sal_free(vxlan_info->vxlan_tunnel_init);
    355         vxlan_info->vxlan_tunnel_init = NULL;
    356     }
    357 
    358     if (vxlan_info->vxlan_tunnel_term) {
    359         sal_free(vxlan_info->vxlan_tunnel_term);
    360         vxlan_info->vxlan_tunnel_term = NULL;
    361     }
    362 
    363     if (vxlan_info->vxlan_vpn_vlan) {
    364         sal_free(vxlan_info->vxlan_vpn_vlan);
    365         vxlan_info->vxlan_vpn_vlan = NULL;
    366     }
    367     if (vxlan_info->vxlan_vpn_info) {
    368         sal_free(vxlan_info->vxlan_vpn_info);
    369         vxlan_info->vxlan_vpn_info = NULL;
    370     }
    371     if (vxlan_info->vfi_vnid_map_count) {
    372         sal_free(vxlan_info->vfi_vnid_map_count);
    373         vxlan_info->vfi_vnid_map_count = NULL;
    374     }
    375     /* Free module data. */
    376     sal_free(VXLAN_INFO(unit));
    377     VXLAN_INFO(unit) = NULL;
    378 }
    379 
    380 /*
    381  * Function:
    382  *      bcm_td2_vxlan_allocate_bk
    383  * Purpose:
    384  *      Initialize VXLAN software book-kepping
    385  * Parameters:
    386  *      unit     - Device Number
    387  * Returns:
    388  *      BCM_E_XXX
    389  */
    390 
    391 STATIC int
    392 bcm_td2_vxlan_allocate_bk(int unit)
    393 {
    394     /* Allocate/Init unit software tables. */
    395     if (NULL == VXLAN_INFO(unit)) {
    396         BCMI_VXLAN_ALLOC(VXLAN_INFO(unit), sizeof(_bcm_td2_vxlan_bookkeeping_t),
    397                          "vxlan_bk_module_data");
    398         if (NULL == VXLAN_INFO(unit)) {
    399             return (BCM_E_MEMORY);
    400         } else {
    401             VXLAN_INFO(unit)->initialized = FALSE;
    402         }
    403     }
    404     return BCM_E_NONE;
    405 }
    406 
    407 /*
    408  * Function:
    409  *      _bcm_td2_vxlan_hw_clear
    410  * Purpose:
    411  *     Perform hw tables clean up for VXLAN module. 
    412  * Parameters:
    413  *      unit     - Device Number
    414  * Returns:
    415  *      BCM_E_XXX
    416  */
    417  
    418 STATIC int
    419 _bcm_td2_vxlan_hw_clear(int unit)
    420 {
    421     int rv = BCM_E_NONE, rv_error = BCM_E_NONE;
    422 
    423     rv = bcm_td2_vxlan_tunnel_terminator_destroy_all(unit);
    424     if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) {
    425         rv_error = rv;
    426     }
    427 
    428     rv = bcm_td2_vxlan_tunnel_initiator_destroy_all(unit);
    429     if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) {
    430         rv_error = rv;
    431     }
    432 
    433     rv =_bcm_td2_vxlan_vp_based_vnid_delete_all(unit);
    434     if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)){
    435         rv_error = rv;
    436     }
    437 
    438     rv = bcm_td2_vxlan_vpn_destroy_all(unit);
    439     if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) {
    440         rv_error = rv;
    441     }
    442 
    443     rv = _bcm_td2_vxlan_bud_loopback_disable(unit);
    444     if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) {
    445         rv_error = rv;
    446     }
    447 
    448     return rv_error;
    449 }
    450 
    451 /*
    452  * Function:
    453  *      bcm_td2_vxlan_cleanup
    454  * Purpose:
    455  *      DeInit  VXLAN software module
    456  * Parameters:
    457  *      unit     - Device Number
    458  * Returns:
    459  *      BCM_E_XXX
    460  */
    461 
    462 int
    463 bcm_td2_vxlan_cleanup(int unit)
    464 {
    465     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
    466     int rv = BCM_E_UNAVAIL;
    467 
    468     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
    469          return BCM_E_UNIT;
    470     }
    471 
    472     vxlan_info = VXLAN_INFO(unit);
    473 
    474     if (FALSE == vxlan_info->initialized) {
    475         return (BCM_E_NONE);
    476     } 
    477 
    478     rv = bcm_td2_vxlan_lock (unit);
    479     if (BCM_FAILURE(rv)) {
    480         return rv;
    481     }
    482 
    483     if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 
    484         rv = _bcm_td2_vxlan_hw_clear(unit);
    485     }
    486 
    487     /* Mark the state as uninitialized */
    488     vxlan_info->initialized = FALSE;
    489 
    490     sal_mutex_give(vxlan_info->vxlan_mutex);
    491 
    492     /* Destroy protection mutex. */
    493     sal_mutex_destroy(vxlan_info->vxlan_mutex );
    494 
    495     /* Free software resources */
    496     (void) _bcm_td2_vxlan_free_resource(unit);
    497 
    498     return rv;
    499 }
    500 
    501 /*
    502  * Function:
    503  *      bcm_td2_vxlan_port_match_count_adjust
    504  * Purpose:
    505  *      Obtain ref-count for a VXLAN port
    506  * Returns:
    507  *      BCM_E_XXX
    508  */
    509 
    510 void
    511 bcm_td2_vxlan_port_match_count_adjust(int unit, int vp, int step)
    512 {
    513     _bcm_td2_vxlan_bookkeeping_t *vxlan_info = VXLAN_INFO(unit);
    514  
    515     vxlan_info->match_key[vp].match_count += step;
    516 }
    517 
    518 
    519 #ifdef BCM_WARM_BOOT_SUPPORT
    520 
    521 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1, 0)
    522 #define BCM_WB_VERSION_1_1                SOC_SCACHE_VERSION(1, 1)
    523 #define BCM_WB_VERSION_1_2                SOC_SCACHE_VERSION(1, 2)
    524 #define BCM_WB_VERSION_1_3                SOC_SCACHE_VERSION(1, 3)
    525 #define BCM_WB_VERSION_1_4                SOC_SCACHE_VERSION(1, 4)
    526 #define BCM_WB_VERSION_1_5                SOC_SCACHE_VERSION(1, 5)
    527 #define BCM_WB_VERSION_1_6                SOC_SCACHE_VERSION(1, 6)
    528 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_6
    529 
    530 STATIC int _bcm_td2_vxlan_wb_alloc(int unit);
    531 
    532 /*
    533  * Function:
    534  *      _bcm_td2_vxlan_wb_recover
    535  *
    536  * Purpose:
    537  *      Recover VXLAN module info for Level 2 Warm Boot from persisitent memory
    538  *
    539  * Warm Boot Version Map:
    540  *      see _bcm_esw_vxlan_sync definition
    541  *
    542  * Parameters:
    543  *      unit - (IN) Device Unit Number.
    544  *
    545  * Returns:
    546  *      BCM_E_XXX
    547  */
    548  
    549 STATIC int
    550 _bcm_td2_vxlan_wb_recover(int unit)
    551 {
    552     int i, sz = 0, rv = BCM_E_NONE;
    553     int num_tnl = 0, num_vp = 0;
    554     int stable_size;
    555     int additional_scache_size = 0;
    556     uint16 recovered_ver = 0;
    557     int add_sz_1_0 = 0;
    558     int add_sz_1_1 = 0;
    559     int add_sz_1_2 = 0;
    560     int add_sz_1_4 = 0;
    561     int tnl_idx = 0;
    562     bcm_ip_t sip = 0;
    563     bcm_gport_t gport;
    564     uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS];
    565     uint8 *vxlan_state = NULL;
    566     soc_scache_handle_t scache_handle;
    567     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
    568     int num_vfi = 0;
    569 
    570     vxlan_info = VXLAN_INFO(unit);
    571 
    572     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    573 
    574     /* Requires extended scache support level-2 warmboot */
    575     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
    576         return BCM_E_NONE;
    577     }
    578 
    579     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_VXLAN, 0);
    580     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    581                                  0, &vxlan_state, 
    582                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
    583     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    584         return rv;
    585     } else if (rv == BCM_E_NOT_FOUND) {
    586         return _bcm_td2_vxlan_wb_alloc(unit);
    587     }
    588 
    589     if (vxlan_state != NULL) {
    590         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    591         num_tnl = soc_mem_index_count(unit, EGR_IP_TUNNELm);
    592         num_vfi = soc_mem_index_count(unit, VFIm);
    593 
    594         if (recovered_ver >= BCM_WB_VERSION_1_4) {
    595             sz = num_vp * sizeof(_bcm_vxlan_tunnel_endpoint_t);
    596         } else if (recovered_ver >= BCM_WB_VERSION_1_2) {
    597             sz = num_vp * (sizeof(_bcm_vxlan_tunnel_endpoint_t) - sizeof(bcm_vlan_t));
    598             additional_scache_size =
    599                      ((num_vp * sizeof(_bcm_vxlan_tunnel_endpoint_t)) - sz) * 2;
    600         } else if (recovered_ver >= BCM_WB_VERSION_1_1) {
    601             /* Warm boot upgrade case, activate_flag was added.*/
    602             sz = num_vp * (sizeof(_bcm_vxlan_tunnel_endpoint_t) - sizeof(int)
    603                             - sizeof(bcm_vlan_t));
    604             additional_scache_size =
    605                      ((num_vp * sizeof(_bcm_vxlan_tunnel_endpoint_t)) - sz) * 2;
    606         } else {
    607             /* Warm boot upgrade case, in the previous version (SDK 6.3.4)
    608                 tunnel_state was uint8, now changed to uint16 */
    609             sz = num_vp * (sizeof(_bcm_vxlan_tunnel_endpoint_t) - 1 - sizeof(int)
    610                             - sizeof(bcm_vlan_t));
    611             additional_scache_size =
    612                       ((num_vp * sizeof(_bcm_vxlan_tunnel_endpoint_t)) - sz) * 2;
    613         } 
    614 
    615         /* Version_1_0: _bcm_vxlan_tunnel_endpoint_t in vxlan_bookkeeping_t
    616          * bcm_ip_t dip + bcm_ip_t sip + uint8 tunnel_state
    617          * comments: (tunnel_state is ONLY valid to Tunnel Terminator in v_1_0)
    618          * Version_1_1: _bcm_vxlan_tunnel_endpoint_t in vxlan_bookkeeping_t
    619          * bcm_ip_t dip +  bcm_ip_t  sip + uint16 tunnel_state; 
    620          *   
    621          * Version_1_2: _bcm_vxlan_tunnel_endpoint_t in vxlan_bookkeeping_t
    622          * bcm_ip_t dip + bcm_ip_t sip + uint16 tunnel_state + int activate_flag
    623          * comments: (activate_flag is ONLY valid to Tunnel Terminator in v_1_2)
    624          * Version_1_0 -> Version_1_1: tunnel_state (uni8->unit16)
    625          * Version_1_0 -> Version_1_2: tunnel_state (uni8->unit16)
    626          *                             + activate_flag
    627          * Version_1_1 -> Version_1_2: + activate_flag
    628          */
    629         
    630         /* size of (DIP, SIP, Tunnel State(uint8)) */
    631         add_sz_1_0 = sizeof(bcm_ip_t) + sizeof(bcm_ip_t) + sizeof(uint8);
    632         
    633         /* Tunnel State uint8==> uint16 */
    634         add_sz_1_1 = 1;
    635 
    636         /* Add activate_flag */
    637         add_sz_1_2 = sizeof(int);
    638 
    639         /* Add vlan */
    640         add_sz_1_4 = sizeof(bcm_vlan_t);
    641 
    642         /* Recover Vxlan Tunnel Terminator (DIP, SIP, Tunnel State(unit8))
    643          * To correspond with the sync actions in Version_1_0
    644          */
    645         if (recovered_ver == BCM_WB_VERSION_1_0) {
    646             for (i = 0; i < num_vp; i++) {
    647                 sal_memcpy(&(vxlan_info->vxlan_tunnel_term[i]),
    648                     vxlan_state, add_sz_1_0 - sizeof(uint8));
    649                 vxlan_state += add_sz_1_0 - sizeof(uint8);
    650                 /* Tunnel State uint8 --> uint16 */
    651                 vxlan_info->vxlan_tunnel_term[i].tunnel_state = 
    652                     *((uint8 *)vxlan_state);
    653                 vxlan_state += sizeof(uint8);
    654             }
    655         }
    656 
    657         /* Recover Vxlan Tunnel Terminator (DIP, SIP, Tunnel State(uint16))
    658          * To correspond with the sync actions in Version_1_1
    659          */
    660         if (recovered_ver == BCM_WB_VERSION_1_1) {
    661             for (i = 0; i < num_vp; i++) {
    662                 sal_memcpy(&(vxlan_info->vxlan_tunnel_term[i]),
    663                     vxlan_state, add_sz_1_0 + add_sz_1_1);
    664                 vxlan_state += add_sz_1_0 + add_sz_1_1;
    665             }
    666         }
    667 
    668         /* Recover Vxlan Tunnel Terminator 
    669          * (DIP, SIP, Tunnel State(uint16), activate_flag)
    670          * To correspond with the sync actions in Version_1_2
    671          */
    672         if ((recovered_ver >= BCM_WB_VERSION_1_2) 
    673              && (recovered_ver < BCM_WB_VERSION_1_4)) {
    674             for (i = 0; i < num_vp; i++) {
    675                 sal_memcpy(&(vxlan_info->vxlan_tunnel_term[i]),
    676                     vxlan_state, add_sz_1_0 + add_sz_1_1 + add_sz_1_2);
    677                 vxlan_state += add_sz_1_0 + add_sz_1_1 + add_sz_1_2;
    678             }
    679         }
    680 
    681         /* Recover Vxlan Tunnel Terminator 
    682           * (DIP, SIP, Tunnel State(uint16), activate_flag, vlan)
    683           * To correspond with the sync actions in Version_1_4
    684           */
    685         if (recovered_ver >= BCM_WB_VERSION_1_4) {
    686             for (i = 0; i < num_vp; i++) {
    687                 sal_memcpy(&(vxlan_info->vxlan_tunnel_term[i]),
    688                     vxlan_state,
    689                     add_sz_1_0 + add_sz_1_1 + add_sz_1_2 + add_sz_1_4);
    690                 vxlan_state += add_sz_1_0 + add_sz_1_1 + add_sz_1_2 + add_sz_1_4;
    691             }
    692         }
    693         /* Recover Vxlan Tunnel Initiator (DIP, SIP, Tunnel State(unit8))
    694          * To correspond with the sync actions in Version_1_0
    695          */
    696         if (recovered_ver == BCM_WB_VERSION_1_0) {
    697             for (i = 0; i < num_vp; i++) {
    698                 sal_memcpy(&(vxlan_info->vxlan_tunnel_init[i]),
    699                     vxlan_state, add_sz_1_0 - sizeof(uint8));
    700                 vxlan_state += add_sz_1_0 - sizeof(uint8);
    701                 vxlan_info->vxlan_tunnel_init[i].tunnel_state = 
    702                     *((uint8 *)vxlan_state);
    703                 vxlan_state += sizeof(uint8);
    704             }
    705         }
    706 
    707         /* Recover Vxlan Tunnel Initiator (DIP, SIP, Tunnel State(uint16)) 
    708          * To correspond with the sync actions in Version_1_1
    709          */
    710         if (recovered_ver == BCM_WB_VERSION_1_1) {
    711             for (i = 0; i < num_vp; i++) {                
    712                 sal_memcpy(&(vxlan_info->vxlan_tunnel_init[i]),
    713                     vxlan_state, add_sz_1_0 + add_sz_1_1);
    714                 vxlan_state += (add_sz_1_0 + add_sz_1_1);
    715             }
    716         }
    717         
    718         /* Recover Vxlan Tunnel Initiator
    719          * (DIP, SIP, Tunnel State(uint16), activate_flag)
    720          * To correspond with the sync actions in Version_1_2
    721          */
    722         if (recovered_ver >= BCM_WB_VERSION_1_2 
    723             && (recovered_ver < BCM_WB_VERSION_1_4)) {
    724             for (i = 0; i < num_vp; i++) {
    725                 sal_memcpy(&(vxlan_info->vxlan_tunnel_init[i]),
    726                     vxlan_state, add_sz_1_0 + add_sz_1_1 + add_sz_1_2);
    727                 vxlan_state += add_sz_1_0 + add_sz_1_1 + add_sz_1_2;
    728             }
    729         }
    730 		
    731         /* Recover Vxlan Tunnel Initiator
    732                * (DIP, SIP, Tunnel State(uint16), activate_flag, vlan)
    733                * To correspond with the sync actions in Version_1_4
    734                */
    735 
    736         if (recovered_ver >= BCM_WB_VERSION_1_4) {
    737             for (i = 0; i < num_vp; i++) {
    738                 sal_memcpy(&(vxlan_info->vxlan_tunnel_init[i]),
    739                     vxlan_state, add_sz_1_0 + add_sz_1_1 + add_sz_1_2 + add_sz_1_4);
    740                 vxlan_state += add_sz_1_0 + add_sz_1_1 + add_sz_1_2 + add_sz_1_4;
    741             }
    742         }
    743 
    744         /* Recover the BITMAP of Vxlan Tunnel usage */
    745         sal_memcpy(vxlan_info->vxlan_ip_tnl_bitmap, vxlan_state, 
    746                     SHR_BITALLOCSIZE(num_tnl));
    747         vxlan_state += SHR_BITALLOCSIZE(num_tnl);
    748 
    749         /* Recover the flags & match_tunnel_index of each Match Key */
    750         for (i = 0; i < num_vp; i++) {
    751             sal_memcpy(&(vxlan_info->match_key[i].flags), vxlan_state, 
    752                         sizeof(uint32));
    753             vxlan_state += sizeof(uint32);        
    754             sal_memcpy(&(vxlan_info->match_key[i].match_tunnel_index), vxlan_state, 
    755                         sizeof(uint32));
    756             vxlan_state += sizeof(uint32);
    757         }
    758 
    759         /* set default information for warm boot upgrade case */
    760         if (recovered_ver < BCM_WB_VERSION_1_2) {
    761             for (i = 0; i < num_vp; i++) {
    762                 /* Version_1_0/Version_1_1 -> Version_1_2: 
    763                  * activate_flag is introduced by Version_1_2
    764                  * and ONLY valid to Tunnel Terminator.
    765                  * Here is to set default flag with TERM_ENABLE.
    766                  */
    767                 if (vxlan_info->vxlan_tunnel_term[i].sip != 0) {
    768                     vxlan_info->vxlan_tunnel_term[i].activate_flag |=
    769                         _BCM_VXLAN_TUNNEL_TERM_ENABLE;
    770                 }
    771             }
    772 
    773             if (recovered_ver == BCM_WB_VERSION_1_0) {
    774                 /* Version_1_0 -> Version_1_2:
    775                  * Start from Version_1_1 - Set dest udp port on tunnel_state 
    776                  * field for Tunnel Initiator. Here is to get dest udp port 
    777                  * from HW entry.
    778                  */
    779                 for (tnl_idx = 0; tnl_idx < num_tnl; tnl_idx++) {
    780                     BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_IP_TUNNELm,
    781                         MEM_BLOCK_ANY, tnl_idx, tnl_entry));
    782                     sip = soc_mem_field32_get(unit, EGR_IP_TUNNELm,
    783                         tnl_entry, SIPf);
    784                     if (sip != 0) {
    785                         for (i = 0; i < num_vp; i++) {
    786                             if (sip == vxlan_info->vxlan_tunnel_init[i].sip) {
    787                                 vxlan_info->vxlan_tunnel_init[i].tunnel_state =
    788                                     soc_mem_field32_get(unit, EGR_IP_TUNNELm,
    789                                         tnl_entry, L4_DEST_PORTf);
    790                             }
    791                         }
    792                     }
    793                 }
    794             }
    795         }
    796 
    797         /* 
    798          * Recover the index && gport(trunk_id, modid, port) && match_vlan && 
    799          * match_inner_vlan of each Match Key
    800          */
    801         if (recovered_ver >= BCM_WB_VERSION_1_3) {
    802             for (i = 0; i < num_vp; i++) {
    803                 sal_memcpy(&(vxlan_info->match_key[i].index), vxlan_state, 
    804                            sizeof(uint32));
    805                 vxlan_state += sizeof(uint32);        
    806                 sal_memcpy(&gport, vxlan_state, sizeof(bcm_gport_t));
    807                 if (BCM_GPORT_IS_TRUNK(gport)) {
    808                     vxlan_info->match_key[i].trunk_id = 
    809                                              BCM_GPORT_TRUNK_GET(gport);
    810                 } else if (BCM_GPORT_IS_MODPORT(gport)) {
    811                     vxlan_info->match_key[i].modid = 
    812                                              BCM_GPORT_MODPORT_MODID_GET(gport);
    813                     vxlan_info->match_key[i].port = 
    814                                              BCM_GPORT_MODPORT_PORT_GET(gport);
    815                 }
    816                 vxlan_state += sizeof(bcm_gport_t);        
    817                 sal_memcpy(&(vxlan_info->match_key[i].match_vlan), vxlan_state, 
    818                            sizeof(bcm_vlan_t));
    819                 vxlan_state += sizeof(bcm_vlan_t);
    820                 sal_memcpy(&(vxlan_info->match_key[i].match_inner_vlan),
    821                            vxlan_state, sizeof(bcm_vlan_t));
    822                 vxlan_state += sizeof(bcm_vlan_t);
    823             }
    824         } else {
    825             additional_scache_size += num_vp * (sizeof(uint32) + 
    826                                                 sizeof(bcm_gport_t) +
    827                                                 sizeof(bcm_vlan_t) * 2);
    828         }
    829 
    830         if (recovered_ver >= BCM_WB_VERSION_1_5) {
    831             for (i = 0; i < num_vfi; i++) {
    832                 sal_memcpy(&(vxlan_info->vxlan_vpn_vlan[i]), vxlan_state,
    833                            sizeof(bcm_vlan_t));
    834                 vxlan_state += sizeof(bcm_vlan_t);
    835             }
    836         } else {
    837             additional_scache_size += num_vfi * sizeof(bcm_vlan_t);
    838         }
    839         if (recovered_ver >= BCM_WB_VERSION_1_6) {
    840              /* Recover the type of each vxlan vpn */
    841             for (i = 0; i < num_vfi; i++) {
    842                 sal_memcpy(&(vxlan_info->vxlan_vpn_info[i].sip), vxlan_state,
    843                            sizeof(bcm_ip_t));
    844                 vxlan_state += sizeof(bcm_ip_t);
    845                 sal_memcpy(&(vxlan_info->vxlan_vpn_info[i].vnid), vxlan_state,
    846                            sizeof(uint32));
    847                 vxlan_state += sizeof(uint32);
    848                 sal_memcpy(&(vxlan_info->vxlan_vpn_info[i].vxlan_vpn_type), vxlan_state,
    849                            sizeof(uint8));
    850                 vxlan_state += sizeof(uint8);          
    851             }
    852             for (i = 0; i < num_vp; i++) {
    853                 sal_memcpy(&(vxlan_info->match_key[i].vfi), vxlan_state,
    854                            sizeof(int));
    855                 vxlan_state += sizeof(int);
    856             }
    857         } else {
    858             additional_scache_size += num_vfi * (sizeof(uint8) + sizeof(bcm_ip_t) +
    859                                                  sizeof(uint32)) + num_vp * sizeof(int);
    860         }
    861 
    862         /* Reallocate additional scache size required for tunnel_state in 
    863            Vxlan Tunnel Terminator and Vxlan Tunnel Initiator */ 
    864         if (additional_scache_size > 0) {
    865             rv = soc_scache_realloc(unit,scache_handle,additional_scache_size);
    866             if(BCM_FAILURE(rv)) {
    867                return rv;
    868             }
    869         }
    870     }
    871 
    872     return BCM_E_NONE;
    873 }
    874 
    875 /*
    876  * Function:
    877  *      _bcm_td2_vxlan_wb_alloc
    878  *
    879  * Purpose:
    880  *      Alloc persisitent memory for Level 2 Warm Boot scache.
    881  *
    882  * Parameters:
    883  *      unit - (IN) Device Unit Number.
    884  *
    885  * Returns:
    886  *      BCM_E_XXX
    887  */
    888  
    889 STATIC int
    890 _bcm_td2_vxlan_wb_alloc(int unit)
    891 {
    892     int alloc_sz = 0, rv = BCM_E_NONE;
    893     soc_scache_handle_t scache_handle;
    894     int num_tnl = 0, num_vp = 0;
    895     int num_vfi = 0;
    896 
    897     uint8 *vxlan_state;
    898     int stable_size;
    899 
    900     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    901 
    902     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
    903         return BCM_E_NONE;
    904     }
    905 
    906     /* Size of Tunnel Terminator & Initiator of all VP */
    907     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    908     alloc_sz += num_vp * sizeof(_bcm_vxlan_tunnel_endpoint_t) * 2;
    909 
    910     /* Size of EGR_IP_TUNNEL index bitmap */
    911     num_tnl = soc_mem_index_count(unit, EGR_IP_TUNNELm);
    912     alloc_sz += SHR_BITALLOCSIZE(num_tnl);
    913 
    914     /* Size of All match_key's flags & match_tunnel_index */
    915     alloc_sz += num_vp * sizeof(uint32) * 2;
    916 
    917     /*
    918      * Size of All match_key's index && gport(trunk_id, modid, port) && 
    919      * match_vlan && match_inner_vlan
    920      */
    921     alloc_sz += num_vp * (sizeof(uint32) + sizeof(bcm_gport_t) +
    922                           sizeof(bcm_vlan_t) * 2);
    923 
    924     /* BCM_WB_VERSION_1_5 */
    925     num_vfi = soc_mem_index_count(unit, VFIm);
    926     alloc_sz += num_vfi * sizeof(bcm_vlan_t);
    927 
    928     /* BCM_WB_VERSION_1_6 */
    929     alloc_sz += num_vfi * sizeof(_bcm_vxlan_vpn_info_t);
    930     alloc_sz += num_vp * sizeof(int);
    931 
    932     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_VXLAN, 0);
    933     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
    934                                  alloc_sz, (uint8**)&vxlan_state, 
    935                                  BCM_WB_DEFAULT_VERSION, NULL);
    936     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    937         return rv;
    938     }
    939 
    940     return BCM_E_NONE;
    941 }
    942 
    943 /*
    944  * Function:
    945  *      _bcm_td2_vxlan_tunnel_initiator_reinit
    946  * Purpose:
    947  *      Tunnel initiator hash and ref-count recovery.
    948  * Parameters:
    949  *      unit          - (IN) BCM device number.
    950  * Returns:
    951  *      BCM_E_XXX
    952  */
    953 STATIC int
    954 _bcm_td2_vxlan_tunnel_initiator_reinit(int unit)
    955 {
    956     bcm_tunnel_initiator_t tnl_init_info;
    957     int rv = BCM_E_NONE;
    958     int i = 0;
    959     int idx_min = 0;
    960     int idx_max = 0;
    961     egr_ip_tunnel_entry_t *egr_tnl_entry = NULL;
    962     uint8                 *egr_tnl_buf   = NULL;
    963 
    964     idx_min = soc_mem_index_min(unit, EGR_IP_TUNNELm);
    965     idx_max = soc_mem_index_max(unit, EGR_IP_TUNNELm);
    966 
    967     egr_tnl_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, EGR_IP_TUNNELm),
    968                                 "EGR_IP_TUNNEL buffer");
    969     if (NULL == egr_tnl_buf) {
    970         return BCM_E_MEMORY;
    971     }
    972 
    973     rv = soc_mem_read_range(unit, EGR_IP_TUNNELm, MEM_BLOCK_ANY,
    974                             idx_min, idx_max, egr_tnl_buf);
    975     if (SOC_FAILURE(rv)) {
    976         goto clean_up;
    977     }
    978 
    979     for (i = idx_min; i <= idx_max; i++) {
    980 
    981         egr_tnl_entry = soc_mem_table_idx_to_pointer(unit, EGR_IP_TUNNELm,
    982                                                      egr_ip_tunnel_entry_t *,
    983                                                      egr_tnl_buf, i);
    984         if (_BCM_VXLAN_TUNNEL_TYPE ==
    985             soc_mem_field32_get(unit, EGR_IP_TUNNELm,
    986                                 egr_tnl_entry, TUNNEL_TYPEf)) {
    987 
    988             bcm_tunnel_initiator_t_init(&tnl_init_info);
    989             tnl_init_info.type = bcmTunnelTypeVxlan;
    990             tnl_init_info.sip =
    991                 soc_mem_field32_get(unit, EGR_IP_TUNNELm,
    992                                     egr_tnl_entry, SIPf);
    993             tnl_init_info.udp_dst_port =
    994                 soc_mem_field32_get(unit, EGR_IP_TUNNELm,
    995                                     egr_tnl_entry, L4_DEST_PORTf);
    996             rv = _bcm_td2_vxlan_tunnel_initiator_hash_calc(
    997                      unit, &tnl_init_info,
    998                      &BCM_XGS3_L3_ENT_HASH(
    999                      BCM_XGS3_L3_TBL_PTR(unit, tnl_init), i));
   1000             if (BCM_FAILURE(rv)) {
   1001                 goto clean_up;
   1002             }
   1003             BCM_XGS3_L3_ENT_REF_CNT_INC(
   1004                 BCM_XGS3_L3_TBL_PTR(unit, tnl_init), i,
   1005                 ((_BCM_TUNNEL_OUTER_HEADER_IPV6(tnl_init_info.type)) ?
   1006                 _BCM_DOUBLE_WIDE : _BCM_SINGLE_WIDE));
   1007         }
   1008     }
   1009 clean_up:
   1010 
   1011     if (NULL != egr_tnl_buf) {
   1012         soc_cm_sfree(unit, egr_tnl_buf);
   1013     }
   1014     return rv;
   1015 }
   1016 
   1017 
   1018 /*
   1019  * Function:
   1020  *      _bcm_d2_vxlan_vp_based_vnid_reinit
   1021  * Purpose:
   1022  *      Per VP VFI-VNID mappings rules ref-count recovery.
   1023  * Parameters:
   1024  *      unit          - (IN) BCM device number.
   1025  * Returns:
   1026  *      BCM_E_XXX
   1027  */
   1028 STATIC int
   1029 _bcm_td2_vxlan_vp_based_vnid_reinit(int unit)
   1030 {
   1031     _bcm_td2_vxlan_bookkeeping_t *vxlan_info = VXLAN_INFO(unit);
   1032     soc_field_t valid_field;
   1033     soc_field_t type_field;
   1034     soc_mem_t egr_vxlate_mem;
   1035     int rv = BCM_E_NONE;
   1036     int i = 0;
   1037     int idx_min = 0;
   1038     int idx_max = 0;
   1039     int decouple = 0;
   1040     void *egr_vxlate_entry = NULL;
   1041     uint8 *egr_vxlate_buf = NULL;
   1042     uint32 entry_type;
   1043     int vfi;
   1044     bcm_vpn_t vpn;
   1045     int vp;
   1046     uint8 vxlan_vpn_type;
   1047 
   1048 #if defined(BCM_TRIDENT3_SUPPORT)
   1049     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   1050         egr_vxlate_mem = EGR_VLAN_XLATE_1_SINGLEm;
   1051         valid_field = BASE_VALIDf;
   1052         type_field = KEY_TYPEf;
   1053         decouple = 1;
   1054     } else
   1055 #endif
   1056     {
   1057         egr_vxlate_mem = EGR_VLAN_XLATEm;
   1058         valid_field = VALIDf;
   1059         type_field = ENTRY_TYPEf;
   1060     }
   1061 
   1062     idx_min = soc_mem_index_min(unit, egr_vxlate_mem);
   1063     idx_max = soc_mem_index_max(unit, egr_vxlate_mem);
   1064 
   1065     egr_vxlate_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, egr_vxlate_mem),
   1066                                 "EGR_VLAN_XLATE buffer");
   1067     if (NULL == egr_vxlate_buf) {
   1068         return BCM_E_MEMORY;
   1069     }
   1070 
   1071     rv = soc_mem_read_range(unit, egr_vxlate_mem, MEM_BLOCK_ANY,
   1072                             idx_min, idx_max, egr_vxlate_buf);
   1073     if (SOC_FAILURE(rv)) {
   1074         goto clean_up;
   1075     }
   1076 
   1077     for (i = idx_min; i <= idx_max; i++) {
   1078         egr_vxlate_entry = soc_mem_table_idx_to_pointer(unit, egr_vxlate_mem,
   1079                                                         void*, egr_vxlate_buf, i);
   1080 
   1081         if (soc_mem_field32_get(unit, egr_vxlate_mem, egr_vxlate_entry, valid_field)) {
   1082             entry_type = soc_mem_field32_get(unit, egr_vxlate_mem, egr_vxlate_entry, type_field);
   1083             if (entry_type != _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI_DVP) {
   1084                 continue;
   1085             }
   1086 
   1087             vfi = soc_mem_field32_get(unit, egr_vxlate_mem,
   1088                 egr_vxlate_entry, BCM_VXLAN_VFI_FIELD(decouple, VFIf));
   1089             _BCM_VXLAN_VPN_SET(vpn, _BCM_VPN_TYPE_VFI, vfi);
   1090             rv = _bcm_td2_vxlan_vpn_is_tunnel_based_vnid(unit, vpn, &vxlan_vpn_type);
   1091             if (BCM_FAILURE(rv)) {
   1092                 goto clean_up;
   1093             }
   1094             if (vxlan_vpn_type) {
   1095                 continue;
   1096             }
   1097 
   1098             vp  = soc_mem_field32_get(unit, egr_vxlate_mem,
   1099                 egr_vxlate_entry, BCM_VXLAN_VFI_FIELD(decouple, DVPf));
   1100             vxlan_info->vfi_vnid_map_count[vp]++;
   1101         }
   1102     }
   1103 
   1104 clean_up:
   1105 
   1106     if (NULL != egr_vxlate_buf) {
   1107         soc_cm_sfree(unit, egr_vxlate_buf);
   1108     }
   1109     return rv;
   1110 }
   1111 
   1112 /*
   1113  * Function:
   1114  *      _bcm_td2_vxlan_reinit
   1115  * Purpose:
   1116  *      Warm boot recovery for the VXLAN software module
   1117  * Parameters:
   1118  *      unit     - Device Number
   1119  * Returns:
   1120  *      BCM_E_XXX
   1121  */
   1122 STATIC int 
   1123 _bcm_td2_vxlan_reinit(int unit)
   1124 {
   1125     soc_mem_t mem;  
   1126     int i, index_min, index_max, buf_size;
   1127     int vp;
   1128     int rv = BCM_E_NONE;
   1129     void *entry;
   1130     uint32 trunk, tgid, mod_id, port_num, key_type;
   1131     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   1132     uint8 *trunk_buf = NULL;
   1133     uint8 *xlate_buf = NULL;
   1134     uint8 *mpls_buf = NULL;
   1135     soc_field_t vld_fld = SOURCE_VPf;
   1136     soc_field_t tgid_fld = TGIDf;
   1137     int d = 0;
   1138 
   1139     vxlan_info = VXLAN_INFO(unit);
   1140 
   1141     mem = SOURCE_TRUNK_MAP_TABLEm;
   1142     index_min = soc_mem_index_min(unit, mem);
   1143     index_max = soc_mem_index_max(unit, mem);
   1144 
   1145     /* We check SOURCE_TRUNK_MAP_TABLE table outside to avoid the HUGE loop.
   1146      * Set each match_key[vp].index first, and override it to zero later if 
   1147      *  it's not needed.
   1148      */
   1149     buf_size = SOC_MEM_TABLE_BYTES(unit, mem);
   1150     trunk_buf = soc_cm_salloc(unit, buf_size, "SOURCE_TRUNK_MAP_TABLE buffer");
   1151     if (NULL == trunk_buf) {
   1152         rv = BCM_E_MEMORY;
   1153         goto clean_up;
   1154     }
   1155     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, trunk_buf);
   1156     if (SOC_FAILURE(rv)) {
   1157         goto clean_up;
   1158     }
   1159 
   1160     if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) {
   1161         vld_fld = SVP_VALIDf;
   1162     }
   1163 
   1164     if (SOC_IS_TRIDENT3X(unit) && soc_mem_field_valid(unit, mem, SRC_TGIDf)) {
   1165         tgid_fld = SRC_TGIDf;
   1166     }
   1167 
   1168     for (i = index_min; i <= index_max; i++) {
   1169         bcm_trunk_t tgid = -1;
   1170         int port_type = 0;
   1171         entry = soc_mem_table_idx_to_pointer(unit, mem, void *, trunk_buf, i);
   1172         if (soc_mem_field32_get(unit, mem, entry, vld_fld) == 0) {
   1173             continue;
   1174         }
   1175 
   1176         port_type = soc_mem_field32_get(unit, mem, entry, PORT_TYPEf);
   1177         if (port_type == 1) {                   /* Trunk */
   1178             tgid = soc_mem_field32_get(unit, mem, entry, tgid_fld);
   1179         }
   1180 
   1181         vp = soc_mem_field32_get(unit, mem, entry, SOURCE_VPf);
   1182         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
   1183             if (port_type == 1) {               /* Trunk */
   1184                 vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK;
   1185                 vxlan_info->match_key[vp].trunk_id = tgid; 
   1186                 vxlan_info->match_key[vp].modid = -1;
   1187             } else {
   1188                 vxlan_info->match_key[vp].index = i; /* SRC Trunk table index */
   1189                 vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_PORT;
   1190                 vxlan_info->match_key[vp].trunk_id = -1; 
   1191                 vxlan_info->match_key[vp].modid = -1;            
   1192             }
   1193         }
   1194     }    
   1195 
   1196     /* 
   1197      * For Trident2 device currently
   1198      *
   1199      * foreach valid Source VP used by VXLAN of VLAN_XLANTE table
   1200      *   build the inner/outer 802.1Q tag info, trunk/port info, flag of each SVP.
   1201      *   base on hash key type and trunk.
   1202      * 
   1203      * Sets the following fields:
   1204      *   
   1205      *   VXLAN_INFO[unit].match_key[SVP].flags
   1206      *   VXLAN_INFO[unit].match_key[SVP].match_vlan
   1207      *   VXLAN_INFO[unit].match_key[SVP].match_inner_vlan
   1208      *   VXLAN_INFO[unit].match_key[SVP].trunk_id
   1209      *   VXLAN_INFO[unit].match_key[SVP].port
   1210      *   VXLAN_INFO[unit].match_key[SVP].modid     
   1211      *   VXLAN_INFO[unit].match_key[SVP].index 
   1212  */
   1213 
   1214 #if defined(BCM_TRIDENT3_SUPPORT)
   1215     if (soc_feature(unit, soc_feature_base_valid)) {
   1216         mem = VLAN_XLATE_1_DOUBLEm;
   1217     } else
   1218 #endif
   1219     {
   1220         mem = VLAN_XLATEm;
   1221     }
   1222 
   1223     index_min = soc_mem_index_min(unit, mem);
   1224     index_max = soc_mem_index_max(unit, mem);
   1225 
   1226     buf_size = SOC_MEM_TABLE_BYTES(unit, mem);
   1227     xlate_buf = soc_cm_salloc(unit, buf_size, "VLAN_XLATE buffer");
   1228     if (NULL == xlate_buf) {
   1229         rv = BCM_E_MEMORY;
   1230         goto clean_up;
   1231     }
   1232     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, xlate_buf);
   1233     if (SOC_FAILURE(rv)) {
   1234         goto clean_up;
   1235     } 
   1236     
   1237     for (i = index_min; i <= index_max; i++) {
   1238         entry = soc_mem_table_idx_to_pointer(unit, mem, void *, xlate_buf, i);
   1239 
   1240 #if defined(BCM_TRIDENT3_SUPPORT)
   1241         if (soc_feature(unit, soc_feature_base_valid)) {
   1242             if (soc_mem_field32_get(unit, mem, entry, BASE_VALID_0f) != 3) {
   1243                 continue;
   1244             }
   1245             if (soc_mem_field32_get(unit, mem, entry, BASE_VALID_1f) != 7) {
   1246                 continue;
   1247             }
   1248         } else
   1249 #endif
   1250         {
   1251             if (soc_mem_field32_get(unit, mem, entry, VALIDf) == 0) {
   1252                 continue;
   1253             }
   1254         }
   1255 
   1256         if (soc_mem_field32_get(unit, mem, entry, XLATE__MPLS_ACTIONf) != 0x1) {
   1257             continue;
   1258         }
   1259         
   1260         vp = soc_mem_field32_get(unit, mem, entry, XLATE__SOURCE_VPf);
   1261 
   1262         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
   1263 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1264             _bcm_vp_info_t vp_info;
   1265             BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
   1266 
   1267             if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT) {
   1268                 vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_SHARED;
   1269             } else
   1270 #endif 
   1271             {
   1272                 key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf);
   1273                 trunk = soc_mem_field32_get(unit, mem, entry, XLATE__Tf);
   1274                 tgid = soc_mem_field32_get(unit, mem, entry, XLATE__TGIDf);
   1275                 mod_id = soc_mem_field32_get(unit, mem, entry, XLATE__MODULE_IDf);
   1276                 port_num = soc_mem_field32_get(unit, mem, entry, XLATE__PORT_NUMf);
   1277             
   1278                 if (TR_VLXLT_HASH_KEY_TYPE_OVID == key_type) {
   1279                     vxlan_info->match_key[vp].flags =
   1280                                             _BCM_VXLAN_PORT_MATCH_TYPE_VLAN;
   1281                     vxlan_info->match_key[vp].match_vlan =
   1282                         soc_mem_field32_get(unit, mem, entry, XLATE__OVIDf);
   1283                 } else if (TR_VLXLT_HASH_KEY_TYPE_IVID == key_type) {
   1284                     vxlan_info->match_key[vp].flags =
   1285                                           _BCM_VXLAN_PORT_MATCH_TYPE_INNER_VLAN;
   1286                     vxlan_info->match_key[vp].match_inner_vlan =
   1287                          soc_mem_field32_get(unit, mem, entry, XLATE__IVIDf);
   1288                 } else if (TR_VLXLT_HASH_KEY_TYPE_IVID_OVID == key_type) {
   1289                     vxlan_info->match_key[vp].flags =
   1290                                         _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_STACKED;
   1291                     vxlan_info->match_key[vp].match_vlan =
   1292                         soc_mem_field32_get(unit, mem, entry, XLATE__OVIDf);
   1293                     vxlan_info->match_key[vp].match_inner_vlan =
   1294                          soc_mem_field32_get(unit, mem, entry, XLATE__IVIDf);
   1295                 } else if (TR_VLXLT_HASH_KEY_TYPE_PRI_CFI == key_type) {
   1296                     vxlan_info->match_key[vp].flags =
   1297                                             _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_PRI;
   1298                     vxlan_info->match_key[vp].match_vlan = 
   1299                         soc_mem_field32_get(unit, mem, entry, OTAGf);
   1300                 }
   1301             
   1302                 if (trunk) {
   1303                     vxlan_info->match_key[vp].trunk_id = tgid;
   1304                     vxlan_info->match_key[vp].modid = -1;
   1305                     vxlan_info->match_key[vp].index = 0;
   1306                 } else {
   1307                     vxlan_info->match_key[vp].port = port_num;
   1308                     vxlan_info->match_key[vp].modid = mod_id;
   1309                     vxlan_info->match_key[vp].trunk_id = -1;
   1310                     vxlan_info->match_key[vp].index = 0;
   1311                 }
   1312             }
   1313             bcm_td2_vxlan_port_match_count_adjust(unit, vp, 1);            
   1314         }
   1315     }
   1316 
   1317     /* Recovery based on entry in MPLS tbl */
   1318 
   1319     mem = MPLS_ENTRYm;
   1320 #if defined(BCM_TRIDENT3_SUPPORT)
   1321     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   1322         mem = MPLS_ENTRY_SINGLEm;
   1323         d = 1;
   1324     }
   1325 #endif
   1326     index_min = soc_mem_index_min(unit, mem);
   1327     index_max = soc_mem_index_max(unit, mem);
   1328 
   1329     /* 
   1330      * foreach valid entry with key_type TUNNEL/VFI of MPLS_ENTRY table
   1331      *   recover the tunnel sip info and flag of each SVP used by VXLAN.
   1332      * 
   1333      * Sets the following fields:
   1334      *   
   1335      *   VXLAN_INFO[unit].match_key[SVP].flags
   1336      *   VXLAN_INFO[unit].match_key[SVP].match_tunnel_index
   1337  */
   1338 
   1339     buf_size = SOC_MEM_TABLE_BYTES(unit, mem);
   1340     mpls_buf = soc_cm_salloc(unit, buf_size, "MPLS_ENTRY buffer");
   1341     if (NULL == mpls_buf) {
   1342         rv = BCM_E_MEMORY;
   1343         goto clean_up;
   1344     }
   1345     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max, mpls_buf);
   1346     if (SOC_FAILURE(rv)) {
   1347         goto clean_up;
   1348     } 
   1349     
   1350     for (i = index_min; i <= index_max; i++) {
   1351         entry = soc_mem_table_idx_to_pointer(unit, mem, void *, mpls_buf, i);
   1352 #if defined(BCM_TRIDENT3_SUPPORT)
   1353         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   1354             if (soc_mem_field32_get(unit, mem, entry, BASE_VALIDf) != 1) {
   1355                 continue;
   1356             }
   1357         } else
   1358 #endif
   1359         {
   1360             if (soc_mem_field32_get(unit, mem, entry, VALIDf) == 0) {
   1361                 continue;
   1362             }
   1363         }
   1364 
   1365         /* Looking for entries of type vxlan only */
   1366         key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf);
   1367         if ((key_type != _BCM_VXLAN_KEY_TYPE_TUNNEL) &&
   1368             (key_type != _BCM_VXLAN_KEY_TYPE_VNID_VFI) && 
   1369             (key_type != _BCM_VXLAN_KEY_TYPE_TUNNEL_VNID_VFI)) {
   1370             continue;
   1371         }    
   1372 
   1373         vp = soc_mem_field32_get(unit, mem, entry, BCM_VXLAN_SIP_FIELD(d, SVPf));
   1374         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
   1375             vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_VNID;
   1376         }
   1377         
   1378     }
   1379 
   1380     /* Tunnel initiator hash and ref-count recovery */
   1381     rv = _bcm_td2_vxlan_tunnel_initiator_reinit(unit);
   1382     if (BCM_FAILURE(rv)) {
   1383         goto clean_up;
   1384     } 
   1385 
   1386     /* Recover L2 scache */
   1387     rv = _bcm_td2_vxlan_wb_recover(unit);
   1388     if (BCM_FAILURE(rv)) {
   1389         goto clean_up;
   1390     }
   1391 
   1392     rv = _bcm_td2_vxlan_vp_based_vnid_reinit(unit);
   1393 
   1394 clean_up:
   1395     if (NULL != trunk_buf) {
   1396         soc_cm_sfree(unit, trunk_buf);
   1397     }
   1398     if (NULL != xlate_buf) {
   1399         soc_cm_sfree(unit, xlate_buf);
   1400     }
   1401     if (NULL != mpls_buf) {
   1402         soc_cm_sfree(unit, mpls_buf);
   1403     }
   1404 
   1405     return rv;
   1406 }
   1407 #endif /* BCM_WARM_BOOT_SUPPORT */
   1408 
   1409 /*
   1410  * Function:
   1411  *      bcm_td2_vxlan_init
   1412  * Purpose:
   1413  *      Initialize the VXLAN software module
   1414  * Parameters:
   1415  *      unit     - Device Number
   1416  * Returns:
   1417  *      BCM_E_XXX
   1418  */
   1419 
   1420 
   1421 int
   1422 bcm_td2_vxlan_init(int unit)
   1423 {
   1424     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   1425     int i, num_tnl=0, num_vp=0;
   1426     int rv = BCM_E_NONE;
   1427     int num_vfi = 0;
   1428 
   1429     if (!L3_INFO(unit)->l3_initialized) {
   1430         LOG_ERROR(BSL_LS_BCM_VXLAN,
   1431                   (BSL_META_U(unit,
   1432                               "L3 module must be initialized prior to VXLAN Init\n")));
   1433         return BCM_E_CONFIG;
   1434     }
   1435 
   1436     /* Allocate BK Info */
   1437     BCM_IF_ERROR_RETURN(bcm_td2_vxlan_allocate_bk(unit));
   1438     vxlan_info = VXLAN_INFO(unit);
   1439 
   1440     /*
   1441      * allocate resources
   1442      */
   1443     if (vxlan_info->initialized) {
   1444          BCM_IF_ERROR_RETURN(bcm_td2_vxlan_cleanup(unit));
   1445          BCM_IF_ERROR_RETURN(bcm_td2_vxlan_allocate_bk(unit));
   1446          vxlan_info = VXLAN_INFO(unit);
   1447     }
   1448 
   1449     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   1450     vxlan_info->match_key =
   1451         sal_alloc(sizeof(_bcm_vxlan_match_port_info_t) * num_vp, "match_key");
   1452     if (vxlan_info->match_key == NULL) {
   1453         _bcm_td2_vxlan_free_resource(unit);
   1454         return BCM_E_MEMORY;
   1455     }
   1456     sal_memset(vxlan_info->match_key, 0, 
   1457             sizeof(_bcm_vxlan_match_port_info_t) * num_vp);
   1458     /* Stay same after recover */
   1459     for (i = 0; i < num_vp; i++) {
   1460         bcm_td2_vxlan_match_clear(unit, i);
   1461     }
   1462 
   1463     /* Create EGR_IP_TUNNEL usage bitmap */
   1464     num_tnl = soc_mem_index_count(unit, EGR_IP_TUNNELm);
   1465 
   1466     vxlan_info->vxlan_ip_tnl_bitmap =
   1467         sal_alloc(SHR_BITALLOCSIZE(num_tnl), "vxlan_ip_tnl_bitmap");
   1468     if (vxlan_info->vxlan_ip_tnl_bitmap == NULL) {
   1469         _bcm_td2_vxlan_free_resource(unit);
   1470         return BCM_E_MEMORY;
   1471     }
   1472     sal_memset(vxlan_info->vxlan_ip_tnl_bitmap, 0, SHR_BITALLOCSIZE(num_tnl));
   1473 
   1474     /* Create VXLAN protection mutex. */
   1475     vxlan_info->vxlan_mutex = sal_mutex_create("vxlan_mutex");
   1476     if (!vxlan_info->vxlan_mutex) {
   1477          _bcm_td2_vxlan_free_resource(unit);
   1478          return BCM_E_MEMORY;
   1479     }
   1480 
   1481     if (NULL == vxlan_info->vxlan_tunnel_term) {
   1482         vxlan_info->vxlan_tunnel_term =
   1483             sal_alloc(sizeof(_bcm_vxlan_tunnel_endpoint_t) * num_vp, "vxlan tunnel term store");
   1484         if (vxlan_info->vxlan_tunnel_term == NULL) {
   1485             _bcm_td2_vxlan_free_resource(unit);
   1486             return BCM_E_MEMORY;
   1487         }
   1488         sal_memset(vxlan_info->vxlan_tunnel_term, 0, 
   1489                 sizeof(_bcm_vxlan_tunnel_endpoint_t) * num_vp);
   1490     }
   1491 
   1492     if (NULL == vxlan_info->vxlan_tunnel_init) {
   1493         vxlan_info->vxlan_tunnel_init =
   1494             sal_alloc(sizeof(_bcm_vxlan_tunnel_endpoint_t) * num_vp, "vxlan tunnel init store");
   1495         if (vxlan_info->vxlan_tunnel_init == NULL) {
   1496             _bcm_td2_vxlan_free_resource(unit);
   1497             return BCM_E_MEMORY;
   1498         }
   1499         sal_memset(vxlan_info->vxlan_tunnel_init, 0, 
   1500                 sizeof(_bcm_vxlan_tunnel_endpoint_t) * num_vp);
   1501     }
   1502 
   1503     num_vfi = soc_mem_index_count(unit, VFIm);
   1504     if (NULL == vxlan_info->vxlan_vpn_vlan) {
   1505         vxlan_info->vxlan_vpn_vlan =
   1506             sal_alloc(sizeof(bcm_vlan_t) * num_vfi, "vxlan vpn vlan store");
   1507         if (vxlan_info->vxlan_vpn_vlan == NULL) {
   1508             _bcm_td2_vxlan_free_resource(unit);
   1509             return BCM_E_MEMORY;
   1510         }
   1511         sal_memset(vxlan_info->vxlan_vpn_vlan, 0, sizeof(bcm_vlan_t) * num_vfi);
   1512     }
   1513 
   1514     if (NULL == vxlan_info->vxlan_vpn_info) {
   1515         vxlan_info->vxlan_vpn_info =
   1516             sal_alloc(sizeof(_bcm_vxlan_vpn_info_t) * num_vfi, "vxlan vpn info store");
   1517         if (vxlan_info->vxlan_vpn_info == NULL) {
   1518             _bcm_td2_vxlan_free_resource(unit);
   1519             return BCM_E_MEMORY;
   1520         }
   1521         sal_memset(vxlan_info->vxlan_vpn_info, 0, sizeof(_bcm_vxlan_vpn_info_t) * num_vfi);
   1522     }
   1523 
   1524     if (vxlan_info->vfi_vnid_map_count == NULL) {
   1525         vxlan_info->vfi_vnid_map_count = sal_alloc(sizeof(uint32) * num_vp, "vxlan vfi vnid map count");
   1526         if (vxlan_info->vfi_vnid_map_count == NULL) {
   1527             _bcm_td2_vxlan_free_resource(unit);
   1528             return BCM_E_MEMORY;
   1529         }
   1530         sal_memset(vxlan_info->vfi_vnid_map_count, 0, sizeof(uint32) * num_vp);
   1531     }
   1532 
   1533 #ifdef BCM_WARM_BOOT_SUPPORT
   1534     if (SOC_WARM_BOOT(unit)) {
   1535         rv = _bcm_td2_vxlan_reinit(unit);
   1536         if (BCM_FAILURE(rv)) {
   1537             _bcm_td2_vxlan_free_resource(unit);
   1538         }
   1539     } else {
   1540         rv = _bcm_td2_vxlan_wb_alloc(unit);    
   1541     }
   1542 #endif /* BCM_WARM_BOOT_SUPPORT */
   1543     /* Mark the state as initialized */
   1544     vxlan_info->initialized = TRUE;
   1545 
   1546     return rv;
   1547 }
   1548 
   1549  /*
   1550   * Function:
   1551   *      _bcm_td2_vxlan_bud_loopback_enable
   1552   * Purpose:
   1553   *      Enable loopback for VXLAN BUD node multicast
   1554   * Parameters:
   1555   *   IN : unit
   1556   * Returns:
   1557   *      BCM_E_XXX
   1558   */
   1559  
   1560 STATIC int
   1561 _bcm_td2_vxlan_bud_loopback_enable(int unit)
   1562 {
   1563     int field_num = 0;
   1564 
   1565     soc_field_t lport_fields[] = {
   1566         VXLAN_TERMINATION_ALLOWEDf,
   1567         V4IPMC_ENABLEf,
   1568         VXLAN_VN_ID_LOOKUP_KEY_TYPEf,
   1569         PORT_TYPEf,
   1570         VXLAN_DEFAULT_SVP_ENABLEf
   1571     };
   1572     uint32 lport_values[] = {
   1573         0x1,  /* VXLAN_TERMINATION_ALLOWEDf */
   1574         0x1,  /* V4IPMC_ENABLEf */
   1575         0x0,  /* VXLAN_VN_ID_LOOKUP_KEY_TYPEf */
   1576         0x0,  /* PORT_TYPEf */
   1577         0x1,  /* VXLAN_DEFAULT_SVP_ENABLEf */
   1578     };
   1579 
   1580     if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, VXLAN_DEFAULT_SVP_ENABLEf)) {
   1581         field_num = 5;
   1582     } else {
   1583         field_num = 3; /* TD3TBD */
   1584     }
   1585 
   1586     /* Update LPORT Profile Table */
   1587     return _bcm_lport_profile_fields32_modify(unit, LPORT_PROFILE_LPORT_TAB,
   1588                                         field_num, lport_fields, lport_values);
   1589 }
   1590 
   1591  /*
   1592   * Function:
   1593   *      _bcm_td2_vxlan_bud_loopback_disable
   1594   * Purpose:
   1595   *      Disable loopback for VXLAN BUD node multicast
   1596   * Parameters:
   1597   *   IN : unit
   1598   * Returns:
   1599   *      BCM_E_XXX
   1600   */
   1601  
   1602 STATIC int
   1603 _bcm_td2_vxlan_bud_loopback_disable(int unit)
   1604 {
   1605      int field_num = 0;
   1606 
   1607      soc_field_t lport_fields[] = {
   1608          VXLAN_TERMINATION_ALLOWEDf,
   1609          VXLAN_VN_ID_LOOKUP_KEY_TYPEf,
   1610          V4IPMC_ENABLEf,
   1611          PORT_TYPEf,
   1612          VXLAN_DEFAULT_SVP_ENABLEf
   1613      };
   1614      uint32 lport_values[] = {
   1615          0x0,  /* VXLAN_TERMINATION_ALLOWEDf */
   1616          0x0,  /* VXLAN_VN_ID_LOOKUP_KEY_TYPEf */
   1617          0x0,  /* V4IPMC_ENABLEf */
   1618          0x0,  /* PORT_TYPEf */
   1619          0x0   /* VXLAN_DEFAULT_SVP_ENABLEf */
   1620      };
   1621 
   1622      if (SOC_MEM_FIELD_VALID(unit, LPORT_TABm, PORT_TYPEf)) {
   1623          field_num = 5;
   1624      } else if (SOC_IS_TRIDENT3X(unit)) {
   1625          field_num = 2;
   1626      } else {
   1627          field_num = 3;
   1628      }
   1629 
   1630      /* Update LPORT Profile Table */
   1631      return _bcm_lport_profile_fields32_modify(unit, LPORT_PROFILE_LPORT_TAB,
   1632                                          field_num, lport_fields, lport_values);
   1633 }
   1634 
   1635  /* Function:
   1636  *      _bcm_td2_vxlan_vpn_is_valid
   1637  * Purpose:
   1638  *      Find if given VXLAN VPN is Valid 
   1639  * Parameters:
   1640  *      unit     - Device Number
   1641  *      l2vpn   - VXLAN VPN
   1642  * Returns:
   1643  *      BCM_E_XXXX
   1644  */
   1645 int
   1646 _bcm_td2_vxlan_vpn_is_valid( int unit, bcm_vpn_t l2vpn)
   1647 {
   1648     bcm_vpn_t vxlan_vpn_min=0;
   1649     int vfi_index=-1, num_vfi=0;
   1650 
   1651     num_vfi = soc_mem_index_count(unit, VFIm);
   1652 
   1653     /* Check for Valid vpn */
   1654     _BCM_VXLAN_VPN_SET(vxlan_vpn_min, _BCM_VPN_TYPE_VFI, 0);
   1655     if ( l2vpn < vxlan_vpn_min || l2vpn > (vxlan_vpn_min+num_vfi-1) ) {
   1656         return BCM_E_PARAM;
   1657     }
   1658 
   1659     _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI,  l2vpn);
   1660 
   1661     if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVxlan)) {
   1662         return BCM_E_NOT_FOUND;
   1663     }
   1664     return BCM_E_NONE;
   1665 }
   1666 
   1667  /* Function:
   1668  *      _bcm_td2_vxlan_vpn_is_eline
   1669  * Purpose:
   1670  *      Find if given VXLAN VPN is ELINE
   1671  * Parameters:
   1672  *      unit     - Device Number
   1673  *      l2vpn   - VXLAN VPN
   1674  *      isEline  - Flag 
   1675  * Returns:
   1676  *      BCM_E_XXXX
   1677  * Assumes:
   1678  *      l2vpn is valid
   1679  */
   1680 
   1681 int
   1682 _bcm_td2_vxlan_vpn_is_eline( int unit, bcm_vpn_t l2vpn, uint8 *isEline)
   1683 {
   1684     int vfi_index=-1;
   1685     vfi_entry_t vfi_entry;
   1686 
   1687     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_valid(unit, l2vpn));
   1688 
   1689     _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI,  l2vpn);
   1690     BCM_IF_ERROR_RETURN(READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
   1691 
   1692     /* Set the returned VPN id */
   1693     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
   1694         *isEline = 1;  /* ELINE */
   1695     } else {
   1696         *isEline = 0;  /* ELAN */
   1697     }
   1698     return BCM_E_NONE;
   1699 }
   1700 
   1701 /* Function:
   1702  *      _bcm_td2_vxlan_vpn_is_based_vnid
   1703  * Purpose:
   1704  *      Find if given VXLAN VPN is vnid basedE
   1705  * Parameters:
   1706  *      unit     - Device Number
   1707  *      l2vpn   - VXLAN VPN
   1708  *      vxlan_vpn_type  - type 
   1709  * Returns:
   1710  *      BCM_E_XXXX
   1711  * Assumes:
   1712  *      l2vpn is valid
   1713  */ 
   1714 int
   1715 _bcm_td2_vxlan_vpn_is_tunnel_based_vnid( int unit, bcm_vpn_t l2vpn, uint8 *vxlan_vpn_type)
   1716 {
   1717     int vfi = 0;
   1718     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   1719     if (l2vpn == BCM_VXLAN_VPN_INVALID) {
   1720         *vxlan_vpn_type = 0;
   1721         return BCM_E_NONE;
   1722     }
   1723     vxlan_info = VXLAN_INFO(unit);
   1724     _BCM_VXLAN_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, l2vpn);
   1725     if (vfi > soc_mem_index_count(unit, VFIm)) {
   1726         return BCM_E_PARAM;
   1727     }
   1728     if (vxlan_info->vxlan_vpn_info[vfi].vxlan_vpn_type) {
   1729         *vxlan_vpn_type = _BCM_VXLAN_VPN_TYPE_TUNNEL_BASED_VNID;
   1730     } else {
   1731         *vxlan_vpn_type = 0;
   1732     }
   1733     return BCM_E_NONE;
   1734 }
   1735 
   1736 
   1737 
   1738 
   1739  /* Function:
   1740  *      _bcm_td2_vxlan_vp_is_eline
   1741  * Purpose:
   1742  *      Find if given VXLAN VP is ELINE
   1743  * Parameters:
   1744  *      unit     - Device Number
   1745  *      vp   - VXLAN VP
   1746  *      isEline  - Flag 
   1747  * Returns:
   1748  *      BCM_E_XXXX
   1749  * Assumes:
   1750  *      l2vpn is valid
   1751  */
   1752 
   1753 int
   1754 _bcm_td2_vxlan_vp_is_eline( int unit, int vp, uint8 *isEline)
   1755 {
   1756     source_vp_entry_t svp;
   1757     vfi_entry_t vfi_entry;
   1758     int rv = BCM_E_PARAM;
   1759     int vfi_index;
   1760 
   1761     if (vp == -1) {
   1762         return BCM_E_PARAM;
   1763     }
   1764 
   1765     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
   1766         return BCM_E_NOT_FOUND;
   1767     }
   1768 
   1769     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
   1770     if (rv < 0) {
   1771         return rv;
   1772     }
   1773 
   1774     vfi_index = soc_SOURCE_VPm_field32_get(unit, &svp, VFIf);
   1775     BCM_IF_ERROR_RETURN
   1776         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
   1777 
   1778     /* Set the returned VPN id */
   1779     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
   1780        *isEline = 0x1;
   1781     }  else {
   1782        *isEline = 0x0;
   1783    }
   1784    return BCM_E_NONE;
   1785 }
   1786 
   1787 /*
   1788  * Function:
   1789  *      _bcm_td2_vxlan_nexthop_glp_get
   1790  * Purpose:
   1791  *      Get the modid, port, trunk values for a VXLAN nexthop
   1792  * Returns:
   1793  *      BCM_E_XXX
   1794  */
   1795 STATIC int
   1796 _bcm_td2_vxlan_nexthop_glp_get(int unit, int nh_idx,
   1797         bcm_module_t *modid, bcm_port_t *port, bcm_trunk_t *trunk_id)
   1798 
   1799 {
   1800     ing_l3_next_hop_entry_t ing_nh;
   1801 
   1802     BCM_IF_ERROR_RETURN (soc_mem_read(unit,
   1803         ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, nh_idx, &ing_nh));
   1804 
   1805 #if defined(BCM_TRIDENT3_SUPPORT)
   1806     if (soc_feature(unit, soc_feature_generic_dest)) {
   1807         uint32 dt, dv;
   1808 
   1809         dv = soc_mem_field32_dest_get(unit,
   1810                 ING_L3_NEXT_HOPm, &ing_nh, DESTINATIONf, &dt);
   1811         if (dt == SOC_MEM_FIF_DEST_LAG) {
   1812             *trunk_id = dv & SOC_MEM_FIF_DGPP_TGID_MASK;
   1813         } else if (dt == SOC_MEM_FIF_DEST_DGPP) {
   1814             *port = (dv & SOC_MEM_FIF_DGPP_PORT_MASK);
   1815             *modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
   1816                         SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
   1817         } else {
   1818             return BCM_E_INTERNAL;
   1819         }
   1820     } else
   1821 #endif
   1822     {
   1823         if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
   1824             *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf);
   1825         } else {
   1826             /* Only add this to replication set if destination is local */
   1827             *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
   1828             *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf);
   1829         }
   1830     }
   1831 
   1832     return BCM_E_NONE;
   1833 }
   1834 
   1835 /*
   1836  * Function:
   1837  *      _bcm_td2_vxlan_port_resolve
   1838  * Purpose:
   1839  *      Get the modid, port, trunk values for a VXLAN port
   1840  * Returns:
   1841  *      BCM_E_XXX
   1842  */
   1843 int
   1844 _bcm_td2_vxlan_port_resolve(int unit, bcm_gport_t vxlan_port_id, 
   1845                           bcm_if_t encap_id, bcm_module_t *modid, bcm_port_t *port,
   1846                           bcm_trunk_t *trunk_id, int *id)
   1847 
   1848 {
   1849     int rv = BCM_E_NONE;
   1850     egr_l3_next_hop_entry_t egr_nh;
   1851     ing_dvp_table_entry_t dvp;
   1852     int ecmp=0, nh_index=-1, nh_ecmp_index=-1, vp=-1;
   1853     uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry. */
   1854     int  idx, max_ent_count, base_idx;
   1855 
   1856     rv = _bcm_vxlan_check_init(unit);
   1857     if (rv < 0) {
   1858         return rv;
   1859     }
   1860 
   1861     vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port_id);
   1862     if (vp == -1) {
   1863        return BCM_E_PARAM;
   1864     }
   1865 
   1866     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
   1867         return BCM_E_NOT_FOUND;
   1868     }
   1869     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   1870     ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf);
   1871     if (!ecmp) {
   1872         nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
   1873 
   1874         BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_nexthop_glp_get(unit,
   1875                                 nh_index, modid, port, trunk_id));
   1876     } else {
   1877          /* Select the desired nhop from ECMP group - pointed by encap_id */
   1878          nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf);
   1879          BCM_IF_ERROR_RETURN(
   1880               soc_mem_read(unit, L3_ECMP_COUNTm, MEM_BLOCK_ANY, 
   1881                         nh_ecmp_index, hw_buf));
   1882 
   1883          if (soc_feature(unit, soc_feature_l3_ecmp_1k_groups)) {
   1884               max_ent_count = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 
   1885                                                  hw_buf, COUNTf);
   1886               base_idx = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 
   1887                                                  hw_buf, BASE_PTRf);
   1888          }  else {
   1889               max_ent_count = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 
   1890                                                  hw_buf, COUNT_0f);
   1891               base_idx = soc_mem_field32_get(unit, L3_ECMP_COUNTm, 
   1892                                                  hw_buf, BASE_PTR_0f);
   1893          }
   1894         max_ent_count++; /* Count is zero based. */ 
   1895 
   1896         if(encap_id == -1) {
   1897             BCM_IF_ERROR_RETURN(soc_mem_read(unit,
   1898                   L3_ECMPm, MEM_BLOCK_ANY, base_idx, hw_buf));
   1899             nh_index = soc_mem_field32_get(unit,
   1900                           L3_ECMPm, hw_buf, NEXT_HOP_INDEXf);
   1901 
   1902             BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_nexthop_glp_get(unit,
   1903                                     nh_index, modid, port, trunk_id));
   1904         } else {
   1905             for (idx = 0; idx < max_ent_count; idx++) {
   1906                 BCM_IF_ERROR_RETURN(soc_mem_read(unit,
   1907                     L3_ECMPm, MEM_BLOCK_ANY, (base_idx+idx), hw_buf));
   1908                 nh_index = soc_mem_field32_get(unit,
   1909                     L3_ECMPm, hw_buf, NEXT_HOP_INDEXf);
   1910                 BCM_IF_ERROR_RETURN (soc_mem_read(unit,
   1911                     EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, nh_index, &egr_nh));
   1912                 if (encap_id == soc_mem_field32_get(unit,
   1913                         EGR_L3_NEXT_HOPm, &egr_nh, INTF_NUMf)) {
   1914                     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_nexthop_glp_get(unit,
   1915                                             nh_index, modid, port, trunk_id));
   1916                     break;
   1917                 }
   1918             }
   1919         }
   1920     }
   1921     *id = vp;
   1922     return rv;
   1923 }
   1924 
   1925 /*
   1926  * Function:
   1927  *      _bcm_td2_vxlan_port_nh_cnt_dec
   1928  * Purpose:
   1929  *      Decrease vxlan port's nexthop count.
   1930  * Parameters:
   1931  *      unit  - (IN) SOC unit number.
   1932  *      vp    - (IN) Virtual port number.
   1933  * Returns:
   1934  *      BCM_E_XXX
   1935  */     
   1936 
   1937 STATIC int
   1938 _bcm_td2_vxlan_port_nh_cnt_dec(int unit, int vp)
   1939 {
   1940     int nh_ecmp_index = -1;
   1941     ing_dvp_table_entry_t dvp;
   1942     uint32  flags = 0;
   1943     int  ref_count = 0;
   1944     int ecmp = 0;
   1945 
   1946     BCM_IF_ERROR_RETURN(
   1947         READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   1948 
   1949     ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf);
   1950     if (ecmp) {
   1951         nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf);
   1952         flags = BCM_L3_MULTIPATH;
   1953         /* Decrement reference count */
   1954         BCM_IF_ERROR_RETURN(
   1955              bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index));
   1956     } else {
   1957         nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 
   1958                                               NEXT_HOP_INDEXf);
   1959         if(nh_ecmp_index != 0) {
   1960              /* Decrement reference count */
   1961              BCM_IF_ERROR_RETURN(
   1962                   bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index));
   1963         }
   1964     }
   1965     
   1966     return BCM_E_NONE;
   1967 }
   1968 
   1969 /*
   1970  * Function:
   1971  *      _bcm_td2_vxlan_port_cnt_update
   1972  * Purpose:
   1973  *      Update port's VP count.
   1974  * Parameters:
   1975  *      unit  - (IN) SOC unit number. 
   1976  *      gport - (IN) GPORT ID.
   1977  *      vp    - (IN) Virtual port number.
   1978  *      incr  - (IN) If TRUE, increment VP count, else decrease VP count.
   1979  * Returns:
   1980  *      BCM_X_XXX
   1981  */
   1982 
   1983 STATIC int
   1984 _bcm_td2_vxlan_port_cnt_update(int unit, bcm_gport_t gport,
   1985         int vp, int incr_decr_flag)
   1986 {
   1987     int mod_out=-1, port_out=-1, tgid_out=-1, vp_out=-1;
   1988     bcm_port_t local_member_array[SOC_MAX_NUM_PORTS];
   1989     int local_member_count=0;
   1990     int idx=-1;
   1991     int mod_local=-1;
   1992     _bcm_port_info_t *port_info;
   1993     uint32 port_flags;
   1994 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   1995     bcm_gport_t tmp_gport;
   1996 #endif
   1997 
   1998     BCM_IF_ERROR_RETURN(
   1999        _bcm_td2_vxlan_port_resolve(unit, gport, -1, &mod_out,
   2000                     &port_out, &tgid_out, &vp_out));
   2001 
   2002     if (vp_out == -1) {
   2003        return BCM_E_PARAM;
   2004     }
   2005 
   2006     /* Update the physical port's SW state. If associated with a trunk,
   2007      * update each local physical port's SW state.
   2008      */
   2009 
   2010     if (BCM_TRUNK_INVALID != tgid_out) {
   2011 
   2012         BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid_out, 
   2013                     SOC_MAX_NUM_PORTS, local_member_array, &local_member_count));
   2014 
   2015         for (idx = 0; idx < local_member_count; idx++) {
   2016             _bcm_port_info_access(unit, local_member_array[idx], &port_info);
   2017             if (incr_decr_flag) {
   2018                 port_info->vp_count++;
   2019             } else {
   2020                 port_info->vp_count--;
   2021             }
   2022             BCM_IF_ERROR_RETURN(
   2023                 bcm_esw_port_vlan_member_get(
   2024                     unit, local_member_array[idx], &port_flags));
   2025             BCM_IF_ERROR_RETURN(
   2026                 bcm_esw_port_vlan_member_set(
   2027                     unit, local_member_array[idx], port_flags));
   2028         }
   2029     } else {
   2030 #if defined(BCM_HGPROXY_COE_SUPPORT)
   2031         if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   2032             (_bcm_xgs5_subport_coe_mod_port_local(unit, mod_out, port_out))) {
   2033             BCM_IF_ERROR_RETURN(
   2034                 _bcmi_coe_subport_mod_port_physical_port_get(
   2035                     unit, mod_out, port_out, &port_out));
   2036             mod_local = 1;
   2037         } else
   2038 #endif
   2039         {
   2040             BCM_IF_ERROR_RETURN(
   2041                 _bcm_esw_modid_is_local(unit, mod_out, &mod_local));
   2042             if (mod_local && soc_feature(unit, soc_feature_sysport_remap)) {
   2043                 BCM_XLATE_SYSPORT_S2P(unit, &port_out);
   2044             }
   2045 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2046             if (!mod_local && soc_feature(unit, soc_feature_multi_next_hops_on_port) &&
   2047                 _bcm_esw_is_multi_nexthop_mod_port(unit, mod_out, port_out)) {
   2048                 BCM_GPORT_MODPORT_SET(tmp_gport, mod_out, port_out);
   2049                 BCM_IF_ERROR_RETURN(
   2050                     _bcm_esw_modport_local_get(unit, tmp_gport, &port_out));
   2051                 mod_local = 1;
   2052             }
   2053 #endif
   2054         }
   2055         if (mod_local) {
   2056             if (soc_feature(unit, soc_feature_sysport_remap)) { 
   2057                 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 
   2058             }
   2059             _bcm_port_info_access(unit, port_out, &port_info);
   2060             if (incr_decr_flag) {
   2061                 port_info->vp_count++;
   2062             } else {
   2063                 port_info->vp_count--;
   2064             }
   2065             BCM_IF_ERROR_RETURN(
   2066                 bcm_esw_port_vlan_member_get(
   2067                     unit, port_out, &port_flags));
   2068             BCM_IF_ERROR_RETURN(
   2069                 bcm_esw_port_vlan_member_set(
   2070                     unit, port_out, port_flags));
   2071         }
   2072     }
   2073 
   2074     return BCM_E_NONE;
   2075 }
   2076 
   2077 #if defined(BCM_TRIDENT3_SUPPORT)
   2078 /*
   2079  * Function:
   2080  *      _bcm_td3_vxlan_vxlate_entry_assemble
   2081  * Purpose:
   2082  *      Create a VPN instance
   2083  * Parameters:
   2084  *      unit  - (IN)  Device Number
   2085  *      info  - (IN)  configuration entry info
   2086  *      ment  -  (IN/OUT) point of mem entry
   2087  * Returns:
   2088  *      BCM_E_XXX
   2089  */
   2090  STATIC void
   2091 _bcm_td3_vxlan_vxlate_entry_assemble(int unit, _bcm_td3_vxlan_vxlate_entry_t info, uint32* ment)
   2092 {
   2093     soc_mem_t mmem = VLAN_XLATE_1_DOUBLEm;
   2094     uint32 profile_idx = 0;
   2095     
   2096     soc_mem_field32_set(unit, mmem, ment, BASE_VALID_0f, 3);
   2097     soc_mem_field32_set(unit, mmem, ment, BASE_VALID_1f, 7);
   2098     soc_mem_field32_set(unit, mmem, ment, DATA_TYPEf, info.dtype);
   2099     soc_mem_field32_set(unit, mmem, ment, KEY_TYPEf, info.ktype);
   2100     soc_mem_field32_set(unit, mmem, ment, VXLAN_FLEX__VFI_ACTION_SETf, info.vfi);
   2101     /* action profile */
   2102     if (info.vlan != 0) {
   2103         soc_mem_field32_set(unit, mmem, ment, VXLAN_FLEX__OVIDf, info.vlan);
   2104         _bcm_td3_def_vlan_profile_get(unit, &profile_idx);
   2105         soc_mem_field32_set(unit,mmem, ment,
   2106                     VXLAN_FLEX__ING_TAG_ACTION_PROFILE_IDXf,profile_idx);
   2107     }
   2108 
   2109 }
   2110 #endif
   2111 
   2112 /*
   2113  * Function:
   2114  *      bcm_td2_vxlan_vpn_create
   2115  * Purpose:
   2116  *      Create a VPN instance
   2117  * Parameters:
   2118  *      unit  - (IN)  Device Number
   2119  *      info  - (IN/OUT) VPN configuration info
   2120  * Returns:
   2121  *      BCM_E_XXX
   2122  */
   2123 
   2124 int 
   2125 bcm_td2_vxlan_vpn_create(int unit, bcm_vxlan_vpn_config_t *info)
   2126 {
   2127     int rv = BCM_E_PARAM;
   2128     vfi_entry_t vfi_entry;
   2129     int vfi_index=-1;
   2130     int bc_group=0, umc_group=0, uuc_group=0;
   2131     int bc_group_type=0, umc_group_type=0, uuc_group_type=0;
   2132     uint32 vnid = 0;
   2133     uint32 ment[SOC_MAX_MEM_WORDS];
   2134     soc_mem_t mmem = MPLS_ENTRYm;
   2135     soc_mem_t vxlate_mem;
   2136     uint32 vxlate_entry[SOC_MAX_MEM_WORDS];
   2137     int tpid_index = -1;
   2138     int action_present=0, action_not_present=0;
   2139     uint8 vpn_alloc_flag=0;
   2140     uint8 vnid_alloc_flag = 0;
   2141     int proto_pkt_idx = 0;
   2142     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   2143     int d = 0; /*vxlan decoupled mode*/
   2144 
   2145     sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   2146     sal_memset(vxlate_entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   2147 
   2148 #if defined(BCM_TRIDENT3_SUPPORT)
   2149     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2150         vxlate_mem = EGR_VLAN_XLATE_1_SINGLEm;
   2151         d = 1;
   2152     } else
   2153 #endif
   2154     {
   2155         vxlate_mem = EGR_VLAN_XLATEm;
   2156     }
   2157 
   2158     vxlan_info = VXLAN_INFO(unit);
   2159     /*Allocate VFI*/
   2160     if (info->flags & BCM_VXLAN_VPN_REPLACE) {
   2161         BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_valid(unit, info->vpn));
   2162         _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, info->vpn);
   2163     } else if (info->flags & BCM_VXLAN_VPN_WITH_ID) {
   2164         rv = _bcm_td2_vxlan_vpn_is_valid(unit, info->vpn);
   2165         if (BCM_E_NONE == rv) {
   2166             return BCM_E_EXISTS;
   2167         } else if (BCM_E_NOT_FOUND != rv) {
   2168             return rv;
   2169         }
   2170         _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, info->vpn);
   2171         BCM_IF_ERROR_RETURN(_bcm_vfi_alloc_with_id(unit, VFIm, _bcmVfiTypeVxlan, vfi_index));
   2172         vpn_alloc_flag = 1;
   2173     } else {
   2174         BCM_IF_ERROR_RETURN(_bcm_vfi_alloc(unit, VFIm, _bcmVfiTypeVxlan, &vfi_index));
   2175         _BCM_VXLAN_VPN_SET(info->vpn, _BCM_VPN_TYPE_VFI, vfi_index);
   2176         vpn_alloc_flag = 1;
   2177     }
   2178 
   2179     /*Initial and configure VFI*/
   2180     BCM_IF_ERROR_RETURN(READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
   2181     if (info->flags & BCM_VXLAN_VPN_ELINE) {
   2182         soc_VFIm_field32_set(unit, &vfi_entry, PT2PT_ENf, 0x1);
   2183     } else if (info->flags & BCM_VXLAN_VPN_ELAN) {
   2184         /* Check that the groups are valid. */
   2185         bc_group_type = _BCM_MULTICAST_TYPE_GET(info->broadcast_group);
   2186         bc_group = _BCM_MULTICAST_ID_GET(info->broadcast_group);
   2187         umc_group_type = _BCM_MULTICAST_TYPE_GET(info->unknown_multicast_group);
   2188         umc_group = _BCM_MULTICAST_ID_GET(info->unknown_multicast_group);
   2189         uuc_group_type = _BCM_MULTICAST_TYPE_GET(info->unknown_unicast_group);
   2190         uuc_group = _BCM_MULTICAST_ID_GET(info->unknown_unicast_group);
   2191 
   2192         if ((bc_group_type != _BCM_MULTICAST_TYPE_VXLAN) ||
   2193             (umc_group_type != _BCM_MULTICAST_TYPE_VXLAN) ||
   2194             (uuc_group_type != _BCM_MULTICAST_TYPE_VXLAN) ||
   2195             (bc_group >= soc_mem_index_count(unit, L3_IPMCm)) ||
   2196             (umc_group >= soc_mem_index_count(unit, L3_IPMCm)) ||
   2197             (uuc_group >= soc_mem_index_count(unit, L3_IPMCm))) {
   2198             rv = BCM_E_PARAM;
   2199             _BCM_VXLAN_CLEANUP(rv)
   2200         }
   2201 
   2202         /* Commit the entry to HW */
   2203 #if defined(BCM_TRIDENT3_SUPPORT)
   2204         if (soc_feature(unit, soc_feature_generic_dest)) {
   2205             soc_mem_field32_dest_set(unit, VFIm, &vfi_entry,
   2206                 UMC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, umc_group);
   2207             soc_mem_field32_dest_set(unit, VFIm, &vfi_entry,
   2208                 UUC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, uuc_group);
   2209             soc_mem_field32_dest_set(unit, VFIm, &vfi_entry,
   2210                 BC_DESTINATIONf, SOC_MEM_FIF_DEST_IPMC, bc_group);
   2211         } else
   2212 #endif
   2213         {
   2214             soc_VFIm_field32_set(unit, &vfi_entry, UMC_INDEXf, umc_group);
   2215             soc_VFIm_field32_set(unit, &vfi_entry, UUC_INDEXf, uuc_group);
   2216             soc_VFIm_field32_set(unit, &vfi_entry, BC_INDEXf, bc_group);
   2217         }
   2218 #if defined(BCM_TRIDENT3_SUPPORT)
   2219         if (SOC_IS_TRIDENT3X(unit)) {
   2220             uint32 profile_idx = 0;
   2221             rv = _bcm_td3_def_vfi_profile_add(unit,
   2222                 info->flags & BCM_VXLAN_VPN_ELINE, &profile_idx);
   2223             if (BCM_E_NONE == rv) {
   2224                 soc_VFIm_field32_set(unit, &vfi_entry, VFI_PROFILE_PTRf, profile_idx);
   2225             }
   2226             _BCM_VXLAN_CLEANUP(rv)
   2227         }
   2228 #endif
   2229     }
   2230 
   2231     /* Configure protocol packet control */
   2232     rv = _bcm_xgs3_protocol_packet_actions_validate(unit, &info->protocol_pkt);
   2233     _BCM_VXLAN_CLEANUP(rv)
   2234     proto_pkt_idx = soc_VFIm_field32_get(unit, &vfi_entry, PROTOCOL_PKT_INDEXf);
   2235     rv = _bcm_xgs3_protocol_pkt_ctrl_set(unit, proto_pkt_idx, &info->protocol_pkt, &proto_pkt_idx);
   2236     _BCM_VXLAN_CLEANUP(rv)
   2237     soc_VFIm_field32_set(unit, &vfi_entry, PROTOCOL_PKT_INDEXf, proto_pkt_idx);
   2238     /*Write VFI to ASIC*/
   2239     rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry);
   2240     _BCM_VXLAN_CLEANUP(rv)
   2241 
   2242     if (info->flags & BCM_VXLAN_VPN_WITH_VPNID) {
   2243         if (info->vnid > 0xFFFFFF || 
   2244             (info->flags & BCM_VXLAN_VPN_TUNNEL_BASED_VNID)) {
   2245            rv = BCM_E_PARAM;
   2246            _BCM_VXLAN_CLEANUP(rv)
   2247         }
   2248 
   2249         /* Configure Ingress VNID */
   2250 #if defined(BCM_TRIDENT3_SUPPORT)
   2251         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2252              _bcm_td3_vxlan_vxlate_entry_t ent;
   2253 
   2254              mmem = VLAN_XLATE_1_DOUBLEm;
   2255              sal_memset(&ent, 0, sizeof(_bcm_td3_vxlan_vxlate_entry_t));
   2256              ent.dtype = _BCM_VXLAN_DATA_TYPE_VNID_VFI_FLEX;
   2257              ent.ktype = _BCM_VXLAN_KEY_TYPE_VNID_VFI_FLEX;
   2258              ent.vfi = vfi_index;
   2259              if (info->vlan > BCM_VLAN_MAX) {
   2260                   rv = BCM_E_PARAM;
   2261                   _BCM_VXLAN_CLEANUP(rv)
   2262              }
   2263              ent.vlan = info->default_vlan;
   2264             _bcm_td3_vxlan_vxlate_entry_assemble(unit, ent, ment);
   2265         } else
   2266 #endif
   2267         {
   2268             soc_mem_field32_set(unit, mmem, &ment, VALIDf, 1);
   2269             soc_mem_field32_set(unit, mmem, &ment, KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_VNID_VFI);
   2270             soc_mem_field32_set(unit, mmem, &ment, VXLAN_VN_ID__VFIf, vfi_index);
   2271 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2272             if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   2273                 if (info->vlan > BCM_VLAN_MAX) {
   2274                     rv = BCM_E_PARAM;
   2275                     _BCM_VXLAN_CLEANUP(rv)
   2276                 }
   2277                 soc_mem_field32_set(unit, mmem, &ment, VXLAN_VN_ID__OVIDf, info->vlan);
   2278             }
   2279 #endif
   2280         }
   2281 
   2282         if (info->flags & BCM_VXLAN_VPN_REPLACE) {
   2283             /*Delete old match vnid entry*/
   2284             rv = _bcm_td2_vxlan_egr_xlate_entry_get(unit, vfi_index, -1, vxlate_entry);
   2285             if (rv == BCM_E_NONE) {
   2286                 vnid = soc_mem_field32_get(unit, vxlate_mem,
   2287                             vxlate_entry, (d ? VXLAN_VFI_FLEX__VNIDf : VXLAN_VFI__VN_IDf));
   2288                 soc_mem_field32_set(unit, mmem, &ment, (d ? VXLAN_FLEX__VNIDf : VXLAN_VN_ID__VN_IDf),
   2289                                      vnid);
   2290 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2291                 if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   2292                     soc_mem_field32_set(unit, mmem, &ment, VXLAN_VN_ID__OVIDf,
   2293                                         vxlan_info->vxlan_vpn_vlan[vfi_index]);
   2294                 }
   2295 #endif
   2296                 rv = soc_mem_delete(unit, mmem, MEM_BLOCK_ALL, &ment);
   2297                 _BCM_VXLAN_CLEANUP(rv)
   2298             } else if (rv != BCM_E_NOT_FOUND) {
   2299                 _BCM_VXLAN_CLEANUP(rv)
   2300             }
   2301         }
   2302         soc_mem_field32_set(unit, mmem, &ment,  (d ? VXLAN_FLEX__VNIDf : VXLAN_VN_ID__VN_IDf),
   2303                                 info->vnid);
   2304         rv = soc_mem_insert(unit, mmem, MEM_BLOCK_ALL, &ment);
   2305         _BCM_VXLAN_CLEANUP(rv)
   2306         vnid_alloc_flag = 1;
   2307 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2308         if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   2309             vxlan_info->vxlan_vpn_vlan[vfi_index] = info->vlan;
   2310         }
   2311 #endif
   2312 #if defined(BCM_TRIDENT3_SUPPORT)
   2313         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2314             /*on td3, soc_feature_vrf_aware_vxlan_termination disabled*/
   2315             vxlan_info->vxlan_vpn_vlan[vfi_index] = info->default_vlan;
   2316         }
   2317 #endif
   2318         if (info->flags & BCM_VXLAN_VPN_REPLACE) {
   2319             soc_field_t tpid_fld;
   2320 #if defined(BCM_TRIDENT3_SUPPORT)
   2321             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2322             /*TAP process, delete tpid*/
   2323                 int profile_index = -1;
   2324 
   2325                 tpid_fld = VXLAN_VFI_FLEX__OUTER_TPID_INDEXf;
   2326                 profile_index = soc_mem_field32_get(unit, vxlate_mem, vxlate_entry,
   2327                                    VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf);
   2328                 (void)_bcm_td3_sd_tag_action_get(unit, profile_index, &action_present,
   2329                                &action_not_present);
   2330             } else
   2331 #endif
   2332             {
   2333                 tpid_fld = VXLAN_VFI__SD_TAG_TPID_INDEXf;
   2334                 /*If old tpid exist, delete it*/
   2335                 action_present = soc_mem_field32_get(unit, vxlate_mem, vxlate_entry,
   2336                                                     VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf);
   2337                 action_not_present = soc_mem_field32_get(unit, vxlate_mem, vxlate_entry,
   2338                                                     VXLAN_VFI__SD_TAG_ACTION_IF_NOT_PRESENTf);
   2339             }
   2340 
   2341             if (1 == action_present || 4 == action_present ||
   2342                 7 == action_present || 1 == action_not_present) {
   2343                 tpid_index = soc_mem_field32_get(unit, vxlate_mem, vxlate_entry,
   2344                                                         tpid_fld);
   2345                 rv = _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   2346                 if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) {
   2347                     _BCM_VXLAN_CLEANUP(rv)
   2348                 }            
   2349             }
   2350  
   2351             rv = soc_mem_delete(unit, vxlate_mem, MEM_BLOCK_ALL, vxlate_entry);
   2352             if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) {
   2353                 _BCM_VXLAN_CLEANUP(rv)
   2354             }
   2355         }
   2356 
   2357         /* Configure Egress VNID */
   2358         sal_memset(vxlate_entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   2359 #if defined(BCM_TRIDENT3_SUPPORT)
   2360         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2361             soc_mem_field32_set(unit, vxlate_mem, vxlate_entry, BASE_VALIDf, 1);
   2362             soc_mem_field32_set(unit, vxlate_mem, vxlate_entry,
   2363                                     DATA_TYPEf, _BCM_VXLAN_DATA_TYPE_LOOKUP_VFI);
   2364             soc_mem_field32_set(unit, vxlate_mem, vxlate_entry,
   2365                                     KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI);
   2366         } else
   2367 #endif
   2368         {
   2369             soc_mem_field32_set(unit, vxlate_mem, vxlate_entry, VALIDf, 0x1);
   2370             soc_mem_field32_set(unit, vxlate_mem, vxlate_entry,
   2371                                 ENTRY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI);  		
   2372         }
   2373         soc_mem_field32_set(unit, vxlate_mem, vxlate_entry, BCM_VXLAN_VFI_FIELD(d,VFIf), vfi_index);
   2374         soc_mem_field32_set(unit, vxlate_mem, vxlate_entry, (d ? VXLAN_VFI_FLEX__VNIDf : VXLAN_VFI__VN_IDf), info->vnid);
   2375 
   2376         /* Configure EGR_VLAN_XLATE - SD_TAG setting */
   2377         if (info->flags & BCM_VXLAN_VPN_SERVICE_TAGGED) {
   2378             rv = _bcm_td2_vxlan_sd_tag_set(unit, info, NULL, NULL, vxlate_entry, &tpid_index);
   2379             _BCM_VXLAN_CLEANUP(rv)
   2380         }
   2381 
   2382         rv = soc_mem_insert(unit, vxlate_mem, MEM_BLOCK_ALL, vxlate_entry);
   2383         _BCM_VXLAN_CLEANUP(rv)
   2384         vxlan_info->vxlan_vpn_info[vfi_index].vxlan_vpn_type = 0;        
   2385     } else {
   2386 
   2387         /* Reset match vnid table */
   2388         rv = _bcm_td2_vxlan_egr_xlate_entry_get(unit, vfi_index, -1, vxlate_entry);
   2389         if (rv == BCM_E_NONE) {
   2390             vnid = soc_mem_field32_get(unit, vxlate_mem, vxlate_entry,
   2391                               (d ? VXLAN_VFI_FLEX__VNIDf : VXLAN_VFI__VN_IDf));
   2392             /* Delete mpls_entry */
   2393             rv = _bcm_td2_vxlan_match_vnid_entry_reset(unit, vnid,
   2394                                         vxlan_info->vxlan_vpn_vlan[vfi_index]);
   2395             if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) {
   2396                 return rv;
   2397             }
   2398             /* Delete egr_vxlate entry */
   2399             rv = _bcm_td2_vxlan_egr_xlate_entry_reset(unit, info->vpn);
   2400             if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) {
   2401                 return rv;
   2402             }
   2403         } else if (rv != BCM_E_NOT_FOUND) {
   2404             return rv;
   2405         }
   2406         if (info->flags & BCM_VXLAN_VPN_TUNNEL_BASED_VNID) {
   2407             vxlan_info->vxlan_vpn_info[vfi_index].vxlan_vpn_type = _BCM_VXLAN_VPN_TYPE_TUNNEL_BASED_VNID;
   2408 #if defined(BCM_TRIDENT3_SUPPORT)
   2409             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2410                 vxlan_info->vxlan_vpn_vlan[vfi_index] = info->default_vlan;
   2411             }
   2412 #endif
   2413         }
   2414     }
   2415 
   2416     return BCM_E_NONE;
   2417 
   2418 cleanup:
   2419     if (tpid_index != -1) {
   2420         (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   2421     }
   2422     if (vnid_alloc_flag) {
   2423         soc_mem_delete(unit, mmem, MEM_BLOCK_ALL, &ment);
   2424     }
   2425     if (vpn_alloc_flag) {
   2426         (void) _bcm_vfi_free(unit, _bcmVfiTypeVxlan, vfi_index);
   2427     }
   2428     return rv;
   2429 }
   2430 
   2431  /* Function:
   2432  *      bcm_td2_vxlan_vpn_vnid_get
   2433  * Purpose:
   2434  *      Get VNID per VPN instance
   2435  * Parameters:
   2436  *      unit     - Device Number
   2437  *      l2vpn   - VXLAN VPN
   2438  *      info     - VXLAN VPN Config
   2439  * Returns:
   2440  *      BCM_E_XXXX
   2441  */
   2442 
   2443 STATIC int
   2444 _bcm_td2_vxlan_egr_xlate_entry_get(int unit, int vfi, int vp, uint32 *vxlate_entry)
   2445 {
   2446     soc_mem_t vxlate_mem;
   2447     uint32 key_vxlate[SOC_MAX_MEM_WORDS];
   2448     int index=0;
   2449 
   2450     sal_memset(key_vxlate, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   2451 
   2452 #if defined(BCM_TRIDENT3_SUPPORT)
   2453     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2454         vxlate_mem = EGR_VLAN_XLATE_1_SINGLEm;
   2455 
   2456         soc_mem_field32_set(unit, vxlate_mem, key_vxlate, BASE_VALIDf, 1);
   2457         if (vp != -1) {
   2458             soc_mem_field32_set(unit, vxlate_mem, key_vxlate, VXLAN_VFI_FLEX__DVPf, vp);
   2459             soc_mem_field32_set(unit, vxlate_mem, key_vxlate,
   2460                                 KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI_DVP);
   2461             soc_mem_field32_set(unit, vxlate_mem, key_vxlate,
   2462                                 DATA_TYPEf, _BCM_VXLAN_DATA_TYPE_LOOKUP_VFI);
   2463         } else {
   2464             soc_mem_field32_set(unit, vxlate_mem, key_vxlate,
   2465                                 KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI);
   2466             soc_mem_field32_set(unit, vxlate_mem, key_vxlate,
   2467                                 DATA_TYPEf, _BCM_VXLAN_DATA_TYPE_LOOKUP_VFI);
   2468         }
   2469         soc_mem_field32_set(unit, vxlate_mem, key_vxlate, VXLAN_VFI_FLEX__VFIf, vfi);
   2470     } else
   2471 #endif
   2472     {
   2473         vxlate_mem = EGR_VLAN_XLATEm;
   2474         soc_mem_field32_set(unit, vxlate_mem, key_vxlate, VALIDf, 0x1);
   2475         soc_mem_field32_set(unit, vxlate_mem, key_vxlate, ENTRY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI);
   2476         if (vp != -1) {
   2477             soc_mem_field32_set(unit, vxlate_mem, key_vxlate, VXLAN_VFI__DVPf, vp);
   2478             soc_mem_field32_set(unit, vxlate_mem, key_vxlate,
   2479                                 ENTRY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI_DVP);
   2480         } else {
   2481             soc_mem_field32_set(unit, vxlate_mem, key_vxlate,
   2482                                 ENTRY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI);
   2483         }
   2484         soc_mem_field32_set(unit, vxlate_mem, key_vxlate, VXLAN_VFI__VFIf, vfi);
   2485     }
   2486 
   2487     return soc_mem_search(unit, vxlate_mem, MEM_BLOCK_ANY,
   2488                         &index, key_vxlate, vxlate_entry, 0);
   2489 }
   2490 
   2491 
   2492 /*
   2493  * Function:
   2494  *      bcm_td2_vxlan_vpn_destroy
   2495  * Purpose:
   2496  *      Delete a VPN instance
   2497  * Parameters:
   2498  *      unit - Device Number
   2499  *      vpn - VPN instance ID
   2500  * Returns:
   2501  *      BCM_E_XXX
   2502  */
   2503 
   2504 int
   2505 bcm_td2_vxlan_vpn_destroy(int unit, bcm_vpn_t l2vpn)
   2506 {
   2507     int vfi = 0;
   2508     vfi_entry_t vfi_entry;
   2509     uint8 isEline = 0;
   2510     uint32 vnid = 0;
   2511     uint32 stat_counter_id;
   2512     int num_ctr = 0; 
   2513     int ref_count;
   2514     int index;
   2515     int rv = 0;
   2516     soc_mem_t vxlate_mem;
   2517     uint32 vxlate_entry[SOC_MAX_MEM_WORDS];
   2518     _bcm_td2_vxlan_bookkeeping_t *vxlan_info = VXLAN_INFO(unit);
   2519     int d = 0; /*vxlan decoupled mode*/
   2520 
   2521 #if defined(BCM_TRIDENT3_SUPPORT)
   2522     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2523         d = 1;
   2524         vxlate_mem = EGR_VLAN_XLATE_1_SINGLEm;
   2525     } else
   2526 #endif
   2527     {
   2528         vxlate_mem = EGR_VLAN_XLATEm;
   2529     }
   2530 
   2531     /* Get vfi index */
   2532     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_eline(unit, l2vpn, &isEline));
   2533     if (isEline == 0x1 ) {
   2534         _BCM_VXLAN_VPN_GET(vfi, _BCM_VXLAN_VPN_TYPE_ELINE, l2vpn);
   2535     } else if (isEline == 0x0 ) {
   2536         _BCM_VXLAN_VPN_GET(vfi, _BCM_VXLAN_VPN_TYPE_ELAN, l2vpn);
   2537     }
   2538     if (!vxlan_info->vxlan_vpn_info[vfi].vxlan_vpn_type) {
   2539         /* Reset match vnid table */
   2540         rv = _bcm_td2_vxlan_egr_xlate_entry_get(unit, vfi, -1, vxlate_entry);
   2541         if (rv == BCM_E_NONE) {         
   2542             vnid = soc_mem_field32_get(unit, vxlate_mem, vxlate_entry, (d ? VXLAN_VFI_FLEX__VNIDf : VXLAN_VFI__VN_IDf));
   2543             /* Delete mpls_entry */
   2544             rv = _bcm_td2_vxlan_match_vnid_entry_reset(
   2545                      unit, vnid, vxlan_info->vxlan_vpn_vlan[vfi]);
   2546             if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) {
   2547                 return rv;    
   2548             }
   2549 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2550             if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   2551                 vxlan_info->vxlan_vpn_vlan[vfi] = 0;
   2552             }
   2553 #endif
   2554             /* Delete egr_vxlate entry */
   2555             rv = _bcm_td2_vxlan_egr_xlate_entry_reset(unit, l2vpn);            
   2556             if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) {
   2557                 return rv;    
   2558             }            
   2559         } else if (rv != BCM_E_NOT_FOUND) {
   2560             return rv;
   2561         }
   2562     }
   2563 
   2564     /* Delete all VXLAN ports on this VPN */
   2565     BCM_IF_ERROR_RETURN(bcm_td2_vxlan_port_delete_all(unit, l2vpn));
   2566 
   2567     /* Check counters before delete vpn */
   2568     if (bcm_esw_vxlan_stat_id_get(unit, BCM_GPORT_INVALID, l2vpn,
   2569                    bcmVxlanOutPackets, &stat_counter_id) == BCM_E_NONE) { 
   2570         num_ctr++;
   2571     } 
   2572     if (bcm_esw_vxlan_stat_id_get(unit, BCM_GPORT_INVALID, l2vpn,
   2573                    bcmVxlanInPackets, &stat_counter_id) == BCM_E_NONE) {
   2574         num_ctr++;
   2575     }
   2576 
   2577     if (num_ctr != 0) {
   2578         BCM_IF_ERROR_RETURN(
   2579            bcm_esw_vxlan_stat_detach(unit, BCM_GPORT_INVALID, l2vpn));  
   2580     }
   2581 
   2582     /* Delete protocol packet control */
   2583     sal_memset(&vfi_entry, 0, sizeof(vfi_entry_t));
   2584     BCM_IF_ERROR_RETURN(READ_VFIm(unit, MEM_BLOCK_ALL, vfi, &vfi_entry));
   2585     index = soc_VFIm_field32_get(unit, &vfi_entry, PROTOCOL_PKT_INDEXf);
   2586     BCM_IF_ERROR_RETURN(
   2587         _bcm_prot_pkt_ctrl_ref_count_get(unit, index, &ref_count));
   2588     if ((ref_count > 0) && index) {
   2589         BCM_IF_ERROR_RETURN(_bcm_prot_pkt_ctrl_delete(unit, index));
   2590     }
   2591 
   2592     /* Reset VFI table */
   2593     (void)_bcm_vfi_free(unit, _bcmVfiTypeVxlan, vfi);
   2594     vxlan_info->vxlan_vpn_info[vfi].vxlan_vpn_type = 0;
   2595     return BCM_E_NONE;
   2596 }
   2597 
   2598  /* Function:
   2599  *      bcm_td2_vxlan_vpn_id_destroy_all
   2600  * Purpose:
   2601  *      Delete all L2-VPN instances
   2602  * Parameters:
   2603  *      unit     - Device Number
   2604  * Returns:
   2605  *      BCM_E_XXXX
   2606  */
   2607 
   2608 int 
   2609 bcm_td2_vxlan_vpn_destroy_all(int unit)
   2610 {
   2611     int num_vfi = 0, idx = 0;
   2612     bcm_vpn_t l2vpn = 0;
   2613 
   2614     /* Destroy all VXLAN VPNs */
   2615     num_vfi = soc_mem_index_count(unit, VFIm);
   2616     for (idx = 0; idx < num_vfi; idx++) {
   2617         if (_bcm_vfi_used_get(unit, idx, _bcmVfiTypeVxlan)) {
   2618             _BCM_VXLAN_VPN_SET(l2vpn, _BCM_VPN_TYPE_VFI, idx);
   2619             BCM_IF_ERROR_RETURN(bcm_td2_vxlan_vpn_destroy(unit, l2vpn));
   2620         }
   2621     }
   2622     return BCM_E_NONE;
   2623 }
   2624 
   2625  /* Function:
   2626  *      bcm_td2_vxlan_vpn_get
   2627  * Purpose:
   2628  *      Get L2-VPN instance
   2629  * Parameters:
   2630  *      unit     - Device Number
   2631  *      l2vpn   - VXLAN VPN
   2632  *      info     - VXLAN VPN Config
   2633  * Returns:
   2634  *      BCM_E_XXXX
   2635  */
   2636 
   2637 int 
   2638 bcm_td2_vxlan_vpn_get( int unit, bcm_vpn_t l2vpn, bcm_vxlan_vpn_config_t *info)
   2639 {
   2640     int vfi_index = -1;
   2641     vfi_entry_t vfi_entry;
   2642     uint8 isEline=0;
   2643     int rv = BCM_E_NONE;
   2644     int proto_pkt_inx;
   2645     soc_mem_t vxlate_mem;
   2646     uint32 vxlate_entry[SOC_MAX_MEM_WORDS];
   2647     int d = 0; /*vxlan decoupled mode*/
   2648 
   2649 #if defined(BCM_TRIDENT3_SUPPORT)
   2650     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2651         d = 1;
   2652         vxlate_mem = EGR_VLAN_XLATE_1_SINGLEm;
   2653     } else
   2654 #endif
   2655     {
   2656         vxlate_mem = EGR_VLAN_XLATEm;
   2657     }
   2658 
   2659     /*Get vfi table*/
   2660     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_eline(unit, l2vpn, &isEline));
   2661     if (isEline == 0x1 ) {
   2662         _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VXLAN_VPN_TYPE_ELINE, l2vpn);
   2663     } else if (isEline == 0x0 ) {
   2664         _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VXLAN_VPN_TYPE_ELAN, l2vpn);
   2665     }
   2666     BCM_IF_ERROR_RETURN(READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
   2667 
   2668     /* Get info associated with vfi table */
   2669     if (isEline) {
   2670         info->flags =  BCM_VXLAN_VPN_ELINE;
   2671     } else {
   2672          info->flags =  BCM_VXLAN_VPN_ELAN;
   2673 
   2674 #if defined(BCM_TRIDENT3_SUPPORT)
   2675         if (soc_feature(unit, soc_feature_generic_dest)) {
   2676             uint32 dt, dv;
   2677 
   2678             dv = soc_mem_field32_dest_get(unit, VFIm,
   2679                         &vfi_entry, BC_DESTINATIONf, &dt);
   2680             if (dt == SOC_MEM_FIF_DEST_IPMC) {
   2681                 _BCM_MULTICAST_GROUP_SET(info->broadcast_group,
   2682                                     _BCM_MULTICAST_TYPE_VXLAN, dv);
   2683             } else {
   2684                 return BCM_E_INTERNAL;
   2685             }
   2686 
   2687             dv = soc_mem_field32_dest_get(unit, VFIm,
   2688                         &vfi_entry, UUC_DESTINATIONf, &dt);
   2689             if (dt == SOC_MEM_FIF_DEST_IPMC) {
   2690                 _BCM_MULTICAST_GROUP_SET(info->unknown_unicast_group,
   2691                                         _BCM_MULTICAST_TYPE_VXLAN, dv);
   2692             } else {
   2693                 return BCM_E_INTERNAL;
   2694             }
   2695 
   2696             dv = soc_mem_field32_dest_get(unit, VFIm,
   2697                         &vfi_entry, UMC_DESTINATIONf, &dt);
   2698             if (dt == SOC_MEM_FIF_DEST_IPMC) {
   2699                 _BCM_MULTICAST_GROUP_SET(info->unknown_multicast_group,
   2700                                             _BCM_MULTICAST_TYPE_VXLAN, dv);
   2701             } else {
   2702                 return BCM_E_INTERNAL;
   2703             }
   2704         } else
   2705 #endif
   2706         {
   2707             _BCM_MULTICAST_GROUP_SET(info->broadcast_group,
   2708                                 _BCM_MULTICAST_TYPE_VXLAN,
   2709                  soc_VFIm_field32_get(unit, &vfi_entry, BC_INDEXf));
   2710             _BCM_MULTICAST_GROUP_SET(info->unknown_unicast_group,
   2711                                 _BCM_MULTICAST_TYPE_VXLAN,
   2712                  soc_VFIm_field32_get(unit, &vfi_entry, UUC_INDEXf));
   2713             _BCM_MULTICAST_GROUP_SET(info->unknown_multicast_group,
   2714                                 _BCM_MULTICAST_TYPE_VXLAN,
   2715                  soc_VFIm_field32_get(unit, &vfi_entry, UMC_INDEXf));
   2716         }
   2717     }
   2718     _BCM_VXLAN_VPN_SET(info->vpn, _BCM_VPN_TYPE_VFI, vfi_index);
   2719     /*Get protocol packet control*/
   2720     proto_pkt_inx = soc_VFIm_field32_get(unit, &vfi_entry, PROTOCOL_PKT_INDEXf);
   2721     BCM_IF_ERROR_RETURN(_bcm_xgs3_protocol_pkt_ctrl_get(unit,proto_pkt_inx, &info->protocol_pkt));
   2722 
   2723     /* Get VNID */
   2724     rv = _bcm_td2_vxlan_egr_xlate_entry_get(unit, vfi_index, -1, vxlate_entry);
   2725     if (rv == BCM_E_NONE) {
   2726         info->flags |= BCM_VXLAN_VPN_WITH_VPNID;
   2727         info->vnid = soc_mem_field32_get(unit, vxlate_mem, vxlate_entry,(d ? VXLAN_VFI_FLEX__VNIDf : VXLAN_VFI__VN_IDf));
   2728 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2729         if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   2730             info->vlan = VXLAN_INFO(unit)->vxlan_vpn_vlan[vfi_index];
   2731         }
   2732 #endif
   2733 #if defined(BCM_TRIDENT3_SUPPORT)
   2734         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2735             info->default_vlan = VXLAN_INFO(unit)->vxlan_vpn_vlan[vfi_index];
   2736         }
   2737 #endif
   2738         /* Get SDTAG settings */
   2739         (void)_bcm_td2_vxlan_sd_tag_get( unit, info, NULL, NULL, vxlate_entry, 1);
   2740     } else if (rv == BCM_E_NOT_FOUND) {
   2741         rv = BCM_E_NONE;
   2742     }
   2743     if (VXLAN_INFO(unit)->vxlan_vpn_info[vfi_index].vxlan_vpn_type) {
   2744         info->flags |= BCM_VXLAN_VPN_TUNNEL_BASED_VNID;
   2745     }
   2746     return rv;
   2747 }
   2748 
   2749  /* Function:
   2750  *      _bcm_td2_vxlan_vpn_get
   2751  * Purpose:
   2752  *      Get L2-VPN instance for VXLAN
   2753  * Parameters:
   2754  *      unit     - Device Number
   2755  *      vfi_index   - vfi_index 
   2756  *      vid     (OUT) VLAN Id (l2vpn id)
   2757 
   2758  * Returns:
   2759  *      BCM_E_XXXX
   2760  */
   2761 int 
   2762 _bcm_td2_vxlan_vpn_get(int unit, int vfi_index, bcm_vlan_t *vid)
   2763 {
   2764     vfi_entry_t vfi_entry;
   2765 
   2766     BCM_IF_ERROR_RETURN
   2767         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
   2768 
   2769     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
   2770         _BCM_VXLAN_VPN_SET(*vid, _BCM_VXLAN_VPN_TYPE_ELINE, vfi_index);
   2771     } else {
   2772         _BCM_VXLAN_VPN_SET(*vid, _BCM_VXLAN_VPN_TYPE_ELAN, vfi_index);
   2773     }
   2774     return BCM_E_NONE;
   2775 }
   2776 
   2777 /*
   2778  * Function:
   2779  *      bcm_td2_vxlan_vpn_traverse
   2780  * Purpose:
   2781  *      Get information about a VPN instance
   2782  * Parameters:
   2783  *      unit  - (IN)  Device Number
   2784  *      cb    - (IN)  User-provided callback
   2785  *      info  - (IN/OUT) Cookie
   2786  * Returns:
   2787  *      BCM_E_XXX
   2788  */
   2789 
   2790 int bcm_td2_vxlan_vpn_traverse(int unit, bcm_vxlan_vpn_traverse_cb cb, 
   2791                              void *user_data)
   2792 {
   2793     int idx, num_vfi;
   2794     int vpn;
   2795     bcm_vxlan_vpn_config_t info;
   2796 
   2797     if (cb == NULL) {
   2798          return BCM_E_PARAM;
   2799     }
   2800 
   2801     /* VXLAN VPNs */
   2802     num_vfi = soc_mem_index_count(unit, VFIm);
   2803     for (idx = 0; idx < num_vfi; idx++) {
   2804          if (_bcm_vfi_used_get(unit, idx, _bcmVfiTypeVxlan)) {
   2805               _BCM_VXLAN_VPN_SET(vpn, _BCM_VPN_TYPE_VFI, idx);
   2806               bcm_vxlan_vpn_config_t_init(&info);
   2807               BCM_IF_ERROR_RETURN(bcm_td2_vxlan_vpn_get(unit, vpn, &info));
   2808               BCM_IF_ERROR_RETURN(cb(unit, &info, user_data));
   2809          }
   2810     }
   2811     return BCM_E_NONE;
   2812 }
   2813 
   2814 
   2815 /*
   2816  * Function:
   2817  *      bcm_td2_vxlan_port_traverse
   2818  * Purpose:
   2819  *      Get information about a port instance
   2820  * Parameters:
   2821  *      unit  - (IN)  Device Number
   2822  *      cb    - (IN)  User-provided callback
   2823  *      info  - (IN/OUT) Cookie
   2824  * Returns:
   2825  *      BCM_E_XXX
   2826  */
   2827 
   2828 int bcm_td2_vxlan_port_traverse(int unit, bcm_vxlan_port_traverse_cb cb,
   2829                              void *user_data)
   2830 {
   2831     int idx = 0;
   2832     int vp = 0;
   2833     bcm_vxlan_port_t info;
   2834     int split_horizon_port_flag = 0;
   2835     _bcm_vp_info_t vp_info;
   2836     int default_vp = -1;
   2837     uint32 reg_val = 0;
   2838     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   2839     vxlan_info = VXLAN_INFO(unit);
   2840 
   2841     if (cb == NULL) {
   2842          return BCM_E_PARAM;
   2843     }
   2844 
   2845 #if defined(BCM_TRIDENT3_SUPPORT)
   2846     if (SOC_IS_TRIDENT3X(unit)) {
   2847     } else
   2848 #endif
   2849     {
   2850         BCM_IF_ERROR_RETURN(READ_VXLAN_DEFAULT_NETWORK_SVPr(unit, &reg_val));
   2851         default_vp = soc_reg_field_get(unit,
   2852                         VXLAN_DEFAULT_NETWORK_SVPr, reg_val, SVPf);
   2853     }
   2854 
   2855     /* VXLAN VPNs */
   2856     vp = soc_mem_index_count(unit, SOURCE_VPm);
   2857     for (idx = 0; idx < vp; idx++) {
   2858         if (_bcm_vp_used_get(unit, idx, _bcmVpTypeVxlan)) {
   2859             bcm_vxlan_port_t_init(&info);
   2860 
   2861             BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, idx, &vp_info));
   2862             if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
   2863                 split_horizon_port_flag = TRUE;
   2864             }
   2865 
   2866             /*only for Access VP */
   2867             if ((_bcm_vp_used_get(unit, idx, _bcmVpTypeNiv) ||
   2868                  _bcm_vp_used_get(unit, idx, _bcmVpTypeExtender)) &&
   2869                  (!split_horizon_port_flag)) {
   2870                 BCM_GPORT_VXLAN_PORT_ID_SET(info.vxlan_port_id, idx);
   2871                 BCM_IF_ERROR_RETURN(cb(unit, &info, user_data));
   2872             } else if (_bcm_vp_used_get(unit, idx, _bcmVpTypeVpLag)) {
   2873                 bcm_trunk_t        tid = 0;
   2874                 bcm_trunk_member_t trunk_member;
   2875                 int                port_count = 0;
   2876                 BCM_IF_ERROR_RETURN(
   2877                     _bcm_esw_trunk_vp_lag_vp_to_tid(unit, idx, &tid));
   2878                 BCM_IF_ERROR_RETURN(
   2879                     bcm_td2_vp_lag_get(unit, tid, NULL, 1,
   2880                                        &trunk_member, &port_count));
   2881                 if (BCM_GPORT_IS_NIV_PORT(trunk_member.gport) ||
   2882                     BCM_GPORT_IS_EXTENDER_PORT(trunk_member.gport)) {
   2883                     BCM_GPORT_TRUNK_SET(info.vxlan_port_id, tid);
   2884                     BCM_IF_ERROR_RETURN(cb(unit, &info, user_data));
   2885                 } else {
   2886                     int vfi;
   2887                     uint32 tunnel_sip;
   2888                     uint32 tunnel_index;
   2889                     int tunnel_based_vpn_get = 0;
   2890                     tunnel_index = vxlan_info->match_key[idx].match_tunnel_index;
   2891                     tunnel_sip = vxlan_info->vxlan_tunnel_term[tunnel_index].sip;
   2892                     vfi = vxlan_info->match_key[idx].vfi;
   2893                     if (vxlan_info->vxlan_vpn_info[vfi].vxlan_vpn_type == 
   2894                         _BCM_VXLAN_VPN_TYPE_TUNNEL_BASED_VNID && 
   2895                         tunnel_sip == vxlan_info->vxlan_vpn_info[vfi].sip) {
   2896                         int l2vpn;
   2897                         _BCM_VXLAN_VPN_SET(l2vpn, _BCM_VPN_TYPE_VFI, vfi);
   2898                         BCM_IF_ERROR_RETURN(
   2899                             _bcm_td2_vxlan_port_get(unit, l2vpn, idx, &info));
   2900                         BCM_IF_ERROR_RETURN(cb(unit, &info, user_data));
   2901                         tunnel_based_vpn_get = 1;
   2902                     }
   2903                     if (!tunnel_based_vpn_get) {
   2904                         BCM_IF_ERROR_RETURN(
   2905                             _bcm_td2_vxlan_port_get(unit, BCM_VXLAN_VPN_INVALID, idx, &info));
   2906                         BCM_IF_ERROR_RETURN(cb(unit, &info, user_data));
   2907                     }
   2908                 }
   2909             } else {
   2910 
   2911                 if (idx == default_vp) {
   2912                     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_default_port_get(unit, 
   2913                                           idx, &info));
   2914                     BCM_IF_ERROR_RETURN(cb(unit, &info, user_data));
   2915                 } else {
   2916                     int vfi;
   2917                     uint32 tunnel_sip;
   2918                     uint32 tunnel_index;
   2919                     int tunnel_based_vpn_get = 0;
   2920                     tunnel_index = vxlan_info->match_key[idx].match_tunnel_index;
   2921                     tunnel_sip = vxlan_info->vxlan_tunnel_term[tunnel_index].sip;
   2922                     vfi = vxlan_info->match_key[idx].vfi;
   2923                     if (vxlan_info->vxlan_vpn_info[vfi].vxlan_vpn_type == 
   2924                         _BCM_VXLAN_VPN_TYPE_TUNNEL_BASED_VNID && 
   2925                         tunnel_sip == vxlan_info->vxlan_vpn_info[vfi].sip) {
   2926                         int l2vpn;
   2927                         _BCM_VXLAN_VPN_SET(l2vpn, _BCM_VPN_TYPE_VFI, vfi);
   2928                         BCM_IF_ERROR_RETURN(
   2929                             _bcm_td2_vxlan_port_get(unit, l2vpn, idx, &info));
   2930                         BCM_IF_ERROR_RETURN(cb(unit, &info, user_data));
   2931                         tunnel_based_vpn_get = 1;
   2932                     }
   2933                     if (!tunnel_based_vpn_get) {
   2934                         BCM_IF_ERROR_RETURN(
   2935                             _bcm_td2_vxlan_port_get(unit, BCM_VXLAN_VPN_INVALID, idx, &info));
   2936                         BCM_IF_ERROR_RETURN(cb(unit, &info, user_data));
   2937                     }
   2938                 }
   2939             }
   2940             
   2941         }
   2942     }
   2943     return BCM_E_NONE;
   2944 }
   2945 
   2946 
   2947 /*
   2948  * Function:
   2949  *          _bcm_td2_vxlan_tunnel_terminate_entry_key_set
   2950  * Purpose:
   2951  *          Set VXLAN Tunnel Terminate entry key set
   2952  * Parameters:
   2953  *  IN :  Unit
   2954  *  IN :  tnl_info
   2955  *  IN(OUT) : tr_ent VLAN_XLATE entry pointer
   2956  *  IN : clean_flag
   2957  * Returns: BCM_E_XXX
   2958  */
   2959 
   2960 STATIC void
   2961 _bcm_td2_vxlan_tunnel_terminate_entry_key_set(int unit,
   2962     bcm_tunnel_terminator_t *tnl_info, uint32 *tr_ent, uint8 out_mode, int clean_flag)
   2963 {
   2964     soc_mem_t mem;
   2965     int d = 0; /*vxlan decoupled mode*/
   2966     if (clean_flag) {
   2967          sal_memset(tr_ent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   2968     }
   2969 
   2970 #if defined(BCM_TRIDENT3_SUPPORT)
   2971     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   2972         mem = MPLS_ENTRY_SINGLEm;
   2973         d =1;
   2974         soc_mem_field32_set(unit, mem, tr_ent, BASE_VALIDf, 1);
   2975         soc_mem_field32_set(unit, mem, tr_ent, DATA_TYPEf,
   2976                                 _BCM_VXLAN_DATA_TYPE_LOOKUP_DIP_IN_MPLS_ENTRY);
   2977         soc_mem_field32_set(unit, mem, tr_ent, KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP_IN_MPLS_ENTRY);
   2978         soc_mem_field32_set(unit, mem, tr_ent, VXLAN_FLEX_IPV4_DIP__TERM_TUNNELf, 1);
   2979     } else
   2980 #endif
   2981     {
   2982         mem = VLAN_XLATEm;
   2983         soc_mem_field32_set(unit, mem, tr_ent, VALIDf, 0x1);
   2984         soc_mem_field32_set(unit, mem, tr_ent, KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP);
   2985     }
   2986     soc_mem_field32_set(unit, mem, tr_ent, BCM_VXLAN_DIP_FIELD(d, DIPf), tnl_info->dip);
   2987 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2988     if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   2989         soc_mem_field32_set(unit, mem, tr_ent, VXLAN_DIP__OVIDf, tnl_info->vlan);
   2990     }
   2991 #endif
   2992     if (out_mode == _BCM_VXLAN_MULTICAST_BUD) {
   2993         soc_mem_field32_set(unit, mem, tr_ent,
   2994             BCM_VXLAN_DIP_FIELD(d,NETWORK_RECEIVERS_PRESENTf), 0x1);
   2995         _bcm_td2_vxlan_bud_loopback_enable(unit);
   2996     } else if (out_mode == _BCM_VXLAN_MULTICAST_LEAF) {
   2997         soc_mem_field32_set(unit, mem, tr_ent,
   2998             BCM_VXLAN_DIP_FIELD(d,NETWORK_RECEIVERS_PRESENTf), 0x0);
   2999     }
   3000 
   3001     soc_mem_field32_set(unit, mem, tr_ent, BCM_VXLAN_DIP_FIELD(d,IGNORE_UDP_CHECKSUMf),
   3002         (tnl_info->flags & BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE) ? 0x0 : 0x1);
   3003 
   3004     if (tnl_info->flags & BCM_TUNNEL_TERM_USE_OUTER_DSCP) {
   3005         soc_mem_field32_set(unit, mem, tr_ent,
   3006             BCM_VXLAN_DIP_FIELD(d,USE_OUTER_HEADER_PHBf), 0x1);
   3007     } else if (tnl_info->flags & BCM_TUNNEL_TERM_USE_OUTER_PCP) {
   3008         soc_mem_field32_set(unit, mem, tr_ent,
   3009             BCM_VXLAN_DIP_FIELD(d,USE_OUTER_HEADER_PHBf), 0x2);
   3010     }
   3011 }
   3012 
   3013 /*
   3014  * Function:
   3015  *          _bcm_td2_vxlan_tunnel_terminator_reference_count
   3016  * Purpose:
   3017  *          Find VXLAN Tunnel terminator DIP reference count
   3018  * Returns: BCM_E_XXX
   3019  */
   3020 
   3021 STATIC int
   3022 _bcm_td2_vxlan_tunnel_terminator_reference_count(int unit,
   3023                                                  bcm_ip_t dest_ip_addr,
   3024                                                  int threshold_count)
   3025 {
   3026     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   3027     int tunnel_idx=0, num_vp=0, ref_count=0;
   3028 
   3029     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   3030     vxlan_info = VXLAN_INFO(unit);
   3031 
   3032       for (tunnel_idx=0; tunnel_idx< num_vp; tunnel_idx++) {
   3033           if (vxlan_info->vxlan_tunnel_term[tunnel_idx].dip == dest_ip_addr) {
   3034               ref_count ++;
   3035               if (ref_count == threshold_count) {
   3036                   break;
   3037               }
   3038           }
   3039       }
   3040     return ref_count;
   3041 }
   3042 
   3043 /*
   3044  * Function:
   3045  *          _bcm_td2_vxlan_multicast_tunnel_state_set
   3046  * Purpose:
   3047  *          Set VXLAN Tunnel terminator Multicast State
   3048  * Returns: BCM_E_XXX
   3049  */
   3050 
   3051 
   3052 STATIC void
   3053 _bcm_td2_vxlan_multicast_tunnel_state_set (int unit, int  tunnel_idx, uint16 tunnel_state)
   3054 {
   3055     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   3056 
   3057     vxlan_info = VXLAN_INFO(unit);
   3058 
   3059     if (tunnel_idx != -1) {
   3060         vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state = tunnel_state;
   3061     }
   3062 }
   3063 
   3064 /*
   3065  * Function:
   3066  *          _bcm_td2_vxlan_tunnel_terminator_state_find
   3067  * Purpose:
   3068  *          Find VXLAN Tunnel terminator DIP State
   3069  * Returns: BCM_E_XXX
   3070  */
   3071 
   3072 STATIC int
   3073 _bcm_td2_vxlan_tunnel_terminator_state_find(int unit, bcm_ip_t dest_ip_addr)
   3074 {
   3075     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   3076     int tunnel_idx=0, num_vp=0, tunnel_state=0;
   3077 
   3078     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   3079     vxlan_info = VXLAN_INFO(unit);
   3080 
   3081     for (tunnel_idx=0; tunnel_idx< num_vp; tunnel_idx++) {
   3082           if (vxlan_info->vxlan_tunnel_term[tunnel_idx].dip == dest_ip_addr) {
   3083               if (vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state == _BCM_VXLAN_TUNNEL_TERM_MULTICAST_LEAF ) {
   3084                  tunnel_state += 0;
   3085               } else if (vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state == _BCM_VXLAN_TUNNEL_TERM_MULTICAST_BUD ) {
   3086                  tunnel_state += 1;
   3087                  break;
   3088               }
   3089           }
   3090     }
   3091     return tunnel_state;
   3092 }
   3093 
   3094 /*
   3095  * Function:
   3096  *      bcm_td2_vxlan_multicast_leaf_entry_check
   3097  * Purpose:
   3098  *      To find whether LEAF-multicast entry exists for DIP?
   3099  * Returns:
   3100  *      BCM_E_XXX
   3101  */
   3102 
   3103 int
   3104 bcm_td2_vxlan_multicast_leaf_entry_check(int unit,
   3105                                          int tunnel_idx,
   3106                                          int multicast_flag)
   3107 {
   3108     soc_mem_t mem;
   3109     uint32 vxlate_entry[SOC_MAX_MEM_WORDS];
   3110     int rv=BCM_E_NONE, index=0;
   3111     uint16 tunnel_multicast_state = 0;
   3112     int tunnel_mc_states = 0;
   3113     bcm_ip_t mc_ip_addr;
   3114     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   3115     uint8 net_receiver = 0;
   3116 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3117     bcm_vlan_t    vlan = 0;
   3118 #endif
   3119     int d = 0; /*vxlan decoupled mode*/
   3120 
   3121     vxlan_info = VXLAN_INFO(unit);
   3122     tunnel_multicast_state =
   3123         vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state;
   3124     mc_ip_addr = vxlan_info->vxlan_tunnel_term[tunnel_idx].dip;
   3125 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3126     vlan = vxlan_info->vxlan_tunnel_term[tunnel_idx].vlan;
   3127 #endif
   3128     
   3129     /* Set (SIP, DIP) based Software State */
   3130     if (multicast_flag == BCM_VXLAN_MULTICAST_TUNNEL_STATE_BUD_ENABLE) {
   3131         if (tunnel_multicast_state == _BCM_VXLAN_TUNNEL_TERM_MULTICAST_LEAF) {
   3132              (void) _bcm_td2_vxlan_multicast_tunnel_state_set(unit, 
   3133                            tunnel_idx, _BCM_VXLAN_TUNNEL_TERM_MULTICAST_BUD);
   3134         }
   3135         tunnel_mc_states = 1;
   3136     } else  if (multicast_flag == BCM_VXLAN_MULTICAST_TUNNEL_STATE_BUD_DISABLE){
   3137         if (tunnel_multicast_state == _BCM_VXLAN_TUNNEL_TERM_MULTICAST_BUD) {
   3138              (void) _bcm_td2_vxlan_multicast_tunnel_state_set(unit, 
   3139                            tunnel_idx, _BCM_VXLAN_TUNNEL_TERM_MULTICAST_LEAF);
   3140         }
   3141     }
   3142     
   3143      /* Set DIP-based cumulative hardware State */
   3144     if (!tunnel_mc_states) {
   3145         tunnel_mc_states =
   3146             _bcm_td2_vxlan_tunnel_terminator_state_find(unit, mc_ip_addr);
   3147     }
   3148 
   3149     sal_memset(vxlate_entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   3150 #if defined(BCM_TRIDENT3_SUPPORT)
   3151     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   3152         bcm_tunnel_terminator_t tnl_info;
   3153 
   3154         d =1;
   3155         mem = MPLS_ENTRY_SINGLEm;
   3156         bcm_tunnel_terminator_t_init(&tnl_info);
   3157         tnl_info.dip = mc_ip_addr;
   3158         _bcm_td2_vxlan_tunnel_terminate_entry_key_set(unit, &tnl_info, vxlate_entry, 0, 1);
   3159     } else
   3160 #endif      
   3161     {
   3162 #if defined(BCM_TRIDENT3_SUPPORT)
   3163         if (soc_feature(unit, soc_feature_base_valid)) {
   3164             mem = VLAN_XLATE_1_DOUBLEm;
   3165             soc_mem_field32_set(unit, mem, vxlate_entry, BASE_VALID_0f, 3);
   3166             soc_mem_field32_set(unit, mem, vxlate_entry, BASE_VALID_1f, 7);
   3167             soc_mem_field32_set(unit, mem, vxlate_entry, DATA_TYPEf,
   3168                                     _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP);
   3169         } else
   3170 #endif
   3171     {
   3172         mem = VLAN_XLATEm;
   3173         soc_mem_field32_set(unit, mem, vxlate_entry, VALIDf, 0x1);
   3174     }
   3175 
   3176         soc_mem_field32_set(unit, mem, vxlate_entry,
   3177             KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP);
   3178         soc_mem_field32_set(unit, mem, vxlate_entry, VXLAN_DIP__DIPf, mc_ip_addr);
   3179 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3180     if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   3181         soc_mem_field32_set(unit, mem, vxlate_entry, VXLAN_DIP__OVIDf, vlan);
   3182     }
   3183 #endif
   3184     }
   3185     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index,
   3186                             vxlate_entry, vxlate_entry, 0);
   3187     
   3188     if (rv == SOC_E_NONE) {
   3189         net_receiver = tunnel_mc_states ? 0x1 : 0x0;
   3190 
   3191         if (net_receiver != soc_mem_field32_get(unit, mem,
   3192             vxlate_entry, BCM_VXLAN_DIP_FIELD(d,NETWORK_RECEIVERS_PRESENTf))) {
   3193             soc_mem_field32_set(unit, mem, vxlate_entry,
   3194                 BCM_VXLAN_DIP_FIELD(d,NETWORK_RECEIVERS_PRESENTf), net_receiver);
   3195             if (net_receiver) {
   3196                 _bcm_td2_vxlan_bud_loopback_enable(unit);
   3197             }
   3198             BCM_IF_ERROR_RETURN(
   3199                 soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, vxlate_entry));
   3200         }
   3201     }
   3202 
   3203     return BCM_E_NONE;
   3204 }
   3205 
   3206 /*  
   3207  * Function:
   3208  *      bcm_td2_vxlan_tunnel_terminator_create
   3209  * Purpose:
   3210  *      Set VXLAN Tunnel terminator
   3211  * Parameters:
   3212  *      unit - Device Number
   3213  *      tnl_info
   3214  * Returns:
   3215  *      BCM_E_XXX
   3216  */
   3217 int
   3218 bcm_td2_vxlan_tunnel_terminator_create(int unit, bcm_tunnel_terminator_t *tnl_info)
   3219 {
   3220     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   3221     int index=-1, tunnel_idx=-1;
   3222     soc_mem_t mem;
   3223     uint32 vxlate_entry[SOC_MAX_MEM_WORDS];
   3224     int rv = BCM_E_NONE;
   3225 
   3226     if (tnl_info->type != bcmTunnelTypeVxlan) {
   3227        return BCM_E_PARAM;
   3228     }
   3229 
   3230 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3231     if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   3232         VLAN_CHK_ID(unit, tnl_info->vlan);
   3233     }
   3234 #endif
   3235 
   3236     /* Program tunnel id */
   3237     if (tnl_info->flags & BCM_TUNNEL_TERM_TUNNEL_WITH_ID) {
   3238         if (!BCM_GPORT_IS_TUNNEL(tnl_info->tunnel_id)) {
   3239             return BCM_E_PARAM;
   3240         }
   3241         if ((0 == tnl_info->dip) || (0 == tnl_info->sip)) {
   3242             return BCM_E_PARAM; 
   3243         }
   3244         tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(tnl_info->tunnel_id);
   3245         _BCM_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx);
   3246     } else {
   3247         /* Only BCM_TUNNEL_TERM_TUNNEL_WITH_ID supported */
   3248         /* Use tunnel_id retuned by _create */
   3249         return BCM_E_PARAM; 
   3250     }
   3251 
   3252     vxlan_info = VXLAN_INFO(unit);
   3253 
   3254     if ((0 != vxlan_info->vxlan_tunnel_term[tunnel_idx].dip) && 
   3255         (vxlan_info->vxlan_tunnel_term[tunnel_idx].dip != tnl_info->dip)) {
   3256         /* Entry exists with the same idx*/
   3257         return BCM_E_EXISTS;
   3258     }
   3259 
   3260 #if defined(BCM_TRIDENT3_SUPPORT)
   3261     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   3262         mem = MPLS_ENTRY_SINGLEm;
   3263     } else
   3264 #endif
   3265     {
   3266         mem = VLAN_XLATEm;
   3267     }
   3268 
   3269     /* Search Tunnel term-entry for given DIP to Hardware */
   3270     (void)_bcm_td2_vxlan_tunnel_terminate_entry_key_set(unit, tnl_info, vxlate_entry, 0, 1);
   3271     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, vxlate_entry, vxlate_entry, 0);
   3272     if (rv == SOC_E_NOT_FOUND) {
   3273         /* Insert Tunnel term-entry */
   3274         (void)_bcm_td2_vxlan_tunnel_terminate_entry_key_set(unit, tnl_info, vxlate_entry, 0, 0);
   3275         rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, vxlate_entry);
   3276     } else if (rv != SOC_E_NONE) {
   3277         return rv;
   3278     }
   3279 
   3280     sal_memset(&(vxlan_info->vxlan_tunnel_term[tunnel_idx]), 0, sizeof(_bcm_vxlan_tunnel_endpoint_t));
   3281     if (BCM_SUCCESS(rv) && (tunnel_idx != -1)) {
   3282        vxlan_info->vxlan_tunnel_term[tunnel_idx].sip = tnl_info->sip;
   3283        vxlan_info->vxlan_tunnel_term[tunnel_idx].dip = tnl_info->dip;
   3284        vxlan_info->vxlan_tunnel_term[tunnel_idx].vlan = tnl_info->vlan;
   3285        vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state = _BCM_VXLAN_TUNNEL_TERM_MULTICAST_LEAF;
   3286        vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag |= _BCM_VXLAN_TUNNEL_TERM_ENABLE;
   3287        if (tnl_info->flags & BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE) {    
   3288            vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag |= 
   3289                 _BCM_VXLAN_TUNNEL_TERM_UDP_CHECKSUM_ENABLE;
   3290        }
   3291        if (tnl_info->flags & BCM_TUNNEL_TERM_USE_OUTER_DSCP) {
   3292            vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag |=
   3293                _BCM_VXLAN_TUNNEL_TERM_USE_OUTER_DSCP;
   3294        } else if (tnl_info->flags & BCM_TUNNEL_TERM_USE_OUTER_PCP) {
   3295            vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag |=
   3296                _BCM_VXLAN_TUNNEL_TERM_USE_OUTER_PCP;
   3297        }
   3298     }
   3299     return rv;
   3300 }
   3301 
   3302 /*  
   3303  * Function:
   3304  *      bcm_td2_vxlan_tunnel_terminator_update
   3305  * Purpose:
   3306  *     Update VXLAN Tunnel terminator multicast state
   3307  * Parameters:
   3308  *      unit - Device Number
   3309  *      tnl_info
   3310  * Returns:
   3311  *      BCM_E_XXX
   3312  */
   3313 int
   3314 bcm_td2_vxlan_tunnel_terminator_update(int unit, bcm_tunnel_terminator_t *tnl_info)
   3315 {
   3316     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   3317     int rv = BCM_E_NONE;
   3318     int tunnel_idx=-1, index=-1;
   3319     uint32  tunnel_dip=0;
   3320     soc_mem_t mem;
   3321     uint32 vxlate_entry[SOC_MAX_MEM_WORDS];
   3322 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3323     bcm_vlan_t    vlan = 0;
   3324 #endif
   3325     int d = 0; /*vxlan decoupled mode*/
   3326 
   3327     vxlan_info = VXLAN_INFO(unit);
   3328 
   3329     /* Program tunnel id */
   3330     if (tnl_info->flags & BCM_TUNNEL_TERM_TUNNEL_WITH_ID) {
   3331         if (!BCM_GPORT_IS_TUNNEL(tnl_info->tunnel_id)) {
   3332             return BCM_E_PARAM;
   3333         }
   3334         tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(tnl_info->tunnel_id);
   3335         _BCM_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx);
   3336     } else {
   3337         /* Only BCM_TUNNEL_TERM_TUNNEL_WITH_ID supported */
   3338         /* Use tunnel_id retuned by _create */
   3339         return BCM_E_PARAM; 
   3340     }
   3341 
   3342 
   3343     tunnel_dip = vxlan_info->vxlan_tunnel_term[tunnel_idx].dip;
   3344 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3345     vlan = vxlan_info->vxlan_tunnel_term[tunnel_idx].vlan;
   3346 #endif
   3347 
   3348     sal_memset(vxlate_entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   3349 #if defined(BCM_TRIDENT3_SUPPORT)
   3350     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   3351         bcm_tunnel_terminator_t tnl_info_1;
   3352 
   3353         d = 1;
   3354         mem = MPLS_ENTRY_SINGLEm;
   3355         bcm_tunnel_terminator_t_init(&tnl_info_1);
   3356         tnl_info_1.dip = tunnel_dip;
   3357         _bcm_td2_vxlan_tunnel_terminate_entry_key_set(unit, &tnl_info_1, vxlate_entry, 0, 1);
   3358     } else
   3359 #endif 
   3360     {
   3361 #if defined(BCM_TRIDENT3_SUPPORT)
   3362         if (soc_feature(unit, soc_feature_base_valid)) {
   3363             mem = VLAN_XLATE_1_DOUBLEm;
   3364 
   3365             soc_mem_field32_set(unit, mem, vxlate_entry, BASE_VALID_0f, 3);
   3366             soc_mem_field32_set(unit, mem, vxlate_entry, BASE_VALID_1f, 7);
   3367             soc_mem_field32_set(unit, mem, vxlate_entry, DATA_TYPEf,
   3368                                     _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP);
   3369         } else
   3370 #endif
   3371     {
   3372         mem = VLAN_XLATEm;
   3373         soc_mem_field32_set(unit, mem, vxlate_entry, VALIDf, 0x1);
   3374     }
   3375 
   3376         soc_mem_field32_set(unit, mem, vxlate_entry,
   3377             KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP);
   3378         soc_mem_field32_set(unit, mem, vxlate_entry, VXLAN_DIP__DIPf, tunnel_dip);
   3379 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3380     if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   3381         soc_mem_field32_set(unit, mem, vxlate_entry, VXLAN_DIP__OVIDf, vlan);
   3382     }
   3383 #endif
   3384     }
   3385     if (tnl_info->flags & BCM_TUNNEL_TERM_TUNNEL_DEACTIVATE) {        
   3386         rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index,
   3387                                  vxlate_entry, vxlate_entry, 0);
   3388         if (rv == BCM_E_NONE) {
   3389             rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, vxlate_entry);
   3390             if (BCM_FAILURE(rv)) {
   3391                  return rv;
   3392             }
   3393         } else if (rv != BCM_E_NOT_FOUND) {
   3394             return rv;
   3395         }  
   3396         vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag &= (~_BCM_VXLAN_TUNNEL_TERM_ENABLE);
   3397         return BCM_E_NONE;
   3398     } else if (!(vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag & _BCM_VXLAN_TUNNEL_TERM_ENABLE)) {    
   3399         if (vxlan_info->vxlan_tunnel_term[tunnel_idx].dip != 0) {
   3400             soc_mem_field32_set(unit, mem, vxlate_entry, BCM_VXLAN_DIP_FIELD(d,IGNORE_UDP_CHECKSUMf),
   3401                    (vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag
   3402                    & _BCM_VXLAN_TUNNEL_TERM_UDP_CHECKSUM_ENABLE) ? 0x0 : 0x1);
   3403             if (vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag &
   3404                 _BCM_VXLAN_TUNNEL_TERM_USE_OUTER_DSCP) {
   3405                 soc_mem_field32_set(unit, mem, vxlate_entry, BCM_VXLAN_DIP_FIELD(d,USE_OUTER_HEADER_PHBf), 0x1);
   3406             } else if (vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag &
   3407                 _BCM_VXLAN_TUNNEL_TERM_USE_OUTER_PCP) {
   3408                 soc_mem_field32_set(unit, mem, vxlate_entry, BCM_VXLAN_DIP_FIELD(d,USE_OUTER_HEADER_PHBf), 0x2);
   3409             }
   3410 				   
   3411             rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, vxlate_entry, vxlate_entry, 0);
   3412             if (rv == BCM_E_NOT_FOUND) {
   3413                 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, vxlate_entry);
   3414                 if (BCM_FAILURE(rv)) {
   3415                      return rv;
   3416                 }
   3417             } else if (rv != BCM_E_NONE) {
   3418                 return rv;
   3419             }
   3420             vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag |= _BCM_VXLAN_TUNNEL_TERM_ENABLE;
   3421         }
   3422     }
   3423 
   3424     rv = bcm_td2_vxlan_multicast_leaf_entry_check(unit, tunnel_idx,
   3425                                                   tnl_info->multicast_flag);
   3426     return rv;
   3427 }
   3428 
   3429 /*
   3430  * Function:
   3431  *  bcm_td2_vxlan_tunnel_terminate_destroy
   3432  * Purpose:
   3433  *  Destroy VXLAN  tunnel_terminate Entry 
   3434  * Parameters:
   3435  *  IN :  Unit
   3436  *  IN :  vxlan_tunnel_id
   3437  * Returns:
   3438  *  BCM_E_XXX
   3439  */
   3440 
   3441 int
   3442 bcm_td2_vxlan_tunnel_terminator_destroy(int unit, bcm_gport_t vxlan_tunnel_id)
   3443 {
   3444     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   3445     int tunnel_idx=-1, index=-1;
   3446     soc_mem_t mem;
   3447     uint32 vxlate_entry[SOC_MAX_MEM_WORDS];
   3448     uint32  tunnel_dip=0;
   3449     int rv = BCM_E_NONE;
   3450 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3451     bcm_vlan_t    vlan = 0;
   3452 #endif
   3453     int d = 0; /*vxlan decoupled mode*/
   3454 
   3455     if (!BCM_GPORT_IS_TUNNEL(vxlan_tunnel_id)) {
   3456         return BCM_E_PARAM;
   3457     }
   3458     tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(vxlan_tunnel_id);
   3459     _BCM_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx);
   3460 
   3461     vxlan_info = VXLAN_INFO(unit);
   3462 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3463     vlan = vxlan_info->vxlan_tunnel_term[tunnel_idx].vlan;
   3464 #endif
   3465     tunnel_dip = vxlan_info->vxlan_tunnel_term[tunnel_idx].dip;
   3466     if (tunnel_dip == 0) {
   3467         return BCM_E_NOT_FOUND;
   3468     }
   3469 
   3470     if (!(_BCM_VXLAN_TUNNEL_TERM_ENABLE &
   3471         vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag)) {
   3472         /* Deactivated tunnel terminator can not be destroyed */
   3473         return BCM_E_DISABLED;
   3474     }
   3475 
   3476     sal_memset(vxlate_entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   3477     /* Remove Tunnel term-entry for given DIP from Hardware based on ref-count */
   3478     if (_bcm_td2_vxlan_tunnel_terminator_reference_count(unit, tunnel_dip, 2) == 1)  {
   3479 #if defined(BCM_TRIDENT3_SUPPORT)
   3480         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   3481             bcm_tunnel_terminator_t tnl_info;
   3482 
   3483             mem = MPLS_ENTRY_SINGLEm;
   3484             d = 1;
   3485             bcm_tunnel_terminator_t_init(&tnl_info);
   3486             _bcm_td2_vxlan_tunnel_terminate_entry_key_set(unit, &tnl_info,
   3487                            vxlate_entry, 0, 1);
   3488         } else
   3489 #endif
   3490         {
   3491             mem = VLAN_XLATEm;
   3492             soc_mem_field32_set(unit, mem, vxlate_entry, VALIDf, 0x1);
   3493             soc_mem_field32_set(unit, mem, vxlate_entry,
   3494                 KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP);
   3495         }
   3496          soc_mem_field32_set(unit, mem, vxlate_entry, BCM_VXLAN_DIP_FIELD(d,DIPf), tunnel_dip);
   3497 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3498          if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   3499              soc_mem_field32_set(unit, mem, vxlate_entry, VXLAN_DIP__OVIDf, vlan);
   3500          }
   3501 #endif
   3502          soc_mem_field32_set(unit, mem, vxlate_entry,
   3503                 BCM_VXLAN_DIP_FIELD(d,NETWORK_RECEIVERS_PRESENTf), 0);
   3504 
   3505          rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY,
   3506                 &index, vxlate_entry, vxlate_entry, 0);
   3507          if (BCM_FAILURE(rv)) {
   3508               return rv;
   3509          }
   3510          /* Delete the entry from HW */
   3511          rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, vxlate_entry);
   3512          if (BCM_FAILURE(rv)) {
   3513               return rv;
   3514          }
   3515     }
   3516 
   3517     /* Activate the entry , then Delete the entry */
   3518     if (BCM_SUCCESS(rv) && (tunnel_idx != -1) && 
   3519         (vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag & _BCM_VXLAN_TUNNEL_TERM_ENABLE)) {
   3520        vxlan_info->vxlan_tunnel_term[tunnel_idx].dip = 0;
   3521        vxlan_info->vxlan_tunnel_term[tunnel_idx].vlan = 0;
   3522        vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state = _BCM_VXLAN_TUNNEL_TERM_MULTICAST_LEAF;       
   3523        vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag = 0;
   3524     }
   3525  
   3526     return rv;
   3527 }
   3528 
   3529 /*
   3530  * Function:
   3531  *      bcm_td2_vxlan_tunnel_terminator_destroy_all
   3532  * Purpose:
   3533  *      Destroy all incoming VXLAN tunnel
   3534  * Parameters:
   3535  *      unit           - (IN) Device Number
   3536  */
   3537 int
   3538 bcm_td2_vxlan_tunnel_terminator_destroy_all(int unit) 
   3539 {
   3540     soc_mem_t vxlate_mem;
   3541     _bcm_td2_vxlan_bookkeeping_t *vxlan_info = VXLAN_INFO(unit);
   3542     int rv = BCM_E_UNAVAIL, tnl_idx=0,num_vp=0;
   3543     uint32 *vtab, *vtabp;
   3544     int i, imin, imax, nent;
   3545     int d = 0; /*vxlan decoupled mode*/
   3546 
   3547 #if defined(BCM_TRIDENT3_SUPPORT)
   3548     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   3549         d = 1;
   3550         vxlate_mem = MPLS_ENTRY_SINGLEm;
   3551     } else
   3552 #endif
   3553     {
   3554         vxlate_mem = VLAN_XLATEm;
   3555     }
   3556 
   3557     if (!SOC_HW_RESET(unit) && (SOC_SWITCH_BYPASS_MODE(unit) == SOC_SWITCH_BYPASS_MODE_NONE)) {
   3558         imin = soc_mem_index_min(unit, vxlate_mem);
   3559         imax = soc_mem_index_max(unit, vxlate_mem);
   3560         nent = soc_mem_index_count(unit, vxlate_mem);
   3561 
   3562         vtab = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, vxlate_mem), "vlan_xlate");
   3563         if (vtab == NULL) {
   3564             return BCM_E_MEMORY;
   3565         }
   3566         sal_memset(vtab, 0, SOC_MEM_TABLE_BYTES(unit, vxlate_mem));
   3567 
   3568         soc_mem_lock(unit, vxlate_mem);
   3569         rv = soc_mem_read_range(unit, vxlate_mem, MEM_BLOCK_ANY,
   3570                                 imin, imax, vtab);
   3571         if (BCM_FAILURE(rv)) {
   3572             soc_mem_unlock(unit, vxlate_mem);
   3573             soc_cm_sfree(unit, vtab);
   3574             return rv; 
   3575         }
   3576         for (i = 0; i < nent; i++) {
   3577             vtabp = soc_mem_table_idx_to_pointer(unit, vxlate_mem,
   3578                                                  void *, vtab, i);
   3579 
   3580 #if defined(BCM_TRIDENT3_SUPPORT)
   3581             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   3582                 if (soc_mem_field32_get(unit, vxlate_mem,
   3583                         vtabp, BASE_VALIDf) != 1) {
   3584                     continue;
   3585                 }
   3586                 if (soc_mem_field32_get(unit, vxlate_mem, vtabp, DATA_TYPEf)
   3587                                                 != _BCM_VXLAN_DATA_TYPE_LOOKUP_DIP_IN_MPLS_ENTRY) {
   3588                     continue;
   3589                 }
   3590             } else
   3591 #endif
   3592             {
   3593                 if (!soc_mem_field32_get(unit, vxlate_mem, vtabp, VALIDf)) {
   3594                     continue;
   3595                 }
   3596             }
   3597 
   3598             if (soc_mem_field32_get(unit, vxlate_mem, vtabp, KEY_TYPEf) != 
   3599                 (d ? _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP_IN_MPLS_ENTRY : _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP)) {
   3600                 continue;
   3601             }
   3602             /* Delete the entry from HW */
   3603             rv = soc_mem_delete(unit, vxlate_mem, MEM_BLOCK_ALL, vtabp);
   3604             if (BCM_FAILURE(rv)) {
   3605                 soc_mem_unlock(unit, vxlate_mem);
   3606                 soc_cm_sfree(unit, vtab);
   3607                 return rv;
   3608             }
   3609         }
   3610         soc_mem_unlock(unit, vxlate_mem);
   3611         soc_cm_sfree(unit, vtab);
   3612     }
   3613 
   3614     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   3615     for (tnl_idx = 0; tnl_idx < num_vp; tnl_idx++) {
   3616        vxlan_info->vxlan_tunnel_term[tnl_idx].dip = 0;
   3617        vxlan_info->vxlan_tunnel_term[tnl_idx].vlan = 0;
   3618        vxlan_info->vxlan_tunnel_term[tnl_idx].tunnel_state = 0;
   3619     }
   3620 
   3621     return BCM_E_NONE;
   3622 }
   3623 
   3624 /*
   3625  * Function:
   3626  *      bcm_td2_vxlan_tunnel_initiator_get
   3627  * Purpose:
   3628  *      Get VXLAN  tunnel_terminate Entry
   3629  * Parameters:
   3630  *      unit    - (IN) Device Number
   3631  *      info    - (IN/OUT) Tunnel terminator structure
   3632  */
   3633 int
   3634 bcm_td2_vxlan_tunnel_terminator_get(int unit, bcm_tunnel_terminator_t *tnl_info)
   3635 {
   3636     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   3637     int tunnel_idx=-1, index=-1;
   3638     soc_mem_t mem;
   3639     uint32 vxlate_entry[SOC_MAX_MEM_WORDS];
   3640     uint32  tunnel_dip=0;
   3641     int rv = BCM_E_UNAVAIL;
   3642 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3643     bcm_vlan_t vlan = 0;
   3644 #endif
   3645     int d = 0; /*vxlan decoupled mode*/
   3646 
   3647     /* Program tunnel id */
   3648     if (!BCM_GPORT_IS_TUNNEL(tnl_info->tunnel_id)) {
   3649         return BCM_E_PARAM;
   3650     }
   3651     tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(tnl_info->tunnel_id);
   3652     _BCM_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx);
   3653 
   3654     vxlan_info = VXLAN_INFO(unit);
   3655     tunnel_dip = vxlan_info->vxlan_tunnel_term[tunnel_idx].dip;
   3656 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3657     vlan = vxlan_info->vxlan_tunnel_term[tunnel_idx].vlan;
   3658 #endif
   3659 
   3660      sal_memset(vxlate_entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   3661 #if defined(BCM_TRIDENT3_SUPPORT)
   3662     if (soc_feature(unit, soc_feature_base_valid)) {
   3663         mem = MPLS_ENTRY_SINGLEm;
   3664         d = 1;
   3665         soc_mem_field32_set(unit, mem, vxlate_entry, BASE_VALIDf, 1);
   3666         soc_mem_field32_set(unit, mem, vxlate_entry, DATA_TYPEf,
   3667                                 _BCM_VXLAN_DATA_TYPE_LOOKUP_DIP_IN_MPLS_ENTRY);
   3668         soc_mem_field32_set(unit, mem, vxlate_entry, KEY_TYPEf,
   3669                                 _BCM_VXLAN_DATA_TYPE_LOOKUP_DIP_IN_MPLS_ENTRY);
   3670     } else
   3671 #endif
   3672     {
   3673         mem = VLAN_XLATEm;
   3674         soc_mem_field32_set(unit, mem, vxlate_entry, VALIDf, 0x1);
   3675         soc_mem_field32_set(unit, mem, vxlate_entry, KEY_TYPEf,
   3676                                _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP);
   3677     }
   3678 
   3679     soc_mem_field32_set(unit, mem, vxlate_entry, BCM_VXLAN_DIP_FIELD(d,DIPf), tunnel_dip);
   3680 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3681     if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   3682         soc_mem_field32_set(unit, mem, vxlate_entry, VXLAN_DIP__OVIDf, vlan);
   3683     }
   3684 #endif
   3685 
   3686     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY,
   3687             &index, vxlate_entry, vxlate_entry, 0);
   3688     
   3689     /* not exist or  De-activated */
   3690     if (rv == BCM_E_NOT_FOUND) {
   3691         if (!(vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag & _BCM_VXLAN_TUNNEL_TERM_ENABLE) && 
   3692            (vxlan_info->vxlan_tunnel_term[tunnel_idx].dip != 0)) {
   3693             tnl_info->flags |= BCM_TUNNEL_TERM_TUNNEL_DEACTIVATE;
   3694         } else {
   3695             return rv; 
   3696         }
   3697     } else if (rv != BCM_E_NONE) {
   3698         return rv;    
   3699     }
   3700 
   3701     tnl_info->sip = vxlan_info->vxlan_tunnel_term[tunnel_idx].sip;
   3702     tnl_info->dip = vxlan_info->vxlan_tunnel_term[tunnel_idx].dip;
   3703     tnl_info->vlan = vxlan_info->vxlan_tunnel_term[tunnel_idx].vlan;
   3704     tnl_info->type = bcmTunnelTypeVxlan;
   3705     if (vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state == _BCM_VXLAN_TUNNEL_TERM_MULTICAST_BUD) {
   3706         tnl_info->multicast_flag = BCM_VXLAN_MULTICAST_TUNNEL_STATE_BUD_ENABLE;
   3707     } else if (vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state == _BCM_VXLAN_TUNNEL_TERM_MULTICAST_LEAF){
   3708         tnl_info->multicast_flag = BCM_VXLAN_MULTICAST_TUNNEL_STATE_BUD_DISABLE;
   3709     } else {
   3710         tnl_info->multicast_flag = 0;
   3711     }
   3712 
   3713     if (vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag & _BCM_VXLAN_TUNNEL_TERM_UDP_CHECKSUM_ENABLE) {
   3714         tnl_info->flags |= BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE;
   3715     }
   3716 
   3717     if (vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag &
   3718         _BCM_VXLAN_TUNNEL_TERM_USE_OUTER_DSCP) {
   3719         tnl_info->flags |= BCM_TUNNEL_TERM_USE_OUTER_DSCP;
   3720     } else if (vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag &
   3721         _BCM_VXLAN_TUNNEL_TERM_USE_OUTER_PCP) {
   3722         tnl_info->flags |= BCM_TUNNEL_TERM_USE_OUTER_PCP;
   3723     }
   3724 
   3725     return BCM_E_NONE;
   3726 }
   3727 
   3728 /*
   3729  * Function:
   3730  *      bcm_td2_vxlan_tunnel_terminator_traverse
   3731  * Purpose:
   3732  *      Traverse VXLAN tunnel terminator entries
   3733  * Parameters:
   3734  *      unit    - (IN) Device Number
   3735  *      cb    - (IN) User callback function, called once per entry
   3736  *      user_data    - (IN) User supplied cookie used in parameter in callback function 
   3737  */
   3738 int
   3739 bcm_td2_vxlan_tunnel_terminator_traverse(int unit, bcm_tunnel_terminator_traverse_cb cb, void *user_data)
   3740 {
   3741     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   3742     int num_tnl = 0, idx = 0;
   3743     bcm_tunnel_terminator_t info;
   3744     int rv = BCM_E_NONE;
   3745 
   3746     vxlan_info = VXLAN_INFO(unit);
   3747     num_tnl = soc_mem_index_count(unit, SOURCE_VPm);
   3748 
   3749     /* Iterate over all the entries - search valid ones. */
   3750     for(idx = 0; idx < num_tnl; idx++) {
   3751         /* Check a valid entry */
   3752         if ((vxlan_info->vxlan_tunnel_term[idx].dip) 
   3753             || (vxlan_info->vxlan_tunnel_term[idx].sip)){
   3754             /* Reset buffer before read. */
   3755             bcm_tunnel_terminator_t_init(&info);
   3756 
   3757             BCM_GPORT_TUNNEL_ID_SET(info.tunnel_id, idx);
   3758 
   3759             rv = bcm_td2_vxlan_tunnel_terminator_get(unit,&info);
   3760 
   3761             /* search failure */
   3762             if (BCM_FAILURE(rv)) {
   3763                 if (rv != BCM_E_NOT_FOUND) {
   3764                     break;
   3765                 }
   3766                 continue;
   3767             }            
   3768 
   3769             if (cb) {
   3770                 rv = (*cb) (unit, &info, user_data);
   3771 #ifdef BCM_CB_ABORT_ON_ERR
   3772                 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   3773                     break;
   3774                 }
   3775 #endif
   3776             }
   3777         }
   3778     }
   3779 
   3780     /* Reset last read status. */
   3781     if (BCM_E_NOT_FOUND == rv) {
   3782         rv = BCM_E_NONE;
   3783     }
   3784 
   3785     return rv;
   3786 }
   3787 
   3788 /*
   3789  * Function:
   3790  *      _bcm_td2_vxlan_tunnel_init_add
   3791  * Purpose:
   3792  *      Add tunnel initiator entry to hw. 
   3793  * Parameters:
   3794  *      unit     - (IN)SOC unit number.
   3795  *      idx      - (IN)Index to insert tunnel initiator.
   3796  *      info     - (IN)Tunnel initiator entry info.
   3797  * Returns:
   3798  *      BCM_E_XXX
   3799  */
   3800 STATIC int
   3801 _bcm_td2_vxlan_tunnel_init_add(int unit, int idx, bcm_tunnel_initiator_t *info)
   3802 {
   3803     uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to write hw entry */
   3804     soc_mem_t mem;                        /* Tunnel initiator table memory */  
   3805     int rv = BCM_E_NONE;                  /* Return value                  */
   3806     int df_val=0;                           /* Don't fragment encoding       */
   3807 
   3808     mem = EGR_IP_TUNNELm; 
   3809 
   3810     /* Zero write buffer. */
   3811     sal_memset(tnl_entry, 0, sizeof(tnl_entry));
   3812 
   3813     /* If replacing existing entry, first read the entry to get old 
   3814        profile pointer and TPID */
   3815     if (info->flags & BCM_TUNNEL_REPLACE) {
   3816         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, tnl_entry);
   3817         BCM_IF_ERROR_RETURN(rv);
   3818     }
   3819 
   3820     /* Set source address only within Tunnel Table */
   3821     soc_mem_field_set(unit, mem, tnl_entry, SIPf, (uint32 *)&info->sip);
   3822 
   3823     /* IP tunnel hdr DF bit for IPv4. */
   3824     df_val = 0;
   3825     if (info->flags & BCM_TUNNEL_INIT_USE_INNER_DF) {
   3826         df_val |= 0x2;
   3827     } else if (info->flags & BCM_TUNNEL_INIT_IPV4_SET_DF) { 
   3828         df_val |= 0x1;
   3829     }
   3830     soc_mem_field32_set(unit, mem, tnl_entry, IPV4_DF_SELf, df_val);
   3831 
   3832     /* IP tunnel hdr DF bit for IPv6. */
   3833     if (info->flags & BCM_TUNNEL_INIT_IPV6_SET_DF) { 
   3834         soc_mem_field32_set(unit, mem, tnl_entry, IPV6_DF_SELf, 1);
   3835     }
   3836 
   3837     /* Tunnel header DSCP select. */
   3838     soc_mem_field32_set(unit, mem, tnl_entry, DSCP_SELf, info->dscp_sel);
   3839 
   3840     if (info->dscp_sel == bcmTunnelDscpMap) {
   3841         /* Set DSCP_MAP value. */
   3842         int hw_map_idx = 0;
   3843         BCM_IF_ERROR_RETURN(
   3844             _bcm_tr2_qos_id2idx(unit, info->dscp_map, &hw_map_idx));
   3845         soc_mem_field32_set(unit, mem, tnl_entry,
   3846                             DSCP_MAPPING_PTRf, hw_map_idx);
   3847     } else {
   3848         /* Set DSCP value. */
   3849         soc_mem_field32_set(unit, mem, tnl_entry, DSCPf, info->dscp);
   3850     }
   3851 
   3852     /* Set TTL. */
   3853     soc_mem_field32_set(unit, mem, tnl_entry, TTLf, info->ttl);
   3854 
   3855     /* Set UDP Dest Port */
   3856     soc_mem_field32_set(unit, mem, tnl_entry, L4_DEST_PORTf, info->udp_dst_port);
   3857 
   3858     /* Set UDP Src Port */
   3859     soc_mem_field32_set(unit, mem, tnl_entry, L4_SRC_PORTf, info->udp_src_port);
   3860 
   3861     /* Set Tunnel type = VXLAN */
   3862     soc_mem_field32_set(unit, mem, tnl_entry, TUNNEL_TYPEf, _BCM_VXLAN_TUNNEL_TYPE);
   3863 
   3864     /* Set entry type = IPv4 */
   3865 #if defined(BCM_TRIDENT3_SUPPORT)
   3866     if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
   3867         soc_mem_field32_set(unit, mem, tnl_entry, DATA_TYPEf, 0x1);
   3868     } else
   3869 #endif
   3870     {
   3871         soc_mem_field32_set(unit, mem, tnl_entry, ENTRY_TYPEf, 0x1);
   3872     }
   3873 
   3874     if ((info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_FIXED) ||
   3875         (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_RANDOM)) {
   3876         int val;
   3877         uint16 random;
   3878 #if defined(BCM_TRIDENT3_SUPPORT)
   3879         if (SOC_IS_TRIDENT3X(unit)) {
   3880             uint64 rval;
   3881             uint32 base_idx;
   3882             egr_sequence_number_table_entry_t entry;
   3883 
   3884             BCM_IF_ERROR_RETURN(READ_EGR_SEQUENCE_NUMBER_CTRLr(unit, &rval));
   3885             base_idx = soc_reg64_field32_get(unit, EGR_SEQUENCE_NUMBER_CTRLr,
   3886                 rval,EGR_IP_TUNNEL_OFFSET_BASEf);
   3887 
   3888             BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_SEQUENCE_NUMBER_TABLEm,
   3889                 MEM_BLOCK_ANY, idx + base_idx, &entry));
   3890             if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_FIXED) {
   3891                 soc_EGR_SEQUENCE_NUMBER_TABLEm_field32_set(unit, &entry,
   3892                                                        SEQUENCE_NUMBERf,
   3893                                                        info->ip4_id);
   3894             } else if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_RANDOM) {
   3895                 random = (uint16) (sal_time_usecs() & 0xFFFF);
   3896                 soc_EGR_SEQUENCE_NUMBER_TABLEm_field32_set(unit, &entry,
   3897                                                        SEQUENCE_NUMBERf,
   3898                                                        random);
   3899             }
   3900             BCM_IF_ERROR_RETURN(soc_mem_write(
   3901                 unit, EGR_SEQUENCE_NUMBER_TABLEm, MEM_BLOCK_ANY,
   3902                 idx + base_idx, &entry));
   3903         } else
   3904 #endif
   3905         {
   3906             BCM_IF_ERROR_RETURN(
   3907                 bcm_esw_switch_control_get(unit, bcmSwitchTunnelIp4IdShared, &val));
   3908             if (val == 0) {
   3909                 egr_fragment_id_table_entry_t entry;
   3910                 sal_memset(&entry, 0, sizeof(egr_fragment_id_table_entry_t));
   3911 
   3912                 if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_FIXED) {
   3913                     soc_EGR_FRAGMENT_ID_TABLEm_field32_set(unit, &entry,
   3914                                                            FRAGMENT_IDf,
   3915                                                            info->ip4_id);
   3916                 } else if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_RANDOM) {
   3917                     random = (uint16) (sal_time_usecs() & 0xFFFF);
   3918                     soc_EGR_FRAGMENT_ID_TABLEm_field32_set(unit, &entry,
   3919                                                            FRAGMENT_IDf,
   3920                                                            random);
   3921                 }
   3922                 BCM_IF_ERROR_RETURN(soc_mem_write(
   3923                     unit, EGR_FRAGMENT_ID_TABLEm, SOC_BLOCK_ALL, idx, &entry));
   3924             }
   3925         }
   3926     }
   3927 
   3928     /* Write buffer to hw. */
   3929     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, tnl_entry);
   3930     return rv;
   3931 
   3932 }
   3933 
   3934 /*  
   3935  * Function:
   3936  *      _bcm_td2_vxlan_tunnel_initiator_entry_add
   3937  * Purpose:
   3938  *      Configure VXLAN Tunnel initiator hardware Entry
   3939  * Returns:
   3940  *      BCM_E_XXX
   3941  */
   3942 STATIC int
   3943 _bcm_td2_vxlan_tunnel_initiator_entry_add(int unit, uint32 flags, bcm_tunnel_initiator_t *info, int *tnl_idx)
   3944 {
   3945    int rv = BCM_E_NONE;
   3946 
   3947    rv = bcm_xgs3_tnl_init_add(unit, flags, info, tnl_idx);
   3948    if (BCM_FAILURE(rv)) {
   3949          return rv;
   3950    }
   3951    /* Write the entry to HW */
   3952    rv = _bcm_td2_vxlan_tunnel_init_add(unit, *tnl_idx, info);
   3953    if (BCM_FAILURE(rv)) {
   3954         flags = _BCM_L3_SHR_WRITE_DISABLE;
   3955         (void) bcm_xgs3_tnl_init_del(unit, flags, *tnl_idx);
   3956    }
   3957    return rv;
   3958 }
   3959 
   3960 /*
   3961   * Function:
   3962   *      _bcm_td2_vxlan_tunnel_initiator_get_tunnel_id
   3963   * Purpose:
   3964   *      Get an available tunnel id for vxlan tunnel initiator
   3965   * Parameters:
   3966   *      unit - (IN) SOC unit number.
   3967   *      info - (IN) the informaton of tunnel initiator
   3968   *      hw_match_flag - (IN) Indicate if an existing EGR_IP_TUNNEL entry
   3969   *      soft_tnl_idx - (out) Tunnel id for tunnel initiator
   3970   *      new_id_flag - (out) Indicate if a new free tunnel id
   3971   * Returns:
   3972   *      BCM_E_XXX
   3973   */
   3974 STATIC int
   3975 _bcm_td2_vxlan_tunnel_initiator_get_tunnel_id(int unit,
   3976     bcm_tunnel_initiator_t *info, int hw_match_flag, 
   3977     int *soft_tnl_idx, int *new_id_flag)
   3978 {
   3979     int rv = BCM_E_NONE;
   3980     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   3981     int idx = 0;
   3982     int num_vp = 0;
   3983     int free_index = -1;
   3984     int free_entry_found = 0;
   3985 
   3986     if ((NULL == info) || (NULL == soft_tnl_idx) || (NULL == new_id_flag)) {
   3987         return BCM_E_PARAM;
   3988     }
   3989 
   3990     vxlan_info = VXLAN_INFO(unit);
   3991     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   3992     *new_id_flag = FALSE;
   3993 
   3994     for (idx = 0; idx < num_vp; idx++) {
   3995         if (vxlan_info->vxlan_tunnel_init[idx].sip == info->sip &&
   3996             vxlan_info->vxlan_tunnel_init[idx].tunnel_state ==
   3997             info->udp_dst_port &&
   3998             vxlan_info->vxlan_tunnel_init[idx].dip == info->dip) {
   3999             /* Obtain existed index */
   4000             *soft_tnl_idx = idx;
   4001             return BCM_E_NONE;
   4002         }
   4003 
   4004         if (vxlan_info->vxlan_tunnel_init[idx].sip == 0 && !free_entry_found) {
   4005             /* Obtain Free index */
   4006             free_index = idx;
   4007             free_entry_found = 1;
   4008             if (!hw_match_flag) {
   4009                 break;
   4010             }
   4011         }
   4012     }
   4013 
   4014     if (free_entry_found) {
   4015         *new_id_flag = TRUE;
   4016         *soft_tnl_idx = free_index;
   4017     } else {
   4018         /* No free resource */
   4019         return BCM_E_RESOURCE;
   4020     }
   4021 
   4022     return rv;
   4023 }
   4024 
   4025 /*  
   4026  * Function:
   4027  *      bcm_td2_vxlan_tunnel_initiator_create
   4028  * Purpose:
   4029  *      Set VXLAN Tunnel initiator
   4030  * Parameters:
   4031  *      unit - Device Number
   4032  * Returns:
   4033  *      BCM_E_XXX
   4034  */
   4035 int
   4036 bcm_td2_vxlan_tunnel_initiator_create(int unit, bcm_tunnel_initiator_t *info)
   4037 {
   4038     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   4039     int tnl_idx=-1, rv = BCM_E_NONE,  ref_count=0;
   4040     uint32 flags=0;
   4041     int idx = 0, num_vp = 0;
   4042     uint8  match_entry_present=0;
   4043     int soft_tnl_idx = -1;
   4044     int new_idx_flag = FALSE;
   4045 
   4046     /* Input parameters check. */
   4047     if (NULL == info) {
   4048         return (BCM_E_PARAM);
   4049     }   
   4050     if (info->type != bcmTunnelTypeVxlan)  {
   4051         return BCM_E_PARAM;
   4052     }
   4053     if (!BCM_TTL_VALID(info->ttl)) {
   4054         return BCM_E_PARAM;
   4055     }
   4056     if (info->dscp_sel > 2 || info->dscp_sel < 0) {
   4057         return BCM_E_PARAM;
   4058     }
   4059     if (info->dscp > 63 || info->dscp < 0) {
   4060         return BCM_E_PARAM;
   4061     }
   4062     if ((0 == info->dip) || (0 == info->sip)) {
   4063         return BCM_E_PARAM; 
   4064     }
   4065    
   4066     vxlan_info = VXLAN_INFO(unit);
   4067     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   4068     if (info->flags & BCM_TUNNEL_REPLACE) {
   4069         int tunnel_idx = -1;
   4070         tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id);
   4071         _BCM_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx);
   4072         if(info->sip != vxlan_info->vxlan_tunnel_init[tunnel_idx].sip 
   4073             || info->udp_dst_port != 
   4074                 vxlan_info->vxlan_tunnel_init[tunnel_idx].tunnel_state
   4075             || info->dip != vxlan_info->vxlan_tunnel_init[tunnel_idx].dip) {
   4076             return BCM_E_UNAVAIL;
   4077         }    
   4078     }
   4079 
   4080     /* Allocate either existing or new tunnel initiator entry */
   4081     flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE |
   4082              _BCM_L3_SHR_SKIP_INDEX_ZERO;
   4083 
   4084     if (BCM_E_NONE == _bcm_xgs3_l3_tnl_init_find(unit, info, &tnl_idx)) {
   4085         match_entry_present = 1;
   4086     }
   4087     /* Get an available tunnel id */
   4088     BCM_IF_ERROR_RETURN(
   4089         _bcm_td2_vxlan_tunnel_initiator_get_tunnel_id(
   4090             unit, info, match_entry_present, &soft_tnl_idx, &new_idx_flag));
   4091 
   4092     if (match_entry_present) {
   4093         if (info->flags & BCM_TUNNEL_REPLACE) {
   4094             if (new_idx_flag) {
   4095                 return BCM_E_UNAVAIL;
   4096             }
   4097             flags |= _BCM_L3_SHR_UPDATE | _BCM_L3_SHR_WITH_ID;
   4098             /* Check for Ref-count in (SIP, multi-DIP) situation */
   4099             for (idx = 0; idx < num_vp; idx++) {
   4100                 if ((info->sip ==
   4101                     vxlan_info->vxlan_tunnel_init[idx].sip) &&
   4102                     (info->udp_dst_port ==
   4103                     vxlan_info->vxlan_tunnel_init[idx].tunnel_state)) {
   4104                     if (++ref_count > 1) {
   4105                         return BCM_E_RESOURCE;
   4106                     }
   4107                 }
   4108             }
   4109             rv = _bcm_td2_vxlan_tunnel_initiator_entry_add(
   4110                 unit, flags, info, &tnl_idx);
   4111             if (BCM_FAILURE(rv)) {
   4112                 return rv;
   4113             }
   4114         }
   4115     } else {
   4116          /* Parse tunnel replace flag */
   4117          if (info->flags & BCM_TUNNEL_REPLACE) {
   4118              /* replace an inexistent tunnel initiator */
   4119              return BCM_E_NOT_FOUND;
   4120          }
   4121          rv = _bcm_td2_vxlan_tunnel_initiator_entry_add(unit, flags, info, &tnl_idx);
   4122          if (BCM_FAILURE(rv)) {
   4123              return rv;
   4124          }
   4125     }
   4126 
   4127     if (soft_tnl_idx !=- 1) {
   4128          vxlan_info->vxlan_tunnel_init[soft_tnl_idx].sip = info->sip;
   4129          vxlan_info->vxlan_tunnel_init[soft_tnl_idx].dip = info->dip;
   4130          vxlan_info->vxlan_tunnel_init[soft_tnl_idx].tunnel_state = info->udp_dst_port;
   4131          BCM_GPORT_TUNNEL_ID_SET(info->tunnel_id, soft_tnl_idx);
   4132     } else {
   4133         return BCM_E_NOT_FOUND;
   4134     }
   4135 
   4136     return rv;
   4137 }
   4138 
   4139 /*
   4140  * Function:
   4141  *      _bcm_td2_vxlan_tunnel_init_get
   4142  * Purpose:
   4143  *      Get a tunnel initiator entry from hw. 
   4144  * Parameters:
   4145  *      unit     - (IN)SOC unit number.
   4146  *      idx      - (IN/OUT)Index to read tunnel initiator.
   4147  *      info     - (OUT)Tunnel initiator entry info.
   4148  * Returns:
   4149  *      BCM_E_XXX
   4150  */
   4151 STATIC int
   4152 _bcm_td2_vxlan_tunnel_init_get(int unit, int *hw_idx, bcm_tunnel_initiator_t *info)
   4153 {
   4154     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   4155     egr_fragment_id_table_entry_t entry;
   4156     uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry.  */
   4157     soc_mem_t mem;                         /* Tunnel initiator table memory.*/  
   4158     int df_val=0;                            /* Don't fragment encoded value. */
   4159     int tnl_type=0;                          /* Tunnel type.                  */
   4160     uint32 entry_type = BCM_XGS3_TUNNEL_INIT_V4;/* Entry type (IPv4/IPv6/MPLS)*/
   4161     int idx = 0;
   4162 
   4163     /* Get table memory. */
   4164     mem = EGR_IP_TUNNELm; 
   4165     idx = *hw_idx;
   4166 
   4167     /* Initialize the buffer. */
   4168     sal_memset(tnl_entry, 0, sizeof(tnl_entry));
   4169     vxlan_info = VXLAN_INFO(unit);
   4170     info->dip = vxlan_info->vxlan_tunnel_init[idx].dip;
   4171     BCM_IF_ERROR_RETURN(
   4172         _bcm_td2_vxlan_tunnel_initiator_idx_translate(unit, idx, hw_idx));
   4173     BCM_IF_ERROR_RETURN(
   4174          soc_mem_read(unit, mem, MEM_BLOCK_ANY, *hw_idx, tnl_entry));
   4175 
   4176     /* Get tunnel type. */
   4177     tnl_type = soc_mem_field32_get(unit, mem, tnl_entry, TUNNEL_TYPEf);
   4178     if (tnl_type != _BCM_VXLAN_TUNNEL_TYPE) {
   4179         return BCM_E_NOT_FOUND;
   4180     }
   4181 
   4182     /* Get entry_type. */
   4183 #if defined(BCM_TRIDENT3_SUPPORT)
   4184     if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
   4185         entry_type = soc_mem_field32_get(unit, mem, tnl_entry, DATA_TYPEf);
   4186     } else
   4187 #endif
   4188     {
   4189         entry_type = soc_mem_field32_get(unit, mem, tnl_entry, ENTRY_TYPEf);
   4190     }
   4191     if (entry_type != 0x1) {
   4192         return BCM_E_NOT_FOUND;
   4193     }
   4194 
   4195     /* Parse hw buffer. */
   4196     /* Check will not fail. entry_type already validated */
   4197     if (BCM_XGS3_TUNNEL_INIT_V4 == entry_type) {
   4198         /* Get source ip. */
   4199         info->sip = soc_mem_field32_get(unit, mem, tnl_entry, SIPf);
   4200     } 
   4201 
   4202     /* Tunnel header DSCP select. */
   4203     info->dscp_sel = soc_mem_field32_get(unit, mem, tnl_entry, DSCP_SELf);
   4204 
   4205     if (info->dscp_sel == bcmTunnelDscpMap) {
   4206         /* Tunnel header DSCP_MAP value. */
   4207         BCM_IF_ERROR_RETURN(
   4208             _bcm_tr2_qos_idx2id(unit, soc_mem_field32_get(unit, mem, tnl_entry,
   4209                                                           DSCP_MAPPING_PTRf),
   4210                                 _BCM_QOS_MAP_TYPE_EGR_DSCP_TABLE,
   4211                                 &info->dscp_map));
   4212     } else {
   4213         /* Tunnel header DSCP value. */
   4214         info->dscp = soc_mem_field32_get(unit, mem, tnl_entry, DSCPf);
   4215     }
   4216 
   4217     /* IP tunnel hdr DF bit for IPv4 */
   4218     df_val = soc_mem_field32_get(unit, mem, tnl_entry, IPV4_DF_SELf);
   4219     if (0x2 <= df_val) {
   4220         info->flags |= BCM_TUNNEL_INIT_USE_INNER_DF;  
   4221     } else if (0x1 == df_val) {
   4222         info->flags |= BCM_TUNNEL_INIT_IPV4_SET_DF;  
   4223     }
   4224 
   4225     df_val = soc_mem_field32_get(unit, mem, tnl_entry, IPV6_DF_SELf);
   4226     if (0x1 == df_val) {
   4227         info->flags |= BCM_TUNNEL_INIT_IPV6_SET_DF;  
   4228     }
   4229 
   4230     /* Get TTL. */
   4231     info->ttl = soc_mem_field32_get(unit, mem, tnl_entry, TTLf);
   4232 
   4233     /* Get UDP Dest Port */
   4234     info->udp_dst_port = soc_mem_field32_get(unit, mem, tnl_entry, L4_DEST_PORTf);
   4235 
   4236     /* Get UDP Src Port */
   4237     info->udp_src_port = soc_mem_field32_get(unit, mem, tnl_entry, L4_SRC_PORTf);
   4238 
   4239     /* Translate hw tunnel type into API encoding. - bcmTunnelTypeVxlan */
   4240     BCM_IF_ERROR_RETURN(_bcm_trx_tnl_hw_code_to_type(unit, tnl_type,
   4241                                                      entry_type,
   4242                                                      &info->type));
   4243 #if defined(BCM_TRIDENT3_SUPPORT)
   4244     if (SOC_IS_TRIDENT3X(unit)) {
   4245         uint64 rval;
   4246         uint32 base_idx;
   4247 
   4248         BCM_IF_ERROR_RETURN(READ_EGR_SEQUENCE_NUMBER_CTRLr(unit, &rval));
   4249         base_idx = soc_reg64_field32_get(unit, EGR_SEQUENCE_NUMBER_CTRLr, rval,
   4250             EGR_IP_TUNNEL_OFFSET_BASEf);
   4251         BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_SEQUENCE_NUMBER_TABLEm,
   4252             MEM_BLOCK_ANY, idx + base_idx, &entry));
   4253         info->ip4_id = soc_mem_field32_get(unit, EGR_SEQUENCE_NUMBER_TABLEm,
   4254             &entry, SEQUENCE_NUMBERf);
   4255     } else
   4256 #endif
   4257     {
   4258         BCM_IF_ERROR_RETURN(soc_mem_read(
   4259             unit, EGR_FRAGMENT_ID_TABLEm, MEM_BLOCK_ANY, *hw_idx, &entry));
   4260         info->ip4_id = soc_mem_field32_get(
   4261             unit, EGR_FRAGMENT_ID_TABLEm, &entry, FRAGMENT_IDf);
   4262     }
   4263 
   4264     *hw_idx = idx;
   4265     return BCM_E_NONE;
   4266 }
   4267 
   4268 /*
   4269  * Function:
   4270  *      bcm_td2_vxlan_tunnel_initiator_destroy
   4271  * Purpose:
   4272  *      Destroy outgoing VXLAN tunnel
   4273  * Parameters:
   4274  *      unit           - (IN) Device Number
   4275  *      vxlan_tunnel_id - (IN) Tunnel ID (Gport)
   4276  */
   4277 int
   4278 bcm_td2_vxlan_tunnel_initiator_destroy(int unit, bcm_gport_t vxlan_tunnel_id) 
   4279 {
   4280     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   4281     int tnl_idx=-1, temp_tnl_idx=-1, rv = BCM_E_NONE, ref_count=0, idx=0;
   4282     uint32 flags = 0;
   4283     int num_vp=0;
   4284     bcm_ip_t sip=0;                       /* Tunnel header SIP (IPv4). */
   4285     uint16 udp_dst_port;                /* Destination UDP port */
   4286 
   4287     vxlan_info = VXLAN_INFO(unit);
   4288     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   4289 
   4290     /* Input parameters check. */
   4291     if (!BCM_GPORT_IS_TUNNEL(vxlan_tunnel_id)) {
   4292         return BCM_E_PARAM;
   4293     }
   4294     tnl_idx = BCM_GPORT_TUNNEL_ID_GET(vxlan_tunnel_id);
   4295     _BCM_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tnl_idx);
   4296 
   4297     sip = vxlan_info->vxlan_tunnel_init[tnl_idx].sip;
   4298     udp_dst_port =  vxlan_info->vxlan_tunnel_init[tnl_idx].tunnel_state;
   4299     if (sip == 0) {
   4300         return BCM_E_NOT_FOUND;
   4301     }
   4302     /* Remove HW TNL entry only if all matching SIP, UDP_DEST_PORT gets removed */
   4303     for (idx=0; idx < num_vp; idx++) {
   4304         if ((vxlan_info->vxlan_tunnel_init[idx].sip == sip) &&
   4305              (vxlan_info->vxlan_tunnel_init[idx].tunnel_state == udp_dst_port)) {
   4306                 ref_count++;
   4307         }
   4308     }
   4309 
   4310     if (ref_count == 1) {
   4311        /* Get the entry first */
   4312        temp_tnl_idx = tnl_idx;
   4313        BCM_IF_ERROR_RETURN(
   4314            _bcm_td2_vxlan_tunnel_initiator_idx_translate(
   4315                unit, temp_tnl_idx, &tnl_idx));
   4316        /* Destroy the tunnel entry */
   4317        (void) bcm_xgs3_tnl_init_del(unit, flags, tnl_idx);
   4318        vxlan_info->vxlan_tunnel_init[temp_tnl_idx].sip = 0;
   4319        vxlan_info->vxlan_tunnel_init[temp_tnl_idx].dip = 0;
   4320        vxlan_info->vxlan_tunnel_init[temp_tnl_idx].tunnel_state = 0;
   4321     } else if (ref_count) {
   4322        vxlan_info->vxlan_tunnel_init[tnl_idx].sip = 0;
   4323        vxlan_info->vxlan_tunnel_init[tnl_idx].dip = 0;
   4324        vxlan_info->vxlan_tunnel_init[tnl_idx].tunnel_state = 0;
   4325     }
   4326     return rv;
   4327 }
   4328 
   4329 /*
   4330  * Function:
   4331  *      bcm_td2_vxlan_tunnel_initiator_destroy_all
   4332  * Purpose:
   4333  *      Destroy all outgoing VXLAN tunnel
   4334  * Parameters:
   4335  *      unit           - (IN) Device Number
   4336  */
   4337 int
   4338 bcm_td2_vxlan_tunnel_initiator_destroy_all(int unit) 
   4339 {
   4340     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   4341     soc_field_t type_field;
   4342     egr_ip_tunnel_entry_t *tnl_entry, *tnl_entries;
   4343     int rv = BCM_E_NONE, tnl_idx, num_entries, num_vp;
   4344 
   4345     vxlan_info = VXLAN_INFO(unit);
   4346     num_entries = soc_mem_index_count(unit, EGR_IP_TUNNELm);
   4347     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   4348 
   4349 #if defined(BCM_TRIDENT3_SUPPORT)
   4350     if (SOC_MEM_FIELD_VALID(unit, EGR_IP_TUNNELm, DATA_TYPEf)) {
   4351         type_field = DATA_TYPEf;
   4352     } else
   4353 #endif
   4354     {
   4355         type_field = ENTRY_TYPEf;
   4356     }
   4357 
   4358     tnl_entries = soc_cm_salloc(unit, num_entries * sizeof(*tnl_entries),
   4359                                 "egr_ip_tunnel");
   4360     if (tnl_entries == NULL) {
   4361         return BCM_E_MEMORY;
   4362     }
   4363     sal_memset(tnl_entries, 0, num_entries * sizeof(*tnl_entries));
   4364 
   4365     soc_mem_lock(unit, EGR_IP_TUNNELm);
   4366     rv = soc_mem_read_range(unit, EGR_IP_TUNNELm, MEM_BLOCK_ANY,
   4367                             0, num_entries - 1, tnl_entries);
   4368     if (BCM_FAILURE(rv)) {
   4369         soc_mem_unlock(unit, EGR_IP_TUNNELm);
   4370         soc_cm_sfree(unit, tnl_entries);
   4371         return rv; 
   4372     }
   4373 
   4374     for (tnl_idx = 0; tnl_idx < num_entries; tnl_idx++) {
   4375         tnl_entry = soc_mem_table_idx_to_pointer(unit, EGR_IP_TUNNELm,
   4376                                  egr_ip_tunnel_entry_t *, tnl_entries, tnl_idx);
   4377 
   4378         vxlan_info->vxlan_tunnel_init[tnl_idx].sip = 0;
   4379         vxlan_info->vxlan_tunnel_init[tnl_idx].dip = 0;
   4380         vxlan_info->vxlan_tunnel_init[tnl_idx].tunnel_state = 0;
   4381 
   4382         if (!soc_EGR_IP_TUNNELm_field32_get(unit, tnl_entry, type_field)) {
   4383             continue;
   4384         }
   4385         if (soc_EGR_IP_TUNNELm_field32_get(unit, tnl_entry,
   4386                                       TUNNEL_TYPEf) != _BCM_VXLAN_TUNNEL_TYPE) {
   4387             continue;
   4388         }
   4389 
   4390        /* Delete the entry from HW */
   4391        (void) bcm_xgs3_tnl_init_del(unit, 0, tnl_idx);
   4392 
   4393         vxlan_info->vxlan_tunnel_init[tnl_idx].sip = 0;
   4394         vxlan_info->vxlan_tunnel_init[tnl_idx].dip = 0;
   4395         vxlan_info->vxlan_tunnel_init[tnl_idx].tunnel_state = 0;
   4396     }
   4397     soc_mem_unlock(unit, EGR_IP_TUNNELm);
   4398     soc_cm_sfree(unit, tnl_entries);
   4399 
   4400     for (tnl_idx = num_entries; tnl_idx < num_vp; tnl_idx++) {
   4401          vxlan_info->vxlan_tunnel_init[tnl_idx].sip = 0;
   4402          vxlan_info->vxlan_tunnel_init[tnl_idx].dip = 0;
   4403          vxlan_info->vxlan_tunnel_init[tnl_idx].tunnel_state = 0;
   4404     }
   4405     return BCM_E_NONE;
   4406 
   4407 }
   4408 
   4409 /*
   4410  * Function:
   4411  *      bcm_td2_vxlan_tunnel_initiator_get
   4412  * Purpose:
   4413  *      Get an outgong VXLAN tunnel info
   4414  * Parameters:
   4415  *      unit    - (IN) Device Number
   4416  *      info    - (IN/OUT) Tunnel initiator structure
   4417  */
   4418 int
   4419 bcm_td2_vxlan_tunnel_initiator_get(int unit, bcm_tunnel_initiator_t *info)
   4420 {
   4421     int tnl_idx=-1, rv = BCM_E_NONE;
   4422 
   4423     /* Input parameters check. */
   4424     if (info == NULL) {
   4425         return BCM_E_PARAM;
   4426     }
   4427     if (!BCM_GPORT_IS_TUNNEL(info->tunnel_id)) {
   4428         return BCM_E_PARAM;
   4429     }
   4430     tnl_idx = BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id);
   4431     _BCM_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tnl_idx);
   4432 
   4433     /* Get the entry */
   4434     rv = _bcm_td2_vxlan_tunnel_init_get(unit, &tnl_idx, info);
   4435     return rv;
   4436 }
   4437 
   4438 /*
   4439  * Function:
   4440  *      bcm_td2_vxlan_tunnel_initiator_traverse
   4441  * Purpose:
   4442  *      Traverse VXLAN tunnel initiator entries
   4443  * Parameters:
   4444  *      unit    - (IN) Device Number
   4445  *      cb    - (IN) User callback function, called once per entry
   4446  *      user_data    - (IN) User supplied cookie used in parameter in callback function 
   4447  */
   4448 int
   4449 bcm_td2_vxlan_tunnel_initiator_traverse(int unit, bcm_tunnel_initiator_traverse_cb cb, void *user_data)
   4450 {
   4451     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   4452     int num_vp = 0, idx = 0;
   4453     bcm_tunnel_initiator_t info;
   4454     int rv = BCM_E_NONE;
   4455 
   4456     vxlan_info = VXLAN_INFO(unit);
   4457     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   4458 
   4459     /* Iterate over all the entries - search valid ones. */
   4460     for(idx = 0; idx < num_vp; idx++) {
   4461         /* Check a valid entry */
   4462         if (vxlan_info->vxlan_tunnel_init[idx].sip != 0) {
   4463             /* Reset buffer before read. */
   4464             bcm_tunnel_initiator_t_init(&info);
   4465 
   4466             BCM_GPORT_TUNNEL_ID_SET(info.tunnel_id, idx);
   4467             rv = bcm_td2_vxlan_tunnel_initiator_get(unit, &info);
   4468 
   4469             /* search failure */
   4470             if (BCM_FAILURE(rv)) {
   4471                 if (rv != BCM_E_NOT_FOUND) {
   4472                     break;
   4473                 }
   4474                 continue;
   4475             }  
   4476 
   4477             if (cb) {
   4478                 rv = (*cb) (unit, &info, user_data);
   4479 #ifdef BCM_CB_ABORT_ON_ERR
   4480                 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   4481                     break;
   4482                 }
   4483 #endif
   4484             }   
   4485         }
   4486     }
   4487 
   4488     /* Reset last read status. */
   4489     if (BCM_E_NOT_FOUND == rv) {
   4490         rv = BCM_E_NONE;
   4491     }
   4492 
   4493     return rv;
   4494 }
   4495 
   4496 /*
   4497   * Function:
   4498   *      _bcm_td2_vxlan_tunnel_initiator_idx_translate
   4499   * Purpose:
   4500   *      Translate the index of software object to the index 
   4501   *      of hw entry for tunnel initiator
   4502   * Parameters:
   4503   *      unit     - (IN) SOC unit number.
   4504   *      soft_idx - (IN) The index of software object 
   4505   *      hw_idx   - (IN) The index of hw entry
   4506   * Returns:
   4507   *      BCM_E_XXX
   4508   */
   4509 STATIC int
   4510 _bcm_td2_vxlan_tunnel_initiator_idx_translate(int unit, int soft_idx, 
   4511                                                      int *hw_idx)
   4512 {
   4513     bcm_tunnel_initiator_t init_tnl_info;
   4514     int rv = BCM_E_NONE;
   4515     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   4516     vxlan_info = VXLAN_INFO(unit);
   4517 
   4518     if (NULL == hw_idx) {
   4519         return BCM_E_PARAM;
   4520     }
   4521 
   4522     bcm_tunnel_initiator_t_init(&init_tnl_info);
   4523     init_tnl_info.type = bcmTunnelTypeVxlan;
   4524     init_tnl_info.sip =  vxlan_info->vxlan_tunnel_init[soft_idx].sip;
   4525     init_tnl_info.udp_dst_port = 
   4526         vxlan_info->vxlan_tunnel_init[soft_idx].tunnel_state;
   4527 
   4528     rv = _bcm_xgs3_l3_tnl_init_find(unit, &init_tnl_info, hw_idx);
   4529 
   4530     return rv;
   4531 }
   4532 
   4533 /*
   4534   * Function:
   4535   *      _bcm_td2_vxlan_tunnel_initiator_cmp
   4536   * Purpose:
   4537   *      Routine compares vxlan tunnel initiator entry with entry in the chip
   4538   *      with specified index.
   4539   * Parameters:
   4540   *      unit       - (IN) SOC unit number.
   4541   *      buf        - (IN) Tunnel initiator entry to compare.
   4542   *      index      - (IN) Entry index in the chip to compare.
   4543   *      cmp_result - (OUT)Compare result.
   4544   * Returns:
   4545   *      BCM_E_XXX
   4546   */
   4547 int
   4548 _bcm_td2_vxlan_tunnel_initiator_cmp(int unit, void *buf, 
   4549                                           int index, int *cmp_result)
   4550 {
   4551     bcm_tunnel_initiator_t hw_entry;   /* Entry read from hw */
   4552     bcm_tunnel_initiator_t *tnl_entry; /* Api passed buffer */
   4553     int rv = BCM_E_NONE;
   4554 
   4555     if ((NULL == buf) || (NULL == cmp_result)) {
   4556         return BCM_E_PARAM;
   4557     }
   4558 
   4559     *cmp_result = BCM_L3_CMP_NOT_EQUAL;
   4560 
   4561     /* Copy buffer to structure */
   4562     tnl_entry = (bcm_tunnel_initiator_t *)buf;
   4563 
   4564     /* Initialization */
   4565     bcm_tunnel_initiator_t_init(&hw_entry);
   4566 
   4567     /* Get tunnel initiator entry from hw */
   4568     if (BCM_XGS3_L3_HWCALL_CHECK(unit, tnl_init_get)) {
   4569         BCM_XGS3_L3_MODULE_LOCK(unit);
   4570         rv = (BCM_XGS3_L3_HWCALL_EXEC(unit, tnl_init_get)(
   4571             unit, index, &hw_entry));
   4572         BCM_XGS3_L3_MODULE_UNLOCK(unit);
   4573         BCM_IF_ERROR_RETURN(rv);
   4574     } else {
   4575         return BCM_E_UNAVAIL;
   4576     }
   4577 
   4578     /* Compare source ip */
   4579     if (tnl_entry->sip != hw_entry.sip) {
   4580         return BCM_E_NONE;
   4581     }
   4582                 
   4583     /* Compare udp dst port */
   4584     if (tnl_entry->udp_dst_port != hw_entry.udp_dst_port) {
   4585         return BCM_E_NONE;
   4586     }
   4587             
   4588     *cmp_result = BCM_L3_CMP_EQUAL;
   4589     return BCM_E_NONE;
   4590 }
   4591 
   4592 /*
   4593  * Function:
   4594  *      _bcm_td2_vxlan_tunnel_initiator_hash_calc
   4595  * Purpose:
   4596  *      Calculate tunnel initiator entry hash(signature).
   4597  * Parameters:
   4598  *      unit - (IN) SOC unit number.
   4599  *      buf  - (IN) Tunnel initiator entry information.
   4600  *      hash - (OUT)Hash(signature) calculated value.
   4601  * Returns:
   4602  *      BCM_X_XXX
   4603  */
   4604 int
   4605 _bcm_td2_vxlan_tunnel_initiator_hash_calc(int unit, void *buf, uint16 *hash)
   4606 {
   4607 
   4608     bcm_tunnel_initiator_t tnl_entry;
   4609 
   4610     if ((NULL == buf) || (NULL == hash)) {
   4611         return (BCM_E_PARAM);
   4612     }
   4613 
   4614     bcm_tunnel_initiator_t_init(&tnl_entry);
   4615     tnl_entry.type = ((bcm_tunnel_initiator_t *)buf)->type;
   4616 
   4617     /* Set source ip */
   4618     tnl_entry.sip = ((bcm_tunnel_initiator_t *)buf)->sip;
   4619 
   4620     tnl_entry.udp_dst_port =
   4621         ((bcm_tunnel_initiator_t *)buf)->udp_dst_port;
   4622     /* Calculate hash */
   4623     *hash = _shr_crc16(0, (uint8 *)&tnl_entry,
   4624         sizeof(bcm_tunnel_initiator_t));
   4625     return BCM_E_NONE;
   4626 }
   4627 
   4628 /*
   4629  * Function:
   4630  *     _bcm_td2_vxlan_ingress_dvp_set
   4631  * Purpose:
   4632  *     Set Ingress DVP tables
   4633  * Parameters:
   4634  *   IN :  Unit
   4635  *   IN :  vp
   4636  *   IN :  vxlan_port
   4637  * Returns:
   4638  *   BCM_E_XXX
   4639  */
   4640 
   4641 STATIC int
   4642 _bcm_td2_vxlan_ingress_dvp_set(int unit, int vp, uint32 mpath_flag,
   4643                                     int vp_nh_ecmp_index, bcm_vxlan_port_t *vxlan_port)
   4644 {
   4645     ing_dvp_table_entry_t dvp;
   4646     int network_group;
   4647     int rv = BCM_E_NONE;
   4648 
   4649          if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
   4650             BCM_IF_ERROR_RETURN(
   4651                 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   4652          } else if (vxlan_port->flags & BCM_VXLAN_PORT_WITH_ID ) {
   4653             sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t));
   4654          } else {
   4655             sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t));
   4656          }
   4657 
   4658         if (!(vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) {
   4659              if (mpath_flag) {
   4660                   soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 
   4661                                            NEXT_HOP_INDEXf, 0x0);
   4662                   soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 
   4663                                            ECMPf, 0x1);
   4664                   soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 
   4665                                            ECMP_PTRf, vp_nh_ecmp_index);
   4666              } else {
   4667                   soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 
   4668                                            ECMPf, 0x0);
   4669                   soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 
   4670                                            ECMP_PTRf, 0);
   4671                   soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 
   4672                                            NEXT_HOP_INDEXf, vp_nh_ecmp_index);
   4673              }
   4674         }
   4675 
   4676 #if defined(BCM_TRIDENT3_SUPPORT)
   4677         if (SOC_IS_TRIDENT3X(unit)) {
   4678         } else
   4679 #endif
   4680         {
   4681             network_group = vxlan_port->network_group_id;
   4682             BCM_IF_ERROR_RETURN(_bcm_validate_splithorizon_network_group(unit,
   4683                     vxlan_port->flags & BCM_VXLAN_PORT_NETWORK, &network_group));
   4684             if (vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) {
   4685                  /* Not setting dvp as network port for RIOT as all
   4686                     routed packet gets dropped if overlay SVP and DVP
   4687                     both are network ports.
   4688                     SVP and DVP as network ports is a valid used case
   4689                     but reg file says that this field
   4690                     is set when DVP is a TRILL port */
   4691 #ifdef BCM_RIOT_SUPPORT
   4692                  if ((BCMI_RIOT_IS_ENABLED(unit))) {
   4693                     /* explicitly setting it to zero. */
   4694                      if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   4695                          soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf,0x0);
   4696                      } else {
   4697                          soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 0x0);
   4698                      }
   4699                  } else
   4700 #endif
   4701                  {
   4702                      if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   4703                          soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf,
   4704                                                          network_group);
   4705                      } else {
   4706                          if (!(vxlan_port->flags &
   4707                              BCM_VXLAN_PORT_NO_SPLIT_HORIZON_INGRESS)) {
   4708                              soc_ING_DVP_TABLEm_field32_set(unit, &dvp,
   4709                                                             NETWORK_PORTf, 0x1);
   4710                          }
   4711                      }
   4712                  }
   4713             } else {
   4714                 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   4715                     soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf,
   4716                                                    network_group);
   4717                 } else {
   4718                     soc_ING_DVP_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 0x0);
   4719                 }
   4720             }
   4721         }
   4722 
   4723         if (vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) {
   4724              soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 
   4725                            VP_TYPEf, _BCM_VXLAN_INGRESS_DEST_VP_TYPE);
   4726         } else {
   4727              soc_ING_DVP_TABLEm_field32_set(unit, &dvp, 
   4728                            VP_TYPEf, _BCM_VXLAN_DEST_VP_TYPE_ACCESS);
   4729         }
   4730 
   4731         rv =  WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp);   
   4732         return rv;
   4733 }
   4734 
   4735 /*
   4736  * Function:
   4737  *     _bcm_td2_vxlan_ingress_dvp_get
   4738  * Purpose:
   4739  *     Get Ingress DVP tables
   4740  * Parameters:
   4741  *   IN :  Unit
   4742  *   IN :  vp
   4743  *   IN :  vxlan_port
   4744  * Returns:
   4745  *   BCM_E_XXX
   4746  */
   4747 
   4748 STATIC int
   4749 _bcm_td2_vxlan_ingress_dvp_get(int unit, int vp, bcm_vxlan_port_t *vxlan_port)
   4750 {
   4751     int rv = BCM_E_NONE;
   4752     ing_dvp_table_entry_t dvp;
   4753     int vp_type = 0; /* access / tunnel vp type*/
   4754     int network_port = 0;
   4755     _bcm_vp_info_t vp_info;
   4756 
   4757 #ifdef BCM_RIOT_SUPPORT
   4758     if ((BCMI_RIOT_IS_ENABLED(unit))) {
   4759         return rv;
   4760     } else
   4761 #endif
   4762     {
   4763         sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t));
   4764         BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_DVP_TABLEm,
   4765                           MEM_BLOCK_ANY, vp, &dvp));
   4766 
   4767         vp_type = soc_mem_field32_get(unit,
   4768                                       ING_DVP_TABLEm, &dvp, VP_TYPEf);
   4769         if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_PORTf) &&
   4770             (vp_type == _BCM_VXLAN_INGRESS_DEST_VP_TYPE)) {
   4771             network_port = soc_mem_field32_get(unit, ING_DVP_TABLEm, &dvp,
   4772                                                NETWORK_PORTf);
   4773             BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
   4774             if ((vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) &&
   4775                 network_port == 0) {
   4776                 vxlan_port->flags |= BCM_VXLAN_PORT_NO_SPLIT_HORIZON_INGRESS;
   4777             }
   4778         }
   4779     }
   4780 
   4781     return rv;
   4782 }
   4783 
   4784 
   4785 /*
   4786  * Function:
   4787  *     _bcm_td2_vxlan_ingress_dvp_2_set
   4788  * Purpose:
   4789  *     Set Ingress DVP tables
   4790  * Parameters:
   4791  *   IN :  Unit
   4792  *   IN :  vp
   4793  *   IN :  vxlan_port
   4794  * Returns:
   4795  *   BCM_E_XXX
   4796  */
   4797 
   4798 STATIC int
   4799 _bcm_td2_vxlan_ingress_dvp_2_set(int unit, int vp, uint32 mpath_flag,
   4800                                     int vp_nh_ecmp_index, bcm_vxlan_port_t *vxlan_port)
   4801 {
   4802     ing_dvp_2_table_entry_t dvp;
   4803     int rv = BCM_E_NONE;
   4804     int network_group=0;
   4805 
   4806          if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
   4807             BCM_IF_ERROR_RETURN(
   4808                 READ_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   4809          } else if (vxlan_port->flags & BCM_VXLAN_PORT_WITH_ID ) {
   4810             sal_memset(&dvp, 0, sizeof(ing_dvp_2_table_entry_t));
   4811          } else {
   4812             sal_memset(&dvp, 0, sizeof(ing_dvp_2_table_entry_t));
   4813          }
   4814 
   4815          if (!(vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) {
   4816              if (mpath_flag) {
   4817                   soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 
   4818                                            NEXT_HOP_INDEXf, 0x0);
   4819                   soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 
   4820                                            ECMPf, 0x1);
   4821                   soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 
   4822                                            ECMP_PTRf, vp_nh_ecmp_index);
   4823              } else {
   4824                   soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 
   4825                                            ECMPf, 0x0);
   4826                   soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 
   4827                                            ECMP_PTRf, 0);
   4828                   soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 
   4829                                            NEXT_HOP_INDEXf, vp_nh_ecmp_index);
   4830              }
   4831         }
   4832 
   4833          network_group = vxlan_port->network_group_id;
   4834          rv = _bcm_validate_splithorizon_network_group(unit,
   4835                  vxlan_port->flags & BCM_VXLAN_PORT_NETWORK, &network_group);
   4836          BCM_IF_ERROR_RETURN(rv);
   4837         /* Enable DVP as Network_port */
   4838         if (vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) {
   4839              /* Not setting dvp as network port for RIOT as all
   4840                 routed packet gets dropped if overlay SVP and DVP
   4841                 both are network ports.
   4842                 SVP and DVP as network ports is a valid used case
   4843                 but reg file says that this field
   4844                 is set when DVP is a TRILL port */
   4845 #ifdef BCM_RIOT_SUPPORT
   4846              if ((BCMI_RIOT_IS_ENABLED(unit))) {
   4847                  if (soc_feature(unit,
   4848                      soc_feature_multiple_split_horizon_group)) {
   4849                      soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp,
   4850                              NETWORK_GROUPf, 0x0);
   4851                  } else { 
   4852                      soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp,
   4853                              NETWORK_PORTf, 0x0);
   4854                  }
   4855              } else
   4856 #endif
   4857              {
   4858 
   4859                  if (soc_feature(unit, 
   4860                              soc_feature_multiple_split_horizon_group)) {
   4861                      soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf,
   4862                                  network_group);
   4863                  } else { 
   4864                      if (!(vxlan_port->flags &
   4865                          BCM_VXLAN_PORT_NO_SPLIT_HORIZON_INGRESS)) {
   4866                          soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp,
   4867                                                           NETWORK_PORTf, 0x1);
   4868                      }
   4869                  }
   4870              }
   4871              soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 
   4872                            VP_TYPEf, _BCM_VXLAN_INGRESS_DEST_VP_TYPE);
   4873         } else {
   4874 
   4875             if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   4876                 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, NETWORK_GROUPf,
   4877                             network_group);
   4878             } else { 
   4879                 soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, NETWORK_PORTf, 0x0);
   4880             }
   4881              soc_ING_DVP_2_TABLEm_field32_set(unit, &dvp, 
   4882                            VP_TYPEf, _BCM_VXLAN_DEST_VP_TYPE_ACCESS);
   4883         }
   4884 
   4885         rv =  WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp);   
   4886         return rv;
   4887 }
   4888 
   4889 
   4890 /*
   4891  * Function:
   4892  *     _bcm_td2_vxlan_ingress_dvp_reset
   4893  * Purpose:
   4894  *     Reset Ingress DVP tables
   4895  * Parameters:
   4896  *   IN :  Unit
   4897  *   IN :  vp
   4898  * Returns:
   4899  *   BCM_E_XXX
   4900  */
   4901 
   4902 STATIC int
   4903 _bcm_td2_vxlan_ingress_dvp_reset(int unit, int vp)
   4904 {
   4905     int rv=BCM_E_UNAVAIL;
   4906     ing_dvp_table_entry_t dvp;
   4907     ing_dvp_2_table_entry_t dvp_2;
   4908 
   4909   
   4910     sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t));
   4911     rv =  WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp);   
   4912     BCM_IF_ERROR_RETURN(rv); 
   4913     sal_memset(&dvp_2, 0, sizeof(ing_dvp_2_table_entry_t));
   4914     rv =  WRITE_ING_DVP_2_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp_2);  
   4915 
   4916     return rv;
   4917 }
   4918 
   4919 /*
   4920  * Function:
   4921  *     _bcm_td2_vxlan_egress_access_dvp_set
   4922  * Purpose:
   4923  *     Set Egress DVP tables - For access virtual ports
   4924  * Parameters:
   4925  *   IN :  Unit
   4926  *   IN :  vp
   4927  *   IN :  drop (unused for now)
   4928  *   IN :  vxlan_port
   4929  * Returns:
   4930  *   BCM_E_XXX
   4931  */
   4932 
   4933 STATIC int
   4934 _bcm_td2_vxlan_egress_access_dvp_set(int unit, int vp, int drop,
   4935                                      bcm_vxlan_port_t *vxlan_port)
   4936 {
   4937     int rv = BCM_E_UNAVAIL;
   4938     int network_group=0;
   4939     soc_mem_t mem = EGR_DVP_ATTRIBUTEm;
   4940     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   4941 
   4942     /* Access ports only */
   4943     if (vxlan_port->flags & BCM_VXLAN_PORT_NETWORK) {
   4944         return BCM_E_PARAM;
   4945     }
   4946 
   4947     /* Read entry and then update */
   4948     sal_memset(&egr_dvp_attribute, 0, sizeof(egr_dvp_attribute_entry_t));
   4949     rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
   4950 
   4951 #if defined(BCM_TRIDENT3_SUPPORT)
   4952     if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
   4953         soc_mem_field32_set(unit, mem, &egr_dvp_attribute,
   4954                 DATA_TYPEf, _BCM_VXLAN_DEST_VP_TYPE_ACCESS);
   4955     } else
   4956 #endif
   4957     {
   4958         soc_mem_field32_set(unit, mem, &egr_dvp_attribute,
   4959                 VP_TYPEf, _BCM_VXLAN_DEST_VP_TYPE_ACCESS);
   4960     }
   4961 
   4962 
   4963     if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   4964         network_group = vxlan_port->network_group_id;
   4965         rv = _bcm_validate_splithorizon_network_group(unit,
   4966                 vxlan_port->flags & BCM_VXLAN_PORT_NETWORK, &network_group);
   4967         BCM_IF_ERROR_RETURN(rv);
   4968 #if defined(BCM_TRIDENT3_SUPPORT)
   4969         if (SOC_MEM_FIELD_VALID(unit, mem, COMMON__DVP_NETWORK_GROUPf)) {
   4970             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   4971                     COMMON__DVP_NETWORK_GROUPf, network_group);
   4972         } else
   4973 #endif
   4974         {
   4975             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   4976                     VXLAN__DVP_NETWORK_GROUPf, network_group);
   4977         }
   4978     }
   4979 
   4980     /* L2 MTU - This is different from L3 MTU */
   4981     if (vxlan_port->mtu > 0) {
   4982         soc_mem_field32_set(unit, mem, &egr_dvp_attribute,
   4983                             COMMON__MTU_VALUEf, vxlan_port->mtu);
   4984         soc_mem_field32_set(unit, mem, &egr_dvp_attribute,
   4985                             COMMON__MTU_ENABLEf, 0x1);
   4986     } else {
   4987         /* Disable mtu checking if mtu = 0 */
   4988         soc_mem_field32_set(unit, mem, &egr_dvp_attribute,
   4989                             COMMON__MTU_ENABLEf, 0x0);
   4990     }
   4991 
   4992 
   4993     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
   4994     BCM_IF_ERROR_RETURN(rv);
   4995 
   4996     return rv;
   4997 
   4998 }
   4999 
   5000 /*
   5001  * Function:
   5002  *     _bcm_td2_vxlan_egress_dvp_set
   5003  * Purpose:
   5004  *     Set Egress DVP tables
   5005  * Parameters:
   5006  *   IN :  Unit
   5007  *   IN :  vp
   5008  *   IN :  vxlan_port
   5009  * Returns:
   5010  *   BCM_E_XXX
   5011  */
   5012 
   5013 STATIC int
   5014 _bcm_td2_vxlan_egress_dvp_set(int unit, int vp, int drop, bcm_vxlan_port_t *vxlan_port)
   5015 {
   5016     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   5017     int rv=BCM_E_UNAVAIL;
   5018     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   5019     egr_dvp_attribute_1_entry_t  egr_dvp_attribute_1;
   5020     bcm_ip_t dip=0;                       /* DIP for tunnel header */
   5021     int tunnel_index = -1;
   5022     int local_drop = 0;
   5023     int network_group=0;
   5024 
   5025     vxlan_info = VXLAN_INFO(unit);
   5026 
   5027     tunnel_index = BCM_GPORT_TUNNEL_ID_GET(vxlan_port->egress_tunnel_id);
   5028     _BCM_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_index);
   5029 
   5030     /* Obtain Tunnel DIP */
   5031     dip = vxlan_info->vxlan_tunnel_init[tunnel_index].dip;
   5032 
   5033     /* Got HW tunnel index */
   5034     BCM_IF_ERROR_RETURN(
   5035            _bcm_td2_vxlan_tunnel_initiator_idx_translate(
   5036                unit, tunnel_index, &tunnel_index));
   5037    
   5038     /* Zero write buffer. */
   5039     if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
   5040         BCM_IF_ERROR_RETURN(soc_mem_read(unit,
   5041                 EGR_DVP_ATTRIBUTEm, MEM_BLOCK_ANY, vp, &egr_dvp_attribute));
   5042     } else {
   5043         /* Zero write buffer. */
   5044         sal_memset(&egr_dvp_attribute, 0, sizeof(egr_dvp_attribute_entry_t));
   5045     }
   5046 
   5047 #if defined(BCM_TRIDENT3_SUPPORT)
   5048     if (SOC_MEM_FIELD_VALID(unit, EGR_DVP_ATTRIBUTEm, DATA_TYPEf)) {
   5049         soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   5050             &egr_dvp_attribute, DATA_TYPEf, _BCM_VXLAN_EGRESS_DEST_VP_TYPE);
   5051     } else
   5052 #endif
   5053     {
   5054         soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   5055             &egr_dvp_attribute, VP_TYPEf, _BCM_VXLAN_EGRESS_DEST_VP_TYPE);
   5056     }
   5057     soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   5058                                             VXLAN__TUNNEL_INDEXf, tunnel_index);
   5059     soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   5060                                             VXLAN__DIPf, dip);
   5061 
   5062     if (soc_feature(unit, soc_feature_multiple_split_horizon_group)){
   5063             network_group = vxlan_port->network_group_id;
   5064             rv = _bcm_validate_splithorizon_network_group(unit,
   5065                     vxlan_port->flags & BCM_VXLAN_PORT_NETWORK, &network_group);
   5066             BCM_IF_ERROR_RETURN(rv);
   5067             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   5068                     VXLAN__DVP_NETWORK_GROUPf, network_group);
   5069     } else {
   5070         if (!(vxlan_port->flags & BCM_VXLAN_PORT_NO_SPLIT_HORIZON_EGRESS)) {
   5071         soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   5072                 VXLAN__DVP_IS_NETWORK_PORTf, 0x1);
   5073     }
   5074     }
   5075     
   5076     soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   5077                                             VXLAN__DISABLE_VP_PRUNINGf, 0x0);
   5078     soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   5079                                             VXLAN__DELETE_VNTAGf, 0x1);
   5080 
   5081 #if defined(BCM_TRIDENT3_SUPPORT)
   5082     if (SOC_IS_TRIDENT3X(unit)) {
   5083         soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   5084             &egr_dvp_attribute, VXLAN__CLASS_IDf, vxlan_port->if_class);
   5085 
   5086         /* L2 MTU - This is different from L3 MTU */
   5087         if (vxlan_port->mtu > 0) {
   5088             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   5089                 &egr_dvp_attribute, VXLAN__MTU_VALUEf, vxlan_port->mtu);
   5090             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   5091                 &egr_dvp_attribute, VXLAN__MTU_ENABLEf, 0x1);
   5092         } else {
   5093             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   5094                 &egr_dvp_attribute, VXLAN__MTU_VALUEf, 0x0);
   5095             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   5096                 &egr_dvp_attribute, VXLAN__MTU_ENABLEf, 0x0);
   5097         }
   5098         if (vxlan_port->flags & BCM_VXLAN_PORT_MULTICAST) {
   5099             local_drop = drop ? 1 : 0;
   5100         }
   5101         soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   5102             &egr_dvp_attribute, VXLAN__UUC_DROPf, local_drop);
   5103         soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   5104             &egr_dvp_attribute, VXLAN__UMC_DROPf, local_drop);
   5105         soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   5106             &egr_dvp_attribute, VXLAN__BC_DROPf, local_drop);
   5107     } else
   5108 #endif
   5109     {
   5110         if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
   5111             BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_DVP_ATTRIBUTE_1m,
   5112                                 MEM_BLOCK_ANY, vp, &egr_dvp_attribute_1));
   5113         } else {
   5114             /* Zero write buffer. */
   5115             sal_memset(&egr_dvp_attribute_1, 0, sizeof(egr_dvp_attribute_1_entry_t));
   5116         }
   5117 
   5118         soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m,
   5119             &egr_dvp_attribute_1, VXLAN__CLASS_IDf, vxlan_port->if_class);
   5120         /* L2 MTU - This is different from L3 MTU */
   5121         if (vxlan_port->mtu > 0) {
   5122             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m,
   5123                 &egr_dvp_attribute_1, VXLAN__MTU_VALUEf, vxlan_port->mtu);
   5124             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m,
   5125                 &egr_dvp_attribute_1, VXLAN__MTU_ENABLEf, 0x1);
   5126         } else {
   5127             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m,
   5128                 &egr_dvp_attribute_1, VXLAN__MTU_VALUEf, 0x0);
   5129             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m,
   5130                 &egr_dvp_attribute_1, VXLAN__MTU_ENABLEf, 0x0);
   5131         }
   5132         if (vxlan_port->flags & BCM_VXLAN_PORT_MULTICAST) {
   5133             local_drop = drop ? 1 : 0;
   5134         }
   5135         soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m,
   5136             &egr_dvp_attribute_1, VXLAN__UUC_DROPf, local_drop);
   5137         soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m,
   5138             &egr_dvp_attribute_1, VXLAN__UMC_DROPf, local_drop);
   5139         soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m,
   5140             &egr_dvp_attribute_1, VXLAN__BC_DROPf, local_drop);
   5141 
   5142         BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_DVP_ATTRIBUTE_1m,
   5143                             MEM_BLOCK_ALL, vp, &egr_dvp_attribute_1));
   5144     }
   5145 
   5146 #if defined(BCM_TRIDENT3_SUPPORT)
   5147     if(SOC_MEM_FIELD_VALID(unit,EGR_DVP_ATTRIBUTEm,VXLAN__EVXLT_KEY_SELf)) {
   5148         if (vxlan_port->vnid <= 0xFFFFFF) {
   5149             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   5150                    &egr_dvp_attribute, VXLAN__EVXLT_KEY_SELf, TD2PLUS_DVP_EVLXLT_HASH_KEY_TYPE_DVP_VFI);
   5151         } else {
   5152             soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm,
   5153                &egr_dvp_attribute, VXLAN__EVXLT_KEY_SELf, TD2PLUS_DVP_EVLXLT_HASH_KEY_TYPE_VFI);
   5154         }
   5155     }
   5156 #endif
   5157 
   5158     rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTEm,
   5159             MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
   5160     return rv;
   5161 }
   5162 
   5163 
   5164 /*
   5165  * Function:
   5166  *     _bcm_td2_vxlan_egress_dvp_get
   5167  * Purpose:
   5168  *     Get Egress DVP tables
   5169  * Parameters:
   5170  *   IN :  Unit
   5171  *   IN :  vp
   5172  *   IN :  vxlan_port
   5173  * Returns:
   5174  *   BCM_E_XXX
   5175  */
   5176 
   5177 STATIC int
   5178 _bcm_td2_vxlan_egress_dvp_get(int unit, int vp, bcm_vxlan_port_t *vxlan_port)
   5179 {
   5180     _bcm_td2_vxlan_bookkeeping_t *vxlan_info;
   5181     int rv=BCM_E_NONE;
   5182     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   5183     egr_dvp_attribute_1_entry_t  egr_dvp_attribute_1;
   5184     int tunnel_index=-1;
   5185     bcm_ip_t dip=0;                       /* DIP for tunnel header */
   5186     int idx=0, num_vp=0;
   5187     int vp_type = 0; /* access / tunnel vp type*/
   5188     int network_port = 0;
   5189     _bcm_vp_info_t vp_info;
   5190 
   5191     vxlan_info = VXLAN_INFO(unit);
   5192     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   5193 
   5194     sal_memset(&egr_dvp_attribute, 0, sizeof(egr_dvp_attribute_entry_t));
   5195     rv = soc_mem_read(unit, EGR_DVP_ATTRIBUTEm,
   5196                                             MEM_BLOCK_ANY, vp, &egr_dvp_attribute);
   5197     BCM_IF_ERROR_RETURN(rv);
   5198 
   5199 #if defined(BCM_TRIDENT3_SUPPORT)
   5200     if (SOC_MEM_FIELD_VALID(unit, EGR_DVP_ATTRIBUTEm, DATA_TYPEf)) {
   5201         vp_type = soc_mem_field32_get(unit,
   5202             EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, DATA_TYPEf);
   5203     } else
   5204 #endif
   5205     {
   5206         vp_type = soc_mem_field32_get(unit,
   5207             EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, VP_TYPEf);
   5208     }
   5209 
   5210     /* Only mtu field is valid for access DVPs */
   5211     if (vp_type == 0) {
   5212         if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
   5213                     &egr_dvp_attribute, COMMON__MTU_ENABLEf)) {
   5214             vxlan_port->mtu = soc_mem_field32_get(unit,
   5215                 EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute, COMMON__MTU_VALUEf);
   5216         }
   5217         return rv;
   5218     }
   5219 
   5220     /* Extract Network port details */
   5221     dip = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 
   5222                                             &egr_dvp_attribute, VXLAN__DIPf);
   5223 
   5224     /* Find DIP within Softare State */
   5225     for (idx=0; idx < num_vp; idx++) {
   5226         if (vxlan_info->vxlan_tunnel_init[idx].dip == dip) {
   5227             tunnel_index = idx;
   5228             break;
   5229         }
   5230     }
   5231 
   5232     BCM_GPORT_TUNNEL_ID_SET(vxlan_port->egress_tunnel_id, tunnel_index);
   5233 
   5234 #if defined(BCM_TRIDENT3_SUPPORT)
   5235     if (SOC_IS_TRIDENT3X(unit)) {
   5236         vxlan_port->if_class = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
   5237                                         &egr_dvp_attribute, VXLAN__CLASS_IDf);
   5238         if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
   5239                                     &egr_dvp_attribute, VXLAN__MTU_ENABLEf)) {
   5240              vxlan_port->mtu = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
   5241                                         &egr_dvp_attribute, VXLAN__MTU_VALUEf);
   5242         }
   5243         if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
   5244                                 &egr_dvp_attribute, VXLAN__BC_DROPf)
   5245             || soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
   5246                                &egr_dvp_attribute, VXLAN__UUC_DROPf)
   5247             || soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
   5248                                &egr_dvp_attribute, VXLAN__UMC_DROPf)) {
   5249              vxlan_port->flags |= BCM_VXLAN_PORT_DROP;
   5250         }
   5251     } else
   5252 #endif
   5253     {
   5254         sal_memset(&egr_dvp_attribute_1, 0, sizeof(egr_dvp_attribute_1_entry_t));
   5255         BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_DVP_ATTRIBUTE_1m,
   5256                             MEM_BLOCK_ANY, vp, &egr_dvp_attribute_1));
   5257 
   5258         vxlan_port->if_class = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTE_1m,
   5259                                         &egr_dvp_attribute_1, VXLAN__CLASS_IDf);
   5260         if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTE_1m,
   5261                                     &egr_dvp_attribute_1, VXLAN__MTU_ENABLEf)) {
   5262              vxlan_port->mtu = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTE_1m,
   5263                                         &egr_dvp_attribute_1, VXLAN__MTU_VALUEf);
   5264         }
   5265         if (soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTE_1m,
   5266                                 &egr_dvp_attribute_1, VXLAN__BC_DROPf)
   5267             || soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTE_1m,
   5268                                &egr_dvp_attribute_1, VXLAN__UUC_DROPf)
   5269             || soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTE_1m,
   5270                                &egr_dvp_attribute_1, VXLAN__UMC_DROPf)) {
   5271              vxlan_port->flags |= BCM_VXLAN_PORT_DROP;
   5272         }
   5273     }
   5274 
   5275     if (soc_mem_field_valid(unit, EGR_DVP_ATTRIBUTEm, VXLAN__DVP_IS_NETWORK_PORTf) &&
   5276         (vp_type == _BCM_VXLAN_EGRESS_DEST_VP_TYPE)) {
   5277         network_port = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm,
   5278                                            &egr_dvp_attribute,
   5279                                            VXLAN__DVP_IS_NETWORK_PORTf);
   5280         BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
   5281         if ((vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) &&
   5282             network_port == 0) {
   5283             vxlan_port->flags |= BCM_VXLAN_PORT_NO_SPLIT_HORIZON_EGRESS;
   5284         }
   5285     }
   5286 
   5287     return rv;
   5288 }
   5289 
   5290 /*
   5291  * Function:
   5292  *      _bcm_td2_vxlan_egress_dvp_reset
   5293  * Purpose:
   5294  *      Reet Egress DVP tables
   5295  * Parameters:
   5296  *      IN :  Unit
   5297  *           IN :  vp
   5298  * Returns:
   5299  *      BCM_E_XXX
   5300  */
   5301 
   5302 STATIC int
   5303 _bcm_td2_vxlan_egress_dvp_reset(int unit, int vp)
   5304 {
   5305     uint32 dvp[SOC_MAX_MEM_WORDS];
   5306 
   5307     sal_memset(dvp, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   5308     BCM_IF_ERROR_RETURN(soc_mem_write(unit,
   5309             EGR_DVP_ATTRIBUTEm, MEM_BLOCK_ALL, vp, dvp));
   5310 
   5311     if (!SOC_IS_TRIDENT3X(unit)) {
   5312         BCM_IF_ERROR_RETURN(soc_mem_write(unit,
   5313                 EGR_DVP_ATTRIBUTE_1m, MEM_BLOCK_ALL, vp, dvp));
   5314     }
   5315 
   5316     return BCM_E_NONE;
   5317 }
   5318 
   5319 #if defined(BCM_TRIDENT3_SUPPORT)
   5320 /*
   5321  * Function:
   5322  *      _bcm_td3_vxlan_tpid_delete
   5323  * Purpose:
   5324  *      del TPID
   5325  * Parameters:
   5326  *      IN :  Unit
   5327  *      IN :  ptr of vxlate entry
   5328  *      IN :  ptr of egr nh entry
   5329  * Returns:
   5330  *      BCM_E_XXX
   5331  */
   5332 
   5333 STATIC int
   5334 _bcm_td3_vxlan_tpid_delete(int unit, uint32* vxlate, uint32* egr_nh){
   5335     int rv = BCM_E_NONE;
   5336     int profile_idx = -1;
   5337     int action_present = 0;
   5338     int action_not_present = 0;
   5339     int tpid_index = -1;
   5340 
   5341     if (vxlate != NULL) {
   5342         soc_mem_t vxlate_mem = EGR_VLAN_XLATE_1_SINGLEm; 
   5343         profile_idx = soc_mem_field32_get(unit, vxlate_mem, vxlate,
   5344                                                      VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf);
   5345         (void)_bcm_td3_sd_tag_action_get(unit, profile_idx, &action_present,
   5346                        &action_not_present);
   5347 
   5348         if (1 == action_present || 4 == action_present ||
   5349             7 == action_present || 1 == action_not_present) {
   5350             tpid_index = soc_mem_field32_get(unit,
   5351                              vxlate_mem, vxlate, 
   5352                               VXLAN_VFI_FLEX__OUTER_TPID_INDEXf);
   5353             rv = _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   5354             if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) {
   5355                 return rv;
   5356             }
   5357         }
   5358     } else if (egr_nh != NULL) {
   5359         soc_mem_t vxlate_mem = EGR_L3_NEXT_HOPm; 
   5360         profile_idx = soc_mem_field32_get(unit, vxlate_mem, egr_nh,
   5361                                                      L2_OTAG__TAG_ACTION_PROFILE_PTRf);
   5362         (void)_bcm_td3_sd_tag_action_get(unit, profile_idx, &action_present,
   5363                        &action_not_present);
   5364 
   5365         if (1 == action_present || 4 == action_present ||
   5366             7 == action_present || 1 == action_not_present) {
   5367             tpid_index = soc_mem_field32_get(unit,
   5368                              vxlate_mem, egr_nh, 
   5369                              L2_OTAG__TPID_INDEXf);
   5370             rv = _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   5371             if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) {
   5372                 return rv;
   5373             }
   5374         }
   5375     }
   5376 
   5377     return rv;
   5378 }
   5379 #endif
   5380 
   5381 /*
   5382  * Function:
   5383  *      _bcm_td2_vxlan_egr_xlate_entry_reset
   5384  * Purpose:
   5385  *      Reset VXLAN  egr_xlate Entry 
   5386  * Parameters:
   5387  *      IN :  Unit
   5388  *      IN :  vpn id
   5389  * Returns:
   5390  *      BCM_E_XXX
   5391  */
   5392 
   5393 STATIC int
   5394 _bcm_td2_vxlan_egr_xlate_entry_reset(int unit, bcm_vpn_t vpn)
   5395 {
   5396     int index = 0;
   5397     int vfi = 0;
   5398     int tpid_index = -1;
   5399     soc_mem_t vxlate_mem;
   5400     uint32 vxlate[SOC_MAX_MEM_WORDS];
   5401     int action_present = 0, action_not_present = 0;
   5402     int d = 0; /*vxlan decoupled mode*/
   5403 
   5404     sal_memset(vxlate, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   5405     _BCM_VXLAN_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
   5406 
   5407 #if defined(BCM_TRIDENT3_SUPPORT)
   5408     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   5409         vxlate_mem = EGR_VLAN_XLATE_1_SINGLEm;
   5410         d = 1;
   5411         soc_mem_field32_set(unit, vxlate_mem, vxlate, BASE_VALIDf, 1);
   5412         soc_mem_field32_set(unit, vxlate_mem, vxlate,
   5413                             KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI);
   5414         soc_mem_field32_set(unit, vxlate_mem, vxlate,
   5415                             DATA_TYPEf, _BCM_VXLAN_DATA_TYPE_LOOKUP_VFI);
   5416     } else
   5417 #endif
   5418     {
   5419         vxlate_mem = EGR_VLAN_XLATEm;
   5420         soc_mem_field32_set(unit, vxlate_mem, vxlate, VALIDf, 0x1);
   5421         soc_mem_field32_set(unit, vxlate_mem, vxlate,
   5422                     ENTRY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI);
   5423     }
   5424     soc_mem_field32_set(unit, vxlate_mem, vxlate, BCM_VXLAN_VFI_FIELD(d,VFIf), vfi);
   5425 
   5426     BCM_IF_ERROR_RETURN(soc_mem_search(unit, vxlate_mem,
   5427                 MEM_BLOCK_ANY, &index, vxlate, vxlate, 0));
   5428 #if defined(BCM_TRIDENT3_SUPPORT)
   5429     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   5430         _bcm_td3_vxlan_tpid_delete(unit, vxlate, NULL);
   5431     
   5432     } else
   5433 #endif
   5434     {
   5435         /* If tpid entry exist, delete it */
   5436         action_present = soc_mem_field32_get(unit, vxlate_mem,
   5437                             vxlate, VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf);
   5438         action_not_present = soc_mem_field32_get(unit, vxlate_mem,
   5439                             vxlate, VXLAN_VFI__SD_TAG_ACTION_IF_NOT_PRESENTf);
   5440         if (1 == action_present || 4 == action_present ||
   5441             7 == action_present || 1 == action_not_present) {
   5442             tpid_index = soc_mem_field32_get(unit, vxlate_mem,
   5443                             vxlate, VXLAN_VFI__SD_TAG_TPID_INDEXf);
   5444             BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_delete(unit, tpid_index));
   5445         }
   5446     }
   5447 
   5448     /* Delete the entry from HW */
   5449     BCM_IF_ERROR_RETURN(soc_mem_delete(unit, vxlate_mem, MEM_BLOCK_ALL, vxlate));
   5450 
   5451     return BCM_E_NONE;
   5452 }
   5453 
   5454 /*
   5455  * Function:
   5456  *      _bcm_td2_vxlan_port_untagged_profile_set
   5457  * Purpose:
   5458  *      Set  VLan profile per Physical port entry
   5459  * Parameters:
   5460  *      unit   - (IN) SOC unit #
   5461  *      port  - (IN) Physical port
   5462  * Returns:
   5463  *      BCM_E_XXX
   5464  */     
   5465 
   5466 STATIC int
   5467 _bcm_td2_vxlan_port_untagged_profile_set (int unit, bcm_port_t port)
   5468 {
   5469     int rv=BCM_E_NONE;
   5470     bcm_vlan_action_set_t action;
   5471     uint32 ing_profile_idx = 0xffffffff;
   5472 
   5473 #if defined(BCM_TRIDENT3_SUPPORT)
   5474     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   5475           return BCM_E_NONE;
   5476     }
   5477 #endif
   5478 
   5479     bcm_vlan_action_set_t_init(&action);
   5480     action.ut_outer = 0x0; /* No Op */
   5481     action.ut_inner = 0x0; /* No Op */
   5482 
   5483     rv = _bcm_trx_vlan_action_profile_entry_add(unit, &action, &ing_profile_idx);
   5484     if (rv < 0) {
   5485         return rv;
   5486     }
   5487 
   5488     rv = _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE,
   5489                                TAG_ACTION_PROFILE_PTRf, ing_profile_idx);
   5490     return rv;
   5491 }
   5492 
   5493 /*
   5494  * Function:
   5495  *      _bcm_td2_vxlan_port_untagged_profile_reset
   5496  * Purpose:
   5497  *      Reset  VLan profile per Physical port entry
   5498  * Parameters:
   5499  *      unit   - (IN) SOC unit #
   5500  *      port  - (IN) Physical port
   5501  * Returns:
   5502  *      BCM_E_XXX
   5503  */     
   5504 
   5505 STATIC int
   5506 _bcm_td2_vxlan_port_untagged_profile_reset(int unit, bcm_port_t port)
   5507 {
   5508     int rv = BCM_E_NONE;
   5509     int ing_profile_idx = -1;
   5510     int def_profile_idx = 0;
   5511 
   5512     SOC_IF_ERROR_RETURN(
   5513         _bcm_esw_port_tab_get(unit, port, TAG_ACTION_PROFILE_PTRf,
   5514                               &ing_profile_idx));
   5515 #if defined(BCM_TRIDENT3_SUPPORT)
   5516     if (SOC_IS_TRIDENT3X(unit) && (ing_profile_idx == 0)) {
   5517         /*index 0 is invalid in Ingress Vlan Tag Action Profile*/
   5518         return rv;
   5519     }
   5520 #endif
   5521     rv = _bcm_trx_vlan_action_profile_entry_delete(unit, ing_profile_idx);
   5522     if (rv < 0) {
   5523         return rv;
   5524     }
   5525     /* default profile defined in _bcm_trx_vlan_action_profile_init */
   5526     if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) {
   5527         def_profile_idx = 1;
   5528     }
   5529 
   5530     rv = _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE,
   5531                                TAG_ACTION_PROFILE_PTRf, def_profile_idx);
   5532 
   5533     return rv;
   5534 }
   5535 
   5536 #if defined(BCM_TRIDENT3_SUPPORT)
   5537 /*
   5538  * Function:
   5539  *      _bcm_td3_vxlan_vlan_action_set
   5540  * Purpose:
   5541  *      Program  SD_TAG settings
   5542  * Parameters:
   5543  *      unit           - (IN)  SOC unit #
   5544  *      vxlan_port  - (IN)  VXLAN VP
   5545  *      egr_nh_info  (IN/OUT) Egress NHop Info
   5546  * Returns:
   5547  *      BCM_E_XXX
   5548  */     
   5549 
   5550 STATIC int
   5551 _bcm_td3_vxlan_vlan_action_set( int unit, bcm_vxlan_vpn_config_t *vxlan_vpn_info, 
   5552                          bcm_vxlan_port_t *vxlan_port, 
   5553                          uint32   *vxlate_entry,
   5554                          int *tpid_index )
   5555 {
   5556     soc_mem_t  hw_mem = EGR_VLAN_XLATE_1_SINGLEm;
   5557     soc_field_t vid_fld = VXLAN_VFI_FLEX__OVIDf;
   5558     soc_field_t pri_fld = VXLAN_VFI_FLEX__OPRIf;
   5559     soc_field_t cfi_fld = VXLAN_VFI_FLEX__OCFIf;
   5560     soc_field_t pri_cfi_sel_fld = VXLAN_VFI_FLEX__OPRI_OCFI_SELf;
   5561     int action_if_not_prt = 0;
   5562     int action_prt = 0;
   5563     uint32 profile_index = -1;
   5564 
   5565     if (vxlan_vpn_info != NULL ) {
   5566         if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_ADD) {
   5567             if (vxlan_vpn_info->egress_service_vlan >= BCM_VLAN_INVALID) {
   5568                 return  BCM_E_PARAM;
   5569             }
   5570             if (vxlan_vpn_info->pkt_pri > BCM_PRIO_MAX) {
   5571                    return  BCM_E_PARAM;
   5572             }
   5573             if (vxlan_vpn_info->pkt_cfi > 1) {
   5574                return  BCM_E_PARAM;
   5575             }
   5576             soc_mem_field32_set(unit, hw_mem,
   5577                                 vxlate_entry, vid_fld,
   5578                                 vxlan_vpn_info->egress_service_vlan);
   5579             if (soc_mem_field_valid(unit, hw_mem,
   5580                                        pri_fld)) {
   5581                 soc_mem_field32_set(unit, hw_mem,
   5582                             vxlate_entry, pri_fld,
   5583                             vxlan_vpn_info->pkt_pri);
   5584             }
   5585             if (soc_mem_field_valid(unit, hw_mem,
   5586                                    cfi_fld)) {
   5587                 soc_mem_field32_set(unit, hw_mem,
   5588                             vxlate_entry, cfi_fld,
   5589                             vxlan_vpn_info->pkt_cfi);
   5590             }
   5591             if (soc_mem_field_valid(unit, hw_mem,
   5592                                    pri_cfi_sel_fld)) {
   5593                 soc_mem_field32_set(unit, hw_mem,
   5594                             vxlate_entry, pri_cfi_sel_fld,
   5595                             0x1);
   5596             }
   5597             action_if_not_prt = 0x1; /* ADD */
   5598         }
   5599 
   5600         if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_TPID_REPLACE) {
   5601             if (vxlan_vpn_info->egress_service_vlan >= BCM_VLAN_INVALID) {
   5602                 return  BCM_E_PARAM;
   5603             }
   5604             soc_mem_field32_set(unit, hw_mem,
   5605                                 vxlate_entry, vid_fld,
   5606                                 vxlan_vpn_info->egress_service_vlan);
   5607             action_prt = 0x1; /* REPLACE_VID_TPID */
   5608         } else if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_REPLACE) {
   5609             if (vxlan_vpn_info->egress_service_vlan >= BCM_VLAN_INVALID) {
   5610                 return  BCM_E_PARAM;
   5611             }
   5612             soc_mem_field32_set(unit, hw_mem,
   5613                                 vxlate_entry, vid_fld,
   5614                                 vxlan_vpn_info->egress_service_vlan);
   5615             action_prt = 0x2; /* REPLACE_VID_ONLY */
   5616         } else if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_DELETE) {
   5617             action_prt = 0x3; /* DELETE */
   5618         } else if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_PRI_TPID_REPLACE) {
   5619                if (vxlan_vpn_info->egress_service_vlan >= BCM_VLAN_INVALID) {
   5620                    return  BCM_E_PARAM;
   5621                }
   5622                if (vxlan_vpn_info->pkt_pri > BCM_PRIO_MAX) {
   5623                    return  BCM_E_PARAM;
   5624                }
   5625                if (vxlan_vpn_info->pkt_cfi > 1) {
   5626                    return  BCM_E_PARAM;
   5627                }
   5628                soc_mem_field32_set(unit, hw_mem,
   5629                                 vxlate_entry, vid_fld,
   5630                                 vxlan_vpn_info->egress_service_vlan);
   5631                if (soc_mem_field_valid(unit, hw_mem,
   5632                                        pri_fld)) {
   5633                    soc_mem_field32_set(unit, hw_mem,
   5634                                 vxlate_entry, pri_fld,
   5635                                 vxlan_vpn_info->pkt_pri);
   5636                }
   5637                if (soc_mem_field_valid(unit, hw_mem,
   5638                                        cfi_fld)) {
   5639                    soc_mem_field32_set(unit, hw_mem,
   5640                                 vxlate_entry, cfi_fld,
   5641                                 vxlan_vpn_info->pkt_cfi);
   5642                }
   5643                if (soc_mem_field_valid(unit, hw_mem,
   5644                                        pri_cfi_sel_fld)) {
   5645                    soc_mem_field32_set(unit, hw_mem,
   5646                                 vxlate_entry, pri_cfi_sel_fld,
   5647                                 0x1);
   5648                }
   5649                action_prt = 0x4; /* REPLACE_VID_PRI_TPID */
   5650 
   5651         } else if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_PRI_REPLACE ){
   5652                 if (vxlan_vpn_info->egress_service_vlan >= BCM_VLAN_INVALID) {
   5653                     return  BCM_E_PARAM;
   5654                 }
   5655                 if (vxlan_vpn_info->pkt_pri > BCM_PRIO_MAX) {
   5656                     return  BCM_E_PARAM;
   5657                 }
   5658                 if (vxlan_vpn_info->pkt_cfi > 1) {
   5659                     return  BCM_E_PARAM;
   5660                 }
   5661                 soc_mem_field32_set(unit, hw_mem,
   5662                                 vxlate_entry, vid_fld,
   5663                                 vxlan_vpn_info->egress_service_vlan);
   5664 
   5665                 if (soc_mem_field_valid(unit, hw_mem,
   5666                                        pri_fld)) {
   5667                    soc_mem_field32_set(unit, hw_mem,
   5668                                 vxlate_entry, pri_fld,
   5669                                 vxlan_vpn_info->pkt_pri);
   5670                 }
   5671                 if (soc_mem_field_valid(unit, hw_mem,
   5672                                        cfi_fld)) {
   5673                    soc_mem_field32_set(unit, hw_mem,
   5674                                 vxlate_entry, cfi_fld,
   5675                                 vxlan_vpn_info->pkt_cfi);
   5676                 }
   5677                 if (soc_mem_field_valid(unit, hw_mem,
   5678                                        pri_cfi_sel_fld)) {
   5679                    soc_mem_field32_set(unit, hw_mem,
   5680                                 vxlate_entry, pri_cfi_sel_fld,
   5681                                 0x1);
   5682                }
   5683 
   5684                 action_prt = 0x5; /* REPLACE_VID_PRI */
   5685         } else if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_PRI_REPLACE ) {
   5686                 if (vxlan_vpn_info->pkt_pri > BCM_PRIO_MAX) {
   5687                     return  BCM_E_PARAM;
   5688                 }
   5689                 if (vxlan_vpn_info->pkt_cfi > 1) {
   5690                     return  BCM_E_PARAM;
   5691                 }
   5692                 if (soc_mem_field_valid(unit, hw_mem,
   5693                                        pri_fld)) {
   5694                    soc_mem_field32_set(unit, hw_mem,
   5695                                 vxlate_entry, pri_fld,
   5696                                 vxlan_vpn_info->pkt_pri);
   5697                 }
   5698                 if (soc_mem_field_valid(unit, hw_mem,
   5699                                        cfi_fld)) {
   5700                    soc_mem_field32_set(unit, hw_mem,
   5701                                 vxlate_entry, cfi_fld,
   5702                                 vxlan_vpn_info->pkt_cfi);
   5703                 }
   5704                 if (soc_mem_field_valid(unit, hw_mem,
   5705                                        pri_cfi_sel_fld)) {
   5706                    soc_mem_field32_set(unit, hw_mem,
   5707                                 vxlate_entry, pri_cfi_sel_fld,
   5708                                 0x1);
   5709                 }
   5710                 action_prt = 0x6; /* REPLACE_PRI_ONLY */
   5711         } else if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_TPID_REPLACE ) {
   5712                 action_prt = 0x7; /* REPLACE_TPID_ONLY */
   5713         }
   5714         
   5715         profile_index = soc_mem_field32_get(unit, hw_mem, vxlate_entry,
   5716                         VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf);
   5717         _bcm_td3_sd_tag_action_profile_get(unit, action_prt,
   5718                          action_if_not_prt, &profile_index);
   5719         soc_mem_field32_set(unit, hw_mem, vxlate_entry, VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf,
   5720                          profile_index);
   5721 
   5722         if ((vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_ADD) ||
   5723             (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_TPID_REPLACE) ||
   5724             (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_TPID_REPLACE) ||
   5725             (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_PRI_TPID_REPLACE)) {
   5726             /* TPID value is used */
   5727             BCM_IF_ERROR_RETURN(
   5728                 _bcm_fb2_outer_tpid_entry_add(unit, vxlan_vpn_info->egress_service_tpid, tpid_index));
   5729             soc_mem_field32_set(unit, hw_mem,
   5730                                 vxlate_entry, VXLAN_VFI_FLEX__OUTER_TPID_INDEXf, *tpid_index);
   5731         }
   5732     } else if (vxlan_port != NULL) {
   5733         if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD) {
   5734             if (vxlan_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   5735                 return  BCM_E_PARAM;
   5736             }
   5737             if (vxlan_port->pkt_pri > BCM_PRIO_MAX) {
   5738                    return  BCM_E_PARAM;
   5739             }
   5740             if (vxlan_port->pkt_cfi > 1) {
   5741                return  BCM_E_PARAM;
   5742             }
   5743             soc_mem_field32_set(unit, hw_mem,
   5744                                 vxlate_entry, vid_fld,
   5745                                 vxlan_port->egress_service_vlan);
   5746             if (soc_mem_field_valid(unit, hw_mem,
   5747                                        pri_fld)) {
   5748                 soc_mem_field32_set(unit, hw_mem,
   5749                             vxlate_entry, pri_fld,
   5750                             vxlan_port->pkt_pri);
   5751             }
   5752             if (soc_mem_field_valid(unit, hw_mem,
   5753                                    cfi_fld)) {
   5754                 soc_mem_field32_set(unit, hw_mem,
   5755                             vxlate_entry, cfi_fld,
   5756                             vxlan_port->pkt_cfi);
   5757             }
   5758             if (soc_mem_field_valid(unit, hw_mem,
   5759                                    pri_cfi_sel_fld)) {
   5760                 soc_mem_field32_set(unit, hw_mem,
   5761                             vxlate_entry, pri_cfi_sel_fld,
   5762                             0x1);
   5763             }
   5764             action_if_not_prt = 0x1; /* ADD */
   5765         }
   5766 
   5767         if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_TPID_REPLACE) {
   5768             if (vxlan_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   5769                 return  BCM_E_PARAM;
   5770             }
   5771             soc_mem_field32_set(unit, hw_mem,
   5772                                 vxlate_entry, vid_fld,
   5773                                 vxlan_port->egress_service_vlan);
   5774             action_prt = 0x1; /* REPLACE_VID_TPID */
   5775         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_REPLACE) {
   5776             if (vxlan_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   5777                 return  BCM_E_PARAM;
   5778             }
   5779             soc_mem_field32_set(unit, hw_mem,
   5780                                 vxlate_entry, vid_fld,
   5781                                 vxlan_port->egress_service_vlan);
   5782             action_prt = 0x2; /* REPLACE_VID_ONLY */
   5783         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_DELETE) {
   5784             action_prt = 0x3; /* DELETE */
   5785         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE) {
   5786                if (vxlan_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   5787                    return  BCM_E_PARAM;
   5788                }
   5789                if (vxlan_port->pkt_pri > BCM_PRIO_MAX) {
   5790                    return  BCM_E_PARAM;
   5791                }
   5792                if (vxlan_port->pkt_cfi > 1) {
   5793                    return  BCM_E_PARAM;
   5794                }
   5795                soc_mem_field32_set(unit, hw_mem,
   5796                                 vxlate_entry, vid_fld,
   5797                                 vxlan_port->egress_service_vlan);
   5798                if (soc_mem_field_valid(unit, hw_mem,
   5799                                        pri_fld)) {
   5800                    soc_mem_field32_set(unit, hw_mem,
   5801                                 vxlate_entry, pri_fld,
   5802                                 vxlan_port->pkt_pri);
   5803                }
   5804                if (soc_mem_field_valid(unit, hw_mem,
   5805                                        cfi_fld)) {
   5806                    soc_mem_field32_set(unit, hw_mem,
   5807                                 vxlate_entry, cfi_fld,
   5808                                 vxlan_port->pkt_cfi);
   5809                }
   5810                if (soc_mem_field_valid(unit, hw_mem,
   5811                                        pri_cfi_sel_fld)) {
   5812                    soc_mem_field32_set(unit, hw_mem,
   5813                                 vxlate_entry, pri_cfi_sel_fld,
   5814                                 0x1);
   5815                }
   5816 
   5817                action_prt = 0x4; /* REPLACE_VID_PRI_TPID */
   5818 
   5819         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_REPLACE ){
   5820                 if (vxlan_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   5821                     return  BCM_E_PARAM;
   5822                 }
   5823                 if (vxlan_port->pkt_pri > BCM_PRIO_MAX) {
   5824                     return  BCM_E_PARAM;
   5825                 }
   5826                 if (vxlan_port->pkt_cfi > 1) {
   5827                     return  BCM_E_PARAM;
   5828                 }
   5829                 soc_mem_field32_set(unit, hw_mem,
   5830                                 vxlate_entry, vid_fld,
   5831                                 vxlan_port->egress_service_vlan);
   5832 
   5833                 if (soc_mem_field_valid(unit, hw_mem,
   5834                                        pri_fld)) {
   5835                    soc_mem_field32_set(unit, hw_mem,
   5836                                 vxlate_entry, pri_fld,
   5837                                 vxlan_port->pkt_pri);
   5838                 }
   5839                 if (soc_mem_field_valid(unit, hw_mem,
   5840                                        cfi_fld)) {
   5841                    soc_mem_field32_set(unit, hw_mem,
   5842                                 vxlate_entry, cfi_fld,
   5843                                 vxlan_port->pkt_cfi);
   5844                 }
   5845                 if (soc_mem_field_valid(unit, hw_mem,
   5846                                        pri_cfi_sel_fld)) {
   5847                    soc_mem_field32_set(unit, hw_mem,
   5848                                 vxlate_entry, pri_cfi_sel_fld,
   5849                                 0x1);
   5850                }
   5851 
   5852                action_prt = 0x5; /* REPLACE_VID_PRI */
   5853         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_PRI_REPLACE ) {
   5854                 if (vxlan_port->pkt_pri > BCM_PRIO_MAX) {
   5855                     return  BCM_E_PARAM;
   5856                 }
   5857                 if (vxlan_port->pkt_cfi > 1) {
   5858                     return  BCM_E_PARAM;
   5859                 }
   5860                 if (soc_mem_field_valid(unit, hw_mem,
   5861                                        pri_fld)) {
   5862                    soc_mem_field32_set(unit, hw_mem,
   5863                                 vxlate_entry, pri_fld,
   5864                                 vxlan_port->pkt_pri);
   5865                 }
   5866                 if (soc_mem_field_valid(unit, hw_mem,
   5867                                        cfi_fld)) {
   5868                    soc_mem_field32_set(unit, hw_mem,
   5869                                 vxlate_entry, cfi_fld,
   5870                                 vxlan_port->pkt_cfi);
   5871                 }
   5872                 if (soc_mem_field_valid(unit, hw_mem,
   5873                                        pri_cfi_sel_fld)) {
   5874                    soc_mem_field32_set(unit, hw_mem,
   5875                                 vxlate_entry, pri_cfi_sel_fld,
   5876                                 0x1);
   5877                }
   5878                 action_prt = 0x6; /* REPLACE_PRI_ONLY */
   5879         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TPID_REPLACE ) {
   5880                 action_prt = 0x7; /* REPLACE_TPID_ONLY */
   5881         }
   5882 
   5883         profile_index = soc_mem_field32_get(unit, hw_mem, vxlate_entry,
   5884                         VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf);
   5885         _bcm_td3_sd_tag_action_profile_get(unit, action_prt,
   5886                          action_if_not_prt, &profile_index);
   5887         soc_mem_field32_set(unit, hw_mem, vxlate_entry, VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf,
   5888                          profile_index);
   5889         if ((vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD) ||
   5890             (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_TPID_REPLACE) ||
   5891             (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TPID_REPLACE) ||
   5892             (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) {
   5893             /* TPID value is used */
   5894             BCM_IF_ERROR_RETURN(
   5895                 _bcm_fb2_outer_tpid_entry_add(unit, vxlan_port->egress_service_tpid, tpid_index));
   5896             soc_mem_field32_set(unit, hw_mem,
   5897                                 vxlate_entry, VXLAN_VFI_FLEX__OUTER_TPID_INDEXf, *tpid_index);
   5898         }
   5899     }
   5900     return  BCM_E_NONE;
   5901 }
   5902 
   5903 /*
   5904  * Function:
   5905  *      _bcm_td3_vxlan_vlan_action_get
   5906  * Purpose:
   5907  *      Get  SD_TAG settings
   5908  * Parameters:
   5909  *      unit           - (IN)  SOC unit #
   5910  *      vxlan_port  - (IN)  VXLAN VP
   5911  *      egr_nh_info  (IN/OUT) Egress NHop Info
   5912  * Returns:
   5913  *      BCM_E_XXX
   5914  */
   5915 
   5916 STATIC void
   5917 _bcm_td3_vxlan_vlan_action_get( int unit, bcm_vxlan_vpn_config_t *vxlan_vpn_info,
   5918                          bcm_vxlan_port_t *vxlan_port,
   5919                          egr_l3_next_hop_entry_t *egr_nh,
   5920                          uint32   *vxlate_entry,
   5921                          int network_port_flag )
   5922 {
   5923     int action_present=0, action_not_present=0, tpid_index = 0;
   5924     soc_mem_t vxlate_mem = EGR_VLAN_XLATE_1_SINGLEm;
   5925     int profile_index = -1;
   5926     uint32 flags                   = 0;
   5927     bcm_vlan_t egress_service_vlan = 0;
   5928     uint8 pkt_pri                  = 0;
   5929     uint8 pkt_cfi                  = 0;
   5930     uint16 egress_service_tpid     = 0;
   5931     soc_field_t vid_fld = VXLAN_VFI_FLEX__OVIDf;
   5932     soc_field_t pri_fld = VXLAN_VFI_FLEX__OPRIf;
   5933     soc_field_t cfi_fld = VXLAN_VFI_FLEX__OCFIf;
   5934 
   5935     if (network_port_flag) {
   5936        profile_index = soc_mem_field32_get(unit, vxlate_mem, vxlate_entry,
   5937                                VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf);
   5938        (void)_bcm_td3_sd_tag_action_get(unit, profile_index, &action_present,
   5939                            &action_not_present);
   5940 
   5941        if (action_not_present == 1) {
   5942             flags |= BCM_VXLAN_VPN_SERVICE_TAGGED;
   5943             flags |= BCM_VXLAN_VPN_SERVICE_VLAN_ADD;
   5944             egress_service_vlan = soc_mem_field32_get(unit,
   5945                             vxlate_mem, vxlate_entry, vid_fld);
   5946        }
   5947 
   5948        if (action_present) {
   5949             flags |= BCM_VXLAN_VPN_SERVICE_TAGGED;
   5950        }
   5951        switch (action_present) {
   5952          case 1:
   5953             flags |= BCM_VXLAN_VPN_SERVICE_VLAN_TPID_REPLACE;
   5954             egress_service_vlan = soc_mem_field32_get(unit,
   5955                             vxlate_mem, vxlate_entry, vid_fld);
   5956             break;
   5957 
   5958          case 2:
   5959             flags |= BCM_VXLAN_VPN_SERVICE_VLAN_REPLACE;
   5960             egress_service_vlan = soc_mem_field32_get(unit,
   5961                             vxlate_mem, vxlate_entry, vid_fld);
   5962             break;
   5963 
   5964          case 3:
   5965             flags |= BCM_VXLAN_VPN_SERVICE_VLAN_DELETE;
   5966             egress_service_vlan = BCM_VLAN_INVALID;
   5967             break;
   5968 
   5969          case 4:
   5970             flags |= BCM_VXLAN_VPN_SERVICE_VLAN_PRI_TPID_REPLACE;
   5971             egress_service_vlan = soc_mem_field32_get(unit,
   5972                             vxlate_mem, vxlate_entry, vid_fld);
   5973             pkt_pri = soc_mem_field32_get(unit,
   5974                 vxlate_mem, vxlate_entry, pri_fld);
   5975             pkt_cfi = soc_mem_field32_get(unit,
   5976                 vxlate_mem, vxlate_entry, cfi_fld);
   5977             break;
   5978 
   5979          case 5:
   5980             flags |= BCM_VXLAN_VPN_SERVICE_VLAN_PRI_REPLACE;
   5981             egress_service_vlan = soc_mem_field32_get(unit,
   5982                             vxlate_mem, vxlate_entry, vid_fld);
   5983             pkt_pri = soc_mem_field32_get(unit,
   5984                 vxlate_mem, vxlate_entry, pri_fld);
   5985             pkt_cfi = soc_mem_field32_get(unit,
   5986                 vxlate_mem, vxlate_entry, cfi_fld);
   5987             break;
   5988 
   5989          case 6:
   5990             flags |= BCM_VXLAN_VPN_SERVICE_PRI_REPLACE;
   5991             egress_service_vlan =   BCM_VLAN_INVALID;
   5992             pkt_pri = soc_mem_field32_get(unit,
   5993                 vxlate_mem, vxlate_entry, pri_fld);
   5994             pkt_cfi = soc_mem_field32_get(unit,
   5995                 vxlate_mem, vxlate_entry, cfi_fld);
   5996             break;
   5997 
   5998          case 7:
   5999             flags |= BCM_VXLAN_VPN_SERVICE_TPID_REPLACE;
   6000             egress_service_vlan = BCM_VLAN_INVALID;
   6001             break;
   6002 
   6003          default:
   6004             break;
   6005        }
   6006 
   6007        if ((flags & BCM_VXLAN_VPN_SERVICE_VLAN_ADD) ||
   6008             (flags & BCM_VXLAN_VPN_SERVICE_VLAN_TPID_REPLACE) ||
   6009             (flags & BCM_VXLAN_VPN_SERVICE_TPID_REPLACE) ||
   6010             (flags & BCM_VXLAN_VPN_SERVICE_VLAN_PRI_TPID_REPLACE)) {
   6011             tpid_index = soc_mem_field32_get(unit, vxlate_mem, vxlate_entry,
   6012                                                 VXLAN_VFI_FLEX__OUTER_TPID_INDEXf);
   6013             _bcm_fb2_outer_tpid_entry_get(unit,
   6014                 &egress_service_tpid, tpid_index);
   6015        }
   6016 
   6017        if (vxlan_vpn_info != NULL) {
   6018            vxlan_vpn_info->flags               |= flags;
   6019            vxlan_vpn_info->egress_service_vlan  = egress_service_vlan;
   6020            vxlan_vpn_info->egress_service_tpid  = egress_service_tpid;
   6021            vxlan_vpn_info->pkt_pri              = pkt_pri;
   6022            vxlan_vpn_info->pkt_cfi              = pkt_cfi;
   6023        }
   6024        if (vxlan_port != NULL) {
   6025            vxlan_port->flags               |= flags;
   6026            vxlan_port->egress_service_vlan  = egress_service_vlan;
   6027            vxlan_port->egress_service_tpid  = egress_service_tpid;
   6028            vxlan_port->pkt_pri              = pkt_pri;
   6029            vxlan_port->pkt_cfi              = pkt_cfi;
   6030        }
   6031 
   6032     } else {
   6033        vid_fld = L2_OTAG__VIDf;
   6034        pri_fld = L2_OTAG__PCPf;
   6035        cfi_fld = L2_OTAG__DEf;
   6036        profile_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, egr_nh,
   6037                                L2_OTAG__TAG_ACTION_PROFILE_PTRf);
   6038        (void)_bcm_td3_sd_tag_action_get(unit, profile_index, &action_present,
   6039                            &action_not_present);
   6040 
   6041        if (action_not_present == 1) {
   6042             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_ADD;
   6043             vxlan_port->egress_service_vlan =
   6044                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, vid_fld);
   6045        }
   6046 
   6047        switch (action_present) {
   6048          case 1:
   6049             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_TPID_REPLACE;
   6050             vxlan_port->egress_service_vlan =
   6051                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, vid_fld);
   6052             break;
   6053 
   6054          case 2:
   6055             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_REPLACE;
   6056             vxlan_port->egress_service_vlan =
   6057                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, vid_fld);
   6058             break;
   6059 
   6060          case 3:
   6061             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_DELETE;
   6062             vxlan_port->egress_service_vlan = BCM_VLAN_INVALID;
   6063             break;
   6064 
   6065          case 4:
   6066             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE;
   6067             vxlan_port->egress_service_vlan =
   6068                  soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, vid_fld);
   6069             vxlan_port->pkt_pri = 
   6070                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, pri_fld);
   6071             vxlan_port->pkt_cfi = 
   6072                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, cfi_fld);
   6073             break;
   6074 
   6075          case 5:
   6076             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_PRI_REPLACE;
   6077             vxlan_port->egress_service_vlan = 
   6078                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, vid_fld);
   6079             vxlan_port->pkt_pri = 
   6080                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, pri_fld);
   6081             vxlan_port->pkt_cfi = 
   6082                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, cfi_fld);
   6083             break;
   6084 
   6085          case 6:
   6086             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_PRI_REPLACE;
   6087             vxlan_port->egress_service_vlan =   BCM_VLAN_INVALID;
   6088             vxlan_port->pkt_pri = 
   6089                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, pri_fld);
   6090             vxlan_port->pkt_cfi = 
   6091                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, cfi_fld);
   6092             break;
   6093 
   6094          case 7:
   6095             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_TPID_REPLACE;
   6096             vxlan_port->egress_service_vlan = BCM_VLAN_INVALID;
   6097             break;
   6098 
   6099          default:
   6100             break;
   6101        }
   6102 
   6103        if (soc_feature(unit, soc_feature_vp_sharing) &&
   6104               soc_feature(unit, soc_feature_egr_intf_vlan_vfi_deoverlay)) {
   6105            if ((vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD) ||
   6106               (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_TPID_REPLACE) ||
   6107               (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_REPLACE) ||
   6108               (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_REPLACE) ||
   6109               (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) {
   6110                vxlan_port->egress_service_vlan = (vxlan_port->egress_service_vlan == 0) ?
   6111                                                  BCM_VLAN_INVALID : vxlan_port->egress_service_vlan;
   6112            }
   6113        }
   6114 
   6115        if ((vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD) ||
   6116            (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_TPID_REPLACE) ||
   6117            (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TPID_REPLACE) ||
   6118            (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) {
   6119            /* TPID value is used */
   6120            tpid_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, L2_OTAG__TPID_INDEXf);
   6121            _bcm_fb2_outer_tpid_entry_get(unit, &vxlan_port->egress_service_tpid, tpid_index);
   6122        }
   6123     }
   6124 }
   6125 
   6126 #endif
   6127 
   6128 /*
   6129  * Function:
   6130  *      _bcm_td2_vxlan_sd_tag_set
   6131  * Purpose:
   6132  *      Program  SD_TAG settings
   6133  * Parameters:
   6134  *      unit           - (IN)  SOC unit #
   6135  *      vxlan_port  - (IN)  VXLAN VP
   6136  *      egr_nh_info  (IN/OUT) Egress NHop Info
   6137  * Returns:
   6138  *      BCM_E_XXX
   6139  */
   6140 
   6141 STATIC int
   6142 _bcm_td2_vxlan_sd_tag_set( int unit, bcm_vxlan_vpn_config_t *vxlan_vpn_info, 
   6143                          bcm_vxlan_port_t *vxlan_port, 
   6144                          _bcm_td2_vxlan_nh_info_t  *egr_nh_info, 
   6145                          uint32   *vxlate_entry,
   6146                          int *tpid_index )
   6147 {
   6148     soc_mem_t  hw_mem;
   6149 
   6150     if (vxlan_vpn_info != NULL ) {
   6151 #if defined(BCM_TRIDENT3_SUPPORT)
   6152         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   6153             int rv = BCM_E_NONE;
   6154             rv = _bcm_td3_vxlan_vlan_action_set(unit, vxlan_vpn_info, NULL, vxlate_entry, tpid_index);
   6155             return rv;
   6156         }
   6157 #endif
   6158 #if defined(BCM_TRIDENT3_SUPPORT)
   6159         if (soc_feature(unit, soc_feature_base_valid)) {
   6160             hw_mem = EGR_VLAN_XLATE_1_DOUBLEm;
   6161         } else
   6162 #endif
   6163         {
   6164             hw_mem = EGR_VLAN_XLATEm;
   6165         }
   6166 
   6167         if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_ADD) {
   6168             if (vxlan_vpn_info->egress_service_vlan >= BCM_VLAN_INVALID) {
   6169                 return  BCM_E_PARAM;
   6170             }
   6171             if (vxlan_vpn_info->pkt_pri > BCM_PRIO_MAX) {
   6172                    return  BCM_E_PARAM;
   6173             }
   6174             if (vxlan_vpn_info->pkt_cfi > 1) {
   6175                return  BCM_E_PARAM;
   6176             }
   6177             soc_mem_field32_set(unit, hw_mem,
   6178                                 vxlate_entry, VXLAN_VFI__SD_TAG_VIDf,
   6179                                 vxlan_vpn_info->egress_service_vlan);
   6180             if (soc_mem_field_valid(unit, hw_mem,
   6181                                        VXLAN_VFI__SD_TAG_NEW_PRIf)) {
   6182                 soc_mem_field32_set(unit, hw_mem,
   6183                             vxlate_entry, VXLAN_VFI__SD_TAG_NEW_PRIf,
   6184                             vxlan_vpn_info->pkt_pri);
   6185             }
   6186             if (soc_mem_field_valid(unit, hw_mem,
   6187                                    VXLAN_VFI__SD_TAG_NEW_CFIf)) {
   6188                 soc_mem_field32_set(unit, hw_mem,
   6189                             vxlate_entry, VXLAN_VFI__SD_TAG_NEW_CFIf,
   6190                             vxlan_vpn_info->pkt_cfi);
   6191             }
   6192             if (soc_mem_field_valid(unit, hw_mem,
   6193                                    VXLAN_VFI__SD_TAG_REMARK_CFIf)) {
   6194                 soc_mem_field32_set(unit, hw_mem,
   6195                             vxlate_entry, VXLAN_VFI__SD_TAG_REMARK_CFIf,
   6196                             0x1);
   6197             }
   6198             soc_mem_field32_set(unit, hw_mem,
   6199                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_NOT_PRESENTf,
   6200                                 0x1); /* ADD */
   6201         }
   6202 
   6203         if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_TPID_REPLACE) {
   6204             if (vxlan_vpn_info->egress_service_vlan >= BCM_VLAN_INVALID) {
   6205                 return  BCM_E_PARAM;
   6206             }
   6207             soc_mem_field32_set(unit, hw_mem,
   6208                                 vxlate_entry, VXLAN_VFI__SD_TAG_VIDf,
   6209                                 vxlan_vpn_info->egress_service_vlan);
   6210             soc_mem_field32_set(unit, hw_mem,
   6211                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf,
   6212                                 0x1); /* REPLACE_VID_TPID */
   6213         } else if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_REPLACE) {
   6214             if (vxlan_vpn_info->egress_service_vlan >= BCM_VLAN_INVALID) {
   6215                 return  BCM_E_PARAM;
   6216             }
   6217             soc_mem_field32_set(unit, hw_mem,
   6218                                 vxlate_entry, VXLAN_VFI__SD_TAG_VIDf,
   6219                                 vxlan_vpn_info->egress_service_vlan);
   6220             soc_mem_field32_set(unit, hw_mem,
   6221                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf,
   6222                                 0x2); /* REPLACE_VID_ONLY */
   6223         } else if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_DELETE) {
   6224             soc_mem_field32_set(unit, hw_mem,
   6225                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf,
   6226                                 0x3); /* DELETE */
   6227         } else if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_PRI_TPID_REPLACE) {
   6228                if (vxlan_vpn_info->egress_service_vlan >= BCM_VLAN_INVALID) {
   6229                    return  BCM_E_PARAM;
   6230                }
   6231                if (vxlan_vpn_info->pkt_pri > BCM_PRIO_MAX) {
   6232                    return  BCM_E_PARAM;
   6233                }
   6234                if (vxlan_vpn_info->pkt_cfi > 1) {
   6235                    return  BCM_E_PARAM;
   6236                }
   6237                soc_mem_field32_set(unit, hw_mem,
   6238                                 vxlate_entry, VXLAN_VFI__SD_TAG_VIDf,
   6239                                 vxlan_vpn_info->egress_service_vlan);
   6240                if (soc_mem_field_valid(unit, hw_mem,
   6241                                        VXLAN_VFI__SD_TAG_NEW_PRIf)) {
   6242                    soc_mem_field32_set(unit, hw_mem,
   6243                                 vxlate_entry, VXLAN_VFI__SD_TAG_NEW_PRIf,
   6244                                 vxlan_vpn_info->pkt_pri);
   6245                }
   6246                if (soc_mem_field_valid(unit, hw_mem,
   6247                                        VXLAN_VFI__SD_TAG_NEW_CFIf)) {
   6248                    soc_mem_field32_set(unit, hw_mem,
   6249                                 vxlate_entry, VXLAN_VFI__SD_TAG_NEW_CFIf,
   6250                                 vxlan_vpn_info->pkt_cfi);
   6251                }
   6252                if (soc_mem_field_valid(unit, hw_mem,
   6253                                        VXLAN_VFI__SD_TAG_REMARK_CFIf)) {
   6254                    soc_mem_field32_set(unit, hw_mem,
   6255                                 vxlate_entry, VXLAN_VFI__SD_TAG_REMARK_CFIf,
   6256                                 0x1);
   6257                }
   6258 
   6259                soc_mem_field32_set(unit, hw_mem,
   6260                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf,
   6261                                 0x4); /* REPLACE_VID_PRI_TPID */
   6262 
   6263         } else if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_PRI_REPLACE ){
   6264                 if (vxlan_vpn_info->egress_service_vlan >= BCM_VLAN_INVALID) {
   6265                     return  BCM_E_PARAM;
   6266                 }
   6267                 if (vxlan_vpn_info->pkt_pri > BCM_PRIO_MAX) {
   6268                     return  BCM_E_PARAM;
   6269                 }
   6270                 if (vxlan_vpn_info->pkt_cfi > 1) {
   6271                     return  BCM_E_PARAM;
   6272                 }
   6273                 soc_mem_field32_set(unit, hw_mem,
   6274                                 vxlate_entry, VXLAN_VFI__SD_TAG_VIDf,
   6275                                 vxlan_vpn_info->egress_service_vlan);
   6276 
   6277                 if (soc_mem_field_valid(unit, hw_mem,
   6278                                        VXLAN_VFI__SD_TAG_NEW_PRIf)) {
   6279                    soc_mem_field32_set(unit, hw_mem,
   6280                                 vxlate_entry, VXLAN_VFI__SD_TAG_NEW_PRIf,
   6281                                 vxlan_vpn_info->pkt_pri);
   6282                 }
   6283                 if (soc_mem_field_valid(unit, hw_mem,
   6284                                        VXLAN_VFI__SD_TAG_NEW_CFIf)) {
   6285                    soc_mem_field32_set(unit, hw_mem,
   6286                                 vxlate_entry, VXLAN_VFI__SD_TAG_NEW_CFIf,
   6287                                 vxlan_vpn_info->pkt_cfi);
   6288                 }
   6289                 if (soc_mem_field_valid(unit, hw_mem,
   6290                                        VXLAN_VFI__SD_TAG_REMARK_CFIf)) {
   6291                    soc_mem_field32_set(unit, hw_mem,
   6292                                 vxlate_entry, VXLAN_VFI__SD_TAG_REMARK_CFIf,
   6293                                 0x1);
   6294                }
   6295 
   6296                 soc_mem_field32_set(unit, hw_mem,
   6297                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf,
   6298                                 0x5); /* REPLACE_VID_PRI */
   6299         }else if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_PRI_REPLACE ) {
   6300                 if (vxlan_vpn_info->pkt_pri > BCM_PRIO_MAX) {
   6301                     return  BCM_E_PARAM;
   6302                 }
   6303                 if (vxlan_vpn_info->pkt_cfi > 1) {
   6304                     return  BCM_E_PARAM;
   6305                 }
   6306                 if (soc_mem_field_valid(unit, hw_mem,
   6307                                        VXLAN_VFI__SD_TAG_NEW_PRIf)) {
   6308                    soc_mem_field32_set(unit, hw_mem,
   6309                                 vxlate_entry, VXLAN_VFI__SD_TAG_NEW_PRIf,
   6310                                 vxlan_vpn_info->pkt_pri);
   6311                 }
   6312                 if (soc_mem_field_valid(unit, hw_mem,
   6313                                        VXLAN_VFI__SD_TAG_NEW_CFIf)) {
   6314                    soc_mem_field32_set(unit, hw_mem,
   6315                                 vxlate_entry, VXLAN_VFI__SD_TAG_NEW_CFIf,
   6316                                 vxlan_vpn_info->pkt_cfi);
   6317                 }
   6318                 if (soc_mem_field_valid(unit, hw_mem,
   6319                                        VXLAN_VFI__SD_TAG_REMARK_CFIf)) {
   6320                    soc_mem_field32_set(unit, hw_mem,
   6321                                 vxlate_entry, VXLAN_VFI__SD_TAG_REMARK_CFIf,
   6322                                 0x1);
   6323                 }
   6324 
   6325                 soc_mem_field32_set(unit, hw_mem,
   6326                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf,
   6327                                 0x6); /* REPLACE_PRI_ONLY */
   6328       
   6329         } else if (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_TPID_REPLACE ) {
   6330                  soc_mem_field32_set(unit, hw_mem,
   6331                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf,
   6332                                 0x7); /* REPLACE_TPID_ONLY */
   6333         }
   6334 
   6335         if ((vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_ADD) ||
   6336             (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_TPID_REPLACE) ||
   6337             (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_TPID_REPLACE) ||
   6338             (vxlan_vpn_info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_PRI_TPID_REPLACE)) {
   6339             /* TPID value is used */
   6340             BCM_IF_ERROR_RETURN(
   6341                 _bcm_fb2_outer_tpid_entry_add(unit, vxlan_vpn_info->egress_service_tpid, tpid_index));
   6342             soc_mem_field32_set(unit, hw_mem,
   6343                                 vxlate_entry, VXLAN_VFI__SD_TAG_TPID_INDEXf, *tpid_index);
   6344         }
   6345     } else if (vxlan_port != NULL && egr_nh_info != NULL) {
   6346         if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD) {
   6347             if (vxlan_port->egress_service_vlan >= BCM_VLAN_INVALID) { 
   6348 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 
   6349                 if (soc_feature(unit, soc_feature_vp_sharing)) {
   6350                     egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID;    
   6351                 } else
   6352 #endif
   6353                 {
   6354                     return  BCM_E_PARAM;
   6355                 }
   6356                     
   6357             }
   6358             if (vxlan_port->pkt_pri > BCM_PRIO_MAX) {
   6359                 return  BCM_E_PARAM;
   6360             }
   6361             if (vxlan_port->pkt_cfi > 1) {
   6362                 return  BCM_E_PARAM;
   6363             }
   6364             if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) {
   6365                 egr_nh_info->sd_tag_vlan = vxlan_port->egress_service_vlan; 
   6366             }
   6367             egr_nh_info->sd_tag_pri = vxlan_port->pkt_pri;
   6368             egr_nh_info->sd_tag_cfi = vxlan_port->pkt_cfi;
   6369             egr_nh_info->sd_tag_action_not_present = 0x1; /* ADD */
   6370         }
   6371 
   6372         if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_TPID_REPLACE) {
   6373             if (vxlan_port->egress_service_vlan >= BCM_VLAN_INVALID) { 
   6374 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 
   6375                 if (soc_feature(unit, soc_feature_vp_sharing)) {
   6376                     egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID; 
   6377                 } else
   6378 #endif
   6379                 {
   6380                     return  BCM_E_PARAM;
   6381                 }
   6382             }
   6383             /* REPLACE_VID_TPID */
   6384             if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) {
   6385                 egr_nh_info->sd_tag_vlan = vxlan_port->egress_service_vlan;
   6386             }
   6387             egr_nh_info->sd_tag_action_present = 0x1;
   6388         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_REPLACE) {
   6389 
   6390             if (vxlan_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   6391 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 
   6392                 if (soc_feature(unit, soc_feature_vp_sharing)) {
   6393                     egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID; 
   6394                 } else
   6395 #endif
   6396                 {
   6397                     return  BCM_E_PARAM;
   6398                 }
   6399             }
   6400             /* REPLACE_VID_ONLY */
   6401             if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) {
   6402                 egr_nh_info->sd_tag_vlan = vxlan_port->egress_service_vlan;
   6403             }
   6404             egr_nh_info->sd_tag_action_present = 0x2;
   6405         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_DELETE) {
   6406             egr_nh_info->sd_tag_action_present = 0x3; /* DELETE */
   6407             egr_nh_info->sd_tag_action_not_present = 0;
   6408         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE) { 
   6409             if (vxlan_port->egress_service_vlan >= BCM_VLAN_INVALID) { 
   6410 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 
   6411                 if (soc_feature(unit, soc_feature_vp_sharing)) {
   6412                     egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID; 
   6413                 } else
   6414 #endif
   6415                 {
   6416                     return  BCM_E_PARAM;
   6417                 }
   6418             }
   6419               
   6420             if (vxlan_port->pkt_pri > BCM_PRIO_MAX) {
   6421                 return  BCM_E_PARAM;
   6422             }
   6423             if (vxlan_port->pkt_cfi <= 1) {
   6424                 egr_nh_info->sd_tag_cfi = vxlan_port->pkt_cfi;
   6425             } else if (vxlan_port->pkt_cfi == (uint8)-1) {
   6426                 egr_nh_info->sd_tag_cfi = -1;
   6427             } else {
   6428                 return BCM_E_PARAM;
   6429             }
   6430 
   6431             /* REPLACE_VID_PRI_TPID */          
   6432             if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) {
   6433                 egr_nh_info->sd_tag_vlan = vxlan_port->egress_service_vlan;
   6434             }
   6435             egr_nh_info->sd_tag_pri = vxlan_port->pkt_pri;
   6436             egr_nh_info->sd_tag_action_present = 0x4;
   6437         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_REPLACE ) {
   6438             if (vxlan_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   6439 #if defined(BCM_TRIDENT2PLUS_SUPPORT)             
   6440                 if (soc_feature(unit, soc_feature_vp_sharing)) {
   6441                     egr_nh_info->sd_tag_vlan = BCM_VLAN_INVALID; 
   6442                 } else 
   6443 #endif
   6444                 {
   6445                     return  BCM_E_PARAM;
   6446                 }
   6447             }
   6448             if (vxlan_port->pkt_pri > BCM_PRIO_MAX) {
   6449                 return  BCM_E_PARAM;
   6450             }
   6451             if (vxlan_port->pkt_cfi <= 1) {
   6452                 egr_nh_info->sd_tag_cfi = vxlan_port->pkt_cfi;
   6453             } else if (vxlan_port->pkt_cfi == (uint8)-1) {
   6454                 egr_nh_info->sd_tag_cfi = -1;
   6455             } else {
   6456                 return BCM_E_PARAM;
   6457             }
   6458 
   6459             /* REPLACE_VID_PRI_ONLY */
   6460             if (egr_nh_info->sd_tag_vlan != BCM_VLAN_INVALID) {
   6461                 egr_nh_info->sd_tag_vlan = vxlan_port->egress_service_vlan;
   6462             }
   6463             egr_nh_info->sd_tag_pri = vxlan_port->pkt_pri;
   6464             egr_nh_info->sd_tag_action_present = 0x5;
   6465         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_PRI_REPLACE ) {
   6466                 if (vxlan_port->pkt_pri > BCM_PRIO_MAX) {
   6467                     return  BCM_E_PARAM;
   6468                 }
   6469                 if (vxlan_port->pkt_cfi <= 1) {
   6470                     egr_nh_info->sd_tag_cfi = vxlan_port->pkt_cfi;
   6471                 } else if (vxlan_port->pkt_cfi == (uint8)-1) {
   6472                     egr_nh_info->sd_tag_cfi = -1;
   6473                 } else {
   6474                     return BCM_E_PARAM;
   6475                 }
   6476 
   6477                  /* REPLACE_PRI_ONLY */
   6478                 egr_nh_info->sd_tag_pri = vxlan_port->pkt_pri;
   6479                 egr_nh_info->sd_tag_action_present = 0x6;
   6480         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TPID_REPLACE ) {
   6481                  /* REPLACE_TPID_ONLY */
   6482                 egr_nh_info->sd_tag_action_present = 0x7;
   6483         }
   6484 
   6485         if ((vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD) ||
   6486             (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_TPID_REPLACE) ||
   6487             (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TPID_REPLACE) ||
   6488             (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) {
   6489             /* TPID value is used */
   6490             BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_add(unit, vxlan_port->egress_service_tpid, tpid_index));
   6491             egr_nh_info->tpid_index = *tpid_index;
   6492         }
   6493     } else if (vxlan_port != NULL) {
   6494 #if defined(BCM_TRIDENT3_SUPPORT)
   6495         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   6496             int rv = BCM_E_NONE;
   6497             rv = _bcm_td3_vxlan_vlan_action_set(unit, NULL, vxlan_port, vxlate_entry, tpid_index);
   6498             return rv;
   6499         }
   6500 #endif 
   6501         hw_mem = EGR_VLAN_XLATEm;
   6502         if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD) {
   6503             if (vxlan_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   6504                 return  BCM_E_PARAM;
   6505             }
   6506             if (vxlan_port->pkt_pri > BCM_PRIO_MAX) {
   6507                    return  BCM_E_PARAM;
   6508             }
   6509             if (vxlan_port->pkt_cfi > 1) {
   6510                return  BCM_E_PARAM;
   6511             }
   6512             soc_mem_field32_set(unit, hw_mem,
   6513                                 vxlate_entry, VXLAN_VFI__SD_TAG_VIDf,
   6514                                 vxlan_port->egress_service_vlan);
   6515             if (soc_mem_field_valid(unit, hw_mem,
   6516                                        VXLAN_VFI__SD_TAG_NEW_PRIf)) {
   6517                 soc_mem_field32_set(unit, hw_mem,
   6518                             vxlate_entry, VXLAN_VFI__SD_TAG_NEW_PRIf,
   6519                             vxlan_port->pkt_pri);
   6520             }
   6521             if (soc_mem_field_valid(unit, hw_mem,
   6522                                    VXLAN_VFI__SD_TAG_NEW_CFIf)) {
   6523                 soc_mem_field32_set(unit, hw_mem,
   6524                             vxlate_entry, VXLAN_VFI__SD_TAG_NEW_CFIf,
   6525                             vxlan_port->pkt_cfi);
   6526             }
   6527             if (soc_mem_field_valid(unit, hw_mem,
   6528                                    VXLAN_VFI__SD_TAG_REMARK_CFIf)) {
   6529                 soc_mem_field32_set(unit, hw_mem,
   6530                             vxlate_entry, VXLAN_VFI__SD_TAG_REMARK_CFIf,
   6531                             0x1);
   6532             }
   6533             soc_mem_field32_set(unit, hw_mem,
   6534                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_NOT_PRESENTf,
   6535                                 0x1); /* ADD */
   6536         }
   6537 
   6538         if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_TPID_REPLACE) {
   6539             if (vxlan_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   6540                 return  BCM_E_PARAM;
   6541             }
   6542             soc_mem_field32_set(unit, hw_mem,
   6543                                 vxlate_entry, VXLAN_VFI__SD_TAG_VIDf,
   6544                                 vxlan_port->egress_service_vlan);
   6545             soc_mem_field32_set(unit, hw_mem,
   6546                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf,
   6547                                 0x1); /* REPLACE_VID_TPID */
   6548         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_REPLACE) {
   6549             if (vxlan_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   6550                 return  BCM_E_PARAM;
   6551             }
   6552             soc_mem_field32_set(unit, hw_mem,
   6553                                 vxlate_entry, VXLAN_VFI__SD_TAG_VIDf,
   6554                                 vxlan_port->egress_service_vlan);
   6555             soc_mem_field32_set(unit, hw_mem,
   6556                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf,
   6557                                 0x2); /* REPLACE_VID_ONLY */
   6558         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_DELETE) {
   6559             soc_mem_field32_set(unit, hw_mem,
   6560                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf,
   6561                                 0x3); /* DELETE */
   6562         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE) {
   6563                if (vxlan_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   6564                    return  BCM_E_PARAM;
   6565                }
   6566                if (vxlan_port->pkt_pri > BCM_PRIO_MAX) {
   6567                    return  BCM_E_PARAM;
   6568                }
   6569                if (vxlan_port->pkt_cfi > 1) {
   6570                    return  BCM_E_PARAM;
   6571                }
   6572                soc_mem_field32_set(unit, hw_mem,
   6573                                 vxlate_entry, VXLAN_VFI__SD_TAG_VIDf,
   6574                                 vxlan_port->egress_service_vlan);
   6575                if (soc_mem_field_valid(unit, hw_mem,
   6576                                        VXLAN_VFI__SD_TAG_NEW_PRIf)) {
   6577                    soc_mem_field32_set(unit, hw_mem,
   6578                                 vxlate_entry, VXLAN_VFI__SD_TAG_NEW_PRIf,
   6579                                 vxlan_port->pkt_pri);
   6580                }
   6581                if (soc_mem_field_valid(unit, hw_mem,
   6582                                        VXLAN_VFI__SD_TAG_NEW_CFIf)) {
   6583                    soc_mem_field32_set(unit, hw_mem,
   6584                                 vxlate_entry, VXLAN_VFI__SD_TAG_NEW_CFIf,
   6585                                 vxlan_port->pkt_cfi);
   6586                }
   6587                if (soc_mem_field_valid(unit, hw_mem,
   6588                                        VXLAN_VFI__SD_TAG_REMARK_CFIf)) {
   6589                    soc_mem_field32_set(unit, hw_mem,
   6590                                 vxlate_entry, VXLAN_VFI__SD_TAG_REMARK_CFIf,
   6591                                 0x1);
   6592                }
   6593 
   6594                soc_mem_field32_set(unit, hw_mem,
   6595                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf,
   6596                                 0x4); /* REPLACE_VID_PRI_TPID */
   6597 
   6598         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_REPLACE ){
   6599                 if (vxlan_port->egress_service_vlan >= BCM_VLAN_INVALID) {
   6600                     return  BCM_E_PARAM;
   6601                 }
   6602                 if (vxlan_port->pkt_pri > BCM_PRIO_MAX) {
   6603                     return  BCM_E_PARAM;
   6604                 }
   6605                 if (vxlan_port->pkt_cfi > 1) {
   6606                     return  BCM_E_PARAM;
   6607                 }
   6608                 soc_mem_field32_set(unit, hw_mem,
   6609                                 vxlate_entry, VXLAN_VFI__SD_TAG_VIDf,
   6610                                 vxlan_port->egress_service_vlan);
   6611 
   6612                 if (soc_mem_field_valid(unit, hw_mem,
   6613                                        VXLAN_VFI__SD_TAG_NEW_PRIf)) {
   6614                    soc_mem_field32_set(unit, hw_mem,
   6615                                 vxlate_entry, VXLAN_VFI__SD_TAG_NEW_PRIf,
   6616                                 vxlan_port->pkt_pri);
   6617                 }
   6618                 if (soc_mem_field_valid(unit, hw_mem,
   6619                                        VXLAN_VFI__SD_TAG_NEW_CFIf)) {
   6620                    soc_mem_field32_set(unit, hw_mem,
   6621                                 vxlate_entry, VXLAN_VFI__SD_TAG_NEW_CFIf,
   6622                                 vxlan_port->pkt_cfi);
   6623                 }
   6624                 if (soc_mem_field_valid(unit, hw_mem,
   6625                                        VXLAN_VFI__SD_TAG_REMARK_CFIf)) {
   6626                    soc_mem_field32_set(unit, hw_mem,
   6627                                 vxlate_entry, VXLAN_VFI__SD_TAG_REMARK_CFIf,
   6628                                 0x1);
   6629                }
   6630 
   6631                 soc_mem_field32_set(unit, hw_mem,
   6632                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf,
   6633                                 0x5); /* REPLACE_VID_PRI */
   6634         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_PRI_REPLACE ) {
   6635                 if (vxlan_port->pkt_pri > BCM_PRIO_MAX) {
   6636                     return  BCM_E_PARAM;
   6637                 }
   6638                 if (vxlan_port->pkt_cfi > 1) {
   6639                     return  BCM_E_PARAM;
   6640                 }
   6641                 if (soc_mem_field_valid(unit, hw_mem,
   6642                                        VXLAN_VFI__SD_TAG_NEW_PRIf)) {
   6643                    soc_mem_field32_set(unit, hw_mem,
   6644                                 vxlate_entry, VXLAN_VFI__SD_TAG_NEW_PRIf,
   6645                                 vxlan_port->pkt_pri);
   6646                 }
   6647                 if (soc_mem_field_valid(unit, hw_mem,
   6648                                        VXLAN_VFI__SD_TAG_NEW_CFIf)) {
   6649                    soc_mem_field32_set(unit, hw_mem,
   6650                                 vxlate_entry, VXLAN_VFI__SD_TAG_NEW_CFIf,
   6651                                 vxlan_port->pkt_cfi);
   6652                 }
   6653                 if (soc_mem_field_valid(unit, hw_mem,
   6654                                        VXLAN_VFI__SD_TAG_REMARK_CFIf)) {
   6655                    soc_mem_field32_set(unit, hw_mem,
   6656                                 vxlate_entry, VXLAN_VFI__SD_TAG_REMARK_CFIf,
   6657                                 0x1);
   6658                }
   6659 
   6660                 soc_mem_field32_set(unit, hw_mem,
   6661                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf,
   6662                                 0x6); /* REPLACE_PRI_ONLY */
   6663       
   6664         } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TPID_REPLACE ) {
   6665                  soc_mem_field32_set(unit, hw_mem,
   6666                                 vxlate_entry, VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf,
   6667                                 0x7); /* REPLACE_TPID_ONLY */
   6668         }
   6669 
   6670         if ((vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD) ||
   6671             (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_TPID_REPLACE) ||
   6672             (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TPID_REPLACE) ||
   6673             (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) {
   6674             /* TPID value is used */
   6675             BCM_IF_ERROR_RETURN(
   6676                 _bcm_fb2_outer_tpid_entry_add(unit, vxlan_port->egress_service_tpid, tpid_index));
   6677             soc_mem_field32_set(unit, hw_mem,
   6678                                 vxlate_entry, VXLAN_VFI__SD_TAG_TPID_INDEXf, *tpid_index);
   6679         }
   6680     }
   6681     return  BCM_E_NONE;
   6682 }
   6683 
   6684 /*
   6685  * Function:
   6686  *      _bcm_td2_vxlan_sd_tag_get
   6687  * Purpose:
   6688  *      Get  SD_TAG settings
   6689  * Parameters:
   6690  *      unit           - (IN)  SOC unit #
   6691  *      vxlan_port  - (IN)  VXLAN VP
   6692  *      egr_nh_info  (IN/OUT) Egress NHop Info
   6693  * Returns:
   6694  *      BCM_E_XXX
   6695  */     
   6696 
   6697 STATIC void
   6698 _bcm_td2_vxlan_sd_tag_get( int unit, bcm_vxlan_vpn_config_t *vxlan_vpn_info, 
   6699                          bcm_vxlan_port_t *vxlan_port, 
   6700                          egr_l3_next_hop_entry_t *egr_nh, 
   6701                          uint32   *vxlate_entry,
   6702                          int network_port_flag )
   6703 {
   6704     int action_present=0, action_not_present=0, tpid_index = 0;
   6705     soc_mem_t vxlate_mem;
   6706     uint32 flags                   = 0;
   6707     bcm_vlan_t egress_service_vlan = 0;
   6708     uint16 egress_service_tpid     = 0;
   6709     uint8 pkt_pri                  = 0;
   6710     uint8 pkt_cfi                  = 0;
   6711     
   6712 #if defined(BCM_TRIDENT3_SUPPORT)
   6713     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   6714         _bcm_td3_vxlan_vlan_action_get(unit, vxlan_vpn_info, vxlan_port, egr_nh,
   6715                                   vxlate_entry, network_port_flag);
   6716         return;
   6717     }
   6718 #endif
   6719 
   6720 #if defined(BCM_TRIDENT3_SUPPORT)
   6721     if (soc_feature(unit, soc_feature_base_valid)) {
   6722         vxlate_mem = EGR_VLAN_XLATE_1_DOUBLEm;
   6723     } else
   6724 #endif
   6725     {
   6726         vxlate_mem = EGR_VLAN_XLATEm;
   6727     }
   6728 
   6729     if (network_port_flag) {
   6730        action_present = soc_mem_field32_get(unit, vxlate_mem, vxlate_entry,
   6731                                         VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf);
   6732        action_not_present = soc_mem_field32_get(unit, vxlate_mem, vxlate_entry,
   6733                                         VXLAN_VFI__SD_TAG_ACTION_IF_NOT_PRESENTf);
   6734 
   6735        if (action_not_present == 1) {
   6736             flags |= BCM_VXLAN_VPN_SERVICE_TAGGED;
   6737             flags |= BCM_VXLAN_VPN_SERVICE_VLAN_ADD;
   6738             egress_service_vlan = soc_mem_field32_get(unit,
   6739                             vxlate_mem, vxlate_entry, VXLAN_VFI__SD_TAG_VIDf);
   6740        }
   6741 
   6742        if (action_present) {
   6743             flags |= BCM_VXLAN_VPN_SERVICE_TAGGED;
   6744        }
   6745        switch (action_present) {
   6746          case 1:
   6747             flags |= BCM_VXLAN_VPN_SERVICE_VLAN_TPID_REPLACE;
   6748             egress_service_vlan = soc_mem_field32_get(unit,
   6749                             vxlate_mem, vxlate_entry, VXLAN_VFI__SD_TAG_VIDf);
   6750             break;
   6751 
   6752          case 2:
   6753             flags |= BCM_VXLAN_VPN_SERVICE_VLAN_REPLACE;
   6754             egress_service_vlan = soc_mem_field32_get(unit,
   6755                             vxlate_mem, vxlate_entry, VXLAN_VFI__SD_TAG_VIDf);
   6756             break;
   6757 
   6758          case 3:
   6759             flags |= BCM_VXLAN_VPN_SERVICE_VLAN_DELETE;
   6760             egress_service_vlan = BCM_VLAN_INVALID;
   6761             break;
   6762 
   6763          case 4:
   6764             flags |= BCM_VXLAN_VPN_SERVICE_VLAN_PRI_TPID_REPLACE;
   6765             egress_service_vlan = soc_mem_field32_get(unit,
   6766                             vxlate_mem, vxlate_entry, VXLAN_VFI__SD_TAG_VIDf);
   6767             pkt_pri = soc_mem_field32_get(unit,
   6768                 vxlate_mem, vxlate_entry, VXLAN_VFI__SD_TAG_NEW_PRIf);
   6769             pkt_cfi = soc_mem_field32_get(unit,
   6770                 vxlate_mem, vxlate_entry, VXLAN_VFI__SD_TAG_NEW_CFIf);
   6771             break;
   6772 
   6773          case 5:
   6774             flags |= BCM_VXLAN_VPN_SERVICE_VLAN_PRI_REPLACE;
   6775             egress_service_vlan = soc_mem_field32_get(unit,
   6776                             vxlate_mem, vxlate_entry, VXLAN_VFI__SD_TAG_VIDf);
   6777             pkt_pri = soc_mem_field32_get(unit,
   6778                 vxlate_mem, vxlate_entry, VXLAN_VFI__SD_TAG_NEW_PRIf);
   6779             pkt_cfi = soc_mem_field32_get(unit,
   6780                 vxlate_mem, vxlate_entry, VXLAN_VFI__SD_TAG_NEW_CFIf);
   6781             break;
   6782 
   6783          case 6:
   6784             flags |= BCM_VXLAN_VPN_SERVICE_PRI_REPLACE;
   6785             egress_service_vlan =   BCM_VLAN_INVALID;
   6786             pkt_pri = soc_mem_field32_get(unit,
   6787                 vxlate_mem, vxlate_entry, VXLAN_VFI__SD_TAG_NEW_PRIf);
   6788             pkt_cfi = soc_mem_field32_get(unit,
   6789                 vxlate_mem, vxlate_entry, VXLAN_VFI__SD_TAG_NEW_CFIf);
   6790             break;
   6791 
   6792          case 7:
   6793             flags |= BCM_VXLAN_VPN_SERVICE_TPID_REPLACE;
   6794             egress_service_vlan = BCM_VLAN_INVALID;
   6795             break;
   6796 
   6797          default:
   6798             break;
   6799        }
   6800 
   6801        if ((flags & BCM_VXLAN_VPN_SERVICE_VLAN_ADD) ||
   6802             (flags & BCM_VXLAN_VPN_SERVICE_VLAN_TPID_REPLACE) ||
   6803             (flags & BCM_VXLAN_VPN_SERVICE_TPID_REPLACE) ||
   6804             (flags & BCM_VXLAN_VPN_SERVICE_VLAN_PRI_TPID_REPLACE)) {
   6805             tpid_index = soc_mem_field32_get(unit, vxlate_mem, vxlate_entry,
   6806                                                 VXLAN_VFI__SD_TAG_TPID_INDEXf);
   6807             _bcm_fb2_outer_tpid_entry_get(unit,
   6808                 &egress_service_tpid, tpid_index);
   6809        }
   6810        if (vxlan_vpn_info) {
   6811            vxlan_vpn_info->flags |= flags;
   6812            vxlan_vpn_info->egress_service_vlan = egress_service_vlan;
   6813            vxlan_vpn_info->egress_service_tpid = egress_service_tpid;
   6814            vxlan_vpn_info->pkt_cfi = pkt_cfi;
   6815            vxlan_vpn_info->pkt_pri = pkt_pri;
   6816        }
   6817 
   6818        if (vxlan_port) {
   6819            vxlan_port->flags |= flags;
   6820            vxlan_port->egress_service_vlan = egress_service_vlan;
   6821            vxlan_port->egress_service_tpid = egress_service_tpid;
   6822            vxlan_port->pkt_cfi = pkt_cfi;
   6823            vxlan_port->pkt_pri = pkt_pri;
   6824        }
   6825 
   6826     } else {
   6827        action_present = 
   6828             soc_EGR_L3_NEXT_HOPm_field32_get(unit, 
   6829                                      egr_nh,
   6830                                      SD_TAG__SD_TAG_ACTION_IF_PRESENTf);
   6831        action_not_present = 
   6832             soc_EGR_L3_NEXT_HOPm_field32_get(unit, 
   6833                                      egr_nh,
   6834                                      SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf);
   6835 
   6836        if (action_not_present == 1) {
   6837             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_ADD;
   6838             vxlan_port->egress_service_vlan =
   6839                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__SD_TAG_VIDf);
   6840        }
   6841 
   6842        switch (action_present) {
   6843          case 1:
   6844             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_TPID_REPLACE;
   6845             vxlan_port->egress_service_vlan =
   6846                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__SD_TAG_VIDf);
   6847             break;
   6848 
   6849          case 2:
   6850             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_REPLACE;
   6851             vxlan_port->egress_service_vlan =
   6852                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__SD_TAG_VIDf);
   6853             break;
   6854 
   6855          case 3:
   6856             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_DELETE;
   6857             vxlan_port->egress_service_vlan = BCM_VLAN_INVALID;
   6858             break;
   6859 
   6860          case 4:
   6861             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE;
   6862             vxlan_port->egress_service_vlan =                 
   6863                  soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__SD_TAG_VIDf);
   6864             vxlan_port->pkt_pri = 
   6865                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__NEW_PRIf);
   6866             vxlan_port->pkt_cfi = 
   6867                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__NEW_CFIf);
   6868             break;
   6869 
   6870          case 5:
   6871             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_PRI_REPLACE;
   6872             vxlan_port->egress_service_vlan = 
   6873                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__SD_TAG_VIDf);
   6874             vxlan_port->pkt_pri = 
   6875                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__NEW_PRIf);
   6876             vxlan_port->pkt_cfi = 
   6877                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__NEW_CFIf);
   6878             break;
   6879 
   6880          case 6:
   6881             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_PRI_REPLACE;
   6882             vxlan_port->egress_service_vlan =   BCM_VLAN_INVALID;
   6883             vxlan_port->pkt_pri = 
   6884                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__NEW_PRIf);
   6885             vxlan_port->pkt_cfi = 
   6886                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__NEW_CFIf);
   6887             break;
   6888 
   6889          case 7:
   6890             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_TPID_REPLACE;
   6891             vxlan_port->egress_service_vlan = BCM_VLAN_INVALID;
   6892             break;
   6893 
   6894          default:
   6895             break;
   6896        }
   6897 
   6898 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 
   6899     if (soc_feature(unit, soc_feature_vp_sharing) &&
   6900         SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, SD_TAG__SD_TAG_NOT_VALIDf)) {
   6901         int sd_tag_invalid = -1;
   6902         sd_tag_invalid = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, 
   6903                                                   SD_TAG__SD_TAG_NOT_VALIDf);
   6904         if (sd_tag_invalid) {
   6905             vxlan_port->egress_service_vlan = BCM_VLAN_INVALID;
   6906         }
   6907     }
   6908 #endif
   6909 
   6910 #if defined(BCM_TRIDENT3_SUPPORT)
   6911        if (soc_feature(unit, soc_feature_vp_sharing) &&
   6912               soc_feature(unit, soc_feature_egr_intf_vlan_vfi_deoverlay)) {
   6913            if ((vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD) ||
   6914               (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_TPID_REPLACE) ||
   6915               (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_REPLACE) ||
   6916               (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_REPLACE) ||
   6917               (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) {
   6918                vxlan_port->egress_service_vlan = (vxlan_port->egress_service_vlan == 0) ?
   6919                                                  BCM_VLAN_INVALID : vxlan_port->egress_service_vlan;
   6920            }
   6921        }
   6922 #endif
   6923 
   6924        if ((vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD) ||
   6925            (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_TPID_REPLACE) ||
   6926            (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TPID_REPLACE) ||
   6927            (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) {
   6928            /* TPID value is used */
   6929            tpid_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh, SD_TAG__SD_TAG_TPID_INDEXf);
   6930            _bcm_fb2_outer_tpid_entry_get(unit, &vxlan_port->egress_service_tpid, tpid_index);
   6931        }
   6932     }
   6933 }
   6934 
   6935 #if defined(BCM_TRIDENT3_SUPPORT)
   6936 /*
   6937  * Function:
   6938  *      _bcm_td3_vxlan_nexthop_l2otag_set 
   6939  * Purpose:
   6940  *     set l2otag in nexthop
   6941  * Parameters:
   6942  *      unit - Device Number
   6943  *      egr_nh_info - ptr of Next Hop Info
   6944  *      egr_nh - ptr of egr nh 
   6945  * Returns:
   6946  *      BCM_E_XXX
   6947  */
   6948 
   6949 STATIC int
   6950 _bcm_td3_vxlan_nexthop_l2otag_set(int unit,
   6951                   _bcm_td2_vxlan_nh_info_t  *egr_nh_info, egr_l3_next_hop_entry_t* egr_nh)
   6952 {
   6953     uint32 profile_idx;
   6954     uint8 pcp_de_sel = 0;
   6955 
   6956     if (egr_nh_info->sd_tag_vlan != -1) { 
   6957         if (egr_nh_info->sd_tag_vlan < BCM_VLAN_INVALID) {
   6958             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   6959                         egr_nh, L2_OTAG__VIDf, egr_nh_info->sd_tag_vlan);
   6960         }
   6961     }
   6962 
   6963     if ((egr_nh_info->sd_tag_action_not_present != -1) || (egr_nh_info->sd_tag_action_present != -1)) {
   6964         profile_idx = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, egr_nh,
   6965                         L2_OTAG__TAG_ACTION_PROFILE_PTRf);
   6966         _bcm_td3_sd_tag_action_profile_get(unit, egr_nh_info->sd_tag_action_present, 
   6967                                                       egr_nh_info->sd_tag_action_not_present, &profile_idx);
   6968         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   6969                          L2_OTAG__TAG_ACTION_PROFILE_PTRf,
   6970                          profile_idx);
   6971     }
   6972 
   6973     if (egr_nh_info->sd_tag_pri != -1) {
   6974         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   6975                L2_OTAG__PCPf,
   6976                egr_nh_info->sd_tag_pri);
   6977         pcp_de_sel = 1;
   6978     }
   6979 
   6980     if (egr_nh_info->sd_tag_cfi != -1) {
   6981        soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   6982              L2_OTAG__DEf,
   6983              egr_nh_info->sd_tag_cfi);
   6984        pcp_de_sel = 1;
   6985     }
   6986 
   6987     if (pcp_de_sel != 0) {
   6988        soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
   6989              L2_OTAG__PCP_DE_SELf,
   6990              pcp_de_sel);
   6991     }
   6992 
   6993     if (egr_nh_info->tpid_index != -1) {
   6994           soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   6995                         egr_nh, L2_OTAG__TPID_INDEXf,
   6996                         egr_nh_info->tpid_index);
   6997     }
   6998 
   6999     return BCM_E_NONE;
   7000 
   7001 }
   7002 #endif
   7003 
   7004 /*
   7005  * Function:
   7006  *      _bcm_td2_vxlan_nexthop_entry_modify
   7007  * Purpose:
   7008  *      Modify Egress entry
   7009  * Parameters:
   7010  *      unit - Device Number
   7011  *      nh_index - Next Hop Index
   7012  *      new_entry_type - New Entry type
   7013  * Returns:
   7014  *      BCM_E_XXX
   7015  */
   7016 
   7017 int
   7018 _bcm_td2_vxlan_nexthop_entry_modify(int unit, int nh_index, int drop, 
   7019               _bcm_td2_vxlan_nh_info_t  *egr_nh_info, int new_entry_type)
   7020 {
   7021     egr_l3_next_hop_entry_t egr_nh;
   7022     int rv = BCM_E_NONE;
   7023     uint32 old_entry_type=0, intf_num=0, vntag_actions=0;
   7024     uint32 vntag_dst_vif=0, vntag_pf=0, vntag_force_lf=0;
   7025     uint32 etag_pcp_de_sourcef=0, etag_pcpf=0, etag_dot1p_mapping_ptr=0, etag_def=0;
   7026     bcm_mac_t mac_addr;                 /* Next hop forwarding destination mac. */
   7027     uint32 hg_ppd_type = 0;
   7028     soc_field_t type_field;
   7029 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7030     ing_l3_next_hop_entry_t ing_nh;
   7031     bcm_port_t port = 0;
   7032     bcm_module_t modid = 0;
   7033 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   7034     int d = 0; /*vxlan decoupled mode*/
   7035 
   7036 #if defined(BCM_TRIDENT3_SUPPORT)
   7037     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   7038         d = 1;
   7039     }
   7040 #endif
   7041 
   7042 #if defined(BCM_TRIDENT3_SUPPORT)
   7043     if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, DATA_TYPEf)) {
   7044         type_field = DATA_TYPEf;
   7045     } else
   7046 #endif
   7047     {
   7048         type_field = ENTRY_TYPEf;
   7049     }
   7050 
   7051     sal_memset(&mac_addr, 0, sizeof (mac_addr));
   7052     BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL,
   7053                       nh_index, &egr_nh));
   7054 
   7055     old_entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, type_field);
   7056 
   7057     if ((new_entry_type == BCM_VXLAN_TAG_VIEW(d)) &&
   7058         (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW)) {
   7059             hg_ppd_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7060                          L3__HG_HDR_SELf);
   7061             /*Zero buffers.*/
   7062             sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   7063 #if defined(BCM_TRIDENT3_SUPPORT)
   7064             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   7065             /*mapping to L2OTA TAP*/
   7066                 BCM_IF_ERROR_RETURN(_bcm_td3_vxlan_nexthop_l2otag_set(unit, egr_nh_info, &egr_nh));
   7067                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7068                          L2_OTAG__FLOW_SELECT_CTRL_IDf, 8);
   7069                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7070                          L2_OTAG__NEXT_PTR_TYPEf, 1);
   7071             } else
   7072 #endif      
   7073             {
   7074                 if (egr_nh_info->sd_tag_vlan != -1) { 
   7075 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7076                     if (soc_feature(unit, soc_feature_vp_sharing)) {
   7077                         if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, SD_TAG__SD_TAG_NOT_VALIDf)) {
   7078                             if (egr_nh_info->sd_tag_vlan == BCM_VLAN_INVALID) {
   7079                                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   7080                                                &egr_nh, SD_TAG__SD_TAG_NOT_VALIDf, 1);
   7081                             } else {
   7082                                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   7083                                                &egr_nh, SD_TAG__SD_TAG_NOT_VALIDf, 0);
   7084                                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   7085                                             &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan);
   7086                             }
   7087                         } else {
   7088                             if (egr_nh_info->sd_tag_vlan < BCM_VLAN_INVALID) {
   7089                                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   7090                                             &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan);
   7091                             }
   7092                         }
   7093                     } else
   7094 #endif
   7095                     {
   7096                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   7097                                         &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan);
   7098                     }
   7099                 }
   7100 
   7101                 if (egr_nh_info->sd_tag_action_present != -1) {
   7102                        soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7103                                  SD_TAG__SD_TAG_ACTION_IF_PRESENTf,
   7104                                  egr_nh_info->sd_tag_action_present);
   7105                 }
   7106 
   7107                 if (egr_nh_info->sd_tag_action_not_present != -1) {
   7108                        soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7109                                  SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf,
   7110                                  egr_nh_info->sd_tag_action_not_present);
   7111                 }
   7112 
   7113                 if (egr_nh_info->sd_tag_pri != -1) {
   7114                      if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__NEW_PRIf)) {
   7115                            soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7116                                  SD_TAG__NEW_PRIf,
   7117                                  egr_nh_info->sd_tag_pri);
   7118                      }
   7119                 }
   7120 
   7121                 if (egr_nh_info->sd_tag_cfi != -1) {
   7122                        if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__NEW_CFIf)) {
   7123                            soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7124                                  SD_TAG__NEW_CFIf,
   7125                                  egr_nh_info->sd_tag_cfi);
   7126                        }
   7127                        if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__SD_TAG_REMARK_CFIf)) {
   7128                            soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7129                                  SD_TAG__SD_TAG_REMARK_CFIf,
   7130                                  0x1);
   7131                        }
   7132                 }
   7133 
   7134                 if (egr_nh_info->tpid_index != -1) {
   7135                       soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   7136                                     &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf,
   7137                                     egr_nh_info->tpid_index);
   7138                 }
   7139             }
   7140 
   7141             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   7142                     BCM_VXLAN_TAG_FIELD(d, BC_DROPf), drop ? 1 : 0);
   7143             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   7144                     BCM_VXLAN_TAG_FIELD(d, UUC_DROPf), drop ? 1 : 0);
   7145             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   7146                     BCM_VXLAN_TAG_FIELD(d, UMC_DROPf), drop ? 1 : 0);
   7147             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7148                     BCM_VXLAN_TAG_FIELD(d, DVPf), egr_nh_info->dvp);
   7149 
   7150 #if defined(BCM_TRIDENT3_SUPPORT)
   7151             if (SOC_IS_TRIDENT3X(unit)) {
   7152             } else
   7153 #endif
   7154             {
   7155                 if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   7156                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   7157                             &egr_nh, SD_TAG__DVP_NETWORK_GROUPf,
   7158                             egr_nh_info->dvp_network_group_id);
   7159                 } else {
   7160                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   7161                             &egr_nh, SD_TAG__DVP_IS_NETWORK_PORTf,
   7162                             egr_nh_info->dvp_is_network);
   7163                 }
   7164             }
   7165             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7166                     BCM_VXLAN_TAG_FIELD(d, HG_LEARN_OVERRIDEf), egr_nh_info->is_eline ? 1 : 0);
   7167             /* HG_MODIFY_ENABLE must be 0x0 for Ingress and Egress Chip */
   7168             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   7169                     BCM_VXLAN_TAG_FIELD(d, HG_MODIFY_ENABLEf), 0x0);
   7170             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   7171                     BCM_VXLAN_TAG_FIELD(d, HG_HDR_SELf), hg_ppd_type);
   7172 
   7173 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7174             if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
   7175                                     BCM_VXLAN_TAG_FIELD(d, HG_MC_DST_PORT_NUMf))) {
   7176                 int is_trunk = 0;
   7177                 BCM_IF_ERROR_RETURN(
   7178                     soc_mem_read(unit, ING_L3_NEXT_HOPm,
   7179                                  MEM_BLOCK_ANY, nh_index, &ing_nh));
   7180 
   7181 #if defined(BCM_TRIDENT3_SUPPORT)
   7182                 if (soc_feature(unit, soc_feature_generic_dest)) {
   7183                     uint32 dt, dv;
   7184 
   7185                     dv = soc_mem_field32_dest_get(unit,
   7186                             ING_L3_NEXT_HOPm, &ing_nh, DESTINATIONf, &dt);
   7187                     if (dt == SOC_MEM_FIF_DEST_DGPP) {
   7188                         port = (dv & SOC_MEM_FIF_DGPP_PORT_MASK);
   7189                         modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
   7190                                     SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
   7191                         is_trunk = 0;
   7192                     } else if (dt == SOC_MEM_FIF_DEST_LAG) {
   7193                         is_trunk = 1;
   7194                     }
   7195                 } else
   7196 #endif
   7197                 {
   7198                     if (!soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, Tf)) {
   7199                         port = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   7200                                                    &ing_nh, PORT_NUMf);
   7201                         modid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   7202                                                     &ing_nh, MODULE_IDf);
   7203                         is_trunk = 0;
   7204                     } else {
   7205                         is_trunk = 1;
   7206                     }
   7207                 }
   7208 
   7209                 if (!is_trunk) {
   7210                     if (_bcm_xgs5_subport_coe_mod_port_local(unit, modid, port)) {
   7211                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7212                                             BCM_VXLAN_TAG_FIELD(d, HG_MC_DST_PORT_NUMf), port);
   7213                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7214                                             BCM_VXLAN_TAG_FIELD(d, HG_MC_DST_MODIDf), modid);
   7215                     }
   7216                 }
   7217             }
   7218 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   7219             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7220                             type_field, BCM_VXLAN_TAG_VIEW(d));
   7221     } else if ((new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) &&
   7222         (old_entry_type == BCM_VXLAN_TAG_VIEW(d))) {
   7223 #if defined(BCM_TRIDENT3_SUPPORT)
   7224             uint32 profile_index = 0;
   7225             int action_present = 0;
   7226             int action_not_present = 0;
   7227             int old_tpid_idx = 0;
   7228 
   7229             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   7230                 profile_index = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   7231                         &egr_nh, L2_OTAG__TAG_ACTION_PROFILE_PTRf);
   7232                 BCM_IF_ERROR_RETURN(_bcm_td3_sd_tag_action_get(unit, profile_index,
   7233                         &action_present, &action_not_present));
   7234                 if (profile_index != 0) {
   7235                     BCM_IF_ERROR_RETURN(
   7236                         _bcm_trx_egr_vlan_action_profile_entry_delete(unit,
   7237                             profile_index));
   7238                 }
   7239                 if ((action_not_present == 0x1) || (action_present == 0x1) ||
   7240                     (action_present == 0x4) || (action_present == 0x7)) {
   7241                     old_tpid_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   7242                         &egr_nh, L2_OTAG__TPID_INDEXf);
   7243                     BCM_IF_ERROR_RETURN(
   7244                         _bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx));
   7245                 }
   7246             }
   7247 #endif
   7248             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7249                             type_field, _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW);
   7250 
   7251 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7252             if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
   7253                                     BCM_VXLAN_TAG_FIELD(d, HG_MC_DST_PORT_NUMf))) {
   7254                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7255                                     BCM_VXLAN_TAG_FIELD(d, HG_MC_DST_PORT_NUMf), 0);
   7256                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7257                                     BCM_VXLAN_TAG_FIELD(d, HG_MC_DST_MODIDf), 0);
   7258             }
   7259 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   7260             if( SOC_IS_APACHE(unit) && (egr_nh_info == NULL)) {
   7261                soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7262                             L3__INTF_NUMf, 0);
   7263            }
   7264     } else if ((new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW) &&
   7265          (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW)) {
   7266 
   7267         /* Get mac address. */
   7268         soc_mem_mac_addr_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7269                          L3__MAC_ADDRESSf, mac_addr);
   7270 
   7271         /* Get int_num */
   7272         intf_num = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7273                          L3__INTF_NUMf);
   7274 
   7275         vntag_actions = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7276                          L3__VNTAG_ACTIONSf);
   7277 
   7278         vntag_dst_vif = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7279                          L3__VNTAG_DST_VIFf);
   7280 
   7281         vntag_pf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7282                          L3__VNTAG_Pf);
   7283 
   7284         vntag_force_lf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7285                          L3__VNTAG_FORCE_Lf);
   7286 
   7287         etag_pcp_de_sourcef = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7288                          L3__ETAG_PCP_DE_SOURCEf);
   7289 
   7290         etag_pcpf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7291                          L3__ETAG_PCPf);
   7292 
   7293         etag_dot1p_mapping_ptr = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7294                          L3__ETAG_DOT1P_MAPPING_PTRf);
   7295 
   7296         etag_def = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7297                          L3__ETAG_DEf);
   7298         hg_ppd_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7299                          L3__HG_HDR_SELf);
   7300         /*Zero buffers.*/
   7301         sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   7302 
   7303         soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7304                          L3MC__MAC_ADDRESSf, mac_addr);
   7305         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7306                                 L3MC__INTF_NUMf, intf_num);
   7307 
   7308 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7309         if (soc_feature(unit, soc_feature_egr_l3_next_hop_next_ptr)) {
   7310             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7311                                     L3MC__NEXT_PTR_TYPEf, 0x1);
   7312         } else
   7313 #endif
   7314         {
   7315             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7316                                     L3MC__DVP_VALIDf, 0x1);
   7317         }
   7318         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7319                                 L3MC__DVPf, egr_nh_info->dvp);
   7320 #if defined(BCM_TRIDENT3_SUPPORT)
   7321         if (SOC_IS_TRIDENT3X(unit)) {
   7322         } else
   7323 #endif
   7324         {
   7325             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7326                                     L3MC__L2_MC_DA_DISABLEf, 0x1);
   7327             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7328                                     L3MC__L2_MC_SA_DISABLEf, 0x1);
   7329             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7330                                     L3MC__L2_MC_VLAN_DISABLEf, 0x1);
   7331         }
   7332         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7333                                     L3MC__L2_DROPf, 0x0);
   7334         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   7335                                 L3MC__L3_DROPf, drop ? 1 : 0);
   7336         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   7337                                 L3MC__L3MC_USE_CONFIGURED_MACf, 0x1);
   7338         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7339                                 L3MC__VNTAG_ACTIONSf, vntag_actions);
   7340         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7341                                 L3MC__VNTAG_DST_VIFf, vntag_dst_vif);
   7342         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7343                                 L3MC__VNTAG_Pf, vntag_pf);
   7344         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7345                                 L3MC__VNTAG_FORCE_Lf, vntag_force_lf);
   7346         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7347                                 L3MC__ETAG_PCP_DE_SOURCEf, etag_pcp_de_sourcef);
   7348         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7349                                 L3MC__ETAG_PCPf, etag_pcpf);
   7350         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7351                                 L3MC__ETAG_DOT1P_MAPPING_PTRf, etag_dot1p_mapping_ptr);
   7352         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7353                                 L3MC__ETAG_DEf, etag_def);
   7354         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7355                                 L3MC__HG_HDR_SELf, hg_ppd_type);
   7356 
   7357 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7358         if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3MC__HG_MC_DST_PORT_NUMf) &&
   7359             soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3MC__USE_MAC_DA_PROFILEf)) {
   7360             int is_trunk = 0;
   7361             BCM_IF_ERROR_RETURN(
   7362                 soc_mem_read(unit, ING_L3_NEXT_HOPm,
   7363                              MEM_BLOCK_ANY, nh_index, &ing_nh));
   7364 #if defined(BCM_TRIDENT3_SUPPORT)
   7365             if (soc_feature(unit, soc_feature_generic_dest)) {
   7366                 uint32 dt, dv;
   7367 
   7368                 dv = soc_mem_field32_dest_get(unit,
   7369                         ING_L3_NEXT_HOPm, &ing_nh, DESTINATIONf, &dt);
   7370                 if (dt == SOC_MEM_FIF_DEST_DGPP) {
   7371                     port = (dv & SOC_MEM_FIF_DGPP_PORT_MASK);
   7372                     modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
   7373                                 SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
   7374                     is_trunk = 0;
   7375                 } else if (dt == SOC_MEM_FIF_DEST_LAG) {
   7376                     is_trunk = 1;
   7377                 }
   7378             } else
   7379 #endif
   7380             {
   7381                 if (!soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, Tf)) {
   7382                     port = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   7383                                                &ing_nh, PORT_NUMf);
   7384                     modid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   7385                                                 &ing_nh, MODULE_IDf);
   7386                     is_trunk = 0;
   7387                 } else {
   7388                     is_trunk = 1;
   7389                 }
   7390             }
   7391 
   7392             if (!is_trunk) {
   7393                 if (_bcm_xgs5_subport_coe_mod_port_local(unit, modid, port)) {
   7394                     uint32 macda_index;
   7395                     void *entries[1];
   7396                     egr_mac_da_profile_entry_t macda;
   7397 
   7398                     sal_memset(&macda, 0, sizeof(egr_mac_da_profile_entry_t));
   7399                     soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm,
   7400                              &macda, MAC_ADDRESSf, mac_addr);
   7401                     entries[0] = &macda;
   7402                     BCM_IF_ERROR_RETURN(
   7403                         _bcm_mac_da_profile_entry_add(unit, entries, 1, &macda_index));
   7404 
   7405                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7406                                         L3MC__HG_MC_DST_PORT_NUMf, port);
   7407                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7408                                         L3MC__HG_MC_DST_MODIDf, modid);
   7409                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7410                                         L3MC__USE_MAC_DA_PROFILEf, 1);
   7411                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7412                                         L3MC__MAC_DA_PROFILE_INDEXf, macda_index);
   7413                 }
   7414             }
   7415         }
   7416 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   7417         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7418                                 type_field, _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW);
   7419 
   7420     } else if ((new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW) &&
   7421         (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW)) {
   7422         
   7423         /* Update entry with DVP info if it is already IPMC entry */ 
   7424 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7425         if (soc_feature(unit, soc_feature_egr_l3_next_hop_next_ptr)) {
   7426             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7427                     L3MC__NEXT_PTR_TYPEf, 0x1);
   7428         } else
   7429 #endif
   7430         {
   7431             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7432                                     L3MC__DVP_VALIDf, 0x1);
   7433         }
   7434 
   7435         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7436                                 L3MC__DVPf, egr_nh_info->dvp);
   7437 #if defined(BCM_TRIDENT3_SUPPORT)
   7438         if (SOC_IS_TRIDENT3X(unit)) {
   7439         } else
   7440 #endif
   7441         {
   7442             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7443                                     L3MC__L2_MC_DA_DISABLEf, 0x1);
   7444             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7445                                     L3MC__L2_MC_SA_DISABLEf, 0x1);
   7446             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7447                                     L3MC__L2_MC_VLAN_DISABLEf, 0x1);
   7448         }
   7449         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7450                                     L3MC__L2_DROPf, 0x0);
   7451         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   7452                                 L3MC__L3_DROPf, drop ? 1 : 0);
   7453         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   7454                                 L3MC__L3MC_USE_CONFIGURED_MACf, 0x1);
   7455         
   7456     } else if ((new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) &&
   7457          (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW)) {
   7458         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7459                             type_field, _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW);
   7460 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7461         if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3MC__HG_MC_DST_PORT_NUMf) &&
   7462             soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3MC__USE_MAC_DA_PROFILEf)) {
   7463             if (soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7464                                     L3MC__USE_MAC_DA_PROFILEf)) {
   7465                 uint32 macda_index;
   7466 
   7467                 macda_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7468                                     L3MC__MAC_DA_PROFILE_INDEXf);
   7469                 BCM_IF_ERROR_RETURN(
   7470                     _bcm_mac_da_profile_entry_delete(unit, macda_index));
   7471             }
   7472         }
   7473 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   7474         /* Get mac address. */
   7475         soc_mem_mac_addr_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7476                              L3MC__MAC_ADDRESSf, mac_addr);
   7477 
   7478         /* Get int_num */
   7479         intf_num = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7480                                        L3MC__INTF_NUMf);
   7481 
   7482         vntag_actions = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7483                                             L3MC__VNTAG_ACTIONSf);
   7484 
   7485         vntag_dst_vif = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7486                                             L3MC__VNTAG_DST_VIFf);
   7487 
   7488         vntag_pf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7489                                        L3MC__VNTAG_Pf);
   7490 
   7491         vntag_force_lf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7492                                              L3MC__VNTAG_FORCE_Lf);
   7493 
   7494         etag_pcp_de_sourcef = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
   7495                                                   &egr_nh,
   7496                                                   L3MC__ETAG_PCP_DE_SOURCEf);
   7497 
   7498         etag_pcpf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7499                                         L3MC__ETAG_PCPf);
   7500 
   7501         etag_dot1p_mapping_ptr = soc_mem_field32_get(
   7502             unit, EGR_L3_NEXT_HOPm, &egr_nh, L3MC__ETAG_DOT1P_MAPPING_PTRf);
   7503 
   7504         etag_def = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7505                                        L3MC__ETAG_DEf);
   7506         hg_ppd_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7507                                           L3MC__HG_HDR_SELf);
   7508         /*Zero buffers.*/
   7509         sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   7510 
   7511         soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7512                              L3__MAC_ADDRESSf, mac_addr);
   7513         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7514                             L3__INTF_NUMf, intf_num);
   7515 
   7516         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7517                             L3__VNTAG_ACTIONSf, vntag_actions);
   7518         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7519                             L3__VNTAG_DST_VIFf, vntag_dst_vif);
   7520         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7521                             L3__VNTAG_Pf, vntag_pf);
   7522         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7523                             L3__VNTAG_FORCE_Lf, vntag_force_lf);
   7524         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7525                             L3__ETAG_PCP_DE_SOURCEf, etag_pcp_de_sourcef);
   7526         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7527                             L3__ETAG_PCPf, etag_pcpf);
   7528         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7529                             L3__ETAG_DOT1P_MAPPING_PTRf,
   7530                             etag_dot1p_mapping_ptr);
   7531         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7532                             L3__ETAG_DEf, etag_def);
   7533         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7534                             L3__HG_HDR_SELf, hg_ppd_type);
   7535 
   7536         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7537                             type_field, _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW);
   7538     } else if ((new_entry_type == BCM_VXLAN_TAG_VIEW(d)) &&
   7539         (old_entry_type == BCM_VXLAN_TAG_VIEW(d))) {
   7540         /* Case of VXLAN Proxy Next-Hop */
   7541 #if defined(BCM_TRIDENT3_SUPPORT)
   7542         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   7543             BCM_IF_ERROR_RETURN(_bcm_td3_vxlan_nexthop_l2otag_set(unit, egr_nh_info, &egr_nh));
   7544             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7545                          L2_OTAG__FLOW_SELECT_CTRL_IDf, 8);
   7546             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7547                          L2_OTAG__NEXT_PTR_TYPEf, 1);
   7548         } else
   7549 #endif
   7550         {
   7551             if (egr_nh_info->sd_tag_vlan != -1) { 
   7552 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 
   7553                 if (soc_feature(unit, soc_feature_vp_sharing)) { 
   7554                     if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, SD_TAG__SD_TAG_NOT_VALIDf)) {
   7555                         if (egr_nh_info->sd_tag_vlan == BCM_VLAN_INVALID) {
   7556                             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   7557                                            &egr_nh, SD_TAG__SD_TAG_NOT_VALIDf, 1);
   7558                         } else {
   7559                             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   7560                                            &egr_nh, SD_TAG__SD_TAG_NOT_VALIDf, 0);
   7561                             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   7562                                         &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan);
   7563                         }
   7564                     } else {
   7565                         if (egr_nh_info->sd_tag_vlan < BCM_VLAN_INVALID) {
   7566                             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   7567                                         &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan);
   7568                         }
   7569                     }
   7570                 } else
   7571 #endif
   7572                 {
   7573                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   7574                                     &egr_nh, SD_TAG__SD_TAG_VIDf, egr_nh_info->sd_tag_vlan);
   7575                 }
   7576             }
   7577 
   7578             if (egr_nh_info->sd_tag_action_present != -1) {
   7579                    soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7580                              SD_TAG__SD_TAG_ACTION_IF_PRESENTf,
   7581                              egr_nh_info->sd_tag_action_present);
   7582             } else {
   7583                    soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7584                              SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 0x0);
   7585 
   7586             }
   7587 
   7588             if (egr_nh_info->sd_tag_action_not_present != -1) {
   7589                    soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7590                              SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf,
   7591                              egr_nh_info->sd_tag_action_not_present);
   7592             } else {
   7593                    soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7594                              SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf, 0x0);
   7595             }
   7596 
   7597             if (egr_nh_info->sd_tag_pri != -1) {
   7598                  if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__NEW_PRIf)) {
   7599                        soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7600                              SD_TAG__NEW_PRIf,
   7601                              egr_nh_info->sd_tag_pri);
   7602                  }
   7603             } else {
   7604                  if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__NEW_PRIf)) {
   7605                        soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7606                              SD_TAG__NEW_PRIf, 0x0);
   7607                  }
   7608             }
   7609 
   7610             if (egr_nh_info->sd_tag_cfi != -1) {
   7611                    if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__NEW_CFIf)) {
   7612                        soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7613                              SD_TAG__NEW_CFIf,
   7614                              egr_nh_info->sd_tag_cfi);
   7615                    }
   7616                    if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__SD_TAG_REMARK_CFIf)) {
   7617                        soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7618                              SD_TAG__SD_TAG_REMARK_CFIf,
   7619                              0x1);
   7620                    }
   7621             } else {
   7622                    if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__SD_TAG_REMARK_CFIf)) {
   7623                           soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7624                                 SD_TAG__SD_TAG_REMARK_CFIf,
   7625                                 0x0);
   7626                    }
   7627             }
   7628 
   7629             if (egr_nh_info->tpid_index != -1) {
   7630                   soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   7631                                 &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf,
   7632                                 egr_nh_info->tpid_index);
   7633             }
   7634         }
   7635         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7636                 BCM_VXLAN_TAG_FIELD(d, DVPf), egr_nh_info->dvp);
   7637         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7638                 BCM_VXLAN_TAG_FIELD(d, BC_DROPf), drop ? 1 : 0);
   7639         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7640                 BCM_VXLAN_TAG_FIELD(d, UUC_DROPf), drop ? 1 : 0);
   7641         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   7642                 BCM_VXLAN_TAG_FIELD(d, UMC_DROPf), drop ? 1 : 0);
   7643     }
   7644 
   7645     rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   7646                        MEM_BLOCK_ALL, nh_index, &egr_nh);
   7647     return rv;
   7648 }
   7649 
   7650 /*
   7651  * Function:
   7652  *           bcm_td2_vxlan_next_hop_set
   7653  * Purpose:
   7654  *           Set VXLAN NextHop Entry
   7655  * Parameters:
   7656  *           IN :  Unit
   7657  *           IN :  nh_index
   7658  * Returns:
   7659  *           BCM_E_XXX
   7660  */
   7661 
   7662 int
   7663 bcm_td2_vxlan_next_hop_set(int unit, int nh_index, uint32 flags, int vp, int drop)
   7664 {
   7665     int rv = BCM_E_NONE;
   7666     ing_l3_next_hop_entry_t ing_nh;
   7667     bcm_port_t  port = -1;
   7668     bcm_module_t modid = -1, local_modid = -1;
   7669     bcm_trunk_t tgid = -1;
   7670     int  num_ports=0, idx=-1;
   7671     bcm_port_t   local_ports[SOC_MAX_NUM_PORTS];
   7672     int  old_nh_index=-1;
   7673     int replace=0;
   7674     int gport = 0;
   7675     _bcm_td2_vxlan_nh_info_t  egr_nh_info;
   7676     _bcm_vp_info_t vp_info;
   7677     soc_mem_t hw_mem = ING_L3_NEXT_HOPm;
   7678 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7679     bcm_trunk_member_t *tmp_member_gports_array = NULL;
   7680 #endif
   7681 
   7682     BCM_IF_ERROR_RETURN(soc_mem_read(unit,
   7683         hw_mem, MEM_BLOCK_ANY, nh_index, &ing_nh));
   7684     soc_mem_field32_set(unit, hw_mem, &ing_nh,
   7685         ENTRY_TYPEf, _BCM_VXLAN_INGRESS_NEXT_HOP_ENTRY_TYPE);
   7686     if (SOC_MEM_FIELD_VALID(unit, hw_mem, MTU_SIZEf)) {
   7687         soc_mem_field32_set(unit, hw_mem, &ing_nh, MTU_SIZEf, 0x3fff);
   7688     }
   7689     BCM_IF_ERROR_RETURN(
   7690         soc_mem_write(unit, hw_mem, MEM_BLOCK_ALL, nh_index, &ing_nh));
   7691 
   7692     if (flags & BCM_L3_IPMC) {
   7693         egr_l3_next_hop_entry_t egr_nh;
   7694         int entry_type = 0;
   7695 
   7696         (void)_bcm_vp_info_get(unit, vp, &vp_info);
   7697 
   7698         if (vp_info.flags & _BCM_VP_INFO_SHARED_PORT &&
   7699                 vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) { /* Shared network VP */
   7700 
   7701             SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL,
   7702                                               nh_index, &egr_nh));
   7703 #if defined(BCM_TRIDENT3_SUPPORT)
   7704             if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, DATA_TYPEf)) {
   7705                 entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, DATA_TYPEf);
   7706             } else
   7707 #endif
   7708             {
   7709                 entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, ENTRY_TYPEf);
   7710             }
   7711             if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) {
   7712                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, L3__HG_HDR_SELf, 1);
   7713             }
   7714             SOC_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   7715                                               MEM_BLOCK_ALL, nh_index, &egr_nh));
   7716             egr_nh_info.dvp = vp;
   7717             BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_nexthop_entry_modify(unit,
   7718                 nh_index, drop, &egr_nh_info, _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW));
   7719         }
   7720     } else { /* Only for VXLAN Unicast Nexthops */
   7721         replace = flags & BCM_L3_REPLACE;
   7722 
   7723         BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_nexthop_glp_get(unit,
   7724                                 nh_index, &modid, &port, &tgid));
   7725 
   7726         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &local_modid));
   7727         if (tgid != -1) {
   7728              BCM_IF_ERROR_RETURN(_bcm_trunk_id_validate(unit, tgid));
   7729              rv = bcm_esw_trunk_get(unit, tgid, NULL, 0, NULL, &num_ports);
   7730              if (BCM_FAILURE(rv)) {
   7731                  return BCM_E_PORT;
   7732              }
   7733              if (num_ports == 0) {
   7734                  return BCM_E_NONE;
   7735              }
   7736 #if defined(BCM_TRIDENT2PLUS_SUPPORT)             
   7737              if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
   7738                  tmp_member_gports_array = sal_alloc(
   7739                      sizeof(bcm_trunk_member_t) * num_ports, "tmp_member_gports_arry");
   7740                  if (tmp_member_gports_array == NULL) {
   7741                      return BCM_E_MEMORY;
   7742                  }
   7743                  sal_memset(tmp_member_gports_array, 0,
   7744                      sizeof(bcm_trunk_member_t) * num_ports);
   7745                  rv = bcm_esw_trunk_get(unit, tgid, NULL,
   7746                           num_ports, tmp_member_gports_array, &num_ports);
   7747                  if (BCM_FAILURE(rv)) {
   7748                      goto clean_up;
   7749                  }
   7750              } else
   7751 #endif
   7752              {
   7753                  BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid,
   7754                      SOC_MAX_NUM_PORTS, local_ports, &num_ports));
   7755                  modid = local_modid;
   7756              }
   7757         } else {
   7758             if (modid != local_modid) {
   7759                 if (!soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
   7760                     /* Ignore EGR_PORT_TO_NHI_MAPPINGs */
   7761                     return BCM_E_NONE;
   7762                 }
   7763             }
   7764 
   7765 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7766             if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
   7767                 /* Alloc one trunk member size memory */
   7768                 tmp_member_gports_array = sal_alloc(
   7769                     sizeof(bcm_trunk_member_t), "tmp_member_gports_arry");
   7770                 if (tmp_member_gports_array == NULL) {
   7771                     return BCM_E_MEMORY;
   7772                 }
   7773                 sal_memset(tmp_member_gports_array, 0,
   7774                     sizeof(bcm_trunk_member_t));
   7775                 BCM_GPORT_MODPORT_SET(gport, modid, port);
   7776                 tmp_member_gports_array[num_ports++].gport = gport;
   7777             } else
   7778 #endif
   7779             {
   7780                 local_ports[num_ports++] = port;
   7781             }
   7782         }
   7783 
   7784        for (idx = 0; idx < num_ports; idx++) {
   7785 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7786             if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
   7787                 gport = tmp_member_gports_array[idx].gport;
   7788             } else
   7789 #endif
   7790             {
   7791                 BCM_GPORT_MODPORT_SET(gport, modid, local_ports[idx]);
   7792             }
   7793 
   7794             rv = _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index);
   7795             if (BCM_FAILURE(rv)) {
   7796                  goto clean_up;
   7797             }
   7798             if (old_nh_index && !replace) {
   7799                 if (old_nh_index != nh_index) {
   7800                     /* Limitation: For TD/TR3/TD2,
   7801                        VxLAN egress port can be configured with one NHI */
   7802                     rv = BCM_E_RESOURCE;
   7803                     goto clean_up;
   7804                 }
   7805             } else {
   7806                 rv = _bcm_trx_gport_to_nhi_set(unit, gport, nh_index);
   7807                 if (BCM_FAILURE(rv)) {
   7808                     goto clean_up;
   7809                 }
   7810             }
   7811          }
   7812     }
   7813 
   7814 clean_up:
   7815 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   7816     if (NULL != tmp_member_gports_array) {
   7817         sal_free(tmp_member_gports_array);
   7818     }
   7819 #endif
   7820     return rv;
   7821 }
   7822 
   7823 /*
   7824  * Function:
   7825  *           bcm_td2_vxlan_nexthop_get
   7826  * Purpose:
   7827  *          Get VXLAN NextHop entry
   7828  * Parameters:
   7829  *          unit       - (IN) SOC unit
   7830  *          egr_nh     - (IN) Egress NHop Info
   7831  *          vxlan_port - (IN/OUT) VXLAN port
   7832  * Returns:
   7833  *           BCM_E_XXX
   7834  */
   7835 
   7836 int
   7837 bcm_td2_vxlan_nexthop_get(int unit, egr_l3_next_hop_entry_t *egr_nh,
   7838                           bcm_vxlan_port_t *vxlan_port)
   7839 {
   7840     soc_mem_t      hw_mem;
   7841     uint32 entry_type;
   7842     int d = 0; /*vxlan decoupled mode*/
   7843 
   7844 #if defined(BCM_TRIDENT3_SUPPORT)
   7845     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   7846         d = 1;
   7847     }
   7848 #endif
   7849 
   7850     hw_mem = EGR_L3_NEXT_HOPm;
   7851 
   7852 #if defined(BCM_TRIDENT3_SUPPORT)
   7853     if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, DATA_TYPEf)) {
   7854         entry_type = soc_mem_field32_get(unit, hw_mem, egr_nh, DATA_TYPEf);
   7855     } else
   7856 #endif
   7857     {
   7858         entry_type = soc_mem_field32_get(unit, hw_mem, egr_nh, ENTRY_TYPEf);
   7859     }
   7860 
   7861     if (entry_type == BCM_VXLAN_TAG_VIEW(d)) {
   7862         if (soc_mem_field32_get(unit, hw_mem, egr_nh, BCM_VXLAN_TAG_FIELD(d, BC_DROPf))
   7863             || soc_mem_field32_get(unit, hw_mem, egr_nh, BCM_VXLAN_TAG_FIELD(d, UUC_DROPf))
   7864             || soc_mem_field32_get(unit, hw_mem, egr_nh, BCM_VXLAN_TAG_FIELD(d, UMC_DROPf))) {
   7865             vxlan_port->flags |= BCM_VXLAN_PORT_DROP;
   7866         }
   7867 
   7868         if (!soc_mem_field32_get(unit, hw_mem, egr_nh, BCM_VXLAN_TAG_FIELD(d, HG_HDR_SELf))) {
   7869             vxlan_port->flags |= BCM_VXLAN_PORT_ENCAP_LOCAL;
   7870         }
   7871     } else if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW) {
   7872         if (soc_mem_field32_get(unit, hw_mem, egr_nh, L3MC__L3_DROPf)) {
   7873             vxlan_port->flags |= BCM_VXLAN_PORT_DROP;
   7874         }
   7875 
   7876         if (!soc_mem_field32_get(unit, hw_mem, egr_nh, L3MC__HG_HDR_SELf)) {
   7877             vxlan_port->flags |= BCM_VXLAN_PORT_ENCAP_LOCAL;
   7878         }
   7879 
   7880         vxlan_port->flags |= BCM_VXLAN_PORT_MULTICAST;
   7881     } else if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) {
   7882         if (!soc_mem_field32_get(unit, hw_mem, egr_nh, L3__HG_HDR_SELf)) {
   7883             vxlan_port->flags |= BCM_VXLAN_PORT_ENCAP_LOCAL;
   7884         }
   7885     }
   7886 
   7887     return BCM_E_NONE;
   7888 }
   7889 
   7890 
   7891 /*
   7892  * Function:
   7893  *           _bcm_td2_vxlan_port_egress_nexthop_reset
   7894  * Purpose:
   7895  *           Reset VXLAN Egress NextHop 
   7896  * Parameters:
   7897  *           IN :  Unit
   7898  *           IN :  nh_index
   7899  * Returns:
   7900  *           BCM_E_XXX
   7901  */
   7902 
   7903 int
   7904 _bcm_td2_vxlan_port_egress_nexthop_reset(int unit, int nh_index, int vp_type, int vp, bcm_vpn_t vpn)
   7905 {
   7906     egr_l3_next_hop_entry_t egr_nh;
   7907     int rv=BCM_E_NONE;
   7908     int action_present=0, action_not_present=0, old_tpid_idx = -1;
   7909     uint32  entry_type=0;
   7910     bcm_vxlan_port_t  vxlan_port;
   7911     int d = 0; /*vxlan decoupled mode*/
   7912 
   7913 #if defined(BCM_TRIDENT3_SUPPORT)
   7914     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   7915         d = 1;
   7916     }
   7917 #endif
   7918 
   7919     BCM_IF_ERROR_RETURN(
   7920         _bcm_td2_vxlan_port_get(unit, vpn, vp, &vxlan_port));
   7921     BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm,
   7922                                 MEM_BLOCK_ANY, nh_index, &egr_nh));
   7923     /* egressing into a regular port */
   7924 #if defined(BCM_TRIDENT3_SUPPORT)
   7925     if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, DATA_TYPEf)) {
   7926         entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DATA_TYPEf);
   7927     } else
   7928 #endif
   7929     {
   7930         entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, ENTRY_TYPEf);
   7931     }
   7932     if (vp_type== _BCM_VXLAN_DEST_VP_TYPE_ACCESS) {
   7933         if (entry_type == BCM_VXLAN_TAG_VIEW(d)) {
   7934 #if defined(BCM_TRIDENT3_SUPPORT)
   7935             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   7936                 _bcm_td3_vxlan_tpid_delete(unit, NULL, (uint32*)&egr_nh);
   7937             } else
   7938 #endif
   7939             {      
   7940                 action_present = 
   7941                     soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   7942                         SD_TAG__SD_TAG_ACTION_IF_PRESENTf);
   7943                 action_not_present = 
   7944                     soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   7945                         SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf);
   7946                 if ((action_not_present == 0x1) || (action_present == 0x1) ||
   7947                     (action_present == 0x4) || (action_present == 0x7)) {
   7948                     old_tpid_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   7949                         &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf);
   7950                     BCM_IF_ERROR_RETURN(
   7951                         _bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx));
   7952                 }
   7953             }
   7954         }
   7955         /* Normalize Next-hop Entry -- L3 View */
   7956         rv = _bcm_td2_vxlan_nexthop_entry_modify(unit, nh_index, 0, 
   7957                              NULL, _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW);
   7958 
   7959     } else if ( vp_type == _BCM_VXLAN_INGRESS_DEST_VP_TYPE ){
   7960         /* egressing into a tunnel, vp type should be _BCM_VXLAN_INGRESS_DEST_VP_TYPE */
   7961         /* Normalize Next-hop Entry -- L3 View */
   7962         if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW) {
   7963             rv = _bcm_td2_vxlan_nexthop_entry_modify(unit, nh_index, 0, NULL, 
   7964                                             _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW);
   7965         }
   7966     }
   7967 
   7968     return rv;
   7969 }
   7970 
   7971 /*
   7972  * Function:
   7973  *           bcm_td2_vxlan_ecmp_port_egress_nexthop_reset
   7974  * Purpose:
   7975  *           Reset VXLAN ecmp Egress NextHop 
   7976  * Parameters:
   7977  *           IN :  Unit
   7978  *           IN :  ecmp_index
   7979  * Returns:
   7980  *           BCM_E_XXX
   7981  */
   7982 
   7983 int
   7984 _bcm_td2_vxlan_ecmp_port_egress_nexthop_reset(int unit, int ecmp_index, int vp_type, int vp, bcm_vpn_t vpn)
   7985 {
   7986     int i = 0, ecmp_member_count = 0;
   7987     int alloc_size, index;
   7988     bcm_l3_egress_ecmp_t ecmp_info;
   7989     bcm_if_t *ecmp_member_array = NULL;
   7990     int rv = BCM_E_NONE;
   7991 
   7992     if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_index)) {
   7993         return BCM_E_PARAM;
   7994     }
   7995     ecmp_info.ecmp_intf = ecmp_index;
   7996     alloc_size = sizeof(bcm_if_t)*BCM_XGS3_L3_ECMP_MAX(unit);
   7997     ecmp_member_array = sal_alloc(alloc_size, "ecmp member array");
   7998     if (NULL == ecmp_member_array) {
   7999         return BCM_E_MEMORY;
   8000     }
   8001     sal_memset(ecmp_member_array, 0, alloc_size);
   8002 
   8003     rv = bcm_esw_l3_egress_ecmp_get(unit, &ecmp_info, BCM_XGS3_L3_ECMP_MAX(unit),
   8004                                   ecmp_member_array, &ecmp_member_count);
   8005     if (BCM_FAILURE(rv)) {
   8006         goto clean_up;
   8007     }
   8008 
   8009     while(i < ecmp_member_count) {
   8010         if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit,
   8011                     ecmp_member_array[i])) {
   8012             index = (ecmp_member_array[i] - BCM_XGS3_EGRESS_IDX_MIN(unit));
   8013         } else {
   8014             rv = BCM_E_PARAM;
   8015             goto clean_up;
   8016         }
   8017 
   8018         rv = _bcm_td2_vxlan_port_egress_nexthop_reset(unit, index, vp_type,
   8019                                      vp, vpn);
   8020         if (BCM_FAILURE(rv)) {
   8021             goto clean_up;
   8022         }
   8023         i++;
   8024     }
   8025 
   8026 clean_up:
   8027     if (ecmp_member_array) {
   8028         sal_free(ecmp_member_array);
   8029         ecmp_member_array = NULL;
   8030     }
   8031 
   8032     return rv;
   8033 }
   8034 
   8035 #if defined(BCM_TRIDENT3_SUPPORT)
   8036 /*
   8037  * Function:
   8038  *           _bcm_td3_vxlan_ecmp_acess_port_egress_nexthop_reset
   8039  * Purpose:
   8040  *           Reset VXLAN access ecmp Egress NextHop
   8041  * Parameters:
   8042  *           IN :  Unit
   8043  *           IN :  vp_type
   8044  *           IN :  vp
   8045  *           IN :  vpn
   8046  * Returns:
   8047  *           BCM_E_XXX
   8048  */
   8049 
   8050 int
   8051 _bcm_td3_vxlan_ecmp_acess_port_egress_nexthop_reset(int unit, int vp_type, int vp, bcm_vpn_t vpn){
   8052     int rv = BCM_E_NONE;
   8053     uint32 *vtab, *vtabp;
   8054     int i, imin, imax, nent;
   8055     soc_mem_t egr_l3_nh_mem = EGR_L3_NEXT_HOPm;
   8056     int d = 0; /*vxlan decoupled mode*/
   8057 
   8058 #if defined(BCM_TRIDENT3_SUPPORT)
   8059     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   8060         d = 1;
   8061     }
   8062 #endif
   8063 
   8064     imin = soc_mem_index_min(unit, egr_l3_nh_mem);
   8065     imax = soc_mem_index_max(unit, egr_l3_nh_mem);
   8066     nent = soc_mem_index_count(unit, egr_l3_nh_mem);
   8067 
   8068     vtab = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, egr_l3_nh_mem), "egr_l3_next_hop");
   8069     if (vtab == NULL) {
   8070         return BCM_E_MEMORY;
   8071     }
   8072     sal_memset(vtab, 0, SOC_MEM_TABLE_BYTES(unit, egr_l3_nh_mem));
   8073 
   8074     soc_mem_lock(unit, egr_l3_nh_mem);
   8075     rv = soc_mem_read_range(unit, egr_l3_nh_mem, MEM_BLOCK_ANY,
   8076                             imin, imax, vtab);
   8077     if (BCM_FAILURE(rv)) {
   8078         soc_mem_unlock(unit, egr_l3_nh_mem);
   8079         soc_cm_sfree(unit, vtab);
   8080         return rv;
   8081     }
   8082 
   8083     for (i = 0; i < nent; i++) {
   8084         vtabp = soc_mem_table_idx_to_pointer(unit, egr_l3_nh_mem,
   8085                                              void *, vtab, i);
   8086         if (soc_mem_field32_get(unit, egr_l3_nh_mem, vtabp, DATA_TYPEf)
   8087                                         != BCM_VXLAN_TAG_VIEW(d)) {
   8088             continue;
   8089         }
   8090 
   8091         if (soc_mem_field32_get(unit, egr_l3_nh_mem, vtabp, BCM_VXLAN_TAG_FIELD(d, DVPf)) != vp) {
   8092             continue;
   8093         }
   8094         /* Delete the entry from HW */
   8095         rv = _bcm_td2_vxlan_port_egress_nexthop_reset(unit, i, vp_type,
   8096                                      vp, vpn);
   8097         if (BCM_FAILURE(rv)) {
   8098             soc_mem_unlock(unit, egr_l3_nh_mem);
   8099             soc_cm_sfree(unit, vtab);
   8100             return rv;
   8101         }
   8102     }
   8103     soc_mem_unlock(unit, egr_l3_nh_mem);
   8104     soc_cm_sfree(unit, vtab);
   8105 
   8106     return rv;
   8107 }
   8108 #endif
   8109 
   8110 /*
   8111  * Function:
   8112  *      bcm_td2_vxlan_nexthop_reset
   8113  * Purpose:
   8114  *      Reset VXLAN NextHop entry
   8115  * Parameters:
   8116  *      IN :  Unit
   8117  *           IN :  nh_index
   8118  * Returns:
   8119  *      BCM_E_XXX
   8120  */
   8121 
   8122 STATIC int
   8123 _bcm_td2_vxlan_nexthop_reset(int unit, int nh_index)
   8124 {
   8125     int rv=BCM_E_NONE;
   8126     ing_l3_next_hop_entry_t ing_nh;
   8127     egr_l3_next_hop_entry_t egr_nh;
   8128     bcm_port_t      port=0;
   8129     bcm_trunk_t tgid= BCM_TRUNK_INVALID;
   8130     int  num_ports=0, idx=-1;
   8131     bcm_port_t   local_ports[SOC_MAX_NUM_PORTS];
   8132     soc_mem_t      hw_mem;
   8133     bcm_module_t modid=0, local_modid=0;
   8134     uint8 multicast_entry=0;
   8135     int  old_nh_index=-1;
   8136     int gport = 0;
   8137     soc_field_t type_field;
   8138 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   8139     bcm_trunk_member_t *tmp_member_gports_array = NULL;
   8140 #endif
   8141 
   8142     hw_mem = EGR_L3_NEXT_HOPm;
   8143 
   8144 #if defined(BCM_TRIDENT3_SUPPORT)
   8145     if (SOC_MEM_FIELD_VALID(unit, hw_mem, DATA_TYPEf)) {
   8146         type_field = DATA_TYPEf;
   8147     } else
   8148 #endif
   8149     {
   8150         type_field = ENTRY_TYPEf;
   8151     }
   8152 
   8153     BCM_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem, 
   8154                                   MEM_BLOCK_ANY, nh_index, &egr_nh));
   8155     if (_BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW == soc_mem_field32_get(unit,
   8156                 hw_mem, &egr_nh, type_field)) {
   8157 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   8158        if (soc_feature(unit, soc_feature_egr_l3_next_hop_next_ptr)) {
   8159            if (0x1 == soc_mem_field32_get(unit, hw_mem, &egr_nh,
   8160                             L3MC__NEXT_PTR_TYPEf)) {
   8161                multicast_entry = 1; /* Multicast NextHop */
   8162            }
   8163        } else
   8164 #endif
   8165        if (0x1 == soc_mem_field32_get(unit, hw_mem, &egr_nh,
   8166                         L3MC__DVP_VALIDf)) {
   8167            multicast_entry = 1; /* Multicast NextHop */
   8168        }
   8169     }
   8170 
   8171     hw_mem = ING_L3_NEXT_HOPm;
   8172     BCM_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem, 
   8173                                   MEM_BLOCK_ANY, nh_index, &ing_nh));
   8174     soc_mem_field32_set(unit, hw_mem, &ing_nh,
   8175                                             DROPf, 0x0);
   8176     soc_mem_field32_set(unit, hw_mem, &ing_nh,
   8177                                             ENTRY_TYPEf, 0x0);
   8178     BCM_IF_ERROR_RETURN(soc_mem_write(unit, hw_mem,
   8179                                             MEM_BLOCK_ALL, nh_index, &ing_nh));
   8180     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_nexthop_glp_get(unit,
   8181                                 nh_index, &modid, &port, &tgid));
   8182     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &local_modid));
   8183     if (tgid != BCM_TRUNK_INVALID) {
   8184          rv = _bcm_trunk_id_validate(unit, tgid);
   8185          if (BCM_FAILURE(rv)) {
   8186             return BCM_E_PORT;
   8187          }
   8188          rv = bcm_esw_trunk_get(unit, tgid, NULL, 0, NULL, &num_ports);
   8189          if (BCM_FAILURE(rv)) {
   8190              return BCM_E_PORT;
   8191          }
   8192          if (num_ports == 0) {
   8193              return BCM_E_NONE;
   8194          }
   8195 
   8196 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   8197          if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
   8198              tmp_member_gports_array = sal_alloc(
   8199                  sizeof(bcm_trunk_member_t) * num_ports, "tmp_member_gports_arry");
   8200              if (tmp_member_gports_array == NULL) {
   8201                  return BCM_E_MEMORY;
   8202              }
   8203              sal_memset(tmp_member_gports_array, 0,
   8204                         sizeof(bcm_trunk_member_t) * num_ports);
   8205              rv = bcm_esw_trunk_get(unit, tgid, NULL,
   8206                           num_ports, tmp_member_gports_array, &num_ports);
   8207              if (BCM_FAILURE(rv)) {
   8208                  goto clean_up;
   8209              }
   8210          } else
   8211 #endif
   8212          {
   8213              BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid,
   8214                      SOC_MAX_NUM_PORTS, local_ports, &num_ports));
   8215              modid = local_modid;
   8216          }
   8217     } else {
   8218         if (modid != local_modid) {
   8219             if (!soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
   8220                 /* Ignore EGR_PORT_TO_NHI_MAPPINGs */
   8221                 return BCM_E_NONE;
   8222             }
   8223         }
   8224 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   8225         if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
   8226             /* Alloc one trunk member size memory */
   8227             tmp_member_gports_array = sal_alloc(
   8228                  sizeof(bcm_trunk_member_t), "tmp_member_gports_arry");
   8229             if (tmp_member_gports_array == NULL) {
   8230                  return BCM_E_MEMORY;
   8231             }
   8232             sal_memset(tmp_member_gports_array, 0,
   8233                        sizeof(bcm_trunk_member_t));
   8234             BCM_GPORT_MODPORT_SET(gport, modid, port);
   8235             tmp_member_gports_array[num_ports++].gport = gport;
   8236         } else
   8237 #endif
   8238         {
   8239             local_ports[num_ports++] = port;
   8240         }
   8241     }
   8242 
   8243     if (!multicast_entry) {
   8244         for (idx = 0; idx < num_ports; idx++) {
   8245 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   8246             if(soc_feature(unit, soc_feature_egr_modport_to_nhi)) {
   8247                 gport = tmp_member_gports_array[idx].gport;
   8248             } else
   8249 #endif
   8250             {
   8251                 BCM_GPORT_MODPORT_SET(gport, modid, local_ports[idx]);
   8252             }
   8253 
   8254             rv = _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index);
   8255             if (BCM_FAILURE(rv)) {
   8256                  goto clean_up;
   8257             }
   8258             if (old_nh_index == nh_index) {
   8259                 rv = _bcm_trx_gport_to_nhi_set(unit, gport, 0);
   8260                 if (BCM_FAILURE(rv)) {
   8261                     goto clean_up;
   8262                 }
   8263             }
   8264         }
   8265     }
   8266 
   8267 clean_up:
   8268 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   8269     if (NULL != tmp_member_gports_array) {
   8270         sal_free(tmp_member_gports_array);
   8271     }
   8272 #endif
   8273     return rv;
   8274 }
   8275 
   8276 /*
   8277  * Function:
   8278  *           bcm_td2_vxlan_egress_reset
   8279  * Purpose:
   8280  *           Reset VXLAN Egress NextHop 
   8281  * Parameters:
   8282  *           IN :  Unit
   8283  *           IN :  nh_index
   8284  * Returns:
   8285  *           BCM_E_XXX
   8286  */
   8287 
   8288 int
   8289 bcm_td2_vxlan_egress_reset(int unit, int nh_index)
   8290 {
   8291     ing_l3_next_hop_entry_t ing_nh;
   8292     soc_mem_t      hw_mem;
   8293     int rv=BCM_E_NONE;
   8294 
   8295     hw_mem = ING_L3_NEXT_HOPm;
   8296     BCM_IF_ERROR_RETURN(soc_mem_read(unit, hw_mem, 
   8297                 MEM_BLOCK_ANY, nh_index, &ing_nh));
   8298     soc_mem_field32_set(unit, hw_mem, &ing_nh,
   8299                 ENTRY_TYPEf, 0x0);
   8300     if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) {
   8301         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   8302                 &ing_nh, MTU_SIZEf, 0x0);
   8303     }
   8304     BCM_IF_ERROR_RETURN(soc_mem_write(unit, hw_mem,
   8305                                   MEM_BLOCK_ALL, nh_index, &ing_nh));
   8306 
   8307     rv = _bcm_td2_vxlan_nexthop_reset(unit, nh_index);
   8308     return rv;
   8309 }
   8310 
   8311 /*
   8312  * Function:
   8313  *           bcm_td2_vxlan_egress_get
   8314  * Purpose:
   8315  *           Get VXLAN Egress NextHop 
   8316  * Parameters:
   8317  *           IN :  Unit
   8318  *           IN :  nh_index
   8319  * Returns:
   8320  *           BCM_E_XXX
   8321  */
   8322 
   8323 int
   8324 bcm_td2_vxlan_egress_get(int unit, bcm_l3_egress_t *egr, int nh_index)
   8325 {
   8326     int int_l3_flag;
   8327     int_l3_flag = BCM_XGS3_L3_ENT_FLAG(BCM_XGS3_L3_TBL_PTR(unit, next_hop),
   8328                                        nh_index);
   8329     if (int_l3_flag == _BCM_L3_VXLAN_ONLY) {
   8330          egr->flags |= BCM_L3_VXLAN_ONLY;
   8331     }
   8332 
   8333     return BCM_E_NONE;
   8334 }
   8335 
   8336 /*
   8337  * Function:
   8338  *           _bcm_td2_vxlan_higig_ppd_select
   8339  * Purpose:
   8340  *           Select PPD type for Higig header
   8341  * Parameters:
   8342  *           IN :  Unit
   8343  *           IN :  nh_index
   8344  *           IN :  flags
   8345  * Returns:
   8346  *           BCM_E_XXX
   8347  */
   8348 int
   8349 _bcm_td2_vxlan_higig_ppd_select(int unit, int nh_index, uint32 flags)
   8350 {
   8351     egr_l3_next_hop_entry_t egr_nh;
   8352     int entry_type = 0;
   8353     int d = 0; /*vxlan decoupled mode*/
   8354 
   8355 #if defined(BCM_TRIDENT3_SUPPORT)
   8356     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   8357         d = 1;
   8358     }
   8359 #endif    
   8360     SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL,
   8361                   nh_index, &egr_nh));
   8362 #if defined(BCM_TRIDENT3_SUPPORT)
   8363     if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, DATA_TYPEf)) {
   8364         entry_type = soc_mem_field32_get(unit,
   8365                         EGR_L3_NEXT_HOPm, &egr_nh, DATA_TYPEf);
   8366     } else
   8367 #endif
   8368     {
   8369         entry_type = soc_mem_field32_get(unit,
   8370                         EGR_L3_NEXT_HOPm, &egr_nh, ENTRY_TYPEf);
   8371     }
   8372 
   8373     if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) {
   8374         if (flags & BCM_VXLAN_PORT_ENCAP_LOCAL) {
   8375             if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
   8376                 L3__HG_L2_TUNNEL_ENCAP_ENABLEf)) {
   8377                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   8378                                 L3__HG_L2_TUNNEL_ENCAP_ENABLEf, 1);
   8379             }
   8380             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   8381                                 L3__HG_HDR_SELf, 0);
   8382         } else {
   8383             if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
   8384                 L3__HG_L2_TUNNEL_ENCAP_ENABLEf)) {
   8385                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   8386                                 L3__HG_L2_TUNNEL_ENCAP_ENABLEf, 0);
   8387             }
   8388             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   8389                                 L3__HG_HDR_SELf, 1);
   8390         }
   8391     } else if (entry_type == BCM_VXLAN_TAG_VIEW(d)) {
   8392         if (flags & BCM_VXLAN_PORT_ENCAP_LOCAL) {
   8393             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   8394                                 BCM_VXLAN_TAG_FIELD(d, HG_HDR_SELf), 0);
   8395         } else {
   8396             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   8397                                 BCM_VXLAN_TAG_FIELD(d, HG_HDR_SELf), 1);
   8398         }
   8399     } else if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW) {
   8400         if (flags & BCM_VXLAN_PORT_ENCAP_LOCAL) {
   8401             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   8402                                 L3MC__HG_HDR_SELf, 0);
   8403         } else {
   8404             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   8405                                 L3MC__HG_HDR_SELf, 1);
   8406         }
   8407     }
   8408 
   8409     SOC_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   8410                        MEM_BLOCK_ALL, nh_index, &egr_nh));
   8411     return BCM_E_NONE;
   8412 }
   8413 
   8414 /*
   8415  * Function:
   8416  *      _bcm_td2_vxlan_ecmp_higig_ppd_select
   8417  * Purpose:
   8418  *      Modify vxlan ecmp member object's higig ppd select
   8419  * Parameters:
   8420  *      unit - Device Number
   8421  *      ecmp_index - ECMP index
   8422  *      flags - vxlan vp flags
   8423  * Returns:
   8424  *      BCM_E_XXX
   8425  */
   8426 
   8427 int
   8428 _bcm_td2_vxlan_ecmp_higig_ppd_select(int unit, int ecmp_index, uint32 flags)
   8429 {
   8430     int i = 0, ecmp_member_count = 0;
   8431     int alloc_size, index;
   8432     bcm_l3_egress_ecmp_t ecmp_info;
   8433     bcm_if_t *ecmp_member_array = NULL;
   8434     int rv = BCM_E_NONE;
   8435 
   8436     if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_index)) {
   8437         return BCM_E_PARAM;
   8438     }
   8439     ecmp_info.ecmp_intf = ecmp_index;
   8440     alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit);
   8441     ecmp_member_array = sal_alloc(alloc_size, "ecmp member array");
   8442     if (NULL == ecmp_member_array) {
   8443         return BCM_E_MEMORY;
   8444     }
   8445     sal_memset(ecmp_member_array, 0, alloc_size);
   8446 
   8447     rv = bcm_esw_l3_egress_ecmp_get(unit, &ecmp_info, BCM_XGS3_L3_ECMP_MAX(unit),
   8448                               ecmp_member_array, &ecmp_member_count);
   8449     if (BCM_FAILURE(rv)) {
   8450         goto clean_up;
   8451     }
   8452 
   8453     while(i < ecmp_member_count) {
   8454         if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit,
   8455                     ecmp_member_array[i])) {
   8456             index = (ecmp_member_array[i] - BCM_XGS3_EGRESS_IDX_MIN(unit));
   8457 
   8458         } else {
   8459             rv = BCM_E_PARAM;
   8460             goto clean_up;
   8461         }
   8462         rv = _bcm_td2_vxlan_higig_ppd_select(unit, index, flags);
   8463 
   8464         if (BCM_FAILURE(rv)) {
   8465             goto clean_up;
   8466         }
   8467 
   8468         i++;
   8469     }
   8470 
   8471 clean_up:
   8472     if (ecmp_member_array) {
   8473         sal_free(ecmp_member_array);
   8474         ecmp_member_array = NULL;
   8475     }
   8476 
   8477     return rv;
   8478 }
   8479 
   8480 /*
   8481  * Function:
   8482  *      _bcm_td2_vxlan_ecmp_nexthop_entry_modify
   8483  * Purpose:
   8484  *      Modify vxlan ecmp member object's Egress next hop entry
   8485  * Parameters:
   8486  *      unit - Device Number
   8487  *      ecmp_nh_index - ECMP index
   8488  *      drop - local drop
   8489  *      egr_nh_info - egr nh info
   8490  *      new_entry_type - New Entry type
   8491  * Returns:
   8492  *      BCM_E_XXX
   8493  */
   8494 
   8495 int
   8496 _bcm_td2_vxlan_ecmp_nexthop_entry_modify(int unit, int ecmp_index, int drop,
   8497         _bcm_td2_vxlan_nh_info_t egr_nh_info, int new_entry_type)
   8498 {
   8499     int i = 0, ecmp_member_count = 0;
   8500     int alloc_size, index;
   8501     bcm_l3_egress_ecmp_t ecmp_info;
   8502     bcm_if_t *ecmp_member_array = NULL;
   8503     int rv = BCM_E_NONE;
   8504 
   8505     if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_index)) {
   8506         return BCM_E_PARAM;
   8507     }
   8508     ecmp_info.ecmp_intf = ecmp_index;
   8509     alloc_size = sizeof(bcm_if_t)*BCM_XGS3_L3_ECMP_MAX(unit);
   8510     ecmp_member_array = sal_alloc(alloc_size, "ecmp member array");
   8511     if (NULL == ecmp_member_array) {
   8512         return BCM_E_MEMORY;
   8513     }
   8514     sal_memset(ecmp_member_array, 0, alloc_size);
   8515 
   8516     rv = bcm_esw_l3_egress_ecmp_get(unit, &ecmp_info, BCM_XGS3_L3_ECMP_MAX(unit),
   8517                                   ecmp_member_array, &ecmp_member_count);
   8518     if (BCM_FAILURE(rv)) {
   8519         goto clean_up;
   8520     }
   8521 
   8522     while(i < ecmp_member_count) {
   8523         if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit,
   8524                     ecmp_member_array[i])) {
   8525             index = (ecmp_member_array[i] - BCM_XGS3_EGRESS_IDX_MIN(unit));
   8526 
   8527         } else {
   8528             rv = BCM_E_PARAM;
   8529             goto clean_up;
   8530         }
   8531         rv = _bcm_td2_vxlan_nexthop_entry_modify(unit, index, drop,
   8532                                      &egr_nh_info, new_entry_type);
   8533         if (BCM_FAILURE(rv)) {
   8534             goto clean_up;
   8535         }
   8536 
   8537         i++;
   8538     }
   8539 clean_up:
   8540     if (ecmp_member_array) {
   8541         sal_free(ecmp_member_array);
   8542         ecmp_member_array = NULL;
   8543     }
   8544 
   8545     return rv;
   8546 }
   8547 
   8548 /*
   8549  * Function:
   8550  *      _bcm_td2_vxlan_port_nh_add
   8551  * Purpose:
   8552  *      Add VXLAN Next Hop entry
   8553  * Parameters:
   8554  * Returns:
   8555  *      BCM_E_XXX
   8556  */     
   8557 
   8558 STATIC int
   8559 _bcm_td2_vxlan_port_nh_add(int unit, bcm_vxlan_port_t *vxlan_port, int vp,
   8560                             bcm_vpn_t vpn, int drop)
   8561 {
   8562     egr_l3_next_hop_entry_t egr_nh;
   8563     _bcm_td2_vxlan_nh_info_t egr_nh_info;
   8564     int rv=BCM_E_NONE;
   8565     int action_present, action_not_present, tpid_index = -1;
   8566     int old_tpid_idx = -1;
   8567     uint32 mpath_flag=0;
   8568     int vp_nh_ecmp_index=-1;
   8569     int ref_count = 0;
   8570 #ifdef BCM_RIOT_SUPPORT
   8571     int nh_ecmp_index = -1;
   8572     ing_dvp_table_entry_t dvp;
   8573 #endif /* BCM_RIOT_SUPPORT */
   8574     int network_group=0;
   8575     int d = 0; /*vxlan decoupled mode*/
   8576     
   8577 #if defined(BCM_TRIDENT3_SUPPORT)
   8578         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   8579             d = 1;
   8580         }
   8581 #endif
   8582     egr_nh_info.dvp = vp;
   8583     egr_nh_info.entry_type = -1;
   8584     egr_nh_info.dvp_is_network = -1;
   8585     egr_nh_info.sd_tag_action_present = -1;
   8586     egr_nh_info.sd_tag_action_not_present = -1;
   8587     egr_nh_info.intf_num = -1;
   8588     egr_nh_info.sd_tag_vlan = -1;
   8589     egr_nh_info.sd_tag_pri = -1;
   8590     egr_nh_info.sd_tag_cfi = -1;
   8591     egr_nh_info.tpid_index = -1;
   8592     egr_nh_info.is_eline = 0; /* Change to 1 for Eline */
   8593     egr_nh_info.dvp_network_group_id = 0;
   8594 
   8595     network_group = vxlan_port->network_group_id;
   8596     rv = _bcm_validate_splithorizon_network_group(unit,
   8597             vxlan_port->flags & BCM_VXLAN_PORT_NETWORK, &network_group);
   8598     BCM_IF_ERROR_RETURN(rv);
   8599     egr_nh_info.dvp_network_group_id = network_group;
   8600 
   8601 #ifdef BCM_RIOT_SUPPORT
   8602     if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
   8603         SOC_IF_ERROR_RETURN(
   8604             READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   8605 
   8606         nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
   8607                                                   NEXT_HOP_INDEXf);
   8608     }
   8609 #endif /* BCM_RIOT_SUPPORT */
   8610 
   8611     /* 
   8612      * Get egress next-hop index from egress object and
   8613      * increment egress object reference count. 
   8614      */
   8615     if (!(vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) {
   8616         rv = bcm_xgs3_get_nh_from_egress_object(unit, vxlan_port->egress_if,
   8617                                                 &mpath_flag, 1, &vp_nh_ecmp_index);
   8618         BCM_IF_ERROR_RETURN(rv);
   8619 
   8620         /* Read the existing egress next_hop entry */
   8621         if (mpath_flag == 0) {
   8622            if (vxlan_port->flags & BCM_VXLAN_PORT_NETWORK) {
   8623                int l3_flag = BCM_XGS3_L3_ENT_FLAG(
   8624                    BCM_XGS3_L3_TBL_PTR(unit, next_hop), vp_nh_ecmp_index);
   8625                if (l3_flag != _BCM_L3_VXLAN_ONLY) {
   8626                    rv = BCM_E_CONFIG;
   8627                    goto cleanup;
   8628                }
   8629            }
   8630 
   8631            rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
   8632                           vp_nh_ecmp_index, &egr_nh);
   8633            _BCM_VXLAN_CLEANUP(rv)
   8634         }
   8635 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT)
   8636         else {
   8637             /*
   8638              * When Multi-level ECMP is enabled, ECMP group pointed
   8639              * to by DVP must be an underlay group.
   8640              */
   8641             if (BCMI_L3_ECMP_IS_MULTI_LEVEL(unit)) {
   8642                 if (vp_nh_ecmp_index < BCMI_L3_ECMP_OVERLAY_ENTRIES(unit)) {
   8643                     return BCM_E_PARAM;
   8644                 }
   8645             }
   8646         }
   8647 #endif
   8648     }
   8649 
   8650     if (vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) {
   8651 
   8652         /* Program DVP entry - Egress */
   8653         rv = _bcm_td2_vxlan_egress_dvp_set(unit, vp, drop, vxlan_port);
   8654         _BCM_VXLAN_CLEANUP(rv)
   8655 
   8656         /* Program DVP entry  - Ingress  */
   8657         rv = _bcm_td2_vxlan_ingress_dvp_set(unit, vp, mpath_flag, vp_nh_ecmp_index, vxlan_port);
   8658         _BCM_VXLAN_CLEANUP(rv)
   8659     
   8660         rv = _bcm_td2_vxlan_ingress_dvp_2_set(unit, vp, mpath_flag, vp_nh_ecmp_index, vxlan_port);
   8661         _BCM_VXLAN_CLEANUP(rv)
   8662         
   8663         if ((vxlan_port->flags & BCM_VXLAN_PORT_MULTICAST) &&
   8664             (!(vxlan_port->flags & BCM_VXLAN_PORT_SHARE))) {
   8665             /* Egress into Network - Tunnel */
   8666             egr_nh_info.dvp_is_network = 1; /* Enable */
   8667             if (mpath_flag == 0) {                
   8668 #if defined(BCM_TRIDENT3_SUPPORT)
   8669                 if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, DATA_TYPEf)) {
   8670                     egr_nh_info.entry_type =
   8671                         soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, DATA_TYPEf);
   8672                 } else
   8673 #endif
   8674                 {
   8675                     egr_nh_info.entry_type =
   8676                         soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, ENTRY_TYPEf);
   8677                 }
   8678 
   8679                 rv = _bcm_td2_vxlan_nexthop_entry_modify(unit, vp_nh_ecmp_index, drop, 
   8680                              &egr_nh_info, _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW);
   8681                 _BCM_VXLAN_CLEANUP(rv)
   8682             } else {
   8683                 /*ecmp*/
   8684                 rv = _bcm_td2_vxlan_ecmp_nexthop_entry_modify(unit, vxlan_port->egress_if, drop, 
   8685                                  egr_nh_info, _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW);
   8686                 _BCM_VXLAN_CLEANUP(rv)
   8687             }
   8688         }
   8689 
   8690         /* Don't select shared network multicast VP's HG header here*/
   8691         if (!(vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) {
   8692             if (mpath_flag == 0) {
   8693                 rv = _bcm_td2_vxlan_higig_ppd_select(unit, vp_nh_ecmp_index, vxlan_port->flags);
   8694                 _BCM_VXLAN_CLEANUP(rv)
   8695             } else {
   8696                 rv = _bcm_td2_vxlan_ecmp_higig_ppd_select(unit, vxlan_port->egress_if,
   8697                                   vxlan_port->flags);
   8698                 _BCM_VXLAN_CLEANUP(rv) 
   8699             }
   8700         }
   8701     } else {
   8702         /* Program DVP entry - Egress */
   8703         rv = _bcm_td2_vxlan_egress_access_dvp_set(unit, vp, drop, vxlan_port);
   8704         _BCM_VXLAN_CLEANUP(rv)
   8705 
   8706         /* Egress into Access - Non Tunnel */
   8707         egr_nh_info.dvp_is_network = 0; /* Disable */
   8708         if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
   8709             action_present = 
   8710                  soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   8711                                              SD_TAG__SD_TAG_ACTION_IF_PRESENTf);
   8712             action_not_present = 
   8713                  soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   8714                                              SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf);
   8715             if ((action_not_present == 0x1) || (action_present == 0x1) ||
   8716                 (action_present == 0x4) || (action_present == 0x7)) {
   8717                 /* If old tpid exist, delete it */
   8718                 old_tpid_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   8719                                           &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf);
   8720                 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx));
   8721             }
   8722         }
   8723 
   8724         egr_nh_info.entry_type = BCM_VXLAN_TAG_VIEW(d);
   8725         /* Configure SD_TAG setting */
   8726         rv = _bcm_td2_vxlan_sd_tag_set(unit, NULL, vxlan_port, &egr_nh_info, NULL, &tpid_index);
   8727         _BCM_VXLAN_CLEANUP(rv)
   8728 #if defined(BCM_TRIDENT3_SUPPORT)
   8729         if (SOC_IS_TRIDENT3X(unit) && mpath_flag) {
   8730             rv = _bcm_td2_vxlan_ecmp_nexthop_entry_modify(unit, vxlan_port->egress_if, drop,
   8731                                  egr_nh_info, BCM_VXLAN_TAG_VIEW(d));
   8732             _BCM_VXLAN_CLEANUP(rv)
   8733 
   8734             rv = _bcm_td2_vxlan_ecmp_higig_ppd_select(unit, vxlan_port->egress_if, vxlan_port->flags);
   8735             _BCM_VXLAN_CLEANUP(rv)
   8736         } else
   8737 #endif
   8738         {
   8739             /* Configure EGR Next Hop entry -- SD_TAG view */
   8740             rv = _bcm_td2_vxlan_nexthop_entry_modify(unit, vp_nh_ecmp_index, drop,
   8741                                  &egr_nh_info, BCM_VXLAN_TAG_VIEW(d));
   8742             _BCM_VXLAN_CLEANUP(rv)
   8743             rv = _bcm_td2_vxlan_higig_ppd_select(unit, vp_nh_ecmp_index, vxlan_port->flags);
   8744             _BCM_VXLAN_CLEANUP(rv)
   8745         }
   8746 
   8747         if (!(vxlan_port->flags & BCM_VXLAN_PORT_MULTICAST)) {
   8748             /* Program DVP entry  with ECMP / Next Hop Index */
   8749             rv = _bcm_td2_vxlan_ingress_dvp_set(unit, vp, mpath_flag, vp_nh_ecmp_index, vxlan_port);
   8750             _BCM_VXLAN_CLEANUP(rv)
   8751 
   8752             rv = _bcm_td2_vxlan_ingress_dvp_2_set(unit, vp, mpath_flag, vp_nh_ecmp_index, vxlan_port);
   8753             _BCM_VXLAN_CLEANUP(rv)
   8754 
   8755         }
   8756     }
   8757 
   8758 #ifdef BCM_RIOT_SUPPORT
   8759     if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
   8760             rv = bcmi_l3_nh_assoc_ol_ul_link_replace(unit, nh_ecmp_index, 
   8761                 vp_nh_ecmp_index);
   8762     }
   8763 #endif /* BCM_RIOT_SUPPORT */
   8764     return rv;
   8765 
   8766 cleanup:
   8767     if (tpid_index != -1) {
   8768         (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   8769     }
   8770     if (vp_nh_ecmp_index != -1) {
   8771         /* Decrement reference count */
   8772         (void) bcm_xgs3_get_ref_count_from_nhi(
   8773             unit, mpath_flag, &ref_count, vp_nh_ecmp_index);
   8774     }
   8775     return rv;
   8776 }
   8777 
   8778 /*
   8779  * Function:
   8780  *      _bcm_td2_vxlan_port_nh_delete
   8781  * Purpose:
   8782  *      Delete VXLAN Next Hop entry
   8783  * Parameters:
   8784  * Returns:
   8785  *      BCM_E_XXX
   8786  */     
   8787 
   8788 STATIC int
   8789 _bcm_td2_vxlan_port_nh_delete(int unit, bcm_vpn_t vpn, int vp)
   8790 {
   8791     int rv=BCM_E_NONE;
   8792     int nh_ecmp_index=-1;
   8793     ing_dvp_table_entry_t dvp;
   8794     uint32  vp_type=0;
   8795     uint32  flags=0;
   8796     int  ref_count=0;
   8797     int ecmp =-1;
   8798     int ecmp_index_check_skip = 0;
   8799 
   8800     BCM_IF_ERROR_RETURN(
   8801         READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   8802 
   8803     vp_type = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, VP_TYPEf);
   8804     ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf);
   8805 #if defined (BCM_MONTEREY_SUPPORT)
   8806     if (SOC_IS_MONTEREY(unit) && (!soc_feature(unit, soc_feature_vp_lag))) {
   8807         ecmp_index_check_skip = 1;
   8808     }
   8809 #endif
   8810 
   8811     if (ecmp) {
   8812         nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf);
   8813         flags = BCM_L3_MULTIPATH;
   8814         /* Decrement reference count */
   8815         BCM_IF_ERROR_RETURN(
   8816              bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index));
   8817         if (ref_count == 1) {
   8818             if (nh_ecmp_index || ecmp_index_check_skip) {
   8819                 if (vp_type == _BCM_VXLAN_INGRESS_DEST_VP_TYPE) {
   8820                     BCM_IF_ERROR_RETURN(
   8821                       _bcm_td2_vxlan_ecmp_port_egress_nexthop_reset
   8822                                 (unit, (nh_ecmp_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)),
   8823                                                                       vp_type, vp, vpn));
   8824                 }
   8825 #if defined(BCM_TRIDENT3_SUPPORT)
   8826                 else if ((vp_type == _BCM_VXLAN_DEST_VP_TYPE_ACCESS) && SOC_IS_TRIDENT3X(unit)) {
   8827                     BCM_IF_ERROR_RETURN(
   8828                       _bcm_td3_vxlan_ecmp_acess_port_egress_nexthop_reset
   8829                                 (unit, vp_type, vp, vpn));
   8830                 }
   8831 #endif
   8832             }
   8833         }
   8834     } else {
   8835         nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 
   8836                                               NEXT_HOP_INDEXf);
   8837         if(nh_ecmp_index != 0) {
   8838              /* Decrement reference count */
   8839              BCM_IF_ERROR_RETURN(
   8840                   bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index));
   8841         }
   8842         if (ref_count == 1) {
   8843               if (nh_ecmp_index) {
   8844                   BCM_IF_ERROR_RETURN(
   8845                      _bcm_td2_vxlan_port_egress_nexthop_reset
   8846                                 (unit, nh_ecmp_index, vp_type, vp, vpn));
   8847               }
   8848          }
   8849     }
   8850     return rv;
   8851 }
   8852 
   8853 /*
   8854  * Function:
   8855  *      _bcm_td2_vxlan_ecmp_member_egress_get_first
   8856  * Purpose:
   8857  *      Modify vxlan ecmp member object's Egress next hop entry
   8858  * Parameters:
   8859  *      unit - Device Number
   8860  *      ecmp_index - ECMP index
   8861  *      index - poiter to first next hop index
   8862  * Returns:
   8863  *      BCM_E_XXX
   8864  */
   8865 
   8866 STATIC int
   8867 _bcm_td2_vxlan_ecmp_member_egress_get_first(int unit, int ecmp_index, int* index)
   8868 {
   8869     int i = 0, ecmp_member_count = 0;
   8870     int alloc_size;
   8871     bcm_l3_egress_ecmp_t ecmp_info;
   8872     bcm_if_t *ecmp_member_array = NULL;
   8873     int rv = BCM_E_NONE;
   8874 
   8875     if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_index)) {
   8876         return BCM_E_PARAM;
   8877     }
   8878     ecmp_info.ecmp_intf = ecmp_index;
   8879     alloc_size = sizeof(bcm_if_t)*BCM_XGS3_L3_ECMP_MAX(unit);
   8880     ecmp_member_array = sal_alloc(alloc_size, "ecmp member array");
   8881     if (NULL == ecmp_member_array) {
   8882         return BCM_E_MEMORY;
   8883     }
   8884     sal_memset(ecmp_member_array, 0, alloc_size);
   8885 
   8886     rv = bcm_esw_l3_egress_ecmp_get(unit, &ecmp_info, BCM_XGS3_L3_ECMP_MAX(unit),
   8887                                   ecmp_member_array, &ecmp_member_count);
   8888     if (BCM_FAILURE(rv)) {
   8889         goto clean_up;
   8890     }
   8891 
   8892     if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit,
   8893                 ecmp_member_array[i])) {
   8894         *index = (ecmp_member_array[i] - BCM_XGS3_EGRESS_IDX_MIN(unit));
   8895     } else {
   8896         rv = BCM_E_PARAM;
   8897         goto clean_up;
   8898     }
   8899 clean_up:
   8900     if (ecmp_member_array) {
   8901         sal_free(ecmp_member_array);
   8902         ecmp_member_array = NULL;
   8903     }
   8904 
   8905     return rv;
   8906 }
   8907 
   8908 /*
   8909  * Function:
   8910  *      _bcm_td2_vxlan_port_nh_get
   8911  * Purpose:
   8912  *      Get VXLAN Next Hop entry
   8913  * Parameters:
   8914  * Returns:
   8915  *      BCM_E_XXX
   8916  */     
   8917 
   8918 STATIC int
   8919 _bcm_td2_vxlan_port_nh_get(int unit, bcm_vpn_t vpn,  int vp, bcm_vxlan_port_t *vxlan_port)
   8920 {
   8921     egr_l3_next_hop_entry_t egr_nh;
   8922     ing_dvp_table_entry_t dvp;
   8923     int nh_ecmp_index=0;
   8924     uint32 ecmp=0;
   8925     int rv = BCM_E_NONE;
   8926 
   8927     /* Read the HW entries */
   8928     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   8929 
   8930     if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, VP_TYPEf) == 
   8931                               _BCM_VXLAN_INGRESS_DEST_VP_TYPE) {
   8932         /* Egress into VXLAN tunnel, find the tunnel_if */
   8933         vxlan_port->flags |= BCM_VXLAN_PORT_EGRESS_TUNNEL;
   8934         BCM_IF_ERROR_RETURN(
   8935              READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   8936         ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf);
   8937         if (ecmp) {
   8938             nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf);
   8939             vxlan_port->egress_if  =  nh_ecmp_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit);
   8940             /*get ecmp's first member nexthop index*/
   8941             BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_ecmp_member_egress_get_first(unit, vxlan_port->egress_if, 
   8942                 &nh_ecmp_index));
   8943         } else {
   8944             nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
   8945             /* Extract next hop index from unipath egress object. */
   8946             vxlan_port->egress_if  =  nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit);
   8947         }
   8948 
   8949         BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm,
   8950             MEM_BLOCK_ANY, nh_ecmp_index, &egr_nh));
   8951 
   8952     } else if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 
   8953                                                 VP_TYPEf) == _BCM_VXLAN_DEST_VP_TYPE_ACCESS) {
   8954         /* Egress into Access-side, find the tunnel_if */
   8955         BCM_IF_ERROR_RETURN(
   8956             READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   8957         nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
   8958         /* Extract next hop index from unipath egress object. */
   8959         vxlan_port->egress_if  =  nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit);
   8960 
   8961         BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
   8962                                       nh_ecmp_index, &egr_nh));
   8963          if (BCM_SUCCESS(rv)) {
   8964               (void) _bcm_td2_vxlan_sd_tag_get( unit, NULL, vxlan_port, &egr_nh,
   8965                          NULL, 0);
   8966          }
   8967     } else {
   8968         return BCM_E_NOT_FOUND;
   8969     }
   8970 
   8971     rv = bcm_td2_vxlan_nexthop_get(unit, &egr_nh, vxlan_port);
   8972 
   8973     return rv;
   8974 }
   8975 
   8976 /*
   8977  * Function:
   8978  *      _bcm_td2_vxlan_match_vnid_entry_reset
   8979  * Purpose:
   8980  *      Reset VXLAN Match VNID Entry 
   8981  * Parameters:
   8982  *  IN :  Unit
   8983  *  IN :  Vnid
   8984  * Returns:
   8985  *      BCM_E_XXX
   8986  */
   8987 
   8988 STATIC int
   8989 _bcm_td2_vxlan_match_vnid_entry_reset(int unit, uint32 vnid,
   8990                                                 bcm_vlan_t ovid)
   8991 {
   8992     soc_mem_t mmem = MPLS_ENTRYm;
   8993     uint32 ment[SOC_MAX_MEM_WORDS];
   8994     int d = 0; /*vxlan decoupled mode*/
   8995 
   8996     sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   8997 
   8998 #if defined(BCM_TRIDENT3_SUPPORT)
   8999     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   9000         mmem = VLAN_XLATE_1_DOUBLEm;
   9001         d =1;
   9002         soc_mem_field32_set(unit, mmem, &ment, BASE_VALID_0f, 3);
   9003         soc_mem_field32_set(unit, mmem, &ment, BASE_VALID_1f, 7);
   9004         soc_mem_field32_set(unit, mmem, &ment,
   9005             DATA_TYPEf, _BCM_VXLAN_DATA_TYPE_VNID_VFI_FLEX);        
   9006         soc_mem_field32_set(unit, mmem, &ment, KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_VNID_VFI_FLEX);
   9007     } else
   9008 #endif
   9009     {
   9010         soc_mem_field32_set(unit, mmem, &ment, VALIDf, 1);        
   9011         soc_mem_field32_set(unit, mmem, &ment, KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_VNID_VFI);
   9012     }
   9013 
   9014     soc_mem_field32_set(unit, mmem, &ment, (d ? VXLAN_FLEX__VNIDf : VXLAN_VN_ID__VN_IDf), vnid);
   9015 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   9016     if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   9017         soc_mem_field32_set(unit, mmem, &ment, VXLAN_VN_ID__OVIDf, ovid);
   9018     }
   9019 #endif
   9020     
   9021     BCM_IF_ERROR_RETURN(soc_mem_delete(unit, mmem, MEM_BLOCK_ALL, &ment));
   9022 
   9023     return BCM_E_NONE;
   9024 }
   9025 
   9026 /*
   9027  * Function:
   9028  *      _bcm_td2_vxlan_match_tunnel_entry_update
   9029  * Purpose:
   9030  *      Update Match VXLAN Tunnel Entry 
   9031  * Parameters:
   9032  *  IN :  Unit
   9033  *  IN :  vxlan_entry
   9034  *  OUT :  vxlan_entry
   9035 
   9036  */
   9037 
   9038 STATIC int
   9039 _bcm_td2_vxlan_match_tunnel_entry_update(int unit,
   9040                                              uint32 *ment, 
   9041                                              uint32 *new_ment,
   9042                                              uint32 *return_ment)
   9043 {
   9044     uint32 value=0, key_type=0;
   9045     soc_mem_t mem = MPLS_ENTRYm;
   9046 
   9047     /* Check if Key_Type identical */
   9048     key_type = soc_mem_field32_get(unit, mem, ment, KEY_TYPEf);
   9049     value = soc_mem_field32_get(unit, mem, return_ment, KEY_TYPEf);
   9050     if (key_type != value) {
   9051          return BCM_E_PARAM;
   9052     }
   9053 #if defined(BCM_TRIDENT3_SUPPORT)
   9054     if (soc_feature(unit, soc_feature_base_valid)) {
   9055         soc_mem_field32_set(unit, mem, new_ment, BASE_VALID_0f, 3);
   9056         soc_mem_field32_set(unit, mem, new_ment, BASE_VALID_1f, 7);
   9057         soc_mem_field32_set(unit, mem, new_ment,
   9058             DATA_TYPEf, key_type);
   9059     } else
   9060 #endif
   9061     {
   9062         soc_mem_field32_set(unit, mem, new_ment, VALIDf, 1);
   9063     }
   9064     soc_mem_field32_set(unit, mem, new_ment, KEY_TYPEf, key_type);
   9065     if (key_type == _BCM_VXLAN_KEY_TYPE_TUNNEL_VNID_VFI) {
   9066         value = soc_mem_field32_get(unit,mem, ment, VXLAN_VN_ID__SIPf);
   9067         soc_mem_field32_set(unit, mem, new_ment, VXLAN_VN_ID__SIPf, value);
   9068         value = soc_mem_field32_get(unit,mem, ment, VXLAN_VN_ID__VFIf);
   9069         soc_mem_field32_set(unit, mem, new_ment, VXLAN_VN_ID__VFIf, value);
   9070         value = soc_mem_field32_get(unit,mem, ment, VXLAN_VN_ID__VN_IDf);
   9071         soc_mem_field32_set(unit, mem, new_ment, VXLAN_VN_ID__VN_IDf, value);
   9072 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   9073         if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   9074             value = soc_mem_field32_get(unit,mem, ment, VXLAN_VN_ID__OVIDf);
   9075             soc_mem_field32_set(unit, mem, new_ment, VXLAN_VN_ID__OVIDf, value);
   9076         }
   9077 #endif        
   9078     } else {
   9079         value = soc_mem_field32_get(unit,mem, ment, VXLAN_SIP__SIPf);
   9080         soc_mem_field32_set(unit, mem, new_ment, VXLAN_SIP__SIPf, value);
   9081         value = soc_mem_field32_get(unit,mem, ment, VXLAN_SIP__SVPf);
   9082         soc_mem_field32_set(unit, mem, new_ment, VXLAN_SIP__SVPf, value);
   9083 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   9084         if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   9085             value = soc_mem_field32_get(unit,mem, ment, VXLAN_SIP__OVIDf);
   9086             soc_mem_field32_set(unit, mem, new_ment, VXLAN_SIP__OVIDf, value);
   9087         }
   9088 #endif        
   9089     }
   9090     return BCM_E_NONE;
   9091 }
   9092 
   9093 
   9094 /*
   9095  * Function:
   9096  *      _bcm_td2_vxlan_match_tunnel_entry_set
   9097  * Purpose:
   9098  *      Set VXLAN Match Tunnel Entry 
   9099  * Parameters:
   9100  *  IN :  Unit
   9101  *  IN :  mpls_entry
   9102  * Returns:
   9103  *      BCM_E_XXX
   9104  */
   9105 
   9106 STATIC int
   9107 _bcm_td2_vxlan_match_tunnel_entry_set(int unit, uint32 *ment, uint32 *return_ment)
   9108 {
   9109     int rv = BCM_E_UNAVAIL;
   9110     int index = 0;
   9111     int svp = 0;
   9112     uint32 key_type = 0;
   9113     uint32 tmp_ment[SOC_MAX_MEM_WORDS]={0};
   9114 
   9115     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
   9116                         ment, return_ment, 0);
   9117 
   9118     if (rv == SOC_E_NONE) {
   9119         BCM_IF_ERROR_RETURN(
   9120             _bcm_td2_vxlan_match_tunnel_entry_update(unit, ment, tmp_ment, return_ment));
   9121 
   9122         key_type = soc_mem_field32_get(unit, MPLS_ENTRYm, return_ment, KEY_TYPEf);
   9123         if (key_type == _BCM_VXLAN_KEY_TYPE_TUNNEL) {
   9124             svp = soc_mem_field32_get(unit, MPLS_ENTRYm, return_ment, VXLAN_SIP__SVPf);
   9125             if (_bcm_vp_used_get(unit, svp, _bcmVpTypeVpLag)) {
   9126                 soc_mem_field32_set(unit, MPLS_ENTRYm, tmp_ment, VXLAN_SIP__SVPf, svp);
   9127             }
   9128         }
   9129         rv = soc_mem_write(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, index, tmp_ment);
   9130     } else if (rv != SOC_E_NOT_FOUND) {
   9131         return rv;
   9132     } else {
   9133         rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, ment);
   9134     }
   9135     return rv;
   9136 }
   9137 
   9138 /*
   9139  * Function:
   9140  *      _bcm_td2_vxlan_match_tunnel_entry_delete
   9141  * Purpose:
   9142  *      Delete VXLAN Match Tunnel Entry 
   9143  * Parameters:
   9144  *  IN :  Unit
   9145  *  IN :  mpls_entry
   9146  * Returns:
   9147  *      BCM_E_XXX
   9148  */
   9149 
   9150 STATIC int
   9151 _bcm_td2_vxlan_match_tunnel_entry_delete(int unit, uint32 *ment)
   9152 {
   9153     int rv = BCM_E_UNAVAIL;
   9154     uint32 value=0, key_type=0;
   9155     soc_mem_t mem = MPLS_ENTRYm;
   9156     uint32 tmp_ment[SOC_MAX_MEM_WORDS]={0};
   9157 
   9158     /* Check if Key_Type identical */
   9159     key_type = soc_mem_field32_get(unit, mem, &ment, KEY_TYPEf);
   9160     soc_mem_field32_set(unit, mem, &tmp_ment, KEY_TYPEf, key_type);
   9161 #if defined(BCM_TRIDENT3_SUPPORT)
   9162     if (soc_feature(unit, soc_feature_base_valid)) {
   9163         soc_mem_field32_set(unit, mem, &tmp_ment, BASE_VALID_0f, 3);
   9164         soc_mem_field32_set(unit, mem, &tmp_ment, BASE_VALID_1f, 7);
   9165         soc_mem_field32_set(unit, mem, &tmp_ment,
   9166             DATA_TYPEf, key_type);
   9167     } else
   9168 #endif
   9169     {
   9170         soc_mem_field32_set(unit, mem, &tmp_ment, VALIDf, 1);
   9171     }
   9172     if (key_type == _BCM_VXLAN_KEY_TYPE_TUNNEL_VNID_VFI) {
   9173         value = soc_mem_field32_get(unit, mem, &ment, VXLAN_VN_ID__SIPf);
   9174         soc_mem_field32_set(unit, mem, &tmp_ment, VXLAN_VN_ID__SIPf, value);
   9175         value = soc_mem_field32_get(unit, mem, &ment, VXLAN_VN_ID__VN_IDf);
   9176         soc_mem_field32_set(unit, mem, &tmp_ment, VXLAN_VN_ID__VN_IDf, value);
   9177 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   9178         if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   9179             value = soc_mem_field32_get(unit, mem, &ment, VXLAN_VN_ID__OVIDf);
   9180             soc_mem_field32_set(unit, mem, &tmp_ment, VXLAN_VN_ID__OVIDf, value);
   9181         }
   9182 #endif
   9183     } else {
   9184         value = soc_mem_field32_get(unit, mem, &ment, VXLAN_VN_ID__SIPf);
   9185         soc_mem_field32_set(unit, mem, &tmp_ment, VXLAN_VN_ID__SIPf, value);
   9186 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   9187         if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
   9188             value = soc_mem_field32_get(unit, mem, &ment, VXLAN_SIP__OVIDf);
   9189             soc_mem_field32_set(unit, mem, &tmp_ment, VXLAN_SIP__OVIDf, value);
   9190         }
   9191 #endif
   9192     }
   9193 
   9194     rv = soc_mem_delete(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, tmp_ment);
   9195     return rv;
   9196 }
   9197 
   9198 /*
   9199  * Function:
   9200  *      _bcm_td2_vxlan_match_vp_find
   9201  * Purpose:
   9202  *      Find network VP has the same match
   9203  * Parameters:
   9204  *      unit - (IN) SOC unit number.
   9205  *      vp1 - (IN) Network VP.
   9206  *      vp2 - (OUT) Network VP.
   9207  * Returns:
   9208  *      TRUE - Found
   9209  *      FALSE - Not Found
   9210  */
   9211 int
   9212 _bcm_td2_vxlan_match_vp_find(int unit, int vp1, int *vp2)
   9213 {
   9214     int vp = 0;
   9215     int num_vp = 0;
   9216     uint32 tunnel_index1 = 0;
   9217     uint32 tunnel_index2 = 0;
   9218     uint32 tunnel_sip1 = 0;
   9219     uint32 tunnel_sip2 = 0;
   9220     _bcm_vxlan_match_port_info_t *mkey1 = NULL;
   9221     _bcm_vxlan_match_port_info_t *mkey2 = NULL;
   9222 
   9223     mkey1 = &(VXLAN_INFO(unit)->match_key[vp1]);
   9224     tunnel_index1 = mkey1->match_tunnel_index;
   9225     tunnel_sip1 = VXLAN_INFO(unit)->vxlan_tunnel_term[tunnel_index1].sip;
   9226 
   9227     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   9228     for (vp = 0; vp < num_vp; vp++) {
   9229         if (vp == vp1) {
   9230             continue;
   9231         }
   9232 
   9233         mkey2 = &(VXLAN_INFO(unit)->match_key[vp]);
   9234         if (mkey2->flags == _BCM_VXLAN_PORT_MATCH_TYPE_VNID) {
   9235             tunnel_index2 = mkey2->match_tunnel_index;
   9236             tunnel_sip2 = VXLAN_INFO(unit)->vxlan_tunnel_term[tunnel_index2].sip;
   9237 
   9238             if (tunnel_sip1 == tunnel_sip2) {
   9239                 *vp2 = vp;
   9240                 return TRUE;
   9241             }
   9242         }
   9243     }
   9244 
   9245     return FALSE;
   9246 }
   9247 
   9248 /*
   9249  * Function:
   9250  *      _bcm_td2_vxlan_match_tunnel_entry_reset
   9251  * Purpose:
   9252  *      Reset VXLAN Match Tunnel Entry 
   9253  * Parameters:
   9254  *  IN :  Unit
   9255  *  IN :  mpls_entry
   9256  * Returns:
   9257  *      BCM_E_XXX
   9258  */
   9259 
   9260 STATIC int
   9261 _bcm_td2_vxlan_match_tunnel_entry_reset(int unit, int vp, uint32 *ment, uint32 *return_ment)
   9262 {
   9263     int rv = BCM_E_UNAVAIL;
   9264     int index = 0;
   9265     int svp = 0;
   9266     int d = 0;
   9267     soc_mem_t mem = MPLS_ENTRYm;
   9268 #if defined(BCM_TRIDENT3_SUPPORT)
   9269     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   9270         mem = MPLS_ENTRY_SINGLEm;
   9271         d = 1;
   9272     }
   9273 #endif
   9274     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index,
   9275                         ment, return_ment, 0);
   9276     if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE)) {
   9277          return rv;
   9278     }
   9279 
   9280     if (rv == SOC_E_NONE) {
   9281         svp = soc_mem_field32_get(unit, mem, return_ment,
   9282                 BCM_VXLAN_SIP_FIELD(d, SVPf));
   9283         if (svp != vp) {
   9284             return BCM_E_NONE;
   9285         }
   9286 
   9287         if (_bcm_td2_vxlan_match_vp_find(unit, vp, &svp)) {
   9288             soc_mem_field32_set(unit, mem, return_ment,
   9289                 BCM_VXLAN_SIP_FIELD(d, SVPf), svp);
   9290         } else {
   9291             sal_memset(return_ment, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   9292         }
   9293         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, return_ment);
   9294     }
   9295 
   9296     if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE)) {
   9297        return rv;
   9298     } else {
   9299        return BCM_E_NONE;
   9300     }
   9301 }
   9302 
   9303 /*
   9304  * Function:
   9305  *        _bcm_td2_vxlan_match_vxlate_extd_entry_set
   9306  * Purpose:
   9307  *       Set VXLAN Match Vxlate Entry 
   9308  * Parameters:
   9309  *  IN :  Unit
   9310  *  IN :  vxlan_port
   9311  *  IN :  vlan_xlate_extd_entry_t
   9312  * Returns:
   9313  *      BCM_E_XXX
   9314  */
   9315 
   9316 STATIC int
   9317 _bcm_td2_vxlan_match_egr_vxlate_entry_set(int unit, bcm_vpn_t vpn, 
   9318                                                          bcm_vxlan_port_t *vxlan_port, 
   9319                                                          uint32 *vent, 
   9320                                                          uint32 *return_vent)
   9321 {
   9322     int rv = BCM_E_NONE;
   9323     int index = -1;
   9324     soc_mem_t vxlate_mem;
   9325 
   9326 #if defined(BCM_TRIDENT3_SUPPORT)
   9327     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
   9328         vxlate_mem = EGR_VLAN_XLATE_1_SINGLEm;
   9329     } else
   9330 #endif
   9331     {
   9332         vxlate_mem = EGR_VLAN_XLATEm;
   9333     }
   9334 
   9335     rv = soc_mem_search(unit, vxlate_mem,
   9336                         MEM_BLOCK_ANY, &index, vent, return_vent, 0);
   9337     if (BCM_E_NONE == rv) {
   9338         BCM_IF_ERROR_RETURN(soc_mem_write(unit,
   9339                                           vxlate_mem, MEM_BLOCK_ALL, index,
   9340                                           vent));
   9341     } else if (BCM_E_NOT_FOUND == rv) {
   9342         if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
   9343             return BCM_E_NOT_FOUND;
   9344         }
   9345         BCM_IF_ERROR_RETURN(soc_mem_insert(unit,
   9346                                           vxlate_mem, MEM_BLOCK_ALL, vent));
   9347     } else {
   9348         return rv;
   9349     }
   9350     return BCM_E_NONE;
   9351 }
   9352 
   9353 /*
   9354  * Function:
   9355  *      _bcm_td2_vxlan_match_egr_vxlate_entry_delete
   9356  * Purpose:
   9357  *      Delete VXLAN Match Tunnel Entry 
   9358  * Parameters:
   9359  *  IN :  Unit
   9360  *  IN :  egr_vlan_xlate_entry
   9361  * Returns:
   9362  *      BCM_E_XXX
   9363  */
   9364 
   9365 STATIC int
   9366 _bcm_td2_vxlan_match_egr_vxlate_entry_delete(int unit, uint32 *ment)
   9367 {
   9368     int rv = BCM_E_UNAVAIL;
   9369     uint32 value = 0, entry_type = 0;
   9370     soc_mem_t vxlate_mem; 
   9371     uint32 tmp_ment[SOC_MAX_MEM_WORDS] = {0};
   9372     
   9373 #if defined(BCM_TRIDENT3_SUPPORT)
   9374     if (soc_feature(unit, soc_feature_base_valid)) {
   9375         vxlate_mem = EGR_VLAN_XLATE_1_DOUBLEm;
   9376     } else
   9377 #endif
   9378     {
   9379         vxlate_mem = EGR_VLAN_XLATEm;
   9380     }
   9381     /* Check if Key_Type identical */
   9382     entry_type = soc_mem_field32_get(unit, vxlate_mem, ment, ENTRY_TYPEf);
   9383     soc_mem_field32_set(unit, vxlate_mem, tmp_ment, ENTRY_TYPEf, entry_type);
   9384 
   9385     soc_mem_field32_set(unit, vxlate_mem, tmp_ment, VALIDf, 1);
   9386     if (entry_type == _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI_DVP) {
   9387         value = soc_mem_field32_get(unit, vxlate_mem, ment, VXLAN_VFI__VFIf);
   9388         soc_mem_field32_set(unit, vxlate_mem, tmp_ment, VXLAN_VFI__VFIf, value);
   9389         value = soc_mem_field32_get(unit, vxlate_mem, ment, VXLAN_VFI__DVPf);
   9390         soc_mem_field32_set(unit, vxlate_mem, tmp_ment, VXLAN_VFI__DVPf, value);
   9391     
   9392     } else {
   9393         value = soc_mem_field32_get(unit, vxlate_mem, ment, VXLAN_VFI__VFIf);
   9394         soc_mem_field32_set(unit, vxlate_mem, tmp_ment, VXLAN_VFI__VFIf, value);       
   9395     }
   9396 
   9397     rv = soc_mem_delete(unit, EGR_VLAN_XLATEm, MEM_BLOCK_ALL, tmp_ment);
   9398     return rv;
   9399 }
   9400 
   9401 /*
   9402  * Function:
   9403  *      _bcm_td2_vxlan_match_vxlate_entry_update
   9404  * Purpose:
   9405  *      Update VXLAN Match Vlan_xlate  Entry
   9406  * Parameters:
   9407  *  IN :  Unit
   9408  *  IN :  vxlan_port
   9409  *  IN :  vlan_xlate_entry_t
   9410  *  OUT :  vlan_xlate_entry_t
   9411  */
   9412 STATIC int
   9413 _bcm_td2_vxlan_match_vxlate_entry_update(int unit, bcm_vpn_t vpn,
   9414                                          bcm_vxlan_port_t *vxlan_port,
   9415                                          uint32 *vent, uint32 *return_ent)
   9416 {
   9417     uint32  key_type=0, value=0;
   9418     soc_mem_t mem;
   9419     int vp = _SHR_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
   9420 
   9421 #if defined(BCM_TRIDENT3_SUPPORT)
   9422     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   9423         mem = VLAN_XLATE_1_DOUBLEm;
   9424     } else
   9425 #endif
   9426     {
   9427         mem = VLAN_XLATEm;
   9428     }
   9429 
   9430     if ((vent == NULL) || (return_ent == NULL)) {
   9431         return BCM_E_PARAM;
   9432     }
   9433 
   9434     /* Check if Key_Type identical */
   9435     key_type = soc_mem_field32_get(unit, mem, vent, KEY_TYPEf);
   9436     value = soc_mem_field32_get(unit, mem, return_ent, KEY_TYPEf);
   9437     if (key_type != value) {
   9438          return BCM_E_PARAM;
   9439     }
   9440 
   9441     soc_mem_field32_set(unit, mem, return_ent, SOURCE_TYPEf, 1);
   9442     value = soc_mem_field32_get(unit, mem, return_ent, XLATE__MPLS_ACTIONf);
   9443     /* SVP_VALID and L3_IIF_VALID overlay high and low bits of MPLS_ACTION. */
   9444     if (SOC_MEM_FIELD_VALID(unit, mem, L3_IIF_VALIDf)) {
   9445         value |= 0x1;
   9446     } else {
   9447         value = 0x1;
   9448     }
   9449     /* Retain original Keys -- Update data only */
   9450     soc_mem_field32_set(unit, mem, return_ent, XLATE__MPLS_ACTIONf, value);
   9451 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   9452     if (soc_feature(unit, soc_feature_vlan_vfi_membership)) {
   9453         if (vxlan_port->flags & BCM_VXLAN_PORT_ENABLE_VLAN_CHECKS) {
   9454             return BCM_E_UNAVAIL;
   9455         }
   9456         soc_mem_field32_set(unit, mem, return_ent, XLATE__DISABLE_VLAN_CHECKSf,
   9457                             0);
   9458         soc_mem_field32_set(unit, mem, return_ent, XLATE__VLAN_ACTION_VALIDf,
   9459                             1);
   9460     } else
   9461 #endif
   9462     {
   9463         soc_mem_field32_set(unit, mem, return_ent, XLATE__DISABLE_VLAN_CHECKSf,
   9464                             1);
   9465         if (!(vxlan_port->flags & BCM_VXLAN_PORT_ENABLE_VLAN_CHECKS)) {
   9466             soc_mem_field32_set(unit, mem, return_ent,
   9467                                 XLATE__VLAN_ACTION_VALIDf, 1);
   9468         } else {
   9469             soc_mem_field32_set(unit, mem, return_ent,
   9470                                 XLATE__VLAN_ACTION_VALIDf, 0);
   9471         }
   9472     }
   9473 
   9474 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   9475     if (soc_feature(unit, soc_feature_vp_sharing)) {
   9476         if (vpn != BCM_VXLAN_VPN_INVALID) {
   9477             int vfi = 0;
   9478             _BCM_VXLAN_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
   9479             soc_mem_field32_set(unit, mem, return_ent, XLATE__VFIf, vfi);
   9480         }
   9481     }
   9482 #endif
   9483     soc_mem_field32_set(unit, mem, return_ent, XLATE__SOURCE_VPf, vp);
   9484 
   9485     return BCM_E_NONE;
   9486 }
   9487 
   9488 /*
   9489  * Function:
   9490  *        _bcm_td2_vxlan_match_vxlate_extd_entry_set
   9491  * Purpose:
   9492  *       Set VXLAN Match Vxlate Entry 
   9493  * Parameters:
   9494  *  IN :  Unit
   9495  *  IN :  vxlan_port
   9496  *  IN :  vlan_xlate_extd_entry_t
   9497  * Returns:
   9498  *      BCM_E_XXX
   9499  */
   9500 
   9501 STATIC int
   9502 _bcm_td2_vxlan_match_vxlate_entry_set(int unit, bcm_vpn_t vpn, bcm_vxlan_port_t *vxlan_port, uint32 *vent)
   9503 {
   9504     int rv = BCM_E_NONE;
   9505     int index = -1;
   9506     bcm_module_t mod_out = -1;
   9507     bcm_port_t port_out = -1;
   9508     bcm_trunk_t trunk_id = -1;
   9509     bcm_port_t gport_id = -1;
   9510     soc_mem_t mem;
   9511     uint32 return_vent[SOC_MAX_MEM_WORDS];
   9512     int vp = _SHR_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
   9513     _bcm_td2_vxlan_bookkeeping_t *vxlan_info = VXLAN_INFO(unit);
   9514 
   9515 #if defined(BCM_TRIDENT3_SUPPORT)
   9516     if (soc_feature(unit, soc_feature_base_valid)) {
   9517         mem = VLAN_XLATE_1_DOUBLEm;
   9518 
   9519         soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
   9520         soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
   9521     } else
   9522 #endif
   9523     {
   9524         mem = VLAN_XLATEm;
   9525         soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1);
   9526     }
   9527 
   9528     BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, vxlan_port->match_port,
   9529                                     &mod_out, &port_out, &trunk_id, &gport_id));
   9530     if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) {
   9531         soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 1);
   9532         soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf, trunk_id);
   9533     } else {
   9534         soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf, mod_out);
   9535         soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf, port_out);
   9536     }
   9537 
   9538     soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
   9539     soc_mem_field32_set(unit, mem, vent, XLATE__MPLS_ACTIONf, 0x1); /* SVP */
   9540     soc_mem_field32_set(unit, mem, vent, XLATE__SOURCE_VPf, vp);
   9541 
   9542 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   9543     if (soc_feature(unit, soc_feature_vlan_vfi_membership)) {
   9544         if (vxlan_port->flags & BCM_VXLAN_PORT_ENABLE_VLAN_CHECKS){
   9545             return BCM_E_UNAVAIL;
   9546         }
   9547         soc_mem_field32_set(unit, mem, vent, XLATE__DISABLE_VLAN_CHECKSf, 0);
   9548         soc_mem_field32_set(unit, mem, vent, XLATE__VLAN_ACTION_VALIDf, 1);
   9549     } else
   9550 #endif
   9551     {
   9552         soc_mem_field32_set(unit, mem, vent, XLATE__DISABLE_VLAN_CHECKSf, 1);
   9553         if (!(vxlan_port->flags & BCM_VXLAN_PORT_ENABLE_VLAN_CHECKS)){
   9554             soc_mem_field32_set(unit, mem, vent, XLATE__VLAN_ACTION_VALIDf, 1);
   9555         }
   9556     }
   9557 
   9558 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   9559     if (soc_feature(unit, soc_feature_vp_sharing)) {
   9560         if (vpn != BCM_VXLAN_VPN_INVALID) {
   9561             int vfi = 0;
   9562             _BCM_VXLAN_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
   9563             soc_mem_field32_set(unit, mem, vent, XLATE__VFIf, vfi);
   9564         }
   9565     }
   9566 #endif
   9567 
   9568     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index, vent, return_vent, 0);
   9569     if (BCM_E_NONE == rv) {
   9570         if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
   9571             BCM_IF_ERROR_RETURN(
   9572                 _bcm_td2_vxlan_match_vxlate_entry_update(unit, vpn,
   9573                 vxlan_port, vent, return_vent));
   9574             BCM_IF_ERROR_RETURN(
   9575                 soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, return_vent));
   9576         } else {
   9577             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, vent));
   9578         }
   9579     } else if (BCM_E_NOT_FOUND == rv) {
   9580         if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
   9581             return BCM_E_NOT_FOUND;
   9582         }
   9583         BCM_IF_ERROR_RETURN(soc_mem_insert(unit, mem, MEM_BLOCK_ALL, vent));
   9584     } else {
   9585         return rv;
   9586     }
   9587 
   9588     if (vxlan_info->match_key[vp].flags != _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
   9589         if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) {
   9590             vxlan_info->match_key[vp].trunk_id = trunk_id;
   9591             vxlan_info->match_key[vp].modid = -1;
   9592         } else {
   9593             vxlan_info->match_key[vp].port = port_out;
   9594             vxlan_info->match_key[vp].modid = mod_out;
   9595             vxlan_info->match_key[vp].trunk_id = -1;
   9596         }
   9597     }
   9598 
   9599     return BCM_E_NONE;
   9600 }
   9601 
   9602 /*
   9603  * Function:
   9604  *      bcm_td2_vxlan_match_clear
   9605  * Purpose:
   9606  *      Clear VXLAN Match Software State
   9607  * Parameters:
   9608  *      unit    - (IN) Device Number
   9609  *      vp  - (IN) Source Virtual Port
   9610  * Returns:
   9611  *      void
   9612  */
   9613 
   9614 void
   9615 bcm_td2_vxlan_match_clear (int unit, int vp)
   9616 {
   9617     _bcm_td2_vxlan_bookkeeping_t *vxlan_info = VXLAN_INFO(unit);
   9618 
   9619     vxlan_info->match_key[vp].flags = 0;
   9620     vxlan_info->match_key[vp].match_vlan = 0;
   9621     vxlan_info->match_key[vp].match_inner_vlan = 0;
   9622     vxlan_info->match_key[vp].trunk_id = -1;
   9623     vxlan_info->match_key[vp].port = 0;
   9624     vxlan_info->match_key[vp].modid = -1;
   9625     vxlan_info->match_key[vp].match_tunnel_index = 0;
   9626     return;
   9627 }
   9628 
   9629 /*
   9630  * Function:
   9631  *      _bcm_td2_source_trunk_svp_get
   9632  * Purpose:
   9633  *      get source trunk port svp
   9634  * Parameters:
   9635  *      unit    - (IN) Device Number
   9636  *      modid   - (IN) module ID
   9637  *      port   - (IN) Trunk member port
   9638  * Returns:
   9639  *      BCM_E_XXX
   9640  */
   9641 
   9642 STATIC int
   9643 _bcm_td2_source_trunk_svp_get(int unit, bcm_module_t modid, bcm_port_t port)
   9644 {
   9645     source_trunk_map_table_entry_t trunk_map_entry;/*Trunk table entry buffer.*/
   9646     int     src_trk_idx = -1;
   9647     soc_mem_t mem = SOURCE_TRUNK_MAP_TABLEm;
   9648 
   9649     /* Get index to source trunk map table */
   9650     BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, modid,
   9651                 port, &src_trk_idx));
   9652 
   9653     /* Read source trunk map table. */
   9654     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   9655                         src_trk_idx, &trunk_map_entry));
   9656 
   9657     /* get SVP */
   9658     return soc_mem_field32_get(unit, mem, &trunk_map_entry, SOURCE_VPf);
   9659 }
   9660 
   9661 /*
   9662  * Function:
   9663  *      _bcm_td2_vxlan_trunk_table_set
   9664  * Purpose:
   9665  *      Configure VXLAN Trunk port entry
   9666  * Parameters:
   9667  *      unit    - (IN) Device Number
   9668  *      port   - (IN) Trunk member port
   9669  *      tgid - (IN) Trunk group Id
   9670  *      vp   - (IN) Virtual port
   9671  * Returns:
   9672  *      BCM_E_XXX
   9673  */
   9674 
   9675 STATIC int
   9676 _bcm_td2_vxlan_trunk_table_set(int unit, bcm_port_t port, bcm_trunk_t tgid, int vp)
   9677 {
   9678     source_trunk_map_table_entry_t trunk_map_entry;/*Trunk table entry buffer.*/
   9679     bcm_module_t my_modid;
   9680     int     src_trk_idx = -1;
   9681     int     port_type;
   9682     soc_mem_t mem = SOURCE_TRUNK_MAP_TABLEm;
   9683     int     rv = BCM_E_NONE;
   9684 
   9685     if (tgid != BCM_TRUNK_INVALID) {
   9686         port_type = 1; /* TRUNK_PORT_TYPE */
   9687     } else {
   9688         return BCM_E_PARAM;
   9689     }
   9690 
   9691     /* Get module id for unit. */
   9692     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   9693 
   9694     /* Get index to source trunk map table */
   9695     BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid,
   9696                 port, &src_trk_idx));
   9697 
   9698     soc_mem_lock(unit, mem);
   9699 
   9700     /* Read source trunk map table. */
   9701     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   9702                         src_trk_idx, &trunk_map_entry));
   9703 
   9704     /* Set trunk group id. */
   9705 #if defined(BCM_TRIDENT3_SUPPORT)
   9706     if (soc_mem_field_valid(unit, mem, SRC_TGIDf)) {
   9707         soc_mem_field32_set(unit, mem, &trunk_map_entry, SRC_TGIDf, tgid);
   9708     } else
   9709 #endif
   9710     {
   9711         soc_mem_field32_set(unit, mem, &trunk_map_entry, TGIDf, tgid);
   9712     }
   9713     /* Set port is part of Trunk group */
   9714     soc_mem_field32_set(unit, mem, &trunk_map_entry, PORT_TYPEf, port_type);
   9715 
   9716     /* Enable SVP Mode */
   9717     if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) {
   9718         soc_mem_field32_set(unit, mem, &trunk_map_entry, SVP_VALIDf, 0x1);
   9719     }
   9720 
   9721     /* Set SVP */
   9722     soc_mem_field32_set(unit, mem, &trunk_map_entry, SOURCE_VPf, vp);
   9723 
   9724     /* Write entry to hw. */
   9725     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, src_trk_idx, &trunk_map_entry);
   9726 
   9727     soc_mem_unlock(unit, mem);
   9728 
   9729     return rv; 
   9730 }
   9731 
   9732 
   9733 /*
   9734  * Function:
   9735  *      _bcm_td2_vxlan_trunk_table_reset
   9736  * Purpose:
   9737  *      Reset VXLAN Trunk port entry
   9738  * Parameters:
   9739  *      unit    - (IN) Device Number
   9740  *      port   - (IN) Trunk member port
   9741  * Returns:
   9742  *      BCM_E_XXX
   9743  */
   9744 
   9745 STATIC int
   9746 _bcm_td2_vxlan_trunk_table_reset(int unit, bcm_port_t port)
   9747 {
   9748     source_trunk_map_table_entry_t trunk_map_entry;/*Trunk table entry buffer.*/
   9749     bcm_module_t my_modid;
   9750     int    src_trk_idx = -1;
   9751     int rv = BCM_E_NONE;
   9752     soc_mem_t mem = SOURCE_TRUNK_MAP_TABLEm;
   9753 
   9754     /* Get module id for unit. */
   9755     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   9756 
   9757     /* Get index to source trunk map table */
   9758     BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid,
   9759                         port, &src_trk_idx));
   9760 
   9761     soc_mem_lock(unit, mem);
   9762 
   9763     /* Read source trunk map table. */
   9764     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   9765                                      src_trk_idx, &trunk_map_entry));
   9766 
   9767     /* Enable SVP Mode */
   9768     if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) {
   9769         soc_mem_field32_set(unit, mem, &trunk_map_entry, SVP_VALIDf, 0);
   9770     }
   9771 
   9772     /* Set SVP */
   9773     soc_mem_field32_set(unit, mem, &trunk_map_entry, SOURCE_VPf, 0);
   9774 
   9775     /* Write entry to hw. */
   9776     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, src_trk_idx, &trunk_map_entry);
   9777 
   9778     soc_mem_unlock(unit, mem);
   9779 
   9780     return rv; 
   9781 }
   9782 
   9783 /*
   9784  * Function:
   9785  *      bcm_td2_vxlan_match_trunk_add
   9786  * Purpose:
   9787  *      Assign SVP of  VXLAN Trunk port
   9788  * Parameters:
   9789  *      unit    - (IN) Device Number
   9790  *      tgid - (IN) Trunk group Id
   9791  *      vp  - (IN) Source Virtual Port
   9792  *      is_replace - (IN) flag indicates if replace
   9793  * Returns:
   9794  *      BCM_E_XXX
   9795  */
   9796 
   9797 STATIC int
   9798  bcm_td2_vxlan_match_trunk_add(int unit, bcm_trunk_t tgid, int vp, int is_replace)
   9799 {
   9800     int port_idx=0;
   9801     int local_port_out[SOC_MAX_NUM_PORTS];
   9802     int local_member_count=0;
   9803     int rv = BCM_E_NONE;
   9804     int temp = 0;
   9805     int my_modid = 0;
   9806 
   9807     BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid,
   9808                 SOC_MAX_NUM_PORTS, local_port_out, &local_member_count));
   9809 
   9810     if (local_member_count == 0) {
   9811         return BCM_E_NONE;
   9812     }
   9813 
   9814     /* Get module id for unit. */
   9815     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   9816 
   9817     temp = _bcm_td2_source_trunk_svp_get(unit, my_modid, local_port_out[0]);
   9818     if (temp != 0) {
   9819         if ((temp == vp) && (is_replace)) {
   9820             /*continue*/
   9821         } else {
   9822             return BCM_E_INTERNAL;
   9823         }
   9824     }
   9825 
   9826     for (port_idx = 0; port_idx < local_member_count; port_idx++) {
   9827         rv = _bcm_td2_vxlan_trunk_table_set(unit, local_port_out[port_idx], tgid, vp);
   9828         if (BCM_FAILURE(rv)) {
   9829             goto trunk_cleanup;
   9830         }
   9831         rv = _bcm_esw_port_tab_set(
   9832                  unit, local_port_out[port_idx],
   9833                  _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0x1); /* L2_SVP */
   9834         if (BCM_FAILURE(rv)) {
   9835             goto trunk_cleanup;
   9836         }
   9837 
   9838         rv = _bcm_td2_vxlan_port_untagged_profile_set(unit, local_port_out[port_idx]);
   9839         if (BCM_FAILURE(rv)) {
   9840             goto trunk_cleanup;
   9841         }
   9842     }
   9843 
   9844     return BCM_E_NONE;
   9845 
   9846  trunk_cleanup:
   9847     for (; port_idx >= 0; port_idx--) {
   9848         (void) _bcm_esw_port_tab_set(unit, local_port_out[port_idx],
   9849                                      _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0);
   9850         (void) _bcm_td2_vxlan_trunk_table_reset(unit, local_port_out[port_idx]);
   9851     }
   9852     return rv;
   9853 }
   9854 
   9855 /*
   9856  * Function:
   9857  *      bcm_td2_vxlan_match_trunk_delete
   9858  * Purpose:
   9859  *      Remove SVP of VXLAN Trunk port
   9860  * Parameters:
   9861  *      unit    - (IN) Device Number
   9862  *      tgid - (IN) Trunk group Id
   9863  *      vp  - (IN) Source Virtual Port
   9864  * Returns:
   9865  *      BCM_E_XXX
   9866  */
   9867 
   9868 STATIC int
   9869 bcm_td2_vxlan_match_trunk_delete(int unit, bcm_trunk_t tgid, int vp)
   9870 {
   9871     int port_idx=0;
   9872     int local_port_out[SOC_MAX_NUM_PORTS];
   9873     int local_member_count=0;
   9874     int rv = BCM_E_NONE;
   9875 
   9876     BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid,
   9877                 SOC_MAX_NUM_PORTS, local_port_out, &local_member_count));
   9878 
   9879     for (port_idx = 0; port_idx < local_member_count; port_idx++) {
   9880         rv = _bcm_td2_vxlan_trunk_table_reset(unit, local_port_out[port_idx]);
   9881         if (BCM_FAILURE(rv)) {
   9882             goto trunk_cleanup;
   9883         }
   9884         rv = _bcm_esw_port_tab_set(unit, local_port_out[port_idx],
   9885                                    _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0);
   9886         if (BCM_FAILURE(rv)) {
   9887             goto trunk_cleanup;
   9888         }
   9889 
   9890         rv = _bcm_td2_vxlan_port_untagged_profile_reset(unit, local_port_out[port_idx]);
   9891         if (BCM_FAILURE(rv)) {
   9892             goto trunk_cleanup;
   9893         }
   9894     }
   9895 
   9896     return BCM_E_NONE;
   9897 
   9898  trunk_cleanup:
   9899     for (;port_idx >= 0; port_idx--) {
   9900         (void)_bcm_esw_port_tab_set(unit, local_port_out[port_idx],
   9901                                     _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0x1);
   9902         (void) _bcm_td2_vxlan_trunk_table_set(unit, local_port_out[port_idx], tgid, vp);
   9903     }
   9904     return rv;
   9905 }
   9906 
   9907 #if defined(BCM_TRIDENT3_SUPPORT)
   9908 /*
   9909  * Function:
   9910  *        _bcm_td3_vxlan_match_vxlate_entry_set
   9911  * Purpose:
   9912  *       Set VXLAN Match Vxlate Entry 
   9913  * Parameters:
   9914  *  IN :  Unit
   9915  *  IN :  vxlan_port
   9916  *  IN :  vlan_xlate_extd_entry_t
   9917  * Returns:
   9918  *      BCM_E_XXX
   9919  */
   9920 
   9921 STATIC int
   9922 _bcm_td3_vxlan_match_vxlate_entry_set(int unit, bcm_vpn_t vpn, 
   9923                                                          bcm_vxlan_port_t *vxlan_port, 
   9924                                                          uint32 *vent, 
   9925                                                          uint32 *return_vent)
   9926 {
   9927     int rv = BCM_E_NONE;
   9928     int index = -1;
   9929     soc_mem_t vxlate_mem;
   9930 
   9931     vxlate_mem = VLAN_XLATE_1_DOUBLEm;
   9932 
   9933     rv = soc_mem_search(unit, vxlate_mem,
   9934                         MEM_BLOCK_ANY, &index, vent, return_vent, 0);
   9935     if (BCM_E_NONE == rv) {
   9936         BCM_IF_ERROR_RETURN(soc_mem_write(unit,
   9937                                           vxlate_mem, MEM_BLOCK_ALL, index,
   9938                                           vent));
   9939     } else if (BCM_E_NOT_FOUND == rv) {
   9940         if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
   9941             return BCM_E_NOT_FOUND;
   9942         }
   9943         BCM_IF_ERROR_RETURN(soc_mem_insert(unit,
   9944                                           vxlate_mem, MEM_BLOCK_ALL, vent));
   9945     } else {
   9946         return rv;
   9947     }
   9948     return BCM_E_NONE;
   9949 }
   9950 
   9951 /*
   9952  * Function:
   9953  *        _bcm_td3_vxlan_match_vxlate_entry_set
   9954  * Purpose:
   9955  *       Set VXLAN Match Vxlate Entry
   9956  * Parameters:
   9957  *  IN :  Unit
   9958  *  IN :  vxlan_port
   9959  *  IN :  vlan_xlate_extd_entry_t
   9960  * Returns:
   9961  *      BCM_E_XXX
   9962  */
   9963 
   9964 STATIC int
   9965 _bcm_td3_vxlan_match_tunnel_entry_set(int unit, uint32 *ment, uint32 *return_ment)
   9966 {
   9967     int rv = BCM_E_NONE;
   9968     int index = -1;
   9969     int svp = 0;
   9970     uint32 key_type = 0;
   9971     soc_mem_t vxlate_mem;
   9972 
   9973     vxlate_mem = MPLS_ENTRY_SINGLEm;
   9974 
   9975     rv = soc_mem_search(unit, vxlate_mem,
   9976                         MEM_BLOCK_ANY, &index, ment, return_ment, 0);
   9977     if (BCM_E_NONE == rv) {
   9978         key_type = soc_mem_field32_get(unit, vxlate_mem, return_ment, KEY_TYPEf);
   9979         if (key_type == _BCM_VXLAN_KEY_TYPE_TUNNEL) {
   9980             svp = soc_mem_field32_get(
   9981                 unit, vxlate_mem, return_ment, VXLAN_FLEX_IPV4_SIP__SVPf);
   9982             if (_bcm_vp_used_get(unit, svp, _bcmVpTypeVpLag)) {
   9983                 soc_mem_field32_set(
   9984                     unit, vxlate_mem, ment, VXLAN_FLEX_IPV4_SIP__SVPf, svp);
   9985             }
   9986         }
   9987         BCM_IF_ERROR_RETURN(soc_mem_write(unit,
   9988                                           vxlate_mem, MEM_BLOCK_ALL, index,
   9989                                           ment));
   9990     } else if (BCM_E_NOT_FOUND == rv) {
   9991         BCM_IF_ERROR_RETURN(soc_mem_insert(unit,
   9992                                           vxlate_mem, MEM_BLOCK_ALL, ment));
   9993     } else {
   9994         return rv;
   9995     }
   9996     return BCM_E_NONE;
   9997 }
   9998 
   9999 #endif
  10000 
  10001 /*
  10002  * Function:
  10003  *      _bcm_td2_vxlan_match_add
  10004  * Purpose:
  10005  *      Assign match criteria of an VXLAN port
  10006  * Parameters:
  10007  *      unit    - (IN) Device Number
  10008  *      vxlan_port - (IN) vxlan port information
  10009  *      vp  - (IN) Source Virtual Port
  10010  * Returns:
  10011  *      BCM_E_XXX
  10012  */
  10013 
  10014 int
  10015 _bcm_td2_vxlan_match_add(int unit, bcm_vxlan_port_t *vxlan_port, int vp, bcm_vpn_t vpn)
  10016 {
  10017     _bcm_td2_vxlan_bookkeeping_t *vxlan_info = VXLAN_INFO(unit);
  10018     int rv = BCM_E_NONE;
  10019     bcm_module_t mod_out = -1;
  10020     bcm_port_t port_out = -1;
  10021     bcm_trunk_t trunk_id = -1;
  10022     soc_mem_t mem;
  10023     uint32 vent[SOC_MAX_MEM_WORDS];
  10024     int    src_trk_idx=0;  /*Source Trunk table index.*/
  10025     int    gport_id=-1;
  10026     uint8  vxlan_vpn_type = 0;
  10027 
  10028     if (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_NONE) {
  10029         vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_NONE;
  10030         return BCM_E_NONE;
  10031     }
  10032 
  10033     if (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_SHARE) {
  10034         /* there is no criteria to be configurated for shared vp,
  10035            only updating software state to indicate this is a shared vp */
  10036         vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_SHARED;
  10037         return BCM_E_NONE;
  10038     }
  10039 
  10040     sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  10041 #if defined(BCM_TRIDENT3_SUPPORT)
  10042     if (soc_feature(unit, soc_feature_base_valid)) {
  10043         mem = VLAN_XLATE_1_DOUBLEm;
  10044     } else
  10045 #endif
  10046     {
  10047         mem = VLAN_XLATEm;
  10048     }
  10049 
  10050     if (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_PORT_VLAN ) {
  10051         if (!BCM_VLAN_VALID(vxlan_port->match_vlan)) {
  10052              return BCM_E_PARAM;
  10053         }
  10054 
  10055         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OVID);
  10056 #if defined(BCM_TRIDENT3_SUPPORT)
  10057         if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
  10058             soc_mem_field32_set(unit, mem, vent,
  10059                 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OVID);
  10060         }
  10061 #endif
  10062         soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf, vxlan_port->match_vlan);
  10063 
  10064         rv = _bcm_td2_vxlan_match_vxlate_entry_set(unit, vpn, vxlan_port, vent);
  10065         BCM_IF_ERROR_RETURN(rv);
  10066 
  10067         if (vxlan_info->match_key[vp].flags != _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
  10068             vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_VLAN;
  10069             vxlan_info->match_key[vp].match_vlan = vxlan_port->match_vlan;
  10070         }
  10071 
  10072         if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
  10073             bcm_td2_vxlan_port_match_count_adjust(unit, vp, 1);
  10074         }
  10075     } else if (vxlan_port->criteria ==
  10076                             BCM_VXLAN_PORT_MATCH_PORT_INNER_VLAN) {
  10077         if (!BCM_VLAN_VALID(vxlan_port->match_inner_vlan)) {
  10078             return BCM_E_PARAM;
  10079         }
  10080 
  10081         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID);
  10082 #if defined(BCM_TRIDENT3_SUPPORT)
  10083         if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
  10084             soc_mem_field32_set(unit, mem, vent,
  10085                 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID);
  10086         }
  10087 #endif
  10088         soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf, vxlan_port->match_inner_vlan);
  10089 
  10090         rv = _bcm_td2_vxlan_match_vxlate_entry_set(unit, vpn, vxlan_port, vent);
  10091         BCM_IF_ERROR_RETURN(rv);
  10092 
  10093         if (vxlan_info->match_key[vp].flags != _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
  10094             vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_INNER_VLAN;
  10095             vxlan_info->match_key[vp].match_inner_vlan = vxlan_port->match_inner_vlan;
  10096         }
  10097 
  10098         if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
  10099             bcm_td2_vxlan_port_match_count_adjust(unit, vp, 1);
  10100         }
  10101     } else if (vxlan_port->criteria == 
  10102                             BCM_VXLAN_PORT_MATCH_PORT_VLAN_STACKED) {
  10103         if (!BCM_VLAN_VALID(vxlan_port->match_vlan) ||
  10104                 !BCM_VLAN_VALID(vxlan_port->match_inner_vlan)) {
  10105             return BCM_E_PARAM;
  10106         }
  10107 
  10108         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
  10109 #if defined(BCM_TRIDENT3_SUPPORT)
  10110         if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
  10111             soc_mem_field32_set(unit, mem, vent,
  10112                 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
  10113         }
  10114 #endif
  10115         soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf, vxlan_port->match_vlan);
  10116         soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf, vxlan_port->match_inner_vlan);
  10117 
  10118         rv = _bcm_td2_vxlan_match_vxlate_entry_set(unit, vpn, vxlan_port, vent);
  10119         BCM_IF_ERROR_RETURN(rv);
  10120 
  10121         if (vxlan_info->match_key[vp].flags != _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
  10122             vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_STACKED;
  10123             vxlan_info->match_key[vp].match_vlan = vxlan_port->match_vlan;
  10124             vxlan_info->match_key[vp].match_inner_vlan = vxlan_port->match_inner_vlan;
  10125         }
  10126 
  10127         if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
  10128             bcm_td2_vxlan_port_match_count_adjust(unit, vp, 1);
  10129         }
  10130     } else if (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_VLAN_PRI) {
  10131         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_PRI_CFI);
  10132 #if defined(BCM_TRIDENT3_SUPPORT)
  10133         if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
  10134             soc_mem_field32_set(unit, mem, vent,
  10135                 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_PRI_CFI);
  10136         }
  10137 #endif
  10138         /* match_vlan : Bits 12-15 contains VLAN_PRI + CFI, vlan=BCM_E_NONE */
  10139         soc_mem_field32_set(unit, mem, vent, OTAGf, vxlan_port->match_vlan);
  10140 
  10141         rv = _bcm_td2_vxlan_match_vxlate_entry_set(unit, vpn, vxlan_port, vent);
  10142         BCM_IF_ERROR_RETURN(rv);
  10143 
  10144         if (vxlan_info->match_key[vp].flags != _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
  10145             vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_PRI;
  10146             vxlan_info->match_key[vp].match_vlan = vxlan_port->match_vlan;
  10147         }
  10148 
  10149         if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
  10150             bcm_td2_vxlan_port_match_count_adjust(unit, vp, 1);
  10151         }
  10152     } else if (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_PORT) {
  10153         if (vxlan_info->match_key[vp].flags ==
  10154                      _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
  10155             return BCM_E_PARAM;
  10156         }
  10157 
  10158         BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, vxlan_port->match_port,
  10159                                         &mod_out, &port_out, &trunk_id, &gport_id));
  10160 
  10161         if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) {
  10162             BCM_IF_ERROR_RETURN(bcm_td2_vxlan_match_trunk_add(unit, trunk_id, vp, vxlan_port->flags & BCM_VXLAN_PORT_REPLACE));
  10163             if (vxlan_info->match_key[vp].flags !=
  10164                      _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
  10165                 vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK;
  10166                 vxlan_info->match_key[vp].trunk_id = trunk_id;
  10167             }
  10168         } else {
  10169             int is_local;
  10170             int temp = 0;
  10171 
  10172             temp = _bcm_td2_source_trunk_svp_get(unit, mod_out, port_out);
  10173             if (temp != 0) {
  10174                 if ((temp == vp) && (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
  10175                     /*continue*/
  10176                 } else {
  10177                     return BCM_E_INTERNAL;
  10178                 }
  10179             }
  10180 
  10181             BCM_IF_ERROR_RETURN
  10182                 ( _bcm_esw_modid_is_local(unit, mod_out, &is_local));
  10183 
  10184             /* Get index to source trunk map table */
  10185             BCM_IF_ERROR_RETURN(
  10186                    _bcm_esw_src_mod_port_table_index_get(unit, mod_out,
  10187                      port_out, &src_trk_idx));
  10188 
  10189             /* Enable SVP Mode */
  10190             if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, SVP_VALIDf) ) {
  10191                 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  10192                                         src_trk_idx, SVP_VALIDf, 0x1);
  10193                 BCM_IF_ERROR_RETURN(rv);
  10194             }
  10195             rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm, 
  10196                                         src_trk_idx, SOURCE_VPf, vp);
  10197             BCM_IF_ERROR_RETURN(rv);
  10198 
  10199             if (is_local) {
  10200                 rv = _bcm_esw_port_tab_set(
  10201                          unit, vxlan_port->match_port, _BCM_CPU_TABS_NONE,
  10202                          PORT_OPERATIONf, 0x1); /* L2_SVP */
  10203                 BCM_IF_ERROR_RETURN(rv);
  10204 
  10205                 /* Set TAG_ACTION_PROFILE_PTR */
  10206                 rv = _bcm_td2_vxlan_port_untagged_profile_set(
  10207                          unit, vxlan_port->match_port);
  10208                 BCM_IF_ERROR_RETURN(rv);
  10209             }
  10210             /*
  10211              * The vp has been created based on trunk.
  10212              * When a new port is added into the trunk, a match will be
  10213              * added for the vp through bcm_port_match_add.
  10214              */
  10215             if ((vxlan_info->match_key[vp].flags != _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK) &&
  10216                 (vxlan_info->match_key[vp].flags != _BCM_VXLAN_PORT_MATCH_TYPE_SHARED)) {
  10217                 vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_PORT;
  10218                 vxlan_info->match_key[vp].index = src_trk_idx;
  10219             }
  10220         }
  10221     } else if (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_VN_ID) {
  10222         uint32 ment_svp[SOC_MAX_MEM_WORDS] = {0};
  10223         uint32 ment_vnid[SOC_MAX_MEM_WORDS] = {0};
  10224         uint32 ment_evt[SOC_MAX_MEM_WORDS] = {0};
  10225         uint32 orignal_ment_svp[SOC_MAX_MEM_WORDS] = {0};
  10226         uint32 orignal_ment_vnid[SOC_MAX_MEM_WORDS] = {0};
  10227         uint32 orignal_ment_egr_vt[SOC_MAX_MEM_WORDS] = {0};
  10228         int tunnel_idx=-1;
  10229         uint32 tunnel_sip;
  10230         soc_mem_t vxlate_mem;
  10231         int valid = 0;
  10232         int d = 0; /*vxlan decoupled mode*/
  10233 
  10234 #if defined(BCM_TRIDENT3_SUPPORT)
  10235         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  10236             vxlate_mem = EGR_VLAN_XLATE_1_SINGLEm;
  10237             d = 1;
  10238         } else
  10239 #endif
  10240         {
  10241             vxlate_mem = EGR_VLAN_XLATEm;
  10242         }
  10243 
  10244         if (!BCM_GPORT_IS_TUNNEL(vxlan_port->match_tunnel_id)) {
  10245             return BCM_E_BADID;
  10246         }
  10247         
  10248         BCM_IF_ERROR_RETURN(
  10249             _bcm_td2_vxlan_vpn_is_tunnel_based_vnid(unit, vpn, &vxlan_vpn_type));
  10250         if ((vxlan_vpn_type == _BCM_VXLAN_VPN_TYPE_TUNNEL_BASED_VNID) && 
  10251             vxlan_port->vnid > 0xffffff) {
  10252             return BCM_E_PARAM;
  10253         }
  10254 
  10255         tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(vxlan_port->match_tunnel_id);
  10256         _BCM_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx);
  10257         vxlan_info->match_key[vp].match_tunnel_index = tunnel_idx;
  10258         vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_VNID;
  10259 
  10260         if (vxlan_port->flags & BCM_VXLAN_PORT_MULTICAST) {
  10261               return BCM_E_NONE;
  10262         }
  10263         mem = MPLS_ENTRYm;
  10264 #if defined(BCM_TRIDENT3_SUPPORT)
  10265         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  10266             mem = MPLS_ENTRY_SINGLEm;
  10267             d = 1;
  10268             soc_mem_field32_set(unit, mem, ment_svp, BASE_VALIDf, 1);
  10269             soc_mem_field32_set(unit, mem, ment_svp,
  10270                 DATA_TYPEf, _BCM_VXLAN_FLEX_DATA_TYPE_IPV4_SIP);
  10271         } else
  10272 #endif
  10273         {
  10274             soc_mem_field32_set(unit, mem, ment_svp, VALIDf, 1);
  10275         }
  10276 
  10277         tunnel_sip = vxlan_info->vxlan_tunnel_term[tunnel_idx].sip;
  10278         soc_mem_field32_set(unit, mem, ment_svp, BCM_VXLAN_SIP_FIELD(d, SIPf), tunnel_sip);
  10279 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  10280         if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
  10281             VLAN_CHK_ID(unit, vxlan_port->match_vlan);
  10282             vxlan_info->match_key[vp].match_vlan = vxlan_port->match_vlan;
  10283             soc_mem_field32_set(unit, mem, ment_svp,
  10284                 VXLAN_SIP__OVIDf, vxlan_port->match_vlan);
  10285         }
  10286 #endif
  10287         soc_mem_field32_set(unit, mem, ment_svp, BCM_VXLAN_SIP_FIELD(d, SVPf), vp);
  10288         soc_mem_field32_set(unit, mem, ment_svp, KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_TUNNEL);
  10289 #if defined(BCM_TRIDENT3_SUPPORT)
  10290         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  10291             rv = _bcm_td3_vxlan_match_tunnel_entry_set(unit, ment_svp, orignal_ment_svp);
  10292         } else
  10293 #endif
  10294         {
  10295             rv = _bcm_td2_vxlan_match_tunnel_entry_set(unit, ment_svp, orignal_ment_svp);
  10296         }
  10297         BCM_IF_ERROR_RETURN(rv);
  10298         if (vxlan_vpn_type) {
  10299             int vfi_index;
  10300             int tpid_index = -1;
  10301             _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
  10302             /* set egr_vlan_xlate table */
  10303 #if defined(BCM_TRIDENT3_SUPPORT)
  10304             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  10305                 soc_mem_field32_set(unit, vxlate_mem, ment_evt, BASE_VALIDf, 1);
  10306                 soc_mem_field32_set(unit, vxlate_mem, ment_evt,
  10307                                     DATA_TYPEf, _BCM_VXLAN_DATA_TYPE_LOOKUP_VFI);
  10308                 soc_mem_field32_set(unit, vxlate_mem, ment_evt,
  10309                                 KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI_DVP);
  10310             } else
  10311 #endif
  10312             { 
  10313                 soc_mem_field32_set(unit, vxlate_mem, ment_evt, ENTRY_TYPEf,
  10314                                     _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI_DVP);
  10315                 soc_mem_field32_set(unit, vxlate_mem, ment_evt, VALIDf, 0x1);
  10316             }
  10317             soc_mem_field32_set(unit, vxlate_mem, ment_evt, BCM_VXLAN_VFI_FIELD(d, VFIf), vfi_index);
  10318             soc_mem_field32_set(unit, vxlate_mem, ment_evt, BCM_VXLAN_VFI_FIELD(d, DVPf), vp);
  10319             soc_mem_field32_set(unit, vxlate_mem, ment_evt, (d ? VXLAN_VFI_FLEX__VNIDf : VXLAN_VFI__VN_IDf),
  10320                                  vxlan_port->vnid);
  10321             /* Configure EGR_VLAN_XLATE - SD_TAG setting */
  10322             if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
  10323                 int action_present, action_not_present;
  10324                 uint32 old_vxlate_entry[SOC_MAX_MEM_WORDS] = {0};
  10325 
  10326                 rv = _bcm_td2_vxlan_egr_xlate_entry_get(unit, vfi_index, vp, old_vxlate_entry);
  10327                 if (BCM_FAILURE(rv)) {
  10328                     goto match_add_clean1;
  10329                 }
  10330 #if defined(BCM_TRIDENT3_SUPPORT)
  10331                 if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  10332                     int profile_idx = -1;
  10333                     profile_idx = soc_mem_field32_get(unit, vxlate_mem, old_vxlate_entry,
  10334                                                                  VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf);
  10335                     (void)_bcm_td3_sd_tag_action_get(unit, profile_idx, &action_present,
  10336                                    &action_not_present);
  10337                 } else
  10338 #endif
  10339                 {
  10340                     /*If old tpid exist, delete it*/
  10341                     action_present = soc_mem_field32_get(unit, vxlate_mem, old_vxlate_entry,
  10342                                                                  VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf);
  10343                     action_not_present = soc_mem_field32_get(unit, vxlate_mem, old_vxlate_entry,
  10344                                                              VXLAN_VFI__SD_TAG_ACTION_IF_NOT_PRESENTf);
  10345                 }
  10346                 if (1 == action_present || 4 == action_present ||
  10347                     7 == action_present || 1 == action_not_present) {
  10348                     tpid_index = soc_mem_field32_get(unit,
  10349                                      vxlate_mem, old_vxlate_entry, 
  10350                                      d ? VXLAN_VFI_FLEX__OUTER_TPID_INDEXf : VXLAN_VFI__SD_TAG_TPID_INDEXf);
  10351                     rv = _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
  10352                     if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) {
  10353                         goto match_add_clean1;
  10354                     }            
  10355                 }
  10356             }
  10357 
  10358             if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TAGGED) {
  10359                 rv = _bcm_td2_vxlan_sd_tag_set(unit, NULL, vxlan_port, NULL, ment_evt, &tpid_index);
  10360                 if (BCM_FAILURE(rv)) {
  10361                     goto match_add_clean1;
  10362                 }
  10363             }
  10364             rv = _bcm_td2_vxlan_match_egr_vxlate_entry_set(unit, vpn, vxlan_port, ment_evt, orignal_ment_egr_vt);
  10365             if (BCM_FAILURE(rv)) {
  10366                 goto match_add_clean1;
  10367             }
  10368             
  10369             /* set mpls_entry table */
  10370 #if defined(BCM_TRIDENT3_SUPPORT)
  10371             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  10372                 _bcm_td3_vxlan_vxlate_entry_t ent;
  10373 
  10374                 mem = VLAN_XLATE_1_DOUBLEm;
  10375                 sal_memset(&ent, 0, sizeof(_bcm_td3_vxlan_vxlate_entry_t));
  10376                 ent.dtype = _BCM_VXLAN_DATA_TYPE_VNID_VFI_FLEX;
  10377                 ent.ktype = _BCM_VXLAN_KEY_TYPE_VNID_VFI_SIP_FLEX;
  10378                 ent.vfi = vfi_index;
  10379                 ent.vlan = vxlan_info->vxlan_vpn_vlan[vfi_index];
  10380                 _bcm_td3_vxlan_vxlate_entry_assemble(unit, ent, ment_vnid);
  10381             } else
  10382 #endif
  10383             {
  10384                 soc_mem_field32_set(unit, mem, ment_vnid, VALIDf, 1);
  10385                 soc_mem_field32_set(unit, mem, ment_vnid, KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_TUNNEL_VNID_VFI);
  10386                 soc_mem_field32_set(unit, mem, ment_vnid, VXLAN_VN_ID__VFIf, vfi_index);
  10387             }
  10388             soc_mem_field32_set(unit, mem, ment_vnid, BCM_VXLAN_VNID_FIELD(d, SIPf), tunnel_sip);
  10389 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  10390             if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
  10391                 VLAN_CHK_ID(unit, vxlan_port->match_vlan);
  10392                 vxlan_info->match_key[vp].match_vlan = vxlan_port->match_vlan;
  10393                 soc_mem_field32_set(unit, mem, ment_vnid, VXLAN_VN_ID__OVIDf,
  10394                                             vxlan_port->match_vlan);
  10395             }
  10396 #endif
  10397             soc_mem_field32_set(unit, mem, ment_vnid, (d ? VXLAN_FLEX__VNIDf : VXLAN_VN_ID__VN_IDf), vxlan_port->vnid);
  10398 
  10399 #if defined(BCM_TRIDENT3_SUPPORT)
  10400             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  10401                rv = _bcm_td3_vxlan_match_vxlate_entry_set(unit, vpn, vxlan_port, ment_vnid, orignal_ment_vnid);
  10402             } else
  10403 #endif
  10404             {
  10405                 rv = _bcm_td2_vxlan_match_tunnel_entry_set(unit, ment_vnid, orignal_ment_vnid);
  10406             }    
  10407             if (BCM_FAILURE(rv)) {
  10408                 goto match_add_clean2;
  10409             }
  10410             vxlan_info->vxlan_vpn_info[vfi_index].vnid = vxlan_port->vnid;
  10411             vxlan_info->vxlan_vpn_info[vfi_index].sip = tunnel_sip;
  10412             vxlan_info->match_key[vp].vfi = vfi_index;
  10413             return rv;
  10414 match_add_clean2:
  10415             if (soc_feature(unit, soc_feature_base_valid)) {
  10416                 if ((soc_mem_field32_get(unit, vxlate_mem, orignal_ment_egr_vt, BASE_VALID_0f) == 3) &&
  10417                     (soc_mem_field32_get(unit, vxlate_mem, orignal_ment_egr_vt, BASE_VALID_1f) == 7)) {
  10418                      valid = 1;
  10419                 }
  10420             } else {
  10421                 valid = soc_mem_field32_get(unit, vxlate_mem, orignal_ment_egr_vt, VALIDf);
  10422             }
  10423             if (valid) {
  10424                 rv = _bcm_td2_vxlan_match_egr_vxlate_entry_set(unit, vpn, vxlan_port, 
  10425                                                                orignal_ment_egr_vt, 
  10426                                                                ment_evt);
  10427                 BCM_IF_ERROR_RETURN(rv);
  10428             } else {
  10429                 rv = _bcm_td2_vxlan_match_egr_vxlate_entry_delete(unit, ment_evt);
  10430                 BCM_IF_ERROR_RETURN(rv);
  10431             }
  10432 match_add_clean1:
  10433             if (soc_feature(unit, soc_feature_base_valid)) {
  10434                 if ((soc_mem_field32_get(unit, vxlate_mem, orignal_ment_egr_vt, BASE_VALID_0f) == 3) &&
  10435                     (soc_mem_field32_get(unit, vxlate_mem, orignal_ment_egr_vt, BASE_VALID_1f) == 7)) {
  10436                      valid = 1;
  10437                 }     
  10438             } else {
  10439                 valid = soc_mem_field32_get(unit, vxlate_mem, orignal_ment_egr_vt, VALIDf);
  10440             } 
  10441             if (valid) {
  10442                 rv = _bcm_td2_vxlan_match_tunnel_entry_set(unit, orignal_ment_svp, ment_svp);
  10443                 BCM_IF_ERROR_RETURN(rv);                   
  10444             } else {
  10445                 rv = _bcm_td2_vxlan_match_tunnel_entry_delete(unit, ment_svp);
  10446                 BCM_IF_ERROR_RETURN(rv);
  10447             }
  10448             if (tpid_index != -1) {
  10449                 (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
  10450             }
  10451 
  10452             return rv;    
  10453         }
  10454     }
  10455     return rv;
  10456 }
  10457 
  10458 /*
  10459  * Function:
  10460  *      _bcm_td2_vxlan_match_delete
  10461  * Purpose:
  10462  *      Delete match criteria of an VXLAN port
  10463  * Parameters:
  10464  *      unit    - (IN) Device Number
  10465  *      vxlan_port - (IN) VXLAN port information
  10466  *      vp  - (IN) Source Virtual Port
  10467  * Returns:
  10468  *      BCM_E_XXX
  10469  */
  10470 
  10471 int
  10472 _bcm_td2_vxlan_match_delete(int unit,  int vp , bcm_vxlan_port_t vxlan_port, bcm_vpn_t vpn)
  10473 {
  10474     _bcm_td2_vxlan_bookkeeping_t *vxlan_info = VXLAN_INFO(unit);
  10475     int rv=BCM_E_NONE;
  10476     soc_mem_t mem;
  10477     uint32 vent[SOC_MAX_MEM_WORDS] = {0};
  10478     bcm_trunk_t trunk_id;
  10479     int    src_trk_idx=0;   /*Source Trunk table index.*/
  10480     int    mod_id_idx=0;   /* Module_Id */
  10481     int port=0, tunnel_index = -1;
  10482     bcm_module_t mod_out = -1;
  10483     bcm_port_t port_out = -1;
  10484     int    gport_id =-1;
  10485     uint32 ment_svp[SOC_MAX_MEM_WORDS] = {0};
  10486     uint32 ment_vnid[SOC_MAX_MEM_WORDS] = {0};
  10487     uint32 ment_evt[SOC_MAX_MEM_WORDS] = {0};
  10488     uint32 orignal_ment_svp[SOC_MAX_MEM_WORDS] = {0};
  10489     uint32 orignal_ment_vnid[SOC_MAX_MEM_WORDS] = {0};
  10490     uint32 orignal_ment_evt[SOC_MAX_MEM_WORDS] = {0};
  10491     uint8 vxlan_vpn_type = 0;
  10492 
  10493 #if defined(BCM_TRIDENT3_SUPPORT)
  10494     if (soc_feature(unit, soc_feature_base_valid)) {
  10495         mem = VLAN_XLATE_1_DOUBLEm;
  10496 
  10497         soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  10498         soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  10499     } else
  10500 #endif
  10501     {
  10502         mem = VLAN_XLATEm;
  10503 
  10504         soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  10505     }
  10506 
  10507     if  (vxlan_info->match_key[vp].flags == _BCM_VXLAN_PORT_MATCH_TYPE_VLAN) {
  10508         soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  10509         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OVID);
  10510 #if defined(BCM_TRIDENT3_SUPPORT)
  10511         if (mem == VLAN_XLATE_1_DOUBLEm) {
  10512             soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OVID);
  10513         }
  10514 #endif
  10515         soc_mem_field32_set(unit, mem, vent,
  10516             XLATE__OVIDf, vxlan_info->match_key[vp].match_vlan);
  10517 
  10518         if (vxlan_info->match_key[vp].modid != -1) {
  10519             soc_mem_field32_set(unit, mem, vent,
  10520                 XLATE__MODULE_IDf, vxlan_info->match_key[vp].modid);
  10521             soc_mem_field32_set(unit, mem, vent,
  10522                 XLATE__PORT_NUMf, vxlan_info->match_key[vp].port);
  10523 
  10524         } else {
  10525             soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 1);
  10526             soc_mem_field32_set(unit, mem, vent,
  10527                 XLATE__TGIDf, vxlan_info->match_key[vp].trunk_id);
  10528         }
  10529         rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, &vent);
  10530         BCM_IF_ERROR_RETURN(rv);
  10531 
  10532         bcm_td2_vxlan_port_match_count_adjust(unit, vp, -1);
  10533     } else if  (vxlan_info->match_key[vp].flags == 
  10534                      _BCM_VXLAN_PORT_MATCH_TYPE_INNER_VLAN) {
  10535         soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  10536         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID);
  10537 #if defined(BCM_TRIDENT3_SUPPORT)
  10538         if (mem == VLAN_XLATE_1_DOUBLEm) {
  10539             soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID);
  10540         }
  10541 #endif
  10542         soc_mem_field32_set(unit, mem, vent,
  10543             XLATE__IVIDf, vxlan_info->match_key[vp].match_inner_vlan);
  10544         if (vxlan_info->match_key[vp].modid != -1) {
  10545             soc_mem_field32_set(unit, mem, vent,
  10546                 XLATE__MODULE_IDf, vxlan_info->match_key[vp].modid);
  10547             soc_mem_field32_set(unit, mem, vent,
  10548                 XLATE__PORT_NUMf, vxlan_info->match_key[vp].port);
  10549         } else {
  10550             soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 1);
  10551             soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf,
  10552                                         vxlan_info->match_key[vp].trunk_id);
  10553         }
  10554         rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent);
  10555         BCM_IF_ERROR_RETURN(rv);
  10556 
  10557         bcm_td2_vxlan_port_match_count_adjust(unit, vp, -1);
  10558     }else if (vxlan_info->match_key[vp].flags == 
  10559                     _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_STACKED) {
  10560         soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  10561         soc_mem_field32_set(unit, mem, vent,
  10562             KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
  10563 #if defined(BCM_TRIDENT3_SUPPORT)
  10564         if (mem == VLAN_XLATE_1_DOUBLEm) {
  10565             soc_mem_field32_set(unit, mem, vent,
  10566                 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
  10567         }
  10568 #endif
  10569         soc_mem_field32_set(unit, mem, vent,
  10570             XLATE__OVIDf, vxlan_info->match_key[vp].match_vlan);
  10571         soc_mem_field32_set(unit, mem, vent,
  10572             XLATE__IVIDf, vxlan_info->match_key[vp].match_inner_vlan);
  10573         if (vxlan_info->match_key[vp].modid != -1) {
  10574             soc_mem_field32_set(unit, mem, vent,
  10575                 XLATE__MODULE_IDf, vxlan_info->match_key[vp].modid);
  10576             soc_mem_field32_set(unit, mem, vent,
  10577                 XLATE__PORT_NUMf, vxlan_info->match_key[vp].port);
  10578         } else {
  10579             soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 1);
  10580             soc_mem_field32_set(unit, mem, vent,
  10581                 XLATE__TGIDf, vxlan_info->match_key[vp].trunk_id);
  10582         }
  10583         rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent);
  10584         BCM_IF_ERROR_RETURN(rv);
  10585 
  10586         bcm_td2_vxlan_port_match_count_adjust(unit, vp, -1);
  10587     } else if   (vxlan_info->match_key[vp].flags ==
  10588                                                _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_PRI) {
  10589         soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  10590         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_PRI_CFI);
  10591 #if defined(BCM_TRIDENT3_SUPPORT)
  10592         if (mem == VLAN_XLATE_1_DOUBLEm) {
  10593             soc_mem_field32_set(unit, mem, vent,
  10594                 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_PRI_CFI);
  10595         }
  10596 #endif
  10597         soc_mem_field32_set(unit, mem, vent,
  10598             XLATE__OTAGf, vxlan_info->match_key[vp].match_vlan);
  10599         if (vxlan_info->match_key[vp].modid != -1) {
  10600             soc_mem_field32_set(unit, mem, vent,
  10601                 XLATE__MODULE_IDf, vxlan_info->match_key[vp].modid);
  10602             soc_mem_field32_set(unit, mem, vent,
  10603                 XLATE__PORT_NUMf, vxlan_info->match_key[vp].port);
  10604         } else {
  10605             soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 1);
  10606             soc_mem_field32_set(unit, mem, vent,
  10607                 XLATE__TGIDf, vxlan_info->match_key[vp].trunk_id);
  10608         }
  10609         rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, &vent);
  10610         BCM_IF_ERROR_RETURN(rv);
  10611 
  10612         bcm_td2_vxlan_port_match_count_adjust(unit, vp, -1);
  10613     }
  10614 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  10615     else if (vxlan_info->match_key[vp].flags == 
  10616                     _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
  10617 
  10618         soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  10619 
  10620         if (BCM_VXLAN_PORT_MATCH_PORT_VLAN == vxlan_port.criteria) {
  10621             soc_mem_field32_set(unit, mem, vent,
  10622                 KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OVID);
  10623 #if defined(BCM_TRIDENT3_SUPPORT)
  10624             if (mem == VLAN_XLATE_1_DOUBLEm) {
  10625                 soc_mem_field32_set(unit, mem, vent,
  10626                     DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID);
  10627             }
  10628 #endif
  10629             soc_mem_field32_set(unit, mem, vent,
  10630                 XLATE__OVIDf, vxlan_port.match_vlan);
  10631         } else if (BCM_VXLAN_PORT_MATCH_PORT_VLAN_STACKED == vxlan_port.criteria) {
  10632             soc_mem_field32_set(unit, mem, vent,
  10633                 KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
  10634 #if defined(BCM_TRIDENT3_SUPPORT)
  10635             if (mem == VLAN_XLATE_1_DOUBLEm) {
  10636                 soc_mem_field32_set(unit, mem, vent,
  10637                     DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID);
  10638             }
  10639 #endif
  10640             soc_mem_field32_set(unit, mem, vent,
  10641                 XLATE__OVIDf, vxlan_port.match_vlan);
  10642             soc_mem_field32_set(unit, mem, vent,
  10643                 XLATE__IVIDf, vxlan_port.match_inner_vlan);
  10644         } else if (BCM_VXLAN_PORT_MATCH_PORT_INNER_VLAN == vxlan_port.criteria) {
  10645             soc_mem_field32_set(unit, mem, vent,
  10646                 KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID);
  10647 #if defined(BCM_TRIDENT3_SUPPORT)
  10648             if (mem == VLAN_XLATE_1_DOUBLEm) {
  10649                 soc_mem_field32_set(unit, mem, vent,
  10650                     DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID);
  10651             }
  10652 #endif
  10653             soc_mem_field32_set(unit, mem, vent,
  10654                 XLATE__IVIDf, vxlan_port.match_inner_vlan);
  10655         } else if (BCM_VXLAN_PORT_MATCH_VLAN_PRI == vxlan_port.criteria) {
  10656             soc_mem_field32_set(unit, mem, vent,
  10657                 KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_PRI_CFI);
  10658 #if defined(BCM_TRIDENT3_SUPPORT)
  10659             if (mem == VLAN_XLATE_1_DOUBLEm) {
  10660                 soc_mem_field32_set(unit, mem, vent,
  10661                     DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID);
  10662             }
  10663 #endif
  10664             soc_mem_field32_set(unit, mem, vent,
  10665                 XLATE__OTAGf, vxlan_port.match_vlan);
  10666         } else {
  10667             return BCM_E_UNAVAIL;
  10668         }
  10669         
  10670         BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, vxlan_port.match_port, &mod_out,
  10671                         &port_out, &trunk_id, &gport_id));
  10672         
  10673         if (BCM_GPORT_IS_TRUNK(vxlan_port.match_port)) {
  10674             soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 1);
  10675             soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf, trunk_id);
  10676         } else {
  10677             soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf, mod_out);
  10678             soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf, port_out);
  10679         }
  10680 
  10681         rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, vent);
  10682         BCM_IF_ERROR_RETURN(rv);
  10683 
  10684         bcm_td2_vxlan_port_match_count_adjust(unit, vp, -1);
  10685     }
  10686 #endif
  10687     else if ((vxlan_info->match_key[vp].flags == _BCM_VXLAN_PORT_MATCH_TYPE_PORT)
  10688              || ((vxlan_info->match_key[vp].flags == _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK)
  10689                  && (!BCM_GPORT_IS_TRUNK(vxlan_port.match_port)))) {
  10690         int is_local;
  10691 
  10692         if (vxlan_info->match_key[vp].flags == _BCM_VXLAN_PORT_MATCH_TYPE_PORT) {
  10693             src_trk_idx = vxlan_info->match_key[vp].index;
  10694         } else {
  10695             /*
  10696              * The vp has been created based on trunk.
  10697              * When a new port is deleted from the trunk, a match will be deleted
  10698              * for the vp through bcm_port_match_delete.
  10699              */
  10700             BCM_IF_ERROR_RETURN(
  10701                 _bcm_esw_gport_resolve(unit, vxlan_port.match_port, &mod_out,
  10702                                        &port_out, &trunk_id, &gport_id));
  10703             /* Get index to source trunk map table */
  10704             BCM_IF_ERROR_RETURN(
  10705                 _bcm_esw_src_mod_port_table_index_get(
  10706                     unit, mod_out, port_out, &src_trk_idx));
  10707         }
  10708         rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  10709                                     src_trk_idx, SOURCE_VPf, 0);
  10710         BCM_IF_ERROR_RETURN(rv);
  10711 
  10712         /* Disable SVP Mode */
  10713         if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, SVP_VALIDf) ) {
  10714             rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
  10715                                         src_trk_idx, SVP_VALIDf, 0x0);
  10716             BCM_IF_ERROR_RETURN(rv);
  10717         }
  10718 
  10719         BCM_IF_ERROR_RETURN(
  10720             _bcm_esw_src_modid_port_get(unit, src_trk_idx, &mod_id_idx, &port));
  10721         BCM_IF_ERROR_RETURN(
  10722             _bcm_esw_modid_is_local(unit, mod_id_idx, &is_local));
  10723 
  10724         if (is_local) {
  10725             rv = _bcm_esw_port_tab_set(unit, vxlan_port.match_port,
  10726                                        _BCM_CPU_TABS_NONE, PORT_OPERATIONf, 0);
  10727             BCM_IF_ERROR_RETURN(rv);
  10728 
  10729             /* Reset TAG_ACTION_PROFILE_PTR */
  10730             rv = _bcm_td2_vxlan_port_untagged_profile_reset(
  10731                      unit, vxlan_port.match_port);
  10732             BCM_IF_ERROR_RETURN(rv);
  10733         }
  10734     } else if  (vxlan_info->match_key[vp].flags == 
  10735                   _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK) {
  10736          trunk_id = vxlan_info->match_key[vp].trunk_id;
  10737          rv = bcm_td2_vxlan_match_trunk_delete(unit, trunk_id, vp);
  10738          BCM_IF_ERROR_RETURN(rv);
  10739     } else if (vxlan_info->match_key[vp].flags == 
  10740                   _BCM_VXLAN_PORT_MATCH_TYPE_VNID) {
  10741         int d = 0; /*vxlan decoupled mode*/
  10742 
  10743         if (vxlan_port.flags & BCM_VXLAN_PORT_MULTICAST) {
  10744             return BCM_E_NONE;
  10745         }
  10746 
  10747         mem = MPLS_ENTRYm;
  10748         BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_tunnel_based_vnid(unit, vpn, &vxlan_vpn_type));
  10749 
  10750 #if defined(BCM_TRIDENT3_SUPPORT)
  10751         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  10752             mem = MPLS_ENTRY_SINGLEm;
  10753             d = 1;
  10754             soc_mem_field32_set(unit, mem, ment_svp, BASE_VALIDf, 1);
  10755             soc_mem_field32_set(unit, mem, ment_svp,
  10756                 DATA_TYPEf, _BCM_VXLAN_FLEX_DATA_TYPE_IPV4_SIP);
  10757         } else
  10758 #endif
  10759         {
  10760             soc_mem_field32_set(unit, mem, ment_svp, VALIDf, 1);
  10761         }
  10762 
  10763         tunnel_index = vxlan_info->match_key[vp].match_tunnel_index;
  10764         soc_mem_field32_set(unit, mem, ment_svp, BCM_VXLAN_SIP_FIELD(d, SIPf),
  10765                 vxlan_info->vxlan_tunnel_term[tunnel_index].sip);
  10766 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  10767         if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
  10768             soc_mem_field32_set(unit, mem, ment_svp,
  10769                 VXLAN_SIP__OVIDf, vxlan_info->match_key[vp].match_vlan);
  10770         }
  10771 #endif
  10772         soc_mem_field32_set(unit, mem, ment_svp, KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_TUNNEL);
  10773 
  10774         BCM_IF_ERROR_RETURN(
  10775             _bcm_td2_vxlan_match_tunnel_entry_reset(unit, vp, ment_svp, 
  10776                                                     orignal_ment_svp));  
  10777 
  10778         if (vxlan_vpn_type) {            
  10779             int vfi_index;
  10780             int index;
  10781             soc_mem_t vxlate_mem;
  10782 #if defined(BCM_TRIDENT3_SUPPORT)
  10783             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  10784                 d = 1;
  10785                 vxlate_mem = EGR_VLAN_XLATE_1_SINGLEm;
  10786             } else
  10787 #endif
  10788             {     
  10789                vxlate_mem = EGR_VLAN_XLATEm;
  10790             }   
  10791             
  10792             _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
  10793             /* set egr_vlan_xlate table */
  10794 #if defined(BCM_TRIDENT3_SUPPORT)
  10795             if (soc_feature(unit, soc_feature_base_valid)) {
  10796                 soc_mem_field32_set(unit, vxlate_mem, ment_evt, BASE_VALIDf, 1);
  10797                 soc_mem_field32_set(unit, vxlate_mem, ment_evt,
  10798                                     DATA_TYPEf, _BCM_VXLAN_DATA_TYPE_LOOKUP_VFI);
  10799                 soc_mem_field32_set(unit, vxlate_mem, ment_evt,
  10800                                 KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI_DVP);
  10801             } else
  10802 #endif
  10803             {
  10804                 soc_mem_field32_set(unit, vxlate_mem, ment_evt, ENTRY_TYPEf,
  10805                                     _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI_DVP);
  10806                 soc_mem_field32_set(unit, vxlate_mem, ment_evt, VALIDf, 0x1);
  10807             }
  10808             soc_mem_field32_set(unit, vxlate_mem, ment_evt, BCM_VXLAN_VFI_FIELD(d, VFIf), vfi_index);
  10809             soc_mem_field32_set(unit, vxlate_mem, ment_evt, BCM_VXLAN_VFI_FIELD(d, DVPf), vp);
  10810                     
  10811            rv = soc_mem_search(unit, vxlate_mem, MEM_BLOCK_ANY, &index,
  10812                                 ment_evt, orignal_ment_evt, 0);
  10813             if (BCM_FAILURE(rv)) {
  10814                 goto match_delete_clean1;
  10815             }            
  10816             sal_memset(ment_evt, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
  10817             rv = soc_mem_write(unit, vxlate_mem, MEM_BLOCK_ALL, index, ment_evt);
  10818             if (BCM_FAILURE(rv)) {
  10819                 goto match_delete_clean1;
  10820 
  10821             }
  10822 
  10823             /* set mpls_entry table */
  10824 #if defined(BCM_TRIDENT3_SUPPORT)
  10825             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  10826                 mem = VLAN_XLATE_1_DOUBLEm;
  10827                 soc_mem_field32_set(unit, mem, ment_vnid, BASE_VALID_0f, 3);
  10828                 soc_mem_field32_set(unit, mem, ment_vnid, BASE_VALID_1f, 7);
  10829                 soc_mem_field32_set(unit, mem, ment_vnid,
  10830                     DATA_TYPEf, _BCM_VXLAN_DATA_TYPE_VNID_VFI_FLEX);
  10831                 soc_mem_field32_set(unit, mem, &ment_vnid, KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_VNID_VFI_SIP_FLEX);
  10832             } else
  10833 #endif
  10834             {
  10835                 soc_mem_field32_set(unit, mem, ment_vnid, VALIDf, 1);
  10836                 soc_mem_field32_set(unit, mem, ment_vnid, KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_TUNNEL_VNID_VFI);
  10837             }            
  10838             soc_mem_field32_set(unit, mem, ment_vnid, BCM_VXLAN_VNID_FIELD(d, SIPf),
  10839                                         vxlan_info->vxlan_tunnel_term[tunnel_index].sip);
  10840 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  10841             if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
  10842                 soc_mem_field32_set(unit, mem, ment_vnid, VXLAN_VN_ID__OVIDf,
  10843                                             vxlan_port.match_vlan);
  10844             }
  10845 #endif
  10846             soc_mem_field32_set(unit, mem, ment_vnid, (d ? VXLAN_FLEX__VNIDf : VXLAN_VN_ID__VN_IDf), vxlan_port.vnid);
  10847             rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index,
  10848                                 ment_vnid, orignal_ment_vnid, 0);
  10849             if (BCM_FAILURE(rv)) {
  10850                 goto match_delete_clean2;
  10851             }
  10852 
  10853             sal_memset(ment_vnid, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
  10854             rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, ment_vnid);
  10855             if (BCM_FAILURE(rv)) {
  10856                 goto match_delete_clean2;                
  10857             }
  10858             vxlan_info->vxlan_vpn_info[vfi_index].vnid = 0;
  10859             vxlan_info->vxlan_vpn_info[vfi_index].sip = 0;
  10860             vxlan_info->match_key[vp].vfi = 0;
  10861         }
  10862         if (!vxlan_info->vxlan_tunnel_term[tunnel_index].dip) {
  10863             vxlan_info->vxlan_tunnel_term[tunnel_index].sip = 0; 
  10864         }
  10865         return rv;
  10866 match_delete_clean2:
  10867         rv = _bcm_td2_vxlan_match_egr_vxlate_entry_set(unit, vpn, &vxlan_port, 
  10868                                                        orignal_ment_evt, 
  10869                                                        ment_evt);
  10870         BCM_IF_ERROR_RETURN(rv);
  10871 match_delete_clean1:   
  10872         rv = _bcm_td2_vxlan_match_tunnel_entry_set(unit, orignal_ment_svp, ment_svp);
  10873         BCM_IF_ERROR_RETURN(rv);
  10874         return rv;
  10875     }
  10876  
  10877     return BCM_E_NONE;
  10878 }
  10879 
  10880 /*
  10881  * Function:
  10882  *      _bcm_td2_vxlan_match_get
  10883  * Purpose:
  10884  *      Obtain match information of an VXLAN port
  10885  * Parameters:
  10886  *      unit    - (IN) Device Number
  10887  *      vxlan_port - (OUT) VXLAN port information
  10888  *      vp  - (IN) Source Virtual Port
  10889  * Returns:
  10890  *      BCM_E_XXX
  10891  */
  10892 
  10893 int
  10894 _bcm_td2_vxlan_match_get(int unit, bcm_vxlan_port_t *vxlan_port, int vp, bcm_vpn_t vpn)
  10895 {
  10896     _bcm_td2_vxlan_bookkeeping_t *vxlan_info = VXLAN_INFO(unit);
  10897     int rv = BCM_E_NONE;
  10898     bcm_module_t mod_in=0, mod_out=0;
  10899     bcm_port_t port_in=0, port_out=0;
  10900     bcm_trunk_t trunk_id=0;
  10901     int    src_trk_idx=0;    /*Source Trunk table index.*/
  10902     int    tunnel_idx = -1;
  10903     uint8  vxlan_vpn_type;
  10904     if  (vxlan_info->match_key[vp].flags & _BCM_VXLAN_PORT_MATCH_TYPE_VLAN) {
  10905 
  10906          vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_PORT_VLAN;
  10907          vxlan_port->match_vlan = vxlan_info->match_key[vp].match_vlan;
  10908 
  10909         if (vxlan_info->match_key[vp].trunk_id != -1) {
  10910              trunk_id = vxlan_info->match_key[vp].trunk_id;
  10911              BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id);
  10912         } else {
  10913              port_in = vxlan_info->match_key[vp].port;
  10914              mod_in = vxlan_info->match_key[vp].modid;
  10915              rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
  10916                                   mod_in, port_in, &mod_out, &port_out);
  10917              vxlan_port->match_port =
  10918                  _bcm_esw_port_gport_get_from_modport(unit, mod_out, port_out);
  10919         }
  10920     } else if (vxlan_info->match_key[vp].flags &  
  10921                  _BCM_VXLAN_PORT_MATCH_TYPE_INNER_VLAN) {
  10922          vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_PORT_INNER_VLAN;
  10923          vxlan_port->match_inner_vlan = vxlan_info->match_key[vp].match_inner_vlan;
  10924 
  10925         if (vxlan_info->match_key[vp].trunk_id != -1) {
  10926              trunk_id = vxlan_info->match_key[vp].trunk_id;
  10927              BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id);
  10928         } else {
  10929              port_in = vxlan_info->match_key[vp].port;
  10930              mod_in = vxlan_info->match_key[vp].modid;
  10931              rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
  10932                                   mod_in, port_in, &mod_out, &port_out);
  10933              vxlan_port->match_port =
  10934                  _bcm_esw_port_gport_get_from_modport(unit, mod_out, port_out);
  10935         }
  10936     }else if (vxlan_info->match_key[vp].flags &
  10937                     _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_STACKED) {
  10938 
  10939          vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_PORT_VLAN_STACKED;
  10940          vxlan_port->match_vlan = vxlan_info->match_key[vp].match_vlan;
  10941          vxlan_port->match_inner_vlan = vxlan_info->match_key[vp].match_inner_vlan;
  10942 
  10943          if (vxlan_info->match_key[vp].trunk_id != -1) {
  10944               trunk_id = vxlan_info->match_key[vp].trunk_id;
  10945               BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id);
  10946          } else {
  10947               port_in = vxlan_info->match_key[vp].port;
  10948               mod_in = vxlan_info->match_key[vp].modid;
  10949               rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
  10950                              mod_in, port_in, &mod_out, &port_out);
  10951               vxlan_port->match_port =
  10952                   _bcm_esw_port_gport_get_from_modport(unit, mod_out, port_out);
  10953          }
  10954     } else if  (vxlan_info->match_key[vp].flags & _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_PRI) {
  10955 
  10956          vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_VLAN_PRI;
  10957          vxlan_port->match_vlan = vxlan_info->match_key[vp].match_vlan;
  10958 
  10959         if (vxlan_info->match_key[vp].trunk_id != -1) {
  10960              trunk_id = vxlan_info->match_key[vp].trunk_id;
  10961              BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id);
  10962         } else {
  10963              port_in = vxlan_info->match_key[vp].port;
  10964              mod_in = vxlan_info->match_key[vp].modid;
  10965              rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
  10966                                   mod_in, port_in, &mod_out, &port_out);
  10967              vxlan_port->match_port =
  10968                  _bcm_esw_port_gport_get_from_modport(unit, mod_out, port_out);
  10969         }
  10970     } else if (vxlan_info->match_key[vp].flags &
  10971                    _BCM_VXLAN_PORT_MATCH_TYPE_PORT) {
  10972 
  10973          src_trk_idx = vxlan_info->match_key[vp].index;
  10974          BCM_IF_ERROR_RETURN(_bcm_esw_src_modid_port_get( unit, src_trk_idx,
  10975                                                           &mod_in, &port_in));
  10976 
  10977          vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_PORT;
  10978          rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
  10979                                mod_in, port_in, &mod_out, &port_out);
  10980          vxlan_port->match_port =
  10981              _bcm_esw_port_gport_get_from_modport(unit, mod_out, port_out);
  10982     }else if (vxlan_info->match_key[vp].flags &
  10983                   _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK) {
  10984 
  10985          trunk_id = vxlan_info->match_key[vp].trunk_id;
  10986          vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_PORT;
  10987          BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id);
  10988     } else if ((vxlan_info->match_key[vp].flags &
  10989                           _BCM_VXLAN_PORT_MATCH_TYPE_VNID)) {
  10990         vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_VN_ID;
  10991 
  10992         tunnel_idx = vxlan_info->match_key[vp].match_tunnel_index;
  10993         BCM_GPORT_TUNNEL_ID_SET(vxlan_port->match_tunnel_id, tunnel_idx);
  10994         vxlan_port->match_vlan = vxlan_info->match_key[vp].match_vlan;
  10995         BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_tunnel_based_vnid(unit, vpn, &vxlan_vpn_type));
  10996         if (vxlan_vpn_type) {
  10997             int vfi_idx;
  10998             _BCM_VXLAN_VPN_GET(vfi_idx, _BCM_VPN_TYPE_VFI, vpn);
  10999             vxlan_port->vnid = vxlan_info->vxlan_vpn_info[vfi_idx].vnid;
  11000         }
  11001     }else if (vxlan_info->match_key[vp].flags & _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
  11002         vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_SHARE;
  11003     } else {
  11004         vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_NONE;
  11005     }
  11006     return rv;
  11007 }
  11008 
  11009 /*
  11010  * Function:
  11011  *      _bcm_td2_vxlan_eline_vp_map_set
  11012  * Purpose:
  11013  *      Set VXLAN ELINE ports from VPN
  11014  * Parameters:
  11015  *      unit    - (IN) Device Number
  11016  *      vpn     - (IN) VPN instance ID
  11017  * Returns:
  11018  *      BCM_E_XXX
  11019  */
  11020 STATIC int
  11021 _bcm_td2_vxlan_eline_vp_map_set(int unit, int vfi_index, int vp1, int vp2)
  11022 {
  11023     vfi_entry_t vfi_entry;
  11024     int rv=BCM_E_NONE;
  11025     int num_vp=0;
  11026     int vp1_invalid = 0;
  11027     int vp2_invalid = 0;
  11028 
  11029     if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVxlan)) {
  11030         return BCM_E_NOT_FOUND;
  11031     }
  11032     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  11033 
  11034     BCM_IF_ERROR_RETURN
  11035         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
  11036 
  11037     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
  11038          if ((vp1 > 0) && (vp1 < num_vp)) {
  11039               soc_VFIm_field32_set(unit, &vfi_entry, VP_0f, vp1);
  11040          } else {
  11041               vp1_invalid = 1;
  11042          }
  11043          if ((vp2 > 0) && (vp2 < num_vp)) {
  11044               soc_VFIm_field32_set(unit, &vfi_entry, VP_1f, vp2);
  11045          } else {
  11046               vp2_invalid = 1;
  11047          }
  11048          if (vp1_invalid && vp2_invalid) {
  11049              return BCM_E_PARAM;
  11050          }
  11051     } else {
  11052          /* ELAN */
  11053          return BCM_E_PARAM;
  11054     }
  11055 
  11056     rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry);
  11057     return rv;
  11058 }
  11059 
  11060 /*
  11061  * Function:
  11062  *      _bcm_td2_vxlan_eline_vp_map_get
  11063  * Purpose:
  11064  *      Get VXLAN ELINE ports from VPN
  11065  * Parameters:
  11066  *      unit    - (IN) Device Number
  11067  *      vpn     - (IN) VPN instance ID
  11068  * Returns:
  11069  *      BCM_E_XXX
  11070  */
  11071 
  11072 STATIC int
  11073 _bcm_td2_vxlan_eline_vp_map_get(int unit, int vfi_index, int *vp1, int *vp2)
  11074 {
  11075     vfi_entry_t vfi_entry;
  11076 
  11077     if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVxlan)) {
  11078         return BCM_E_NOT_FOUND;
  11079     }
  11080 
  11081     BCM_IF_ERROR_RETURN
  11082         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
  11083 
  11084     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
  11085         *vp1 = soc_VFIm_field32_get(unit, &vfi_entry, VP_0f);
  11086         *vp2 = soc_VFIm_field32_get(unit, &vfi_entry, VP_1f);
  11087          return BCM_E_NONE;
  11088     } else {
  11089          return BCM_E_PARAM;
  11090     }
  11091 }
  11092 
  11093 /*
  11094  * Function:
  11095  *      _bcm_td2_vxlan_eline_vp_map_clear
  11096  * Purpose:
  11097  *      Clear VXLAN ELINE ports from VPN
  11098  * Parameters:
  11099  *      unit    - (IN) Device Number
  11100  *      vpn     - (IN) VPN instance ID
  11101  * Returns:
  11102  *      BCM_E_XXX
  11103  */
  11104 
  11105 STATIC int
  11106 _bcm_td2_vxlan_eline_vp_map_clear(int unit, int vfi_index, int vp1, int vp2)
  11107 {
  11108     vfi_entry_t vfi_entry;
  11109     int rv=BCM_E_NONE;
  11110     int num_vp=0;
  11111 
  11112     if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVxlan)) {
  11113         return BCM_E_NOT_FOUND;
  11114     }
  11115 
  11116     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  11117 
  11118     BCM_IF_ERROR_RETURN
  11119         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
  11120 
  11121     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
  11122         if ((vp1 > 0) && (vp1 < num_vp)) {
  11123             soc_VFIm_field32_set(unit, &vfi_entry, VP_0f, 0);
  11124         }
  11125         if ((vp2 > 0) && (vp2 < num_vp)) {
  11126             soc_VFIm_field32_set(unit, &vfi_entry, VP_1f, 0);
  11127         }
  11128     } else {
  11129         /* ELAN */
  11130         return BCM_E_PARAM;
  11131     }
  11132     rv = WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry);
  11133     return rv;
  11134 }
  11135 
  11136 /*
  11137  * Function:
  11138  *      _bcm_td2_vxlan_eline_vp_configure
  11139  * Purpose:
  11140  *      Configure VXLAN ELINE virtual port
  11141  * Parameters:
  11142  *      unit    - (IN) Device Number
  11143  *      vpn     - (IN) VPN instance ID
  11144  * Returns:
  11145  *      BCM_E_XXX
  11146  */
  11147 
  11148 STATIC int
  11149 _bcm_td2_vxlan_eline_vp_configure (int unit, int vfi_index, int active_vp, 
  11150                   source_vp_entry_t *svp, uint32 tpid_enable, bcm_vxlan_port_t  *vxlan_port)
  11151 {
  11152     int rv = BCM_E_NONE;
  11153     int network_group=0;
  11154     source_vp_2_entry_t svp_2_entry;
  11155 
  11156     /* Set SOURCE_VP */
  11157     soc_SOURCE_VPm_field32_set(unit, svp, CLASS_IDf,
  11158                                 vxlan_port->if_class);
  11159 
  11160     /* Default Split Horizon Group Id
  11161      * 0 - For Access Port;1 - For Network Port*/
  11162     network_group = vxlan_port->network_group_id;
  11163     rv = _bcm_validate_splithorizon_network_group(unit,
  11164             vxlan_port->flags & BCM_VXLAN_PORT_NETWORK, &network_group);
  11165     BCM_IF_ERROR_RETURN(rv);
  11166     if (vxlan_port->flags & BCM_VXLAN_PORT_NETWORK) {
  11167         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
  11168             soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_GROUPf,
  11169                  network_group);
  11170         } else {
  11171             soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_PORTf, 1);
  11172         }
  11173 #if defined(BCM_TRIDENT3_SUPPORT)
  11174         if (SOC_IS_TRIDENT3X(unit)) {
  11175         } else
  11176 #endif
  11177         {
  11178             soc_SOURCE_VPm_field32_set(unit, svp, TPID_SOURCEf, _BCM_VXLAN_TPID_SVP_BASED);
  11179         }
  11180     } else {
  11181         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
  11182             soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_GROUPf,
  11183                         network_group);
  11184         } else {
  11185             soc_SOURCE_VPm_field32_set(unit, svp, NETWORK_PORTf, 0);
  11186         }
  11187 #if defined(BCM_TRIDENT3_SUPPORT)
  11188         if (SOC_IS_TRIDENT3X(unit)) {
  11189         } else
  11190 #endif
  11191         {
  11192             soc_SOURCE_VPm_field32_set(unit, svp, TPID_SOURCEf, _BCM_VXLAN_TPID_SVP_BASED);
  11193             /*  Configure IPARS Parser to signal to IMPLS Parser - Applicable only for HG2 PPD2 packets
  11194                   to reconstruct TPID state based on HG header information - Only for VXLAN Access ports */
  11195             sal_memset(&svp_2_entry, 0, sizeof(source_vp_2_entry_t));
  11196             soc_SOURCE_VP_2m_field32_set(unit, &svp_2_entry, PARSE_USING_SGLP_TPIDf, 1);
  11197             BCM_IF_ERROR_RETURN(WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, active_vp, &svp_2_entry));
  11198         }
  11199     }
  11200 
  11201     if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TAGGED) {
  11202          soc_SOURCE_VPm_field32_set(unit, svp, SD_TAG_MODEf, 1);
  11203 #if defined(BCM_TRIDENT3_SUPPORT)
  11204          if (SOC_IS_TRIDENT3X(unit)) {
  11205              uint32 svp1[SOC_MAX_MEM_WORDS];
  11206 
  11207              sal_memset(svp1, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  11208              soc_SVP_ATTRS_1m_field_set(unit, &svp1, TPID_ENABLEf, &tpid_enable);
  11209              BCM_IF_ERROR_RETURN(
  11210                 WRITE_SVP_ATTRS_1m(unit, MEM_BLOCK_ALL, active_vp, &svp1));
  11211          } else
  11212 #endif
  11213          {
  11214              soc_SOURCE_VPm_field32_set(unit, svp, TPID_ENABLEf, tpid_enable);
  11215          }
  11216     } else {
  11217          soc_SOURCE_VPm_field32_set(unit, svp, SD_TAG_MODEf, 0);
  11218     }
  11219 
  11220     soc_SOURCE_VPm_field32_set(unit, svp, DISABLE_VLAN_CHECKSf, 1);
  11221     soc_SOURCE_VPm_field32_set(unit, svp, 
  11222                            ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_VFI); /* VFI Type */
  11223     soc_SOURCE_VPm_field32_set(unit, svp, VFIf, vfi_index);
  11224 
  11225     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, svp);
  11226 #if defined(BCM_TRIDENT3_SUPPORT)
  11227     if (SOC_IS_TRIDENT3X(unit)) {
  11228         if ((vfi_index != _BCM_VXLAN_VFI_INVALID) &&
  11229             (vxlan_port->flags & BCM_VXLAN_PORT_NETWORK)) {
  11230             if ( BCM_E_NONE != soc_cancun_app_dest_entry_set (unit, SOURCE_VPm,
  11231                 active_vp, ENTRY_TYPEf, CANCUN_APP__SOURCE_VP__No_Control_Word,
  11232                 _BCM_VXLAN_SOURCE_VP_TYPE_VFI)) {
  11233                 LOG_ERROR(BSL_LS_BCM_VXLAN,
  11234                    (BSL_META_U(unit,"SOURCE_VP cancun app cfg error\n")));
  11235             }
  11236         }
  11237     }
  11238 #endif
  11239     return rv;
  11240 }
  11241 
  11242 /*
  11243  * Function:
  11244  *      _bcm_td2_vxlan_access_niv_pe_set
  11245  * Purpose:
  11246  *      Set VXLAN Access virtual port which is of NIV/PE type
  11247  * Parameters:
  11248  *      unit    - (IN) Device Number
  11249  *      vp      -  (IN) Access Virtual Port
  11250  *      vfi      -  (IN) Virtial forwarding instance
  11251  * Returns:
  11252  *      BCM_E_XXX
  11253  */
  11254 
  11255 STATIC int
  11256 _bcm_td2_vxlan_access_niv_pe_set (int unit, int vp, int vfi)
  11257 {
  11258     source_vp_entry_t svp;
  11259     int  rv = BCM_E_PARAM; 
  11260 
  11261         rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
  11262         if (rv < 0) {
  11263             return rv;
  11264         }
  11265 
  11266         if (vfi == _BCM_VXLAN_VFI_INVALID) {
  11267             soc_SOURCE_VPm_field32_set(unit, &svp, 
  11268                                        ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_INVALID);
  11269         } else {
  11270             /* Initialize VP parameters */
  11271             soc_SOURCE_VPm_field32_set(unit, &svp, 
  11272                                        ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_VFI);
  11273         }     
  11274         soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, vfi);
  11275         rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
  11276         return rv;
  11277 }
  11278 
  11279 /*
  11280  * Function:
  11281  *      _bcm_td2_vxlan_access_niv_pe_reset
  11282  * Purpose:
  11283  *      Reset VXLAN Access virtual port which is of NIV/PE type
  11284  * Parameters:
  11285  *      unit    - (IN) Device Number
  11286  *      vp      -  (IN) Access Virtual Port
  11287  * Returns:
  11288  *      BCM_E_XXX
  11289  */
  11290 
  11291 STATIC int
  11292 _bcm_td2_vxlan_access_niv_pe_reset (int unit, int vp)
  11293 {
  11294     source_vp_entry_t svp;
  11295 
  11296     BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
  11297 
  11298     /* Initialize VP parameters */
  11299     soc_SOURCE_VPm_field32_set(unit, &svp,
  11300         ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_VLAN);
  11301     soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, 0);
  11302     BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp));
  11303 
  11304     return BCM_E_NONE;
  11305 }
  11306 
  11307 
  11308 /*
  11309  * Function:
  11310  *      _bcm_td2_vxlan_vp_based_vnid_add
  11311  * Purpose:
  11312  *      Add VXLAN VP-based VFI-VNID mapping
  11313  * Parameters:
  11314  *      unit    - (IN) Device Number
  11315  *      vpn     - (IN) VPN instance ID
  11316  *      vxlan_port - (IN) VXLAN port information
  11317  * Returns:
  11318  *      BCM_E_XXX
  11319  */
  11320 
  11321 STATIC int
  11322 _bcm_td2_vxlan_vp_based_vnid_add(int unit, bcm_vpn_t vpn, bcm_vxlan_port_t *vxlan_port)
  11323 {
  11324     _bcm_td2_vxlan_bookkeeping_t *vxlan_info = VXLAN_INFO(unit);
  11325     int vp, vfi;
  11326     _bcm_vp_info_t vp_info;
  11327     uint32 tunnel_sip;
  11328     int32 tunnel_idx;
  11329     soc_mem_t vxlate_mem;
  11330     soc_mem_t mmem = MPLS_ENTRYm;
  11331     int valid = 0;
  11332     int tpid_index = -1;
  11333     int d = 0; /*vxlan decoupled mode*/
  11334     uint32 ment_evt[SOC_MAX_MEM_WORDS] = {0};
  11335     uint32 ment_vnid[SOC_MAX_MEM_WORDS] = {0};
  11336     uint32 original_ment_evt[SOC_MAX_MEM_WORDS] = {0};
  11337     uint32 original_ment_vnid[SOC_MAX_MEM_WORDS] = {0};
  11338     uint8 vxlan_vpn_type;
  11339     int rv;
  11340     source_vp_entry_t svp;
  11341     bcm_vxlan_port_t  vxlan_port_r;
  11342 
  11343 #if defined(BCM_TRIDENT3_SUPPORT)
  11344     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  11345         vxlate_mem = EGR_VLAN_XLATE_1_SINGLEm;
  11346         d = 1;
  11347     } else
  11348 #endif
  11349     {
  11350         vxlate_mem = EGR_VLAN_XLATEm;
  11351         }
  11352 
  11353     if (vxlan_port == NULL) {
  11354         return BCM_E_PARAM;
  11355             }
  11356 
  11357                 BCM_IF_ERROR_RETURN (
  11358         _bcm_td2_vxlan_vpn_is_tunnel_based_vnid(unit, vpn, &vxlan_vpn_type));
  11359     if (vxlan_vpn_type == _BCM_VXLAN_VPN_TYPE_TUNNEL_BASED_VNID) {
  11360         /* could not co-exist */
  11361         return BCM_E_PARAM;
  11362             }
  11363 
  11364     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_valid(unit, vpn));
  11365     _BCM_VXLAN_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
  11366 
  11367 
  11368     vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
  11369     if (vp == -1) {
  11370                    return BCM_E_PARAM;
  11371                 }
  11372     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  11373                      return BCM_E_NOT_FOUND;
  11374                 }
  11375     /* Check for Network-Port */
  11376     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  11377     if (!(vp_info.flags & _BCM_VP_INFO_NETWORK_PORT)) {
  11378         return BCM_E_PARAM;
  11379         }
  11380 
  11381     bcm_vxlan_port_t_init(&vxlan_port_r);
  11382     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_port_get(unit, vpn, vp, &vxlan_port_r));
  11383 
  11384 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  11385     if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
  11386         if (!(vxlan_port_r.flags & BCM_VXLAN_PORT_MULTICAST)) {
  11387             /* match_vlan will be used in MPLS_ENTRY table */
  11388             if (vxlan_port->match_vlan != vxlan_info->match_key[vp].match_vlan) {
  11389                                      return BCM_E_PARAM;
  11390                                 }
  11391                                 }
  11392                                 }
  11393 #endif /* defined(BCM_TRIDENT2PLUS_SUPPORT) */
  11394 
  11395     BCM_IF_ERROR_RETURN (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
  11396     if (vfi == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf)) {
  11397         return BCM_E_PARAM;
  11398     }
  11399 
  11400     /* set egr_vlan_xlate table */
  11401 #if defined(BCM_TRIDENT3_SUPPORT)
  11402     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  11403         soc_mem_field32_set(unit, vxlate_mem, ment_evt, BASE_VALIDf, 1);
  11404         soc_mem_field32_set(unit, vxlate_mem, ment_evt,
  11405                             DATA_TYPEf, _BCM_VXLAN_DATA_TYPE_LOOKUP_VFI);
  11406         soc_mem_field32_set(unit, vxlate_mem, ment_evt,
  11407                         KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI_DVP);
  11408     } else
  11409 #endif
  11410     {
  11411         soc_mem_field32_set(unit, vxlate_mem, ment_evt, ENTRY_TYPEf,
  11412                             _BCM_VXLAN_KEY_TYPE_LOOKUP_VFI_DVP);
  11413         soc_mem_field32_set(unit, vxlate_mem, ment_evt, VALIDf, 0x1);
  11414                                 }
  11415     soc_mem_field32_set(unit, vxlate_mem, ment_evt, BCM_VXLAN_VFI_FIELD(d, DVPf), vp);
  11416     soc_mem_field32_set(unit, vxlate_mem, ment_evt, BCM_VXLAN_VFI_FIELD(d, VFIf), vfi);
  11417     soc_mem_field32_set(unit, vxlate_mem, ment_evt, (d ? VXLAN_VFI_FLEX__VNIDf : VXLAN_VFI__VN_IDf),
  11418                             vxlan_port->vnid);
  11419 
  11420     if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TAGGED) {
  11421         rv = _bcm_td2_vxlan_sd_tag_set(unit, NULL, vxlan_port, NULL, ment_evt, &tpid_index);
  11422         if (BCM_FAILURE(rv)) {
  11423                                       return rv;
  11424                                   }
  11425                              }
  11426 
  11427     rv = _bcm_td2_vxlan_match_egr_vxlate_entry_set(unit, vpn, vxlan_port, ment_evt, original_ment_evt);
  11428     if (BCM_FAILURE(rv)) {
  11429         goto _rollback;
  11430     }
  11431 
  11432     if (vxlan_port_r.flags & BCM_VXLAN_PORT_MULTICAST) {
  11433         vxlan_info->vfi_vnid_map_count[vp]++;
  11434          return BCM_E_NONE;
  11435     }
  11436 
  11437     /* set mpls_entry table */
  11438 #if defined(BCM_TRIDENT3_SUPPORT)
  11439     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  11440         _bcm_td3_vxlan_vxlate_entry_t ent;
  11441         mmem = VLAN_XLATE_1_DOUBLEm;
  11442         sal_memset(&ent, 0, sizeof(_bcm_td3_vxlan_vxlate_entry_t));
  11443         ent.dtype = _BCM_VXLAN_DATA_TYPE_VNID_VFI_FLEX;
  11444         ent.ktype = _BCM_VXLAN_KEY_TYPE_VNID_VFI_SIP_FLEX;
  11445         ent.vfi = vfi;
  11446         ent.vlan = vxlan_info->vxlan_vpn_vlan[vfi];
  11447         _bcm_td3_vxlan_vxlate_entry_assemble(unit, ent, ment_vnid);
  11448     } else
  11449 #endif
  11450     {
  11451         soc_mem_field32_set(unit, mmem, ment_vnid, VALIDf, 1);
  11452         soc_mem_field32_set(unit, mmem, ment_vnid, KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_TUNNEL_VNID_VFI);
  11453         soc_mem_field32_set(unit, mmem, ment_vnid, VXLAN_VN_ID__VFIf, vfi);
  11454     }
  11455     tunnel_idx = vxlan_info->match_key[vp].match_tunnel_index;
  11456     tunnel_sip = vxlan_info->vxlan_tunnel_term[tunnel_idx].sip;
  11457     soc_mem_field32_set(unit, mmem, ment_vnid, BCM_VXLAN_VNID_FIELD(d, SIPf), tunnel_sip);
  11458 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  11459     if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
  11460         soc_mem_field32_set(unit, mmem, ment_vnid, VXLAN_VN_ID__OVIDf,
  11461                                     vxlan_port->match_vlan);
  11462     }
  11463 #endif
  11464     soc_mem_field32_set(unit, mmem, ment_vnid, (d ? VXLAN_FLEX__VNIDf : VXLAN_VN_ID__VN_IDf), vxlan_port->vnid);
  11465 
  11466 #if defined(BCM_TRIDENT3_SUPPORT)
  11467     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  11468         rv = _bcm_td3_vxlan_match_vxlate_entry_set(unit, vpn, vxlan_port, ment_vnid, original_ment_vnid);
  11469     } else
  11470 #endif
  11471     {
  11472         rv = _bcm_td2_vxlan_match_tunnel_entry_set(unit, ment_vnid, original_ment_vnid);
  11473     }
  11474     if (BCM_FAILURE(rv)) {
  11475         goto _rollback;
  11476     }
  11477 
  11478     vxlan_info->vfi_vnid_map_count[vp]++;
  11479 
  11480     return rv;
  11481 
  11482 _rollback:
  11483     if (tpid_index != -1) {
  11484         (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
  11485     }
  11486 
  11487     if (soc_feature(unit, soc_feature_base_valid)) {
  11488         if ((soc_mem_field32_get(unit, vxlate_mem, original_ment_evt, BASE_VALID_0f) == 3) &&
  11489             (soc_mem_field32_get(unit, vxlate_mem, original_ment_evt, BASE_VALID_1f) == 7)) {
  11490              valid = 1;
  11491         } else {
  11492             valid = 0;
  11493         }
  11494     } else {
  11495         valid = soc_mem_field32_get(unit, vxlate_mem, original_ment_evt, VALIDf);
  11496     }
  11497     if (valid) {
  11498         (void) _bcm_td2_vxlan_match_egr_vxlate_entry_set(unit, vpn, vxlan_port,
  11499                                                        original_ment_evt,
  11500                                                        ment_evt);
  11501     } else {
  11502        (void) _bcm_td2_vxlan_match_egr_vxlate_entry_delete(unit, ment_evt);
  11503     }
  11504 
  11505     if (soc_feature(unit, soc_feature_base_valid)) {
  11506         if ((soc_mem_field32_get(unit, vxlate_mem, original_ment_vnid, BASE_VALID_0f) == 3) &&
  11507             (soc_mem_field32_get(unit, vxlate_mem, original_ment_vnid, BASE_VALID_1f) == 7)) {
  11508              valid = 1;
  11509         } else {
  11510             valid = 0;
  11511         }
  11512     } else {
  11513         valid = soc_mem_field32_get(unit, vxlate_mem, original_ment_vnid, VALIDf);
  11514     }
  11515     if (valid) {
  11516 #if defined(BCM_TRIDENT3_SUPPORT)
  11517         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  11518             (void) _bcm_td3_vxlan_match_vxlate_entry_set(unit, vpn, vxlan_port, original_ment_vnid, ment_vnid);
  11519         } else
  11520 #endif
  11521         {
  11522             (void) _bcm_td2_vxlan_match_tunnel_entry_set(unit, original_ment_vnid, ment_vnid);
  11523         }
  11524     } else {
  11525         (void) _bcm_td2_vxlan_match_tunnel_entry_delete(unit, ment_vnid);
  11526     }
  11527 
  11528     return rv;
  11529 }
  11530 
  11531 
  11532 /*
  11533  * Function:
  11534  *      _bcm_td2_vxlan_vp_based_vnid_delete
  11535  * Purpose:
  11536  *      Delete VXLAN VP-based VFI-VNID mapping
  11537  * Parameters:
  11538  *      unit    - (IN) Device Number
  11539  *      vpn     - (IN) VPN instance ID
  11540  *      vxlan_port - (IN) VXLAN port information
  11541  * Returns:
  11542  *      BCM_E_XXX
  11543  */
  11544 
  11545 STATIC int
  11546 _bcm_td2_vxlan_vp_based_vnid_delete(int unit, bcm_vpn_t vpn, bcm_vxlan_port_t *vxlan_port)
  11547 {
  11548     _bcm_td2_vxlan_bookkeeping_t *vxlan_info = VXLAN_INFO(unit);
  11549     int vp, vfi;
  11550     _bcm_vp_info_t vp_info;
  11551     uint32 tunnel_sip;
  11552     int32 tunnel_idx;
  11553     soc_mem_t vxlate_mem;
  11554     soc_mem_t mmem = MPLS_ENTRYm;
  11555     int tpid_index = -1;
  11556     int d = 0; /*vxlan decoupled mode*/
  11557     uint32 ment_vnid[SOC_MAX_MEM_WORDS] = {0};
  11558     uint32 original_ment_vnid[SOC_MAX_MEM_WORDS] = {0};
  11559     uint8 vxlan_vpn_type;
  11560     int rv;
  11561     int action_present, action_not_present;
  11562     uint32 old_vxlate_entry[SOC_MAX_MEM_WORDS] = {0};
  11563     int index;
  11564     uint32 vnid;
  11565 
  11566 
  11567 #if defined(BCM_TRIDENT3_SUPPORT)
  11568     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  11569         vxlate_mem = EGR_VLAN_XLATE_1_SINGLEm;
  11570         d = 1;
  11571     } else
  11572 #endif
  11573     {
  11574         vxlate_mem = EGR_VLAN_XLATEm;
  11575     }
  11576 
  11577     if (vxlan_port == NULL) {
  11578         return BCM_E_PARAM;
  11579     }
  11580 
  11581     BCM_IF_ERROR_RETURN(
  11582         _bcm_td2_vxlan_vpn_is_tunnel_based_vnid(unit, vpn, &vxlan_vpn_type));
  11583     if (vxlan_vpn_type == _BCM_VXLAN_VPN_TYPE_TUNNEL_BASED_VNID) {
  11584         return BCM_E_PARAM;
  11585     }
  11586 
  11587     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_valid(unit, vpn));
  11588     _BCM_VXLAN_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
  11589 
  11590     vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
  11591     if (vp == -1) {
  11592         return BCM_E_PARAM;
  11593     }
  11594     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  11595         return BCM_E_NOT_FOUND;
  11596     }
  11597     /* Check for Network-Port */
  11598     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  11599     if (!(vp_info.flags & _BCM_VP_INFO_NETWORK_PORT)) {
  11600         return BCM_E_PARAM;
  11601     }
  11602 
  11603 
  11604     rv = _bcm_td2_vxlan_egr_xlate_entry_get(unit, vfi, vp, old_vxlate_entry);
  11605     if (BCM_FAILURE(rv)) {
  11606         return rv;
  11607     }
  11608 
  11609 #if defined(BCM_TRIDENT3_SUPPORT)
  11610     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  11611         int profile_idx = -1;
  11612         profile_idx = soc_mem_field32_get(unit, vxlate_mem, old_vxlate_entry,
  11613                                                      VXLAN_VFI_FLEX__TAG_ACTION_PROFILE_PTRf);
  11614         (void)_bcm_td3_sd_tag_action_get(unit, profile_idx, &action_present,
  11615                        &action_not_present);
  11616     } else
  11617 #endif
  11618     {
  11619         /*If tpid exists, delete it*/
  11620         action_present = soc_mem_field32_get(unit, vxlate_mem, old_vxlate_entry,
  11621                                                      VXLAN_VFI__SD_TAG_ACTION_IF_PRESENTf);
  11622         action_not_present = soc_mem_field32_get(unit, vxlate_mem, old_vxlate_entry,
  11623                                                  VXLAN_VFI__SD_TAG_ACTION_IF_NOT_PRESENTf);
  11624     }
  11625 
  11626     if (1 == action_present || 4 == action_present ||
  11627         7 == action_present || 1 == action_not_present) {
  11628         tpid_index = soc_mem_field32_get(unit,
  11629                          vxlate_mem, old_vxlate_entry,
  11630                          d ? VXLAN_VFI_FLEX__OUTER_TPID_INDEXf : VXLAN_VFI__SD_TAG_TPID_INDEXf);
  11631         rv = _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
  11632         if (BCM_FAILURE(rv)) {
  11633             return rv;
  11634         }
  11635     }
  11636 
  11637     vnid = soc_mem_field32_get(unit, vxlate_mem, old_vxlate_entry, (d ? VXLAN_VFI_FLEX__VNIDf : VXLAN_VFI__VN_IDf));
  11638 
  11639     rv = _bcm_td2_vxlan_match_egr_vxlate_entry_delete(unit, old_vxlate_entry);
  11640     if (BCM_FAILURE(rv)) {
  11641         return rv;
  11642     }
  11643 
  11644     if (!(vxlan_port->flags & BCM_VXLAN_PORT_MULTICAST)) {
  11645         /* set mpls_entry table */
  11646 #if defined(BCM_TRIDENT3_SUPPORT)
  11647         if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  11648             _bcm_td3_vxlan_vxlate_entry_t ent;
  11649             mmem = VLAN_XLATE_1_DOUBLEm;
  11650             sal_memset(&ent, 0, sizeof(_bcm_td3_vxlan_vxlate_entry_t));
  11651             ent.dtype = _BCM_VXLAN_DATA_TYPE_VNID_VFI_FLEX;
  11652             ent.ktype = _BCM_VXLAN_KEY_TYPE_VNID_VFI_SIP_FLEX;
  11653             ent.vfi = vfi;
  11654             ent.vlan = vxlan_info->vxlan_vpn_vlan[vfi];
  11655             _bcm_td3_vxlan_vxlate_entry_assemble(unit, ent, ment_vnid);
  11656         } else
  11657 #endif
  11658         {
  11659             soc_mem_field32_set(unit, mmem, ment_vnid, VALIDf, 1);
  11660             soc_mem_field32_set(unit, mmem, ment_vnid, KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_TUNNEL_VNID_VFI);
  11661             soc_mem_field32_set(unit, mmem, ment_vnid, VXLAN_VN_ID__VFIf, vfi);
  11662         }
  11663         tunnel_idx = vxlan_info->match_key[vp].match_tunnel_index;
  11664         tunnel_sip = vxlan_info->vxlan_tunnel_term[tunnel_idx].sip;
  11665         soc_mem_field32_set(unit, mmem, ment_vnid, BCM_VXLAN_VNID_FIELD(d, SIPf), tunnel_sip);
  11666 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  11667         if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
  11668             soc_mem_field32_set(unit, mmem, ment_vnid, VXLAN_VN_ID__OVIDf,
  11669                                     vxlan_info->match_key[vp].match_vlan);
  11670         }
  11671 #endif
  11672         soc_mem_field32_set(unit, mmem, ment_vnid, (d ? VXLAN_FLEX__VNIDf : VXLAN_VN_ID__VN_IDf),
  11673                                 vnid);
  11674 
  11675         rv = soc_mem_search(unit, mmem, MEM_BLOCK_ANY, &index, ment_vnid, original_ment_vnid, 0);
  11676         if (BCM_FAILURE(rv)) {
  11677             return rv;
  11678         }
  11679         sal_memset(ment_vnid, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
  11680         rv = soc_mem_write(unit, mmem, MEM_BLOCK_ALL, index, ment_vnid);
  11681     }
  11682 
  11683     vxlan_info->vfi_vnid_map_count[vp]--;
  11684 
  11685     return rv;
  11686 }
  11687 
  11688 
  11689 /*
  11690  * Function:
  11691  *      _bcm_td2_vxlan_vp_based_vnid_get
  11692  * Purpose:
  11693  *      Get VXLAN VP-based VFI-VNID mapping
  11694  * Parameters:
  11695  *      unit    - (IN) Device Number
  11696  *      vpn     - (IN) VPN instance ID
  11697  *      vxlan_port - (IN/out) VXLAN port information
  11698  * Returns:
  11699  *      BCM_E_XXX
  11700  */
  11701 
  11702 STATIC int
  11703 _bcm_td2_vxlan_vp_based_vnid_get(int unit, bcm_vpn_t vpn, bcm_vxlan_port_t *vxlan_port)
  11704 {
  11705     int vp, vfi;
  11706     _bcm_vp_info_t vp_info;
  11707     soc_mem_t vxlate_mem;
  11708     int d = 0; /*vxlan decoupled mode*/
  11709     uint8 vxlan_vpn_type;
  11710     int rv = BCM_E_NONE;
  11711     uint32 vxlate_entry[SOC_MAX_MEM_WORDS] = {0};
  11712 
  11713     if (vxlan_port == NULL) {
  11714         return BCM_E_PARAM;
  11715     }
  11716 
  11717 #if defined(BCM_TRIDENT3_SUPPORT)
  11718     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  11719         vxlate_mem = EGR_VLAN_XLATE_1_SINGLEm;
  11720         d = 1;
  11721     } else
  11722 #endif
  11723     {
  11724         vxlate_mem = EGR_VLAN_XLATEm;
  11725     }
  11726 
  11727     BCM_IF_ERROR_RETURN(
  11728         _bcm_td2_vxlan_vpn_is_tunnel_based_vnid(unit, vpn, &vxlan_vpn_type));
  11729     if (vxlan_vpn_type == _BCM_VXLAN_VPN_TYPE_TUNNEL_BASED_VNID) {
  11730         /* should not use this API */
  11731         return BCM_E_PARAM;
  11732     }
  11733 
  11734     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_valid(unit, vpn));
  11735     _BCM_VXLAN_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
  11736 
  11737     vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
  11738     if (vp == -1) {
  11739         return BCM_E_PARAM;
  11740     }
  11741     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  11742         return BCM_E_NOT_FOUND;
  11743     }
  11744     /* Check for Network-Port */
  11745     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  11746     if (!(vp_info.flags & _BCM_VP_INFO_NETWORK_PORT)) {
  11747         return BCM_E_BADID;
  11748     }
  11749 
  11750     rv = _bcm_td2_vxlan_egr_xlate_entry_get(unit, vfi, vp, vxlate_entry);
  11751     if (BCM_FAILURE(rv)) {
  11752         return rv;
  11753     }
  11754 
  11755     /* Get SDTAG settings */
  11756     (void)_bcm_td2_vxlan_sd_tag_get(unit, NULL, vxlan_port, NULL, vxlate_entry, 1);
  11757     vxlan_port->vnid = soc_mem_field32_get(unit, vxlate_mem, vxlate_entry,
  11758                            (d ? VXLAN_VFI_FLEX__VNIDf : VXLAN_VFI__VN_IDf));
  11759 
  11760     vxlan_port->flags |= BCM_VXLAN_PORT_VPN_BASED;
  11761 
  11762     return rv;
  11763 }
  11764 
  11765 
  11766 /*
  11767  * Function:
  11768  *      _bcm_td2_vxlan_vp_based_vnid_count
  11769  * Purpose:
  11770  *      Get number of VXLAN VP-based VFI-VNID mapping rules
  11771  * Parameters:
  11772  *      unit    - (IN) Device Number
  11773  *      vp      - (IN) VXLAN port ID
  11774  *      count   - (out) number of VFI-VNID mapping rules
  11775  * Returns:
  11776  *      BCM_E_XXX
  11777  */
  11778 
  11779 STATIC int
  11780 _bcm_td2_vxlan_vp_based_vnid_count(int unit, int vp, uint32 *count)
  11781 {
  11782     _bcm_td2_vxlan_bookkeeping_t *vxlan_info = VXLAN_INFO(unit);
  11783 
  11784     if (count == NULL) {
  11785         return BCM_E_PARAM;
  11786     }
  11787 
  11788     if (vp == -1) {
  11789         return BCM_E_PARAM;
  11790     }
  11791     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  11792         return BCM_E_NOT_FOUND;
  11793     }
  11794 
  11795     *count = vxlan_info->vfi_vnid_map_count[vp];
  11796 
  11797     return BCM_E_NONE;
  11798 }
  11799 
  11800 
  11801 /*
  11802  * Function:
  11803  *      _bcm_td2_vxlan_vp_based_vnid_delete_all
  11804  * Purpose:
  11805  *      Delete all VXLAN VP-based VFI-VNID mappings
  11806  * Parameters:
  11807  *      unit    - (IN) Device Number
  11808  * Returns:
  11809  *      BCM_E_XXX
  11810  */
  11811 
  11812 STATIC int
  11813 _bcm_td2_vxlan_vp_based_vnid_delete_all(int unit)
  11814 {
  11815     int rv = BCM_E_NONE;
  11816     uint32 num_vp;
  11817     uint32 vp;
  11818     uint32 count;
  11819     uint32 vfi, num_vfi;
  11820     bcm_vpn_t vpn;
  11821     bcm_vxlan_port_t vxlan_port;
  11822 
  11823     num_vp  = soc_mem_index_count(unit, SOURCE_VPm);
  11824     num_vfi = soc_mem_index_count(unit, VFIm);
  11825 
  11826     SHR_BIT_ITER(VIRTUAL_INFO(unit)->vxlan_vp_bitmap, num_vp, vp) {
  11827         BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vp_based_vnid_count(unit, vp, &count));
  11828         for (vfi = 0; (vfi < num_vfi) && count; vfi++) {
  11829             if (_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeVxlan)) {
  11830                 _BCM_VXLAN_VPN_SET(vpn, _BCM_VPN_TYPE_VFI, vfi);
  11831                 bcm_vxlan_port_t_init(&vxlan_port);
  11832                 BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port.vxlan_port_id, vp);
  11833                 rv = _bcm_td2_vxlan_vp_based_vnid_get(unit, vpn, &vxlan_port);
  11834                 if (BCM_SUCCESS(rv)) {
  11835                     bcm_vxlan_port_t_init(&vxlan_port);
  11836                     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_port_get(unit, vpn, vp, &vxlan_port));
  11837                     rv = _bcm_td2_vxlan_vp_based_vnid_delete(unit, vpn, &vxlan_port);
  11838                     if (BCM_SUCCESS(rv)) {
  11839                         count--;
  11840                     } else {
  11841                         return rv;
  11842                     }
  11843                 }
  11844             }
  11845         }
  11846 
  11847     }
  11848 
  11849     return rv;
  11850 }
  11851 
  11852 
  11853 /*
  11854  * Function:
  11855  *      _bcm_td2_vxlan_vplag_vp_update
  11856  * Purpose:
  11857  *      Update vplag vp according to VXLAN port
  11858  * Parameters:
  11859  *      unit   - (IN) Device Number
  11860  *      gport  - (IN) VXLAN port
  11861  * Returns:
  11862  *      BCM_E_XXX
  11863  */
  11864 STATIC int
  11865 _bcm_td2_vxlan_vplag_vp_update(int unit, bcm_gport_t gport)
  11866 {
  11867     int rv = 0;
  11868     int vp = 0;
  11869     int vplag_vp = 0;
  11870     uint32 vfi = 0;
  11871     uint32 network_port = 0;
  11872     uint32 network_group = 0;
  11873     uint32 tpid_enable = 0;
  11874     uint32 sd_tag_mode = 0;
  11875     source_vp_entry_t svp_entry;
  11876     source_vp_entry_t svp_entry1;
  11877 
  11878     rv = bcm_td2_vxlan_port_source_vp_lag_get(unit, gport, &vplag_vp);
  11879     if (BCM_SUCCESS(rv)) {
  11880         vp = BCM_GPORT_VXLAN_PORT_ID_GET(gport);
  11881         BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp_entry));
  11882         BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vplag_vp, &svp_entry1));
  11883 
  11884         vfi = soc_SOURCE_VPm_field32_get(unit, &svp_entry, VFIf);
  11885         sd_tag_mode = soc_SOURCE_VPm_field32_get(unit, &svp_entry, SD_TAG_MODEf);
  11886         soc_SOURCE_VPm_field32_set(unit, &svp_entry1, VFIf, vfi);
  11887         soc_SOURCE_VPm_field32_set(unit, &svp_entry1, SD_TAG_MODEf, sd_tag_mode);
  11888 
  11889         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
  11890             network_group = soc_SOURCE_VPm_field32_get(unit, &svp_entry, NETWORK_GROUPf);
  11891             soc_SOURCE_VPm_field32_set(unit, &svp_entry1, NETWORK_GROUPf, network_group);
  11892         } else {
  11893             network_port = soc_SOURCE_VPm_field32_get(unit, &svp_entry, NETWORK_PORTf);
  11894             soc_SOURCE_VPm_field32_set(unit, &svp_entry1, NETWORK_PORTf, network_port);
  11895         }
  11896 #if defined(BCM_TRIDENT3_SUPPORT)
  11897         if (SOC_IS_TRIDENT3X(unit)) {
  11898             uint32 svp1[SOC_MAX_MEM_WORDS];
  11899             uint32 svp2[SOC_MAX_MEM_WORDS];
  11900             BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, svp1));
  11901             BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vplag_vp, svp2));
  11902             soc_SVP_ATTRS_1m_field_get(unit, &svp1, TPID_ENABLEf, &tpid_enable);
  11903             soc_SVP_ATTRS_1m_field_set(unit, &svp2, TPID_ENABLEf, &tpid_enable);
  11904             BCM_IF_ERROR_RETURN(WRITE_SVP_ATTRS_1m(unit, MEM_BLOCK_ALL, vplag_vp, &svp2));
  11905         } else
  11906 #endif
  11907         {
  11908             tpid_enable = soc_SOURCE_VPm_field32_get(unit, &svp_entry, TPID_ENABLEf);
  11909             soc_SOURCE_VPm_field32_set(unit, &svp_entry1, TPID_ENABLEf, tpid_enable);
  11910         }
  11911         BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vplag_vp, &svp_entry1));
  11912     }
  11913 
  11914     return BCM_E_NONE;
  11915 }
  11916 
  11917 
  11918 /*
  11919  * Function:
  11920  *      _bcm_td2_vxlan_eline_port_add
  11921  * Purpose:
  11922  *      Add VXLAN ELINE port to a VPN
  11923  * Parameters:
  11924  *      unit    - (IN) Device Number
  11925  *      vpn     - (IN) VPN instance ID
  11926  *      vxlan_port - (IN/OUT) VXLAN port information (OUT : vxlan_port_id)
  11927  * Returns:
  11928  *      BCM_E_XXX
  11929  */
  11930 
  11931 STATIC int
  11932 _bcm_td2_vxlan_eline_port_add(int unit, bcm_vpn_t vpn, bcm_vxlan_port_t  *vxlan_port)
  11933 {
  11934     int active_vp = 0; /* default VP */
  11935     source_vp_entry_t svp1, svp2;
  11936     uint8 vp_valid_flag = 0;
  11937     uint32 tpid_enable = 0;
  11938     int tpid_index = -1;
  11939     int customer_drop=0;
  11940     int  rv = BCM_E_PARAM;
  11941     int num_vp=0;
  11942     int vp1=-1, vp2=-1, vfi_index= -1;
  11943     _bcm_vp_info_t vp_info;
  11944 
  11945     _bcm_vp_info_init(&vp_info);
  11946     vp_info.vp_type = _bcmVpTypeVxlan;
  11947 
  11948         if ( vpn != BCM_VXLAN_VPN_INVALID) {
  11949             _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VXLAN_VPN_TYPE_ELINE,  vpn);
  11950              if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVxlan)) {
  11951                 return BCM_E_NOT_FOUND;
  11952              }
  11953         } else {
  11954              vfi_index = _BCM_VXLAN_VFI_INVALID;
  11955         }
  11956 
  11957         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  11958         if ( vpn != BCM_VXLAN_VPN_INVALID) {
  11959 
  11960              /* ---- Read in current table values for VP1 and VP2 ----- */
  11961              (void) _bcm_td2_vxlan_eline_vp_map_get (unit, vfi_index,  &vp1,  &vp2);
  11962 
  11963             if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeVxlan)) {
  11964                 BCM_IF_ERROR_RETURN (
  11965                    READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp1, &svp1));
  11966                 if (soc_SOURCE_VPm_field32_get(unit, &svp1, ENTRY_TYPEf) == 0x1) {
  11967                     vp_valid_flag |= 0x1;  /* -- VP1 Valid ----- */
  11968                 }
  11969             }
  11970 
  11971             if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeVxlan)) {
  11972                 BCM_IF_ERROR_RETURN (
  11973                    READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp2, &svp2));
  11974                 if (soc_SOURCE_VPm_field32_get(unit, &svp2, ENTRY_TYPEf) == 0x1) {
  11975                     vp_valid_flag |= 0x2;        /* -- VP2 Valid ----- */
  11976                 }
  11977             }
  11978 
  11979             if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
  11980                 active_vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
  11981                 if (active_vp == -1) {
  11982                    return BCM_E_PARAM;
  11983                 }
  11984                 if (!_bcm_vp_used_get(unit, active_vp, _bcmVpTypeVxlan)) {
  11985                      return BCM_E_NOT_FOUND;
  11986                 }
  11987                 /* Decrement old-port's nexthop count */
  11988                 rv = _bcm_td2_vxlan_port_nh_cnt_dec(unit, active_vp);
  11989                 if (rv < 0) {
  11990                     return rv;
  11991                 }
  11992                 /* Decrement old-port's VP count */
  11993                 rv = _bcm_td2_vxlan_port_cnt_update(unit, vxlan_port->vxlan_port_id,
  11994                                                      active_vp, FALSE);
  11995                 if (rv < 0) {
  11996                     return rv;
  11997                 }
  11998             }
  11999         }
  12000 
  12001         switch (vp_valid_flag) {
  12002 
  12003               case 0x0: /* No VP is valid */
  12004                              if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
  12005                                   return BCM_E_NOT_FOUND;
  12006                              }
  12007 
  12008                              if (vxlan_port->flags & BCM_VXLAN_PORT_WITH_ID) {
  12009                                 vp1 = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
  12010                                 if (vp1 == -1) {
  12011                                      return BCM_E_PARAM;
  12012                                 }
  12013 
  12014                                 if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeVxlan)) {
  12015                                      return BCM_E_EXISTS;
  12016                                 }
  12017                                 if (vp1 >= num_vp) {
  12018                                      return (BCM_E_BADID);
  12019                                 }
  12020                                 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
  12021                                 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp1, vp_info));
  12022                              } else {
  12023 
  12024                                 /* No entries are used, allocate a new VP index for VP1 */
  12025 
  12026                                 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
  12027                                 rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp1);
  12028                                 if (rv < 0) {
  12029                                   return rv;
  12030                                 }
  12031                                 /* Allocate a new VP index for VP2 */
  12032                                 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  12033                                  rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp2);
  12034                                   if (rv < 0) {
  12035                                      (void) _bcm_vp_free(unit, _bcmVpTypeVxlan, 1, vp1);
  12036                                       return rv;
  12037                                   }
  12038                              }
  12039 
  12040                              active_vp = vp1;
  12041                              vp_valid_flag = 1;
  12042                              sal_memset(&svp1, 0, sizeof(source_vp_entry_t));
  12043                              sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
  12044                              (void) _bcm_td2_vxlan_eline_vp_map_set(unit, vfi_index, vp1, vp2);
  12045                              break;
  12046 
  12047 
  12048          case 0x1:    /* Only VP1 is valid */   
  12049                              if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
  12050                                   if (active_vp != vp1) {
  12051                                        return BCM_E_NOT_FOUND;
  12052                                   }
  12053                              } else if (vxlan_port->flags & BCM_VXLAN_PORT_WITH_ID) {
  12054                                 vp2 = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
  12055                                 if (vp2 == -1) {
  12056                                      return BCM_E_PARAM;
  12057                                 }
  12058 
  12059                                 if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeVxlan)) {
  12060                                      return BCM_E_EXISTS;
  12061                                 }
  12062                                 if (vp2 >= num_vp) {
  12063                                      return (BCM_E_BADID);
  12064                                 }
  12065                                 vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  12066                                 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp2, vp_info));
  12067 
  12068                                 active_vp = vp2;
  12069                                 vp_valid_flag = 3;
  12070                                 sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
  12071                              } else {
  12072                                   active_vp = vp2;
  12073                                   vp_valid_flag = 3;
  12074                                   sal_memset(&svp2, 0, sizeof(source_vp_entry_t));
  12075                              }
  12076 
  12077                              (void) _bcm_td2_vxlan_eline_vp_map_set(unit, vfi_index, vp1, vp2);
  12078                              break;
  12079 
  12080 
  12081 
  12082          case 0x2: /* Only VP2 is valid */
  12083                              if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
  12084                                   if (active_vp != vp2) {
  12085                                        return BCM_E_NOT_FOUND;
  12086                                   }
  12087                              } else if (vxlan_port->flags & BCM_VXLAN_PORT_WITH_ID) {
  12088                                 vp1 = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
  12089                                 if (vp1 == -1) {
  12090                                      return BCM_E_PARAM;
  12091                                 }
  12092 
  12093                                 if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeVxlan)) {
  12094                                      return BCM_E_EXISTS;
  12095                                 }
  12096                                 if (vp1 >= num_vp) {
  12097                                      return (BCM_E_BADID);
  12098                                 }
  12099                                 vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
  12100                                 BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp1, vp_info));
  12101 
  12102                              } else {
  12103                                   active_vp = vp1;
  12104                                   vp_valid_flag = 3;
  12105                                    sal_memset(&svp1, 0, sizeof(source_vp_entry_t));
  12106                              }
  12107 
  12108                              (void) _bcm_td2_vxlan_eline_vp_map_set(unit, vfi_index, vp1, vp2);
  12109                              break;
  12110 
  12111 
  12112               
  12113          case 0x3: /* VP1 and VP2 are valid */
  12114                               if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
  12115                                    return BCM_E_FULL;
  12116                               }
  12117                              break;
  12118        }
  12119 
  12120        if (active_vp == -1) {
  12121            return BCM_E_CONFIG;
  12122        }
  12123 
  12124         /* Set VXLAN port ID */
  12125         if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
  12126             BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port->vxlan_port_id, active_vp);
  12127         }
  12128        /* ======== Configure Next-Hop Properties ========== */
  12129        customer_drop = (vxlan_port->flags & BCM_VXLAN_PORT_DROP) ? 1 : 0;
  12130        rv = _bcm_td2_vxlan_port_nh_add(unit, vxlan_port, active_vp, vpn, customer_drop);
  12131        if (rv < 0) {
  12132             if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
  12133                 (void) _bcm_vp_free(unit, _bcmVfiTypeVxlan, 1, active_vp);
  12134             }
  12135             return rv;
  12136        }
  12137 
  12138        /* ======== Configure Service-Tag Properties =========== */
  12139        if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TAGGED) {
  12140 #if defined(BCM_TRIDENT3_SUPPORT)
  12141             if (SOC_IS_TRIDENT3X(unit)) {
  12142                 rv = _bcm_fb2_outer_tpid_entry_add(unit,
  12143                     vxlan_port->egress_service_tpid, &tpid_index);
  12144             } else
  12145 #endif
  12146             {
  12147                 rv = _bcm_fb2_outer_tpid_lkup(unit, vxlan_port->egress_service_tpid,
  12148                                            &tpid_index);
  12149             }
  12150             if (rv < 0) {
  12151                 goto vxlan_cleanup;
  12152             }
  12153             tpid_enable = (1 << tpid_index);
  12154        }
  12155 
  12156        /* ======== Configure SVP Property ========== */
  12157        if (active_vp == vp1) {
  12158            rv  = _bcm_td2_vxlan_eline_vp_configure (unit, vfi_index, active_vp, &svp1, 
  12159                                                     tpid_enable, vxlan_port);
  12160        } else if (active_vp == vp2) {
  12161            rv  = _bcm_td2_vxlan_eline_vp_configure (unit, vfi_index, active_vp, &svp2, 
  12162                                                     tpid_enable, vxlan_port);
  12163        }
  12164        if (rv < 0) {
  12165             goto vxlan_cleanup;
  12166        }
  12167 
  12168         rv = _bcm_td2_vxlan_match_add(unit, vxlan_port, active_vp, vpn);
  12169         if (rv < 0) {
  12170             goto vxlan_cleanup;
  12171         }
  12172 
  12173         /* Increment new-port's VP count */
  12174         rv = _bcm_td2_vxlan_port_cnt_update(unit, vxlan_port->vxlan_port_id, active_vp, TRUE);
  12175         if (rv < 0) {
  12176             goto vxlan_cleanup;
  12177         }
  12178 
  12179         /* Set VXLAN port ID */
  12180         if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
  12181             BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port->vxlan_port_id, active_vp);
  12182         }
  12183 
  12184 vxlan_cleanup:
  12185         if (rv < 0) {
  12186             if (tpid_enable) {
  12187                 (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
  12188             }
  12189             /* Free the VP's */
  12190             if (vp_valid_flag) {
  12191                 if (vp1 != -1) {
  12192                     (void) _bcm_vp_free(unit, _bcmVpTypeVxlan, 1, vp1);
  12193                 }
  12194                 if (vp2 != -1) {
  12195                     (void) _bcm_vp_free(unit, _bcmVpTypeVxlan, 1, vp2);
  12196                 }
  12197             }
  12198         }
  12199         return rv;
  12200 }
  12201 
  12202 /*
  12203  * Function:
  12204  *     _bcm_td2_vxlan_elan_port_add
  12205  * Purpose:
  12206  *      Add VXLAN ELAN port to a VPN
  12207  * Parameters:
  12208  *   unit - (IN) Device Number
  12209  *   vpn - (IN) VPN instance ID
  12210  *   vxlan_port - (IN/OUT) vxlan port information (OUT : vxlan_port_id)
  12211  * Returns:
  12212  *     BCM_E_XXX
  12213  */
  12214 
  12215 STATIC int
  12216 _bcm_td2_vxlan_elan_port_add(int unit, bcm_vpn_t vpn, bcm_vxlan_port_t *vxlan_port)
  12217 {
  12218     int vp, num_vp, vfi=0;
  12219     source_vp_entry_t svp;
  12220     source_vp_2_entry_t svp2;
  12221     uint32 tpid_enable = 0;
  12222     int tpid_index=-1;
  12223     int drop=0, rv = BCM_E_PARAM;
  12224     int cml_default_enable=0, cml_default_new=0, cml_default_move=0;
  12225     _bcm_vp_info_t vp_info;
  12226     int network_group=0;
  12227     uint8 vpn_type = 0;
  12228 #if defined(BCM_TRIDENT3_SUPPORT)
  12229     uint32 svp1[SOC_MAX_MEM_WORDS];
  12230 #endif
  12231 
  12232     if (vpn != BCM_VXLAN_VPN_INVALID) {
  12233         _BCM_VXLAN_VPN_GET(vfi, _BCM_VXLAN_VPN_TYPE_ELAN,  vpn);
  12234         if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeVxlan)) {
  12235             return BCM_E_NOT_FOUND;
  12236         }
  12237     } else {
  12238         vfi = _BCM_VXLAN_VFI_INVALID;
  12239     }
  12240 
  12241     /*Valid vnid is provided only for tunnel based VPN*/
  12242     BCM_IF_ERROR_RETURN(
  12243             _bcm_td2_vxlan_vpn_is_tunnel_based_vnid(unit, vpn, &vpn_type));
  12244     if ((vpn_type != _BCM_VXLAN_VPN_TYPE_TUNNEL_BASED_VNID) &&
  12245         vxlan_port->vnid <= 0xffffff) {
  12246         return BCM_E_PARAM;
  12247     }
  12248 
  12249     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  12250 
  12251     _bcm_vp_info_init(&vp_info);
  12252     vp_info.vp_type = _bcmVpTypeVxlan;
  12253     if (vxlan_port->flags & BCM_VXLAN_PORT_NETWORK) {
  12254         vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  12255     }
  12256     if ((vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_SHARE) ||
  12257         (vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) {
  12258         vp_info.flags |= _BCM_VP_INFO_SHARED_PORT;
  12259     }
  12260 
  12261    /* ======== Allocate/Get Virtual_Port =============== */
  12262     if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
  12263         if (BCM_GPORT_IS_NIV_PORT(vxlan_port->vxlan_port_id) ||
  12264             BCM_GPORT_IS_EXTENDER_PORT(vxlan_port->vxlan_port_id)) {
  12265             if (BCM_GPORT_IS_NIV_PORT(vxlan_port->vxlan_port_id)) {
  12266                vp = BCM_GPORT_NIV_PORT_ID_GET((vxlan_port->vxlan_port_id));
  12267             } else if (BCM_GPORT_IS_EXTENDER_PORT(vxlan_port->vxlan_port_id)) {
  12268                vp = BCM_GPORT_EXTENDER_PORT_ID_GET((vxlan_port->vxlan_port_id));
  12269             }
  12270             rv = _bcm_td2_vxlan_access_niv_pe_set (unit, vp, vfi);
  12271             if (BCM_SUCCESS(rv)) {
  12272                /* Set VXLAN port ID */
  12273                BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port->vxlan_port_id, vp);
  12274                rv = _bcm_vp_used_set(unit, vp, vp_info);
  12275             }
  12276             return rv;
  12277         } else if (BCM_GPORT_IS_TRUNK(vxlan_port->vxlan_port_id)) {
  12278             bcm_trunk_member_t trunk_member;
  12279             int                port_count = 0;
  12280             bcm_trunk_t        tid = 0;
  12281             int                tid_is_vp_lag = FALSE;
  12282             tid = BCM_GPORT_TRUNK_GET(vxlan_port->vxlan_port_id);
  12283             BCM_IF_ERROR_RETURN(
  12284                 _bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag));
  12285             if (tid_is_vp_lag) {
  12286                 BCM_IF_ERROR_RETURN(
  12287                     bcm_td2_vp_lag_get(unit, tid, NULL, 1,
  12288                                        &trunk_member, &port_count));
  12289                 if (BCM_GPORT_IS_NIV_PORT(trunk_member.gport) ||
  12290                     BCM_GPORT_IS_EXTENDER_PORT(trunk_member.gport)) {
  12291                     BCM_IF_ERROR_RETURN(
  12292                         _bcm_esw_trunk_tid_to_vp_lag_vp(unit, tid, &vp));
  12293                     rv = _bcm_td2_vxlan_access_niv_pe_set(unit, vp, vfi);
  12294                     if (BCM_SUCCESS(rv)) {
  12295                        rv = _bcm_vp_used_set(unit, vp, vp_info);
  12296                     }
  12297                     return rv;
  12298                 }
  12299             }
  12300         }
  12301 
  12302         vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
  12303         if (vp == -1) {
  12304             return BCM_E_PARAM;
  12305         }
  12306 
  12307         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  12308             return BCM_E_NOT_FOUND;
  12309         }
  12310 
  12311         BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
  12312 #if defined(BCM_TRIDENT3_SUPPORT)
  12313         if (SOC_IS_TRIDENT3X(unit)) {
  12314             BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, &svp1));
  12315         }
  12316 #endif
  12317         BCM_IF_ERROR_RETURN(READ_SOURCE_VP_2m(unit, MEM_BLOCK_ANY, vp, &svp2));
  12318         /* Decrement old-port's nexthop count */
  12319         BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_port_nh_cnt_dec(unit, vp));
  12320         /* Decrement old-port's VP count */
  12321         BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_port_cnt_update(
  12322                 unit, vxlan_port->vxlan_port_id, vp, FALSE));
  12323     } else if (vxlan_port->flags & BCM_VXLAN_PORT_WITH_ID ) {
  12324        if (!BCM_GPORT_IS_VXLAN_PORT(vxlan_port->vxlan_port_id)) {
  12325             return (BCM_E_BADID);
  12326         }
  12327 
  12328         vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
  12329         if (vp == -1) {
  12330             return BCM_E_PARAM;
  12331         }
  12332         /* Vp index zero is reserved in function _bcm_virtual_init because of 
  12333          * HW restriction. 
  12334          */
  12335         if (vp >= num_vp || vp < 1) {
  12336             return BCM_E_BADID;
  12337         }
  12338         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeAny)) {
  12339             return BCM_E_EXISTS;
  12340         }
  12341         BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info));
  12342 
  12343         sal_memset(&svp, 0, sizeof(source_vp_entry_t));
  12344 #if defined(BCM_TRIDENT3_SUPPORT)
  12345         sal_memset(svp1, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  12346 #endif
  12347         sal_memset(&svp2, 0, sizeof(source_vp_2_entry_t));
  12348     } else {
  12349         /* allocate a new VP index */
  12350         BCM_IF_ERROR_RETURN(_bcm_vp_alloc
  12351             (unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp));
  12352         BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port->vxlan_port_id, vp);
  12353 
  12354         sal_memset(&svp, 0, sizeof(source_vp_entry_t));
  12355 #if defined(BCM_TRIDENT3_SUPPORT)
  12356         sal_memset(svp1, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  12357 #endif
  12358         sal_memset(&svp2, 0, sizeof(source_vp_2_entry_t));
  12359     }
  12360 
  12361     /* ======== Configure Next-Hop Properties ========== */
  12362     drop = (vxlan_port->flags & BCM_VXLAN_PORT_DROP) ? 1 : 0;
  12363     rv = _bcm_td2_vxlan_port_nh_add(unit, vxlan_port, vp, vpn, drop);
  12364     _BCM_VXLAN_CLEANUP(rv)
  12365 
  12366     /* ======== Configure Service-Tag Properties =========== */
  12367     if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TAGGED) {
  12368 #if defined(BCM_TRIDENT3_SUPPORT)
  12369         if (SOC_IS_TRIDENT3X(unit)) {
  12370             rv = _bcm_fb2_outer_tpid_entry_add(unit,
  12371                 vxlan_port->egress_service_tpid, &tpid_index);
  12372             _BCM_VXLAN_CLEANUP(rv)
  12373         } else
  12374 #endif
  12375         {
  12376             rv = _bcm_fb2_outer_tpid_lkup(unit,
  12377                 vxlan_port->egress_service_tpid, &tpid_index);
  12378             _BCM_VXLAN_CLEANUP(rv)
  12379         }
  12380 
  12381         tpid_enable = (1 << tpid_index);
  12382         soc_SOURCE_VPm_field32_set(unit, &svp, SD_TAG_MODEf, 1);
  12383 #if defined(BCM_TRIDENT3_SUPPORT)
  12384         if (SOC_IS_TRIDENT3X(unit)) {
  12385             soc_SVP_ATTRS_1m_field_set(unit, &svp1, TPID_ENABLEf, &tpid_enable);
  12386         } else
  12387 #endif
  12388         {
  12389             soc_SOURCE_VPm_field32_set(unit, &svp, TPID_ENABLEf, tpid_enable);
  12390         }
  12391     } else {
  12392         soc_SOURCE_VPm_field32_set(unit, &svp, SD_TAG_MODEf, 0);
  12393     }
  12394 
  12395     /* ======== Configure SVP/DVP Properties ========== */
  12396     soc_SOURCE_VPm_field32_set(unit, &svp, CLASS_IDf, vxlan_port->if_class);
  12397     soc_SOURCE_VPm_field32_set(unit, &svp, ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_VFI);
  12398 
  12399     /* Default Split Horizon Group Id
  12400      * 0 - For Access Port;1 - For Network Port*/
  12401     network_group = vxlan_port->network_group_id;
  12402     rv = _bcm_validate_splithorizon_network_group(unit,
  12403             vxlan_port->flags & BCM_VXLAN_PORT_NETWORK, &network_group);
  12404     BCM_IF_ERROR_RETURN(rv);
  12405     if (vxlan_port->flags & BCM_VXLAN_PORT_NETWORK) {
  12406         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {  
  12407             soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf,
  12408                         network_group);
  12409         } else {
  12410             soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 1);
  12411         }
  12412 #if defined(BCM_TRIDENT3_SUPPORT)
  12413         if (SOC_IS_TRIDENT3X(unit)) {
  12414         } else
  12415 #endif
  12416         {
  12417             soc_SOURCE_VPm_field32_set(unit, &svp, TPID_SOURCEf, _BCM_VXLAN_TPID_SVP_BASED);
  12418         }
  12419     } else {
  12420         if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
  12421          soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf,
  12422                  network_group);
  12423         } else {
  12424             soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 0);
  12425         }
  12426 #if defined(BCM_TRIDENT3_SUPPORT)
  12427         if (SOC_IS_TRIDENT3X(unit)) {
  12428         } else
  12429 #endif
  12430         {
  12431             soc_SOURCE_VPm_field32_set(unit, &svp, TPID_SOURCEf, _BCM_VXLAN_TPID_SGLP_BASED);
  12432             /*  Configure IPARS Parser to signal to IMPLS Parser - Applicable only for HG2 PPD2 packets
  12433                  to reconstruct TPID state based on HG header information - Only for VXLAN Access ports */
  12434             soc_SOURCE_VP_2m_field32_set(unit, &svp2, PARSE_USING_SGLP_TPIDf, 1);
  12435         }
  12436     }
  12437     soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, vfi);
  12438 
  12439     /* Keep CML in the replace operation. It may be set by bcm_td2_vxlan_port_learn_set before */
  12440     if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
  12441         rv = _bcm_vp_default_cml_mode_get (unit, &cml_default_enable,
  12442                                     &cml_default_new, &cml_default_move);
  12443         _BCM_VXLAN_CLEANUP(rv)
  12444 
  12445         if (cml_default_enable) {
  12446             /* Set the CML to default values */
  12447             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml_default_new);
  12448             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml_default_move);
  12449         } else {
  12450             /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */
  12451             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, 0x8);
  12452             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, 0x8);
  12453         }
  12454     }
  12455     if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) {
  12456         if (!soc_feature(unit, soc_feature_vlan_vfi_membership)) {
  12457             soc_SOURCE_VPm_field32_set(unit, &svp, DISABLE_VLAN_CHECKSf, 1);
  12458         }
  12459     }
  12460 
  12461     _BCM_VXLAN_CLEANUP(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp));
  12462 #if defined(BCM_TRIDENT3_SUPPORT)
  12463     if (SOC_IS_TRIDENT3X(unit)) {
  12464         _BCM_VXLAN_CLEANUP(WRITE_SVP_ATTRS_1m(unit, MEM_BLOCK_ALL, vp, &svp1));
  12465     }
  12466 #endif
  12467     _BCM_VXLAN_CLEANUP(WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, vp, &svp2));
  12468 
  12469 #if defined(BCM_TRIDENT3_SUPPORT)
  12470     if (SOC_IS_TRIDENT3X(unit)) {
  12471         if (vxlan_port->flags & BCM_VXLAN_PORT_NETWORK) {
  12472             if ( BCM_E_NONE != soc_cancun_app_dest_entry_set (unit, SOURCE_VPm,
  12473                 vp, ENTRY_TYPEf, CANCUN_APP__SOURCE_VP__No_Control_Word,
  12474                 _BCM_VXLAN_SOURCE_VP_TYPE_VFI)) {
  12475                 LOG_ERROR(BSL_LS_BCM_VXLAN,
  12476                    (BSL_META_U(unit,"SOURCE_VP cancun app cfg error\n")));
  12477             }
  12478         }
  12479     }
  12480 #endif
  12481 
  12482     /* Configure VP match criteria */
  12483     rv = _bcm_td2_vxlan_match_add(unit, vxlan_port, vp, vpn);
  12484     _BCM_VXLAN_CLEANUP(rv)
  12485 
  12486     /* Increment new-port's VP count */
  12487     rv = _bcm_td2_vxlan_port_cnt_update(unit, vxlan_port->vxlan_port_id, vp, TRUE);
  12488     _BCM_VXLAN_CLEANUP(rv)
  12489 
  12490     if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
  12491         rv = _bcm_td2_vxlan_vplag_vp_update(unit, vxlan_port->vxlan_port_id);
  12492         _BCM_VXLAN_CLEANUP(rv)
  12493     }
  12494 
  12495     return BCM_E_NONE;
  12496 
  12497 cleanup:
  12498     if (tpid_enable) {
  12499         (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
  12500     }
  12501     if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
  12502         (void) _bcm_vp_free(unit, _bcmVpTypeVxlan, 1, vp);
  12503         _bcm_td2_vxlan_port_nh_delete(unit, vpn, vp);
  12504     }
  12505     return rv;
  12506 }
  12507 
  12508 /*
  12509  * Function:
  12510  *      _bcm_td2_vxlan_eline_port_delete
  12511  * Purpose:
  12512  *      Delete VXLAN ELINE port from a VPN
  12513  * Parameters:
  12514  *      unit       - (IN) Device Number
  12515  *      vpn        - (IN) VPN instance ID
  12516  *      vxlan_port_id - (IN) vxlan port information
  12517  * Returns:
  12518  *      BCM_E_XXX
  12519  */
  12520 
  12521 int
  12522 _bcm_td2_vxlan_eline_port_delete(int unit, bcm_vpn_t vpn, int active_vp)
  12523 {
  12524     source_vp_entry_t svp;
  12525     source_vp_2_entry_t svp_2_entry;
  12526     int network_port_flag=0;
  12527     int vp1=0, vp2=0, vfi_index= -1;
  12528     int rv = BCM_E_UNAVAIL;
  12529     bcm_gport_t  vxlan_port_id;
  12530     bcm_vxlan_port_t vxlan_port;
  12531     _bcm_vp_info_t vp_info;
  12532 
  12533     if ( vpn != BCM_VXLAN_VPN_INVALID) {
  12534          _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VXLAN_VPN_TYPE_ELINE,  vpn);
  12535          if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVxlan)) {
  12536             return BCM_E_NOT_FOUND;
  12537          }
  12538     } else {
  12539          vfi_index = _BCM_VXLAN_VFI_INVALID;
  12540     }
  12541 
  12542     if (!_bcm_vp_used_get(unit, active_vp, _bcmVpTypeVxlan)) {
  12543         return BCM_E_NOT_FOUND;
  12544     }
  12545 
  12546     /* Set VXLAN port ID */
  12547     BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port_id, active_vp);
  12548 
  12549     /* Delete the next-hop info */
  12550     rv = _bcm_td2_vxlan_port_nh_delete(unit, vpn, active_vp);
  12551     if ( rv < 0 ) {
  12552         if (rv != BCM_E_NOT_FOUND) {
  12553             return rv;
  12554         } else {
  12555                 rv = 0;
  12556         }
  12557     }
  12558 
  12559     /* ---- Read in current table values for VP1 and VP2 ----- */
  12560     (void) _bcm_td2_vxlan_eline_vp_map_get (unit, vfi_index,  &vp1,  &vp2);
  12561 
  12562     bcm_vxlan_port_t_init(&vxlan_port);
  12563     vxlan_port.vxlan_port_id = vxlan_port_id;
  12564     BCM_IF_ERROR_RETURN(bcm_td2_vxlan_port_get(unit, vpn, &vxlan_port));
  12565     rv = _bcm_td2_vxlan_match_delete(unit, active_vp, vxlan_port, vpn);
  12566     if ( rv < 0 ) {
  12567         if (rv != BCM_E_NOT_FOUND) {
  12568              return rv;
  12569         } else {
  12570              rv = BCM_E_NONE;
  12571         }
  12572     }
  12573 
  12574     /* If the other port is valid, point it to itself */
  12575     if (active_vp == vp1) {
  12576         if (BCM_SUCCESS(rv)) {
  12577             rv = _bcm_td2_vxlan_eline_vp_map_clear (unit, vfi_index, active_vp, 0);
  12578         }
  12579     } else if (active_vp == vp2) {
  12580         if (BCM_SUCCESS(rv)) {
  12581             rv = _bcm_td2_vxlan_eline_vp_map_clear (unit, vfi_index, 0, active_vp);
  12582         }
  12583     }
  12584 
  12585     if (rv >= 0) {
  12586 
  12587         /* Check for Network-Port */
  12588         BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, active_vp, &vp_info));
  12589         if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
  12590             network_port_flag = TRUE;
  12591         }
  12592 
  12593         if (!network_port_flag) {
  12594             sal_memset(&svp_2_entry, 0, sizeof(source_vp_2_entry_t));
  12595             BCM_IF_ERROR_RETURN
  12596                 (WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, active_vp, &svp_2_entry));
  12597         }
  12598 
  12599         /* Invalidate the VP being deleted */
  12600         sal_memset(&svp, 0, sizeof(source_vp_entry_t));
  12601         rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, &svp);
  12602         if (BCM_SUCCESS(rv)) {
  12603              rv = _bcm_td2_vxlan_egress_dvp_reset(unit, active_vp);
  12604              if (rv < 0) {
  12605                  return rv;
  12606              }
  12607              rv = _bcm_td2_vxlan_ingress_dvp_reset(unit, active_vp);
  12608         }
  12609     }
  12610 
  12611     if (rv < 0) {
  12612         return rv;
  12613     }
  12614 
  12615     /* Decrement port's VP count */
  12616     rv = _bcm_td2_vxlan_port_cnt_update(unit, vxlan_port_id, active_vp, FALSE);
  12617     if (rv < 0) {
  12618         return rv;
  12619     }
  12620 
  12621     /* Free the VP */
  12622     (void) _bcm_vp_free(unit, _bcmVpTypeVxlan, 1, active_vp);
  12623     return rv;
  12624 
  12625 }
  12626 
  12627 /*
  12628  * Function:
  12629  *      _bcm_td2_vxlan_elan_port_delete
  12630  * Purpose:
  12631  *      Delete VXLAN ELAN port from a VPN
  12632  * Parameters:
  12633  *      unit       - (IN) Device Number
  12634  *      vpn        - (IN) VPN instance ID
  12635  *      vxlan_port_id - (IN) vxlan port information
  12636  * Returns:
  12637  *      BCM_E_XXX
  12638  */
  12639 
  12640 int
  12641 _bcm_td2_vxlan_elan_port_delete(int unit, bcm_vpn_t vpn, int vp)
  12642 {
  12643     source_vp_entry_t svp;
  12644     source_vp_2_entry_t svp_2_entry;
  12645     int network_port_flag=0;
  12646     int rv = BCM_E_NONE;
  12647     int vfi_index= -1;
  12648     bcm_gport_t vxlan_port_id;
  12649     bcm_vxlan_port_t  vxlan_port;
  12650     _bcm_vp_info_t vp_info;
  12651 
  12652     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  12653         return BCM_E_NOT_FOUND;
  12654     }
  12655 
  12656     /* Check for Network-Port */
  12657     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  12658     if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
  12659         network_port_flag = TRUE;
  12660     }
  12661 
  12662     /* Set VXLAN port ID */
  12663     BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port_id, vp);
  12664     bcm_vxlan_port_t_init(&vxlan_port);
  12665     vxlan_port.vxlan_port_id = vxlan_port_id;
  12666     BCM_IF_ERROR_RETURN(bcm_td2_vxlan_port_get(unit, vpn, &vxlan_port));
  12667 
  12668 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  12669     if ((!network_port_flag) && (vp_info.flags & _BCM_VP_INFO_SHARED_PORT)) {
  12670         if (VXLAN_INFO(unit)->match_key[vp].match_count > 0) {
  12671             BCM_IF_ERROR_RETURN(bcm_td2p_share_vp_delete(unit, vpn, vp));
  12672         }
  12673         if (vpn != BCM_VXLAN_VPN_INVALID) {
  12674             return BCM_E_NONE;
  12675         }
  12676     } else
  12677 #endif
  12678     {
  12679         rv = _bcm_td2_vxlan_match_delete(unit, vp, vxlan_port, vpn);
  12680         if (rv < 0 && rv != BCM_E_NOT_FOUND) {
  12681             return rv;
  12682         }
  12683     }
  12684 
  12685     (void)bcm_td2_vxlan_match_clear(unit, vp);
  12686 
  12687     if ( vpn != BCM_VXLAN_VPN_INVALID) {
  12688         if (!network_port_flag) { /* Check VPN only for Access VP */
  12689             _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VXLAN_VPN_TYPE_ELAN,  vpn);
  12690             if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVxlan)) {
  12691                 return BCM_E_NOT_FOUND;
  12692             }
  12693             if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv) ||
  12694                 _bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
  12695                 (void) _bcm_vp_free(unit, _bcmVpTypeVxlan, 1, vp);
  12696                 return _bcm_td2_vxlan_access_niv_pe_reset (unit, vp);
  12697             }
  12698         }
  12699     }
  12700 
  12701     /* Decrement port's VP count */
  12702     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_port_cnt_update(unit, vxlan_port_id, vp, FALSE));
  12703 
  12704     /* Delete the next-hop info */
  12705     rv = _bcm_td2_vxlan_port_nh_delete(unit, vpn, vp);
  12706     if (rv < 0 && rv != BCM_E_NOT_FOUND) {
  12707         return rv;
  12708     }
  12709 
  12710     /* Clear the SVP table entries */
  12711     sal_memset(&svp, 0, sizeof(source_vp_entry_t));
  12712     BCM_IF_ERROR_RETURN(WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp));
  12713 
  12714     if (!network_port_flag) {
  12715         sal_memset(&svp_2_entry, 0, sizeof(source_vp_2_entry_t));
  12716         BCM_IF_ERROR_RETURN
  12717             (WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, vp, &svp_2_entry));
  12718     }
  12719 
  12720     /* Clear the DVP table entries */
  12721     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_egress_dvp_reset(unit, vp));
  12722     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_ingress_dvp_reset(unit, vp));
  12723 
  12724     /* Free the VP */
  12725     BCM_IF_ERROR_RETURN(_bcm_vp_free(unit, _bcmVpTypeVxlan, 1, vp));
  12726 
  12727     return BCM_E_NONE;
  12728 }
  12729 
  12730 /*
  12731  * Function:
  12732  *      _bcm_td2_vxlan_port_vlan_get
  12733  * Purpose:
  12734  *      Obtain vlan information
  12735  * Parameters:
  12736  *      unit           - (IN)   Device Number
  12737  *      vp             - (IN)   Source Virtual Port
  12738  *      vxlan_port     - (OUT)  VXLAN port information
  12739  * Returns:
  12740  *      BCM_E_XXX
  12741  */
  12742 
  12743 STATIC int
  12744 _bcm_td2_vxlan_port_vlan_get(int unit, int vp, bcm_vxlan_port_t *vxlan_port)
  12745 {
  12746     _bcm_td2_vxlan_bookkeeping_t *vxlan_info = VXLAN_INFO(unit);
  12747     int index = 0;
  12748     soc_mem_t mem;
  12749     uint32 vent[SOC_MAX_MEM_WORDS];
  12750 
  12751     sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  12752 #if defined(BCM_TRIDENT3_SUPPORT)
  12753     if (soc_feature(unit, soc_feature_base_valid)) {
  12754         mem = VLAN_XLATE_1_DOUBLEm;
  12755 
  12756         soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  12757         soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  12758     } else
  12759 #endif
  12760     {
  12761         mem = VLAN_XLATEm;
  12762 
  12763         soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
  12764     }
  12765 
  12766     if (_BCM_VXLAN_PORT_MATCH_TYPE_VLAN == vxlan_info->match_key[vp].flags) {
  12767         soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  12768         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OVID);
  12769 #if defined(BCM_TRIDENT3_SUPPORT)
  12770         if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
  12771             soc_mem_field32_set(unit, mem, vent,
  12772                 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_OVID);
  12773         }
  12774 #endif
  12775         soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf,
  12776                                     vxlan_info->match_key[vp].match_vlan);
  12777     } else if (_BCM_VXLAN_PORT_MATCH_TYPE_INNER_VLAN ==
  12778         vxlan_info->match_key[vp].flags) {
  12779         soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  12780         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID);
  12781 #if defined(BCM_TRIDENT3_SUPPORT)
  12782         if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
  12783             soc_mem_field32_set(unit, mem, vent,
  12784                 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID);
  12785         }
  12786 #endif
  12787         soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf,
  12788                                     vxlan_info->match_key[vp].match_inner_vlan);
  12789     } else if (_BCM_VXLAN_PORT_MATCH_TYPE_VLAN_STACKED ==
  12790         vxlan_info->match_key[vp].flags) {
  12791         soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  12792         soc_mem_field32_set(unit, mem, vent,
  12793             KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
  12794 #if defined(BCM_TRIDENT3_SUPPORT)
  12795         if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
  12796             soc_mem_field32_set(unit, mem, vent,
  12797                 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_IVID_OVID);
  12798         }
  12799 #endif
  12800         soc_mem_field32_set(unit, mem, vent,
  12801             XLATE__OVIDf, vxlan_info->match_key[vp].match_vlan);
  12802         soc_mem_field32_set(unit, mem, vent,
  12803             XLATE__IVIDf, vxlan_info->match_key[vp].match_inner_vlan);
  12804     } else if (_BCM_VXLAN_PORT_MATCH_TYPE_VLAN_PRI ==
  12805         vxlan_info->match_key[vp].flags) {
  12806         soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
  12807         soc_mem_field32_set(unit, mem, vent,
  12808             KEY_TYPEf, TR_VLXLT_HASH_KEY_TYPE_PRI_CFI);
  12809 #if defined(BCM_TRIDENT3_SUPPORT)
  12810         if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
  12811             soc_mem_field32_set(unit, mem, vent,
  12812                 DATA_TYPEf, TR_VLXLT_HASH_KEY_TYPE_PRI_CFI);
  12813         }
  12814 #endif
  12815         soc_mem_field32_set(unit, mem, vent,
  12816             XLATE__OTAGf, vxlan_info->match_key[vp].match_vlan);
  12817     } else {
  12818         return BCM_E_NONE;
  12819     }
  12820 
  12821     if (vxlan_info->match_key[vp].modid != -1) {
  12822         soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf,
  12823                                     vxlan_info->match_key[vp].modid);
  12824         soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf,
  12825                                     vxlan_info->match_key[vp].port);
  12826     } else {
  12827         soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 1);
  12828         soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf,
  12829                                     vxlan_info->match_key[vp].trunk_id);
  12830     }
  12831 
  12832     BCM_IF_ERROR_RETURN(soc_mem_search(unit,
  12833         mem, MEM_BLOCK_ANY, &index, vent, vent, 0));
  12834     if (!soc_mem_field32_get(unit, mem, vent, XLATE__VLAN_ACTION_VALIDf)) {
  12835         vxlan_port->flags |= BCM_VXLAN_PORT_ENABLE_VLAN_CHECKS;
  12836     }
  12837 
  12838     return BCM_E_NONE;
  12839 }
  12840 
  12841 /*
  12842  * Function:
  12843  *      _bcm_td2_vxlan_port_get
  12844  * Purpose:
  12845  *      Get VXLAN port information from a VPN
  12846  * Parameters:
  12847  *      unit       - (IN) Device Number
  12848  *      vpn        - (IN) VPN instance ID
  12849  *      vxlan_port_id - (IN) vxlan port information
  12850  * Returns:
  12851  *      BCM_E_XXX
  12852  */
  12853 
  12854 int
  12855 _bcm_td2_vxlan_port_get(int unit, bcm_vpn_t vpn, int vp, bcm_vxlan_port_t  *vxlan_port)
  12856 {
  12857     int i, rv = BCM_E_NONE;
  12858     uint32 tpid_enable = 0;
  12859     source_vp_entry_t svp;
  12860     int split_horizon_port_flag=0;
  12861     _bcm_vp_info_t vp_info;
  12862 
  12863     /* Initialize the structure */
  12864     bcm_vxlan_port_t_init(vxlan_port);
  12865     BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port->vxlan_port_id, vp);
  12866     BCM_IF_ERROR_RETURN (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
  12867 
  12868     /* Check for Network-Port */
  12869     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  12870     if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
  12871         split_horizon_port_flag = TRUE;
  12872     }
  12873 
  12874     if ( vpn != BCM_VXLAN_VPN_INVALID) {
  12875          if (!split_horizon_port_flag) { /* Check VPN only for Access VP */
  12876              if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv) ||
  12877                   _bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
  12878                    return BCM_E_NONE;
  12879              }
  12880          }
  12881     }
  12882 
  12883     if (split_horizon_port_flag) {
  12884         vxlan_port->flags |= BCM_VXLAN_PORT_NETWORK;
  12885         vxlan_port->flags |= BCM_VXLAN_PORT_EGRESS_TUNNEL;
  12886         if(vp_info.flags & _BCM_VP_INFO_SHARED_PORT) {
  12887             vxlan_port->flags |= BCM_VXLAN_PORT_SHARE;
  12888             /* Shared VXLAN port is used only for multicast now*/
  12889             vxlan_port->flags |= BCM_VXLAN_PORT_MULTICAST;
  12890         }
  12891     }
  12892 
  12893     /* Get the match parameters */
  12894     rv = _bcm_td2_vxlan_match_get(unit, vxlan_port, vp, vpn);
  12895     BCM_IF_ERROR_RETURN(rv);
  12896 
  12897     /* Get the BCM_VXLAN_PORT_ENABLE_VLAN_CHECKS flag */
  12898     if (!soc_feature(unit, soc_feature_vlan_vfi_membership)) {
  12899         BCM_IF_ERROR_RETURN(
  12900             _bcm_td2_vxlan_port_vlan_get(unit, vp, vxlan_port));
  12901     }
  12902 
  12903     /* Get the next-hop parameters , for shared VXLAN port, don't get next hop here*/
  12904     if (!(vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) {
  12905         rv = _bcm_td2_vxlan_port_nh_get(unit, vpn, vp, vxlan_port);
  12906         BCM_IF_ERROR_RETURN(rv);
  12907     }
  12908 
  12909     rv = _bcm_td2_vxlan_ingress_dvp_get(unit, vp, vxlan_port);
  12910     BCM_IF_ERROR_RETURN(rv);
  12911 
  12912     /* Get Tunnel index */
  12913     rv = _bcm_td2_vxlan_egress_dvp_get(unit, vp, vxlan_port);
  12914     BCM_IF_ERROR_RETURN(rv);
  12915 
  12916     /* Fill in SVP parameters */
  12917     vxlan_port->if_class = soc_SOURCE_VPm_field32_get(unit, &svp, CLASS_IDf);
  12918 
  12919     if (soc_SOURCE_VPm_field32_get(unit, &svp, SD_TAG_MODEf)) {
  12920 #if defined(BCM_TRIDENT3_SUPPORT)
  12921         if (SOC_IS_TRIDENT3X(unit)) {
  12922             uint32 svp1[SOC_MAX_MEM_WORDS];
  12923 
  12924             BCM_IF_ERROR_RETURN(READ_SVP_ATTRS_1m(unit, MEM_BLOCK_ANY, vp, svp1));
  12925             soc_SVP_ATTRS_1m_field_get(unit, &svp1, TPID_ENABLEf, &tpid_enable);
  12926         } else
  12927 #endif
  12928         {
  12929             tpid_enable = soc_SOURCE_VPm_field32_get(unit, &svp, TPID_ENABLEf);
  12930         }
  12931         if (tpid_enable) {
  12932             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_TAGGED;
  12933             for (i = 0; i < 4; i++) {
  12934                 if (tpid_enable & (1 << i)) {
  12935                     _bcm_fb2_outer_tpid_entry_get(unit, &vxlan_port->egress_service_tpid, i);
  12936                 }
  12937             }
  12938         }
  12939     }
  12940 
  12941     return rv;
  12942 }
  12943 
  12944 /*
  12945  * Function:
  12946  *      bcm_td2_vxlan_port_add
  12947  * Purpose:
  12948  *      Add VXLAN port to a VPN
  12949  * Parameters:
  12950  *      unit    - (IN) Device Number
  12951  *      vpn     - (IN) VPN instance ID
  12952  *      vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id)
  12953  * Returns:
  12954  *      BCM_E_XXX
  12955  */
  12956 
  12957 STATIC int
  12958 _bcm_td2_vxlan_default_port_add(int unit, bcm_vxlan_port_t  *vxlan_port)
  12959 {
  12960     source_vp_entry_t svp;
  12961     int rv = BCM_E_PARAM, vp=0, num_vp=0;
  12962     int network_group=0;
  12963     int cml_default_enable=0, cml_default_new=0, cml_default_move=0;
  12964     _bcm_vp_info_t vp_info;
  12965 
  12966     _bcm_vp_info_init(&vp_info);
  12967     vp_info.vp_type = _bcmVpTypeVxlan;
  12968     if(vxlan_port->flags & BCM_VXLAN_PORT_NETWORK) { 
  12969         vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
  12970     }
  12971 
  12972     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  12973 
  12974    /* ======== Allocate/Get Virtual_Port =============== */
  12975     if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
  12976         vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
  12977         if (vp == -1) {
  12978             return BCM_E_PARAM;
  12979         }
  12980 
  12981         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  12982             return BCM_E_NOT_FOUND;
  12983         }
  12984         rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
  12985         if (rv < 0) {
  12986             return rv;
  12987         }
  12988 
  12989         /* Decrement old-port's nexthop count */
  12990         rv = _bcm_td2_vxlan_port_nh_cnt_dec(unit, vp);
  12991         if (rv < 0) {
  12992             return rv;
  12993         }
  12994 
  12995         /* Decrement old-port's VP count */
  12996         rv = _bcm_td2_vxlan_port_cnt_update(unit, vxlan_port->vxlan_port_id, vp, FALSE);
  12997         if (rv < 0) {
  12998             return rv;
  12999         }
  13000 
  13001     } else if (vxlan_port->flags & BCM_VXLAN_PORT_WITH_ID ) {
  13002        if (!BCM_GPORT_IS_VXLAN_PORT(vxlan_port->vxlan_port_id)) {
  13003             return (BCM_E_BADID);
  13004         }
  13005 
  13006         vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
  13007         if (vp == -1) {
  13008             return BCM_E_PARAM;
  13009         }
  13010         /* Vp index zero is reserved in function _bcm_virtual_init because of 
  13011          * HW restriction. 
  13012          */
  13013         if (vp >= num_vp || vp < 1) {
  13014             return BCM_E_BADID;
  13015         } 
  13016         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) { 
  13017             return BCM_E_EXISTS;
  13018         }
  13019 
  13020         BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info));
  13021         sal_memset(&svp, 0, sizeof(source_vp_entry_t));
  13022     } else {
  13023        rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp);
  13024        if (rv < 0) {
  13025            return rv;
  13026        }
  13027         sal_memset(&svp, 0, sizeof(source_vp_entry_t));
  13028         BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info));
  13029     }
  13030 
  13031     /* ======== Configure SVP/DVP Properties ========== */
  13032     soc_SOURCE_VPm_field32_set(unit, &svp, CLASS_IDf, 
  13033                                vxlan_port->if_class);
  13034     if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
  13035         network_group = vxlan_port->network_group_id;
  13036         rv = _bcm_validate_splithorizon_network_group(unit,
  13037                 vxlan_port->flags & BCM_VXLAN_PORT_NETWORK, &network_group);
  13038         BCM_IF_ERROR_RETURN(rv);
  13039         soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf,
  13040                 network_group);
  13041     } else {
  13042         soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 1);
  13043     }
  13044 
  13045     soc_SOURCE_VPm_field32_set(unit, &svp, 
  13046                                       ENTRY_TYPEf, _BCM_VXLAN_SOURCE_VP_TYPE_VFI);
  13047 
  13048     /* Keep CML in the replace operation. It may be set by bcm_td2_vxlan_port_learn_set before */
  13049     if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
  13050         rv = _bcm_vp_default_cml_mode_get (unit, 
  13051                        &cml_default_enable, &cml_default_new, 
  13052                        &cml_default_move);
  13053         if (rv < 0) {
  13054             return rv;
  13055         }
  13056             
  13057         if (cml_default_enable) {
  13058             /* Set the CML to default values */
  13059             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml_default_new);
  13060             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml_default_move);
  13061         } else {
  13062             /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */
  13063             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, 0x8);
  13064             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, 0x8);
  13065         }
  13066     }
  13067     if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) {
  13068         if (!soc_feature(unit, soc_feature_vlan_vfi_membership)) {
  13069             soc_SOURCE_VPm_field32_set(unit, &svp, DISABLE_VLAN_CHECKSf, 1);
  13070         }
  13071     }
  13072 
  13073     /* Configure VXLAN_DEFAULT_NETWORK_SVPr.SVP */
  13074     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
  13075     BCM_IF_ERROR_RETURN(rv);
  13076 
  13077 #if defined(BCM_TRIDENT3_SUPPORT)
  13078     if (SOC_IS_TRIDENT3X(unit)) {
  13079         if ( BCM_E_NONE != soc_cancun_app_dest_entry_set (unit, SOURCE_VPm,
  13080             vp, ENTRY_TYPEf, CANCUN_APP__SOURCE_VP__No_Control_Word,
  13081             _BCM_VXLAN_SOURCE_VP_TYPE_VFI)) {
  13082             LOG_ERROR(BSL_LS_BCM_VXLAN,
  13083                (BSL_META_U(unit,"SOURCE_VP cancun app cfg error\n")));
  13084         }
  13085     }
  13086 #endif
  13087 
  13088     BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port->vxlan_port_id, vp);
  13089 
  13090     /* Increment new-port's VP count */
  13091     rv = _bcm_td2_vxlan_port_cnt_update(unit, vxlan_port->vxlan_port_id, vp, TRUE);
  13092     BCM_IF_ERROR_RETURN(rv);
  13093 
  13094     return (soc_reg_field32_modify(unit, VXLAN_DEFAULT_NETWORK_SVPr, 
  13095              REG_PORT_ANY, SVPf, vp));
  13096 
  13097 }
  13098 
  13099 /*
  13100  * Function:
  13101  *      _bcm_td2_vxlan_default_port_delete
  13102  * Purpose:
  13103  *      Delete VXLAN Default port from a VPN
  13104  * Parameters:
  13105  *      unit       - (IN) Device Number
  13106  *      vpn        - (IN) VPN instance ID
  13107  *      vxlan_port_id - (IN) vxlan port information
  13108  * Returns:
  13109  *      BCM_E_XXX
  13110  */
  13111 
  13112 int
  13113 _bcm_td2_vxlan_default_port_delete(int unit, bcm_vpn_t vpn, int vp)
  13114 {
  13115     source_vp_entry_t svp;
  13116     int rv = BCM_E_UNAVAIL;
  13117     int vfi_index= -1;
  13118     bcm_gport_t vxlan_port_id;
  13119 
  13120     if ( vpn != BCM_VXLAN_VPN_INVALID) {
  13121          _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VXLAN_VPN_TYPE_ELAN,  vpn);
  13122          if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVxlan)) {
  13123             return BCM_E_NOT_FOUND;
  13124          }
  13125     }
  13126 
  13127     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  13128         return BCM_E_NOT_FOUND;
  13129     }
  13130 
  13131     /* Set VXLAN port ID */
  13132     BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port_id, vp);
  13133 
  13134     /* Clear the SVP and DVP table entries */
  13135     sal_memset(&svp, 0, sizeof(source_vp_entry_t));
  13136     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
  13137     if (rv < 0) {
  13138         return rv;
  13139     }
  13140 
  13141     /* Decrement port's VP count */
  13142     rv = _bcm_td2_vxlan_port_cnt_update(unit, vxlan_port_id, vp, FALSE);
  13143     if (rv < 0) {
  13144         return rv;
  13145     }
  13146 
  13147     /* Free the VP */
  13148     (void) _bcm_vp_free(unit, _bcmVpTypeVxlan, 1, vp);
  13149 
  13150     /* Reset VXLAN_DEFAULT_NETWORK_SVP */
  13151     BCM_IF_ERROR_RETURN(soc_reg_field32_modify
  13152         (unit, VXLAN_DEFAULT_NETWORK_SVPr, REG_PORT_ANY, SVPf, 0));
  13153 
  13154     return rv;
  13155 
  13156 }
  13157 
  13158 /*
  13159  * Function:
  13160  *      _bcm_td2_vxlan_default_port_get
  13161  * Purpose:
  13162  *      Get VXLAN Default port information
  13163  * Parameters:
  13164  *      unit       - (IN) Device Number
  13165  *      vp         - (IN) Source Virtual Port
  13166  *      vxlan_port - (IN/OUT) vxlan port information
  13167  * Returns:
  13168  *      BCM_E_XXX
  13169  */
  13170 int
  13171 _bcm_td2_vxlan_default_port_get(int unit, int vp, bcm_vxlan_port_t *vxlan_port)
  13172 {
  13173     int rv = BCM_E_NONE;
  13174     source_vp_entry_t svp;
  13175     _bcm_vp_info_t vp_info;
  13176 
  13177     bcm_vxlan_port_t_init(vxlan_port);
  13178     BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port->vxlan_port_id, vp);
  13179 
  13180     BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
  13181     vxlan_port->if_class = soc_SOURCE_VPm_field32_get(unit, &svp, CLASS_IDf);
  13182 
  13183     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  13184     if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
  13185         vxlan_port->flags |= BCM_VXLAN_PORT_NETWORK;
  13186     }
  13187 
  13188     vxlan_port->flags |= BCM_VXLAN_PORT_DEFAULT;
  13189 
  13190     return rv;
  13191 }
  13192 
  13193 /*
  13194  * Function:
  13195  *      bcm_td2_vxlan_port_add
  13196  * Purpose:
  13197  *      Add VXLAN port to a VPN
  13198  * Parameters:
  13199  *      unit    - (IN) Device Number
  13200  *      vpn     - (IN) VPN instance ID
  13201  *      vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id)
  13202  * Returns:
  13203  *      BCM_E_XXX
  13204  */
  13205 
  13206 int
  13207 bcm_td2_vxlan_port_add(int unit, bcm_vpn_t vpn, bcm_vxlan_port_t  *vxlan_port)
  13208 {
  13209     int mode=0, rv = BCM_E_PARAM;
  13210     uint8 isEline = 0;
  13211 
  13212     BCM_IF_ERROR_RETURN(bcm_xgs3_l3_egress_mode_get(unit, &mode));
  13213     if (!mode) {
  13214         LOG_INFO(BSL_LS_BCM_L3,
  13215                  (BSL_META_U(unit,
  13216                              "L3 egress mode must be set first\n")));
  13217         return BCM_E_DISABLED;
  13218     }
  13219 
  13220     if (vxlan_port->if_class > 0xfff) {
  13221         return BCM_E_PARAM;
  13222     }
  13223 
  13224     if (vxlan_port->mtu > 0x3fff) {
  13225         return BCM_E_PARAM;
  13226     }
  13227 
  13228     if (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_SHARE) {
  13229         if (soc_feature(unit, soc_feature_vp_sharing)) {
  13230             if (vpn != BCM_VXLAN_VPN_INVALID) {
  13231                 return BCM_E_PARAM;
  13232             }
  13233         } else {
  13234             return BCM_E_UNAVAIL;
  13235         }
  13236     }
  13237 
  13238     if (vxlan_port->flags & BCM_VXLAN_PORT_SHARE) {
  13239         if (!((vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) &&
  13240                 (vxlan_port->flags & BCM_VXLAN_PORT_MULTICAST))) {
  13241             return BCM_E_PARAM;
  13242         }
  13243     }
  13244 
  13245 #if defined(BCM_TRIDENT3_SUPPORT)
  13246     if ((vxlan_port->flags & BCM_VXLAN_PORT_DEFAULT) &&
  13247               !SOC_REG_IS_VALID(unit, VXLAN_DEFAULT_NETWORK_SVPr)) {
  13248         return BCM_E_UNAVAIL;
  13249     }
  13250 #endif
  13251 
  13252     if (vpn != BCM_VXLAN_VPN_INVALID) {
  13253         BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_eline(unit, vpn, &isEline));
  13254     }
  13255 
  13256     if (vxlan_port->flags & BCM_VXLAN_PORT_DEFAULT) {
  13257         rv = _bcm_td2_vxlan_default_port_add(unit, vxlan_port);
  13258 #if defined(BCM_TRIDENT3_SUPPORT)
  13259         if (BCM_SUCCESS(rv) && SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) {
  13260             rv = soc_reg_field32_modify
  13261                   (unit, DEFAULT_SVP_ENABLEr, REG_PORT_ANY,
  13262                                 VXLAN_DEFAULT_SVP_ENABLEf, 1);
  13263             /* this register is removed in cch after cancun 5.1.8. It is
  13264              * no longer needed. The cancun access routine will return
  13265              * not found if it doesn't exist in cch. Simply ignore
  13266              * this error.
  13267              */
  13268             if (rv == SOC_E_NOT_FOUND) {
  13269                 rv = SOC_E_NONE;
  13270             }
  13271         }
  13272 #endif
  13273         return rv;
  13274     }
  13275 
  13276     if (isEline) {
  13277         if (vxlan_port->flags & BCM_VXLAN_PORT_VPN_BASED) {
  13278             /* not support for this flag */
  13279             return BCM_E_PARAM;
  13280         }
  13281         rv = _bcm_td2_vxlan_eline_port_add(unit, vpn, vxlan_port);
  13282     } else {
  13283         if (vxlan_port->flags & BCM_VXLAN_PORT_VPN_BASED) {
  13284             /* this flag is reused to indicate adding VP-based VFI-VIND mapping */
  13285             rv = _bcm_td2_vxlan_vp_based_vnid_add(unit, vpn, vxlan_port);
  13286         } else {
  13287         rv = _bcm_td2_vxlan_elan_port_add(unit, vpn, vxlan_port);
  13288     }
  13289     }
  13290 
  13291     return rv;
  13292 }
  13293 
  13294 
  13295 /*
  13296  * Function:
  13297  *      bcm_td2_vxlan_port_delete
  13298  * Purpose:
  13299  *      Delete VXLAN port from a VPN
  13300  * Parameters:
  13301  *      unit       - (IN) Device Number
  13302  *      vpn        - (IN) VPN instance ID
  13303  *      vxlan_port_id - (IN) vxlan port information
  13304  * Returns:
  13305  *      BCM_E_XXX
  13306  */
  13307 
  13308 int
  13309 bcm_td2_vxlan_port_delete(int unit, bcm_vpn_t vpn, bcm_gport_t vxlan_port_id)
  13310 {
  13311     int vp=0;
  13312     int rv = BCM_E_UNAVAIL;
  13313     uint32 reg_val=0;
  13314     uint8 isEline=0;
  13315     uint32 stat_counter_id;
  13316     int num_ctr = 0;
  13317 
  13318     if (BCM_GPORT_IS_TRUNK(vxlan_port_id)) {
  13319         bcm_trunk_member_t trunk_member;
  13320         int                port_count = 0;
  13321         bcm_trunk_t        tid = 0;
  13322         int                tid_is_vp_lag = FALSE;
  13323         if (vpn != BCM_VXLAN_VPN_INVALID) {
  13324             BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_valid(unit, vpn));
  13325         }
  13326         tid = BCM_GPORT_TRUNK_GET(vxlan_port_id);
  13327         BCM_IF_ERROR_RETURN(
  13328             _bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag));
  13329         if (tid_is_vp_lag) {
  13330             BCM_IF_ERROR_RETURN(
  13331                 bcm_td2_vp_lag_get(unit, tid, NULL, 1,
  13332                                    &trunk_member, &port_count));
  13333             if (BCM_GPORT_IS_NIV_PORT(trunk_member.gport) ||
  13334                 BCM_GPORT_IS_EXTENDER_PORT(trunk_member.gport)) {
  13335                 BCM_IF_ERROR_RETURN(
  13336                     _bcm_esw_trunk_tid_to_vp_lag_vp(unit, tid, &vp));
  13337                 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  13338                     return BCM_E_NOT_FOUND;
  13339                 }
  13340                 BCM_IF_ERROR_RETURN(_bcm_vp_free(unit, _bcmVpTypeVxlan, 1, vp));
  13341                 return _bcm_td2_vxlan_access_niv_pe_reset(unit, vp);
  13342             }
  13343         }
  13344     }
  13345 
  13346     /* Check for Valid Vpn */
  13347     if (vpn != BCM_VXLAN_VPN_INVALID) {
  13348         BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_valid(unit, vpn));
  13349     }
  13350 
  13351     vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port_id);
  13352     if (vp == -1) {
  13353         return BCM_E_PARAM;
  13354     }
  13355 
  13356     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  13357         return BCM_E_NOT_FOUND;
  13358     }
  13359 
  13360     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vp_is_eline(unit, vp, &isEline));
  13361 
  13362     /* Check for VXLAN default port */
  13363     if (SOC_REG_IS_VALID(unit, VXLAN_DEFAULT_NETWORK_SVPr)) {
  13364         BCM_IF_ERROR_RETURN(READ_VXLAN_DEFAULT_NETWORK_SVPr(unit, &reg_val));
  13365         if (vp == soc_reg_field_get(unit,
  13366                     VXLAN_DEFAULT_NETWORK_SVPr, reg_val, SVPf)) {
  13367             rv =  _bcm_td2_vxlan_default_port_delete(unit, vpn, vp);
  13368 #if defined(BCM_TRIDENT3_SUPPORT)
  13369             if (BCM_SUCCESS(rv) && SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) {
  13370                 rv = soc_reg_field32_modify
  13371                       (unit, DEFAULT_SVP_ENABLEr, REG_PORT_ANY, VXLAN_DEFAULT_SVP_ENABLEf, 0);
  13372                 if (rv == SOC_E_NOT_FOUND) {
  13373                     rv = SOC_E_NONE;
  13374                 }
  13375             }
  13376 #endif
  13377             return rv;
  13378         }
  13379     }
  13380     
  13381     if (isEline == 0x1 ) {
  13382        rv = _bcm_td2_vxlan_eline_port_delete(unit, vpn, vp);
  13383     } else if (isEline == 0x0 ) {
  13384         uint32 count = 0;
  13385         source_vp_entry_t svp;
  13386         int vfi = 0;
  13387         int vfi_r;
  13388         _bcm_vp_info_t vp_info;
  13389 
  13390         BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
  13391 
  13392         if ((vp_info.flags & _BCM_VP_INFO_NETWORK_PORT)) {
  13393             rv = _bcm_td2_vxlan_vp_based_vnid_count(unit, vp, &count);
  13394 
  13395             /*
  13396              * if no VFI-VNID mappings attached, then delete vxlan port directly,
  13397              * this is to backward-compatible with previous API behavior.
  13398  */
  13399             if (count != 0) {
  13400                 if (vpn == BCM_VXLAN_VPN_INVALID) {
  13401                     return BCM_E_BUSY;
  13402                 }
  13403 
  13404                 BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
  13405                 vfi_r = soc_SOURCE_VPm_field32_get(unit, &svp, VFIf);
  13406                 _BCM_VXLAN_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
  13407 
  13408                 if (vfi != vfi_r) {
  13409                     /* user is trying to delete VFI-VNID mappings */
  13410                     bcm_vxlan_port_t vxlan_port_r;
  13411 
  13412                     bcm_vxlan_port_t_init(&vxlan_port_r);
  13413                     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_port_get(unit, vpn, vp, &vxlan_port_r));
  13414                     rv = _bcm_td2_vxlan_vp_based_vnid_delete(unit, vpn, &vxlan_port_r);
  13415                     return rv;
  13416                 } else {
  13417                     return BCM_E_BUSY;
  13418                 }
  13419             }
  13420         }
  13421 
  13422        rv = _bcm_td2_vxlan_elan_port_delete(unit, vpn, vp);
  13423     }
  13424 
  13425     if (rv != BCM_E_NONE) {
  13426         return rv;
  13427     }
  13428 
  13429     if (bcm_esw_vxlan_stat_id_get(unit, vxlan_port_id, BCM_VXLAN_VPN_INVALID,
  13430                    bcmVxlanOutPackets, &stat_counter_id) == BCM_E_NONE) {
  13431         num_ctr++;
  13432     }
  13433     if (bcm_esw_vxlan_stat_id_get(unit, vxlan_port_id, BCM_VXLAN_VPN_INVALID,
  13434                    bcmVxlanInPackets, &stat_counter_id) == BCM_E_NONE) {
  13435         num_ctr++;
  13436     }
  13437 
  13438     if (num_ctr != 0) {
  13439         BCM_IF_ERROR_RETURN(
  13440            bcm_esw_vxlan_stat_detach(unit, vxlan_port_id, BCM_VXLAN_VPN_INVALID));
  13441     }
  13442 
  13443     return rv;
  13444 }
  13445 
  13446 /*
  13447  * Function:
  13448  *      bcm_td2_vxlan_port_delete_all
  13449  * Purpose:
  13450  *      Delete all VXLAN ports from a VPN
  13451  * Parameters:
  13452  *      unit       - (IN) Device Number
  13453  *      vpn        - (IN) VPN instance ID
  13454  * Returns:
  13455  *      BCM_E_XXX
  13456  */
  13457 int
  13458 bcm_td2_vxlan_port_delete_all(int unit, bcm_vpn_t vpn)
  13459 {
  13460     int rv = BCM_E_NONE;
  13461     int vfi_index=0;
  13462     int vp1 = 0, vp2 = 0;
  13463     uint8 isEline = 0;
  13464     bcm_gport_t vxlan_port_id;
  13465     uint32 reg_val=0;
  13466     uint32 vp=0;
  13467 
  13468     if (vpn != BCM_VXLAN_VPN_INVALID) {
  13469         _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
  13470         BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_eline(unit, vpn, &isEline));
  13471     } else {
  13472         vfi_index = _BCM_VXLAN_VFI_INVALID;
  13473     }
  13474 
  13475     if (isEline == 0x1 ) {
  13476          /* ---- Read in current table values for VP1 and VP2 ----- */
  13477          (void) _bcm_td2_vxlan_eline_vp_map_get (unit, vfi_index,  &vp1,  &vp2);
  13478          if (vp1 != 0) {
  13479               rv = _bcm_td2_vxlan_eline_port_delete(unit, vpn, vp1);
  13480               BCM_IF_ERROR_RETURN(rv);
  13481          }
  13482          if (vp2 != 0) {
  13483               rv = _bcm_td2_vxlan_eline_port_delete(unit, vpn, vp2);
  13484               BCM_IF_ERROR_RETURN(rv);
  13485          }
  13486     } else if (isEline == 0x0 ) {
  13487         uint32 num_vp = 0, entry_type = 0;
  13488         source_vp_entry_t svp;
  13489         if (SOC_REG_IS_VALID(unit, VXLAN_DEFAULT_NETWORK_SVPr)) {
  13490             BCM_IF_ERROR_RETURN(READ_VXLAN_DEFAULT_NETWORK_SVPr(unit, &reg_val));
  13491             vp = soc_reg_field_get(unit, VXLAN_DEFAULT_NETWORK_SVPr, reg_val, SVPf);
  13492             if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  13493                 BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_default_port_delete(unit, vpn, vp));
  13494 #if defined(BCM_TRIDENT3_SUPPORT)
  13495                 if (SOC_REG_IS_VALID(unit, DEFAULT_SVP_ENABLEr)) {
  13496                     rv = soc_reg_field32_modify (unit, DEFAULT_SVP_ENABLEr,
  13497                              REG_PORT_ANY, VXLAN_DEFAULT_SVP_ENABLEf, 0);
  13498                     if (SOC_FAILURE(rv)) {
  13499                         if (rv == SOC_E_NOT_FOUND) {
  13500                             rv = SOC_E_NONE;
  13501                         } else {
  13502                             return rv;
  13503                         }
  13504                     }
  13505                 }
  13506 #endif
  13507             }
  13508         }
  13509         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  13510         SHR_BIT_ITER(VIRTUAL_INFO(unit)->vxlan_vp_bitmap, num_vp, vp) {
  13511 
  13512             BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
  13513             entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf);
  13514             if ((vfi_index == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf) &&
  13515                     entry_type == _BCM_VXLAN_SOURCE_VP_TYPE_VFI)
  13516 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  13517                     || SHR_BITGET(VIRTUAL_INFO(unit)->vp_shared_vp_bitmap, vp)
  13518 #endif
  13519                     ) {
  13520                 if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVpLag)) {
  13521                     bcm_trunk_t        tid = 0;
  13522                     bcm_trunk_member_t trunk_member;
  13523                     int                port_count = 0;
  13524                     BCM_IF_ERROR_RETURN(
  13525                         _bcm_esw_trunk_vp_lag_vp_to_tid(unit, vp, &tid));
  13526                     BCM_IF_ERROR_RETURN(
  13527                         bcm_td2_vp_lag_get(unit, tid, NULL, 1,
  13528                                            &trunk_member, &port_count));
  13529                     if (BCM_GPORT_IS_NIV_PORT(trunk_member.gport) ||
  13530                         BCM_GPORT_IS_EXTENDER_PORT(trunk_member.gport)) {
  13531                         BCM_IF_ERROR_RETURN(
  13532                             _bcm_vp_free(unit, _bcmVpTypeVxlan, 1, vp));
  13533                         BCM_IF_ERROR_RETURN(
  13534                             _bcm_td2_vxlan_access_niv_pe_reset(unit, vp));
  13535                         continue;
  13536                     }
  13537                 }
  13538                    /* Set VXLAN port ID */
  13539                 BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port_id, vp);
  13540                 BCM_IF_ERROR_RETURN(bcm_td2_vxlan_port_delete(unit, vpn, vxlan_port_id));
  13541             }
  13542         }
  13543     }
  13544     return rv;
  13545 }
  13546 
  13547 /*
  13548  * Function:
  13549  *      bcm_td2_vxlan_port_get
  13550  * Purpose:
  13551  *      Get an VXLAN port from a VPN
  13552  * Parameters:
  13553  *      unit       - (IN) Device Number
  13554  *      vpn        - (IN) VPN instance ID
  13555  *      vxlan_port  - (IN/OUT) VXLAN port information
  13556  */
  13557 int
  13558 bcm_td2_vxlan_port_get(int unit, bcm_vpn_t vpn, bcm_vxlan_port_t *vxlan_port)
  13559 {
  13560     int vp=0;
  13561     int rv = BCM_E_NONE;
  13562     uint32 reg_val = 0;
  13563     int default_vp = -1;
  13564     if (BCM_GPORT_IS_TRUNK(vxlan_port->vxlan_port_id)) {
  13565         bcm_trunk_member_t trunk_member;
  13566         int                port_count = 0;
  13567         bcm_trunk_t        tid = 0;
  13568         int                tid_is_vp_lag = FALSE;
  13569         if (vpn != BCM_VXLAN_VPN_INVALID) {
  13570             BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_valid(unit, vpn));
  13571         }
  13572         tid = BCM_GPORT_TRUNK_GET(vxlan_port->vxlan_port_id);
  13573         BCM_IF_ERROR_RETURN(
  13574             _bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag));
  13575         if (tid_is_vp_lag) {
  13576             BCM_IF_ERROR_RETURN(
  13577                 bcm_td2_vp_lag_get(unit, tid, NULL, 1,
  13578                                    &trunk_member, &port_count));
  13579             if (BCM_GPORT_IS_NIV_PORT(trunk_member.gport) ||
  13580                 BCM_GPORT_IS_EXTENDER_PORT(trunk_member.gport)) {
  13581                 BCM_IF_ERROR_RETURN(
  13582                     _bcm_esw_trunk_tid_to_vp_lag_vp(unit, tid, &vp));
  13583                 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  13584                     return BCM_E_NOT_FOUND;
  13585                 }
  13586                 return BCM_E_NONE;
  13587             }
  13588         }
  13589     }
  13590 
  13591     if (SOC_REG_IS_VALID(unit, VXLAN_DEFAULT_NETWORK_SVPr)) {
  13592         BCM_IF_ERROR_RETURN(READ_VXLAN_DEFAULT_NETWORK_SVPr(unit, &reg_val));
  13593         default_vp = soc_reg_field_get(unit,
  13594                             VXLAN_DEFAULT_NETWORK_SVPr, reg_val, SVPf);
  13595     }
  13596 
  13597     vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
  13598     if (vp == -1) {
  13599         return BCM_E_PARAM;
  13600     }
  13601 
  13602     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  13603         return BCM_E_NOT_FOUND;
  13604     }
  13605 
  13606     if (vpn != BCM_VXLAN_VPN_INVALID) {
  13607         BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_valid(unit, vpn));
  13608     }
  13609 
  13610     if (vp == default_vp) {
  13611         rv = _bcm_td2_vxlan_default_port_get(unit, vp, vxlan_port);
  13612     } else {
  13613         if (vxlan_port->flags & BCM_VXLAN_PORT_VPN_BASED) {
  13614             rv = _bcm_td2_vxlan_vp_based_vnid_get(unit, vpn, vxlan_port);
  13615         } else {
  13616         rv = _bcm_td2_vxlan_port_get(unit, vpn, vp, vxlan_port);
  13617     }
  13618     }
  13619 
  13620     return rv;
  13621 }
  13622 
  13623 /*
  13624  * Function:
  13625  *      bcm_td2_vxlan_port_get_all
  13626  * Purpose:
  13627  *      Get all VXLAN ports from a VPN
  13628  * Parameters:
  13629  *      unit     - (IN) Device Number
  13630  *      vpn      - (IN) VPN instance ID
  13631  *      port_max   - (IN) Maximum number of interfaces in array
  13632  *      port_array - (OUT) Array of VXLAN ports
  13633  *      port_count - (OUT) Number of interfaces returned in array
  13634  */
  13635 int
  13636 bcm_td2_vxlan_port_get_all(int unit, bcm_vpn_t vpn, int port_max,
  13637                          bcm_vxlan_port_t *port_array, int *port_count)
  13638 {
  13639     int vp, rv = BCM_E_NONE;
  13640     int vfi_index=-1;
  13641     int vp1 = 0, vp2 = 0;
  13642     uint8 isEline = 0;
  13643     SHR_BITDCL *share_vp_bitmap = NULL;
  13644 
  13645     if (vpn != BCM_VXLAN_VPN_INVALID) {
  13646         _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
  13647         BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_vpn_is_eline(unit, vpn, &isEline));
  13648     } else {
  13649         vfi_index = _BCM_VXLAN_VFI_INVALID;
  13650     }
  13651 
  13652     *port_count = 0;
  13653 
  13654     if (isEline == 0x1 ) {
  13655         /* ---- Read in current table values for VP1 and VP2 ----- */
  13656         (void) _bcm_td2_vxlan_eline_vp_map_get (unit, vfi_index,  &vp1,  &vp2);
  13657         vp = vp1;
  13658         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  13659             if (0 == port_max) {
  13660                 (*port_count)++;
  13661 
  13662             } else if (*port_count < port_max) {
  13663                 rv = _bcm_td2_vxlan_port_get(unit, vpn, vp, 
  13664                                            &port_array[*port_count]);
  13665                 if (rv < 0) {
  13666                     return rv;
  13667                 }
  13668                 (*port_count)++;
  13669             }
  13670         }
  13671 
  13672         vp = vp2;
  13673         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  13674             if (0 == port_max) {
  13675                 (*port_count)++;
  13676 
  13677             } else if (*port_count < port_max) {
  13678                 rv = _bcm_td2_vxlan_port_get(unit, vpn, vp, 
  13679                                            &port_array[*port_count]);
  13680                 if (rv < 0) {
  13681                     return rv;
  13682                 }
  13683                 (*port_count)++;
  13684             }
  13685         }
  13686     } else if (isEline == 0x0 ) {
  13687         uint32 entry_type = 0;
  13688         source_vp_entry_t svp;
  13689         int num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  13690 
  13691         share_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "sharr_vp_bitmap");
  13692         if (share_vp_bitmap == NULL) {
  13693             return BCM_E_MEMORY;
  13694         }
  13695         sal_memset(share_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
  13696 
  13697 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  13698         if (soc_feature(unit, soc_feature_vp_sharing)) {
  13699             rv = bcm_td2p_share_vp_get(unit, vpn, share_vp_bitmap);
  13700             _BCM_VXLAN_CLEANUP(rv)
  13701         }
  13702 #endif
  13703 
  13704         SHR_BIT_ITER(VIRTUAL_INFO(unit)->vxlan_vp_bitmap, num_vp, vp) {
  13705 
  13706             rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
  13707             _BCM_VXLAN_CLEANUP(rv)
  13708             entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf);
  13709 
  13710             if ((vfi_index == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf) &&
  13711                     entry_type == _BCM_VXLAN_SOURCE_VP_TYPE_VFI)
  13712 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  13713                     || SHR_BITGET(share_vp_bitmap, vp)
  13714 #endif
  13715                     ) {
  13716 
  13717                 /* Check if number of ports is requested */
  13718                 if (0 == port_max) {
  13719                     (*port_count)++;
  13720                     continue;
  13721                 } else if (*port_count == port_max) {
  13722                     break;
  13723                 }
  13724 
  13725                rv = _bcm_td2_vxlan_port_get(unit,
  13726                         vpn, vp, &port_array[*port_count]);
  13727                _BCM_VXLAN_CLEANUP(rv)
  13728 
  13729                (*port_count)++;
  13730             }
  13731         }
  13732         sal_free(share_vp_bitmap);
  13733     }
  13734 
  13735     return BCM_E_NONE;
  13736 cleanup:
  13737     sal_free(share_vp_bitmap);
  13738     return rv;
  13739 }
  13740 
  13741 /*
  13742  * Function:
  13743  *      bcm_td2_vxlan_port_learn_set
  13744  * Purpose:
  13745  *      Set the CML bits for a vxlan port.
  13746  * Returns:
  13747  *      BCM_E_XXX
  13748  */
  13749 int
  13750 bcm_td2_vxlan_port_learn_set(int unit, bcm_gport_t vxlan_port_id, 
  13751                                   uint32 flags)
  13752 {
  13753     int vp, cml = 0, rv = BCM_E_NONE, entry_type;
  13754     source_vp_entry_t svp;
  13755 
  13756     rv = _bcm_vxlan_check_init(unit);
  13757 
  13758     if (rv != BCM_E_NONE){
  13759         return rv;
  13760     }
  13761 
  13762     cml = 0;
  13763     if (!(flags & BCM_PORT_LEARN_FWD)) {
  13764        cml |= (1 << 0);
  13765     }
  13766     if (flags & BCM_PORT_LEARN_CPU) {
  13767        cml |= (1 << 1);
  13768     }
  13769     if (flags & BCM_PORT_LEARN_PENDING) {
  13770        cml |= (1 << 2);
  13771     }
  13772     if (flags & BCM_PORT_LEARN_ARL) {
  13773        cml |= (1 << 3);
  13774     }
  13775 
  13776     /* Get the VP index from the gport */
  13777     vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port_id);
  13778 
  13779     MEM_LOCK(unit, SOURCE_VPm);
  13780     /* Be sure the entry is used and is set for VxLAN */
  13781     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  13782         MEM_UNLOCK(unit, SOURCE_VPm);
  13783         return BCM_E_NOT_FOUND;
  13784     }
  13785     /* coverity[negative_returns] */
  13786     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
  13787     if (rv < 0) {
  13788         MEM_UNLOCK(unit, SOURCE_VPm);
  13789         return rv;
  13790     }
  13791 
  13792     /* Ensure that the entry_type is 1 for VxLAN*/
  13793     entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf);
  13794     if (entry_type != 1){
  13795         MEM_UNLOCK(unit, SOURCE_VPm);
  13796         return BCM_E_NOT_FOUND;
  13797     }
  13798 
  13799     soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml);
  13800     soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml);
  13801     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
  13802     MEM_UNLOCK(unit, SOURCE_VPm);
  13803     return rv;
  13804 }
  13805 
  13806 /*
  13807  * Function:    
  13808  *      bcm_td2_vxlan_port_learn_get
  13809  * Purpose:
  13810  *      Get the CML bits for a VxLAN port
  13811  * Returns: 
  13812  *      BCM_E_XXX
  13813  */     
  13814 int     
  13815 bcm_td2_vxlan_port_learn_get(int unit, bcm_gport_t vxlan_port_id,
  13816                                   uint32 *flags)
  13817 {
  13818     int rv, vp, cml = 0, entry_type;
  13819     source_vp_entry_t svp;
  13820     
  13821     rv = _bcm_vxlan_check_init(unit);
  13822 
  13823     if (rv != BCM_E_NONE){
  13824         return rv;
  13825     }
  13826 
  13827     /* Get the VP index from the gport */
  13828     vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port_id);
  13829     if (vp == -1) {
  13830        return BCM_E_PARAM;
  13831     }
  13832 
  13833     /* Be sure the entry is used and is set for VxLAN */
  13834     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  13835         return BCM_E_NOT_FOUND;
  13836     }
  13837     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
  13838     if (rv < 0) {
  13839         return rv;
  13840     }
  13841 
  13842 
  13843     /* Ensure that the entry_type is 1 for VxLAN*/
  13844     entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf);
  13845     if (entry_type != 1){
  13846         return BCM_E_NOT_FOUND;
  13847     }
  13848 
  13849     cml = soc_SOURCE_VPm_field32_get(unit, &svp, CML_FLAGS_NEWf);
  13850     
  13851     *flags = 0;
  13852     if (!(cml & (1 << 0))) {
  13853        *flags |= BCM_PORT_LEARN_FWD;
  13854     }
  13855     if (cml & (1 << 1)) {
  13856        *flags |= BCM_PORT_LEARN_CPU;
  13857     }
  13858     if (cml & (1 << 2)) {
  13859        *flags |= BCM_PORT_LEARN_PENDING;
  13860     }
  13861     if (cml & (1 << 3)) {
  13862        *flags |= BCM_PORT_LEARN_ARL;
  13863     }
  13864     return BCM_E_NONE;
  13865 }
  13866 
  13867 /*
  13868  * Function:
  13869  *      bcm_td2_vxlan_trunk_member_add
  13870  * Purpose:
  13871  *      Activate Trunk Port-membership from 
  13872  *      EGR_PORT_TO_NHI_MAPPING
  13873  * Parameters:
  13874  *     unit  - (IN) Device Number
  13875  *     tgid - (IN)  Trunk Group ID
  13876  *     trunk_member_count - (IN) Count of Trunk members to be added
  13877  *     trunk_member_array - (IN) Trunk member gports to be added
  13878 */
  13879 int
  13880 bcm_td2_vxlan_trunk_member_add(int unit, bcm_trunk_t trunk_id, 
  13881                 int trunk_member_count, bcm_port_t *trunk_member_array) 
  13882 { 
  13883     int idx = 0;
  13884     int rv = BCM_E_NONE;
  13885     uint32 reg_val = 0;
  13886     int nh_index = 0, old_nh_index = -1;
  13887     bcm_l3_egress_t egr;
  13888     int gport = 0;
  13889     _bcm_port_info_t *port_info;
  13890     int local_member = 0;
  13891     uint32 port_flags;
  13892 
  13893     rv = _bcm_trunk_id_validate(unit, trunk_id);
  13894     if (BCM_FAILURE(rv)) {
  13895         return BCM_E_PORT;
  13896     }   
  13897 
  13898     /* Obtain nh_index for trunk_id */
  13899     rv = _bcm_xgs3_trunk_nh_store_get(unit, trunk_id, &nh_index);
  13900     if (nh_index == 0) {
  13901         return rv;
  13902     }
  13903     bcm_l3_egress_t_init(&egr);
  13904     BCM_IF_ERROR_RETURN(bcm_td2_vxlan_egress_get(unit, &egr, nh_index));
  13905 
  13906     if (egr.flags & BCM_L3_VXLAN_ONLY) {
  13907         for (idx = 0; idx < trunk_member_count; idx++) {
  13908             rv = bcm_esw_port_local_get(unit, trunk_member_array[idx], &local_member);
  13909             if (SOC_REG_IS_VALID(unit, EGR_PORT_TO_NHI_MAPPINGr)) {
  13910                 /* Only support trunk local ports */
  13911                 if(BCM_FAILURE(rv)) {
  13912                     continue; 
  13913                 }
  13914                 BCM_IF_ERROR_RETURN(
  13915                         READ_EGR_PORT_TO_NHI_MAPPINGr(unit, local_member, &reg_val));
  13916                 old_nh_index = soc_reg_field_get(unit, EGR_PORT_TO_NHI_MAPPINGr, reg_val, NEXT_HOP_INDEXf);
  13917                 if (!old_nh_index) {
  13918                     /* Set EGR_PORT_TO_NHI_MAPPING */
  13919                     BCM_IF_ERROR_RETURN(
  13920                         soc_reg_field32_modify(unit, EGR_PORT_TO_NHI_MAPPINGr,
  13921                             local_member, NEXT_HOP_INDEXf, nh_index));
  13922                 }
  13923             } else {
  13924                 /* Support trunk remote gports */
  13925                 gport = trunk_member_array[idx];
  13926                 BCM_IF_ERROR_RETURN(
  13927                     _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index));
  13928                 
  13929                 if (!old_nh_index) {
  13930                     BCM_IF_ERROR_RETURN(
  13931                         _bcm_trx_gport_to_nhi_set(unit, gport, nh_index));
  13932                 }
  13933             }
  13934 
  13935             /* Only count the number of VPs on local physical ports */
  13936             if(BCM_SUCCESS(rv)) {
  13937                 _bcm_port_info_access(unit, local_member, &port_info);
  13938                 port_info->vp_count++;
  13939                 BCM_IF_ERROR_RETURN(
  13940                     bcm_esw_port_vlan_member_get(
  13941                         unit, local_member, &port_flags));
  13942                 BCM_IF_ERROR_RETURN(
  13943                     bcm_esw_port_vlan_member_set(
  13944                         unit, local_member, port_flags));
  13945             }
  13946         }
  13947     }
  13948     return BCM_E_NONE;
  13949 }
  13950 
  13951 /*
  13952  * Function:
  13953  *      bcm_td2_vxlan_trunk_member_delete
  13954  * Purpose:
  13955  *      Clear Trunk Port-membership from 
  13956  *      EGR_PORT_TO_NHI_MAPPING and EGR_DGPP_TO_NHI
  13957  * Parameters:
  13958  *     unit  - (IN) Device Number
  13959  *     tgid - (IN)  Trunk Group ID
  13960  *     trunk_member_count - (IN) Count of Trunk members to be deleted
  13961  *     trunk_member_array - (IN) Trunk member gports to be deleted
  13962 */
  13963 int
  13964 bcm_td2_vxlan_trunk_member_delete(int unit, bcm_trunk_t trunk_id, 
  13965                 int trunk_member_count, bcm_port_t *trunk_member_array) 
  13966 { 
  13967     int idx = 0;
  13968     int rv = BCM_E_NONE, rv2 = BCM_E_NONE;
  13969     uint32 reg_val = 0;
  13970     int old_nh_index = 0;
  13971     int nh_index = 0;
  13972     bcm_l3_egress_t egr;
  13973     int gport = 0;
  13974     _bcm_port_info_t *port_info;
  13975     int local_member = 0;
  13976     uint32 port_flags;
  13977 
  13978     rv = _bcm_trunk_id_validate(unit, trunk_id);
  13979     if (BCM_FAILURE(rv)) {
  13980         return BCM_E_PORT;
  13981     }
  13982 
  13983     /* Obtain nh_index for trunk_id */
  13984     rv = _bcm_xgs3_trunk_nh_store_get(unit, trunk_id, &nh_index);
  13985     if (nh_index == 0) {
  13986         for (idx = 0; idx < trunk_member_count; idx++) {
  13987             rv2 = bcm_esw_port_local_get(unit, trunk_member_array[idx], &local_member);
  13988             /* Only support trunk local ports for trunk match */
  13989             if(BCM_FAILURE(rv2)) {
  13990                 continue;
  13991             }
  13992             rv += _bcm_td2_vxlan_trunk_table_reset(unit, local_member);
  13993         }
  13994         if (BCM_FAILURE(rv)) {
  13995             return rv;
  13996         }
  13997     } else {
  13998         bcm_l3_egress_t_init(&egr);
  13999         BCM_IF_ERROR_RETURN(bcm_td2_vxlan_egress_get(unit, &egr, nh_index));
  14000 
  14001         if (egr.flags & BCM_L3_VXLAN_ONLY) {
  14002             for (idx = 0; idx < trunk_member_count; idx++) {
  14003                 rv2 = bcm_esw_port_local_get(unit, trunk_member_array[idx], &local_member);
  14004                 if (SOC_REG_IS_VALID(unit, EGR_PORT_TO_NHI_MAPPINGr)) {
  14005                     /* Only support trunk local ports */
  14006                     if(BCM_FAILURE(rv2)) {
  14007                         continue;
  14008                     }
  14009                     BCM_IF_ERROR_RETURN(
  14010                         READ_EGR_PORT_TO_NHI_MAPPINGr(unit, local_member, &reg_val));
  14011                     old_nh_index = soc_reg_field_get(unit, EGR_PORT_TO_NHI_MAPPINGr, reg_val, NEXT_HOP_INDEXf);
  14012                     if (0 != old_nh_index) {
  14013                         /* Reset EGR_PORT_TO_NHI_MAPPING */
  14014                         rv = soc_reg_field32_modify(unit, EGR_PORT_TO_NHI_MAPPINGr,
  14015                                 local_member, NEXT_HOP_INDEXf, 0x0);
  14016                         if (BCM_FAILURE(rv)) {
  14017                             return rv;
  14018                         }
  14019                     }
  14020                 } else {
  14021                     /* Support trunk remote gports */
  14022                     gport = trunk_member_array[idx];
  14023                     BCM_IF_ERROR_RETURN(
  14024                         _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index));
  14025                     
  14026                     if (0 != old_nh_index) {
  14027                         BCM_IF_ERROR_RETURN(
  14028                             _bcm_trx_gport_to_nhi_set(unit, gport, 0));
  14029                     }
  14030                 }
  14031 
  14032                 /* Only count the number of VPs on local physical ports */
  14033                 if(BCM_SUCCESS(rv2)) {
  14034                     _bcm_port_info_access(unit, local_member, &port_info);
  14035                     port_info->vp_count--;
  14036                     BCM_IF_ERROR_RETURN(
  14037                         bcm_esw_port_vlan_member_get(
  14038                             unit, local_member, &port_flags));
  14039                     BCM_IF_ERROR_RETURN(
  14040                         bcm_esw_port_vlan_member_set(
  14041                             unit, local_member, port_flags));
  14042                 }
  14043             }
  14044         }
  14045     }
  14046     return rv;
  14047 }
  14048 
  14049 /*
  14050  * Function:
  14051  *      _bcm_td2_vxlan_match_vp_replace
  14052  * Purpose:
  14053  *      Replace VP value in VXLAN VP's match entry.
  14054  * Parameters:
  14055  *      unit - (IN) SOC unit number. 
  14056  *      vp - (IN) VXLAN VP whose match entry is being replaced.
  14057  *      new_vp - (IN) New VP value.
  14058  *      old_vp - (OUT) Old VP value.
  14059  * Returns:
  14060  *      BCM_X_XXX
  14061  */
  14062 STATIC int
  14063 _bcm_td2_vxlan_match_vp_replace(int unit, int vp, int new_vp, int *old_vp)
  14064 {
  14065     int                rv = BCM_E_NONE;
  14066     soc_mem_t          mem;
  14067     int                key_type = bcmVlanTranslateKeyInvalid;
  14068     uint32             svp_valid, tunnel_index, tunnel_sip;
  14069     int                entry_index;
  14070     int                port, my_modid, stm_idx, i;
  14071     int                local_port[SOC_MAX_NUM_PORTS];
  14072     int                local_port_count = 0;
  14073     uint32 vent[SOC_MAX_MEM_WORDS];
  14074     source_trunk_map_table_entry_t stm_entry;
  14075     uint32 ment[SOC_MAX_MEM_WORDS];
  14076     _bcm_vxlan_match_port_info_t *mkey = NULL;
  14077     int d = 0;
  14078 
  14079     mkey = &(VXLAN_INFO(unit)->match_key[vp]);
  14080 
  14081 #define _BCM_VLXLT_KTYPE_ASSIGN(_ktype, _k) \
  14082     do { \
  14083         if (_ktype == bcmVlanTranslateKeyInvalid) { \
  14084             _ktype = _k; \
  14085         } \
  14086     } while(0)
  14087 
  14088     switch(mkey->flags) {
  14089         case _BCM_VXLAN_PORT_MATCH_TYPE_VLAN:
  14090             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortOuter);
  14091             /* Fall through */
  14092         case _BCM_VXLAN_PORT_MATCH_TYPE_INNER_VLAN:
  14093             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortInner);
  14094             /* Fall through */
  14095         case _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_STACKED:
  14096             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortDouble);
  14097             /* Fall through */
  14098         case _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_PRI:
  14099             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortOuterPri);
  14100             /* Construct lookup key */
  14101             sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  14102 
  14103 #if defined(BCM_TRIDENT3_SUPPORT)
  14104             if (soc_feature(unit, soc_feature_base_valid)) {
  14105                 mem = VLAN_XLATE_1_DOUBLEm;
  14106 
  14107                 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  14108                 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  14109             } else
  14110 #endif
  14111             {
  14112                 mem = VLAN_XLATEm;
  14113 
  14114                 soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1);
  14115             }
  14116 
  14117             if (mkey->modid != -1) {
  14118                 BCM_GPORT_MODPORT_SET(port, mkey->modid, mkey->port);
  14119             } else {
  14120                 BCM_GPORT_TRUNK_SET(port, mkey->trunk_id);
  14121             }
  14122 
  14123             BCM_IF_ERROR_RETURN(
  14124                 _bcm_trx_vlan_translate_entry_assemble(unit, &vent,
  14125                                                        port, key_type,
  14126                                                        mkey->match_inner_vlan,
  14127                                                        mkey->match_vlan));
  14128             soc_mem_lock(unit, mem);
  14129             /* Lookup existing entry */
  14130             rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL,
  14131                                 &entry_index, &vent, &vent, 0);
  14132             if (BCM_FAILURE(rv)) {
  14133                 soc_mem_unlock(unit, mem);
  14134                 return rv;
  14135             }
  14136             /* Replace entry's VP value */
  14137             *old_vp = soc_mem_field32_get(unit, mem, vent, SOURCE_VPf);
  14138             soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, new_vp);
  14139 
  14140             /* Insert new entry */
  14141             rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, &vent);
  14142             soc_mem_unlock(unit, mem);
  14143             if (rv == SOC_E_EXISTS) {
  14144                 rv = BCM_E_NONE;
  14145             } else {
  14146                 return BCM_E_INTERNAL;
  14147             }
  14148             break;
  14149         case _BCM_VXLAN_PORT_MATCH_TYPE_PORT:
  14150             mem = SOURCE_TRUNK_MAP_TABLEm;
  14151 
  14152             soc_mem_lock(unit, mem);
  14153 
  14154             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, 
  14155                               mkey->index, &stm_entry);
  14156             if (BCM_FAILURE(rv)) {
  14157                 soc_mem_unlock(unit, mem);
  14158                 return rv;
  14159             }
  14160             /* Resolve SVP Mode */
  14161             if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) {
  14162                 svp_valid = soc_mem_field32_get(unit, mem, 
  14163                                                 &stm_entry, SVP_VALIDf);
  14164                 if (svp_valid == 0) {
  14165                     soc_mem_unlock(unit, mem);
  14166                     return BCM_E_INTERNAL;
  14167                 }
  14168             }
  14169             *old_vp = soc_mem_field32_get(unit, mem, 
  14170                                           &stm_entry, SOURCE_VPf);
  14171             rv = soc_mem_field32_modify(unit, mem, mkey->index, 
  14172                                         SOURCE_VPf, new_vp);
  14173 
  14174             soc_mem_unlock(unit, mem);
  14175             break;
  14176         case _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK:
  14177             mem = SOURCE_TRUNK_MAP_TABLEm;
  14178 
  14179             /* Get module id for unit. */
  14180             BCM_IF_ERROR_RETURN(
  14181                 bcm_esw_stk_my_modid_get(unit, &my_modid));
  14182 
  14183             BCM_IF_ERROR_RETURN(
  14184                 _bcm_esw_trunk_local_members_get(unit, mkey->trunk_id,
  14185                                                  SOC_MAX_NUM_PORTS,
  14186                                                  local_port,
  14187                                                  &local_port_count));
  14188             soc_mem_lock(unit, mem);
  14189 
  14190             for (i = 0; i < local_port_count; i++) {
  14191                 /* Get index to source trunk map table */
  14192                 rv = _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
  14193                                                            local_port[i],
  14194                                                            &stm_idx);
  14195                 if (BCM_FAILURE(rv)) {
  14196                     soc_mem_unlock(unit, mem);
  14197                     return rv;
  14198                 }
  14199 
  14200                 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, 
  14201                                   stm_idx, &stm_entry);
  14202                 if (BCM_FAILURE(rv)) {
  14203                     soc_mem_unlock(unit, mem);
  14204                     return rv;
  14205                 }
  14206 
  14207                 /* Resolve SVP Mode */
  14208                 if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) {
  14209                     svp_valid = soc_mem_field32_get(unit, mem, 
  14210                                                     &stm_entry, SVP_VALIDf);
  14211                     if (svp_valid == 0) {
  14212                         soc_mem_unlock(unit, mem);
  14213                         return BCM_E_INTERNAL;
  14214                     }
  14215                 }
  14216                 *old_vp = soc_mem_field32_get(unit, mem, 
  14217                                               &stm_entry, SOURCE_VPf);
  14218 
  14219                 rv = soc_mem_field32_modify(unit, mem, stm_idx, 
  14220                                             SOURCE_VPf, new_vp);
  14221                 if (BCM_FAILURE(rv)) {
  14222                     soc_mem_unlock(unit, mem);
  14223                     return rv;
  14224                 }
  14225             }
  14226 
  14227             soc_mem_unlock(unit, mem);
  14228             break;
  14229         case _BCM_VXLAN_PORT_MATCH_TYPE_VNID:
  14230             tunnel_index = mkey->match_tunnel_index;
  14231             tunnel_sip = VXLAN_INFO(unit)->vxlan_tunnel_term[tunnel_index].sip;
  14232 
  14233             sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  14234             mem = MPLS_ENTRYm;
  14235 #if defined(BCM_TRIDENT3_SUPPORT)
  14236             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  14237                 mem = MPLS_ENTRY_SINGLEm;
  14238                 d = 1;
  14239                 soc_mem_field32_set(unit, mem, &ment, BASE_VALIDf, 1);
  14240                 soc_mem_field32_set(unit, mem, &ment,
  14241                     DATA_TYPEf, _BCM_VXLAN_FLEX_DATA_TYPE_IPV4_SIP);
  14242             } else
  14243 #endif
  14244             {
  14245                 soc_mem_field32_set(unit, mem, &ment, VALIDf, 1);
  14246             }
  14247 
  14248             soc_mem_lock(unit, mem);
  14249             soc_mem_field32_set(unit, mem, &ment, BCM_VXLAN_SIP_FIELD(d, SIPf), tunnel_sip);
  14250 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  14251             if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
  14252                 soc_mem_field32_set(unit, mem, &ment, VXLAN_SIP__OVIDf,
  14253                      VXLAN_INFO(unit)->vxlan_tunnel_term[tunnel_index].vlan);
  14254             }
  14255 #endif
  14256             soc_mem_field32_set(unit, mem, &ment,
  14257                 KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_TUNNEL);
  14258             rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY,
  14259                                 &entry_index, &ment, &ment, 0);
  14260             
  14261             if (rv == BCM_E_NOT_FOUND) {
  14262                 rv = BCM_E_PARAM;
  14263             }
  14264 
  14265             if (BCM_FAILURE(rv)) {
  14266                 soc_mem_unlock(unit, mem);
  14267                 return rv;
  14268             }
  14269             
  14270             /* Replace entry's VP value */
  14271             *old_vp = soc_mem_field32_get(unit, mem, &ment, BCM_VXLAN_SIP_FIELD(d, SVPf));
  14272             soc_mem_field32_set(unit, mem, &ment, BCM_VXLAN_SIP_FIELD(d, SVPf), new_vp);
  14273             /* Insert new entry */
  14274             rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, ment);
  14275 
  14276             soc_mem_unlock(unit, mem);
  14277 
  14278             if (rv == SOC_E_EXISTS) {
  14279                 rv = BCM_E_NONE;
  14280             } else {
  14281                 return BCM_E_INTERNAL;
  14282             }
  14283             break;
  14284         case _BCM_VXLAN_PORT_MATCH_TYPE_NONE:
  14285             *old_vp = vp;
  14286             break;
  14287         default:
  14288             return BCM_E_PARAM;
  14289     }
  14290 
  14291 #undef _BCM_VLXLT_KTYPE_ASSIGN
  14292 
  14293     return rv;
  14294 }
  14295 
  14296 /*
  14297  * Function:
  14298  *      bcm_td2_vxlan_port_source_vp_lag_set
  14299  * Purpose:
  14300  *      Set source VP LAG for a VXLAN virtual port.
  14301  * Parameters:
  14302  *      unit - (IN) SOC unit number. 
  14303  *      gport - (IN) VXLAN virtual port GPORT ID. 
  14304  *      vp_lag_vp - (IN) VP representing the VP LAG. 
  14305  * Returns:
  14306  *      BCM_X_XXX
  14307  */
  14308 int
  14309 bcm_td2_vxlan_port_source_vp_lag_set(int unit, bcm_gport_t gport,
  14310         int vp_lag_vp)
  14311 {
  14312     int vp, old_vp;
  14313 
  14314     if (!BCM_GPORT_IS_VXLAN_PORT(gport)) {
  14315         return BCM_E_PARAM;
  14316     }
  14317     vp = BCM_GPORT_VXLAN_PORT_ID_GET(gport);
  14318     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  14319         return BCM_E_PARAM;
  14320     }
  14321 
  14322     /* Set source VP LAG by replacing the SVP field in VXLAN VP's
  14323      * match entry with the VP value representing the VP LAG.
  14324      */
  14325     BCM_IF_ERROR_RETURN
  14326         (_bcm_td2_vxlan_match_vp_replace(unit, vp, vp_lag_vp, &old_vp));
  14327 
  14328     return BCM_E_NONE;
  14329 }
  14330 
  14331 /*
  14332  * Function:
  14333  *      bcm_td2_vxlan_port_source_vp_lag_clear
  14334  * Purpose:
  14335  *      Clear source VP LAG for a VXLAN virtual port.
  14336  * Parameters:
  14337  *      unit - (IN) SOC unit number. 
  14338  *      gport - (IN) VXLAN virtual port GPORT ID. 
  14339  *      vp_lag_vp - (IN) VP representing the VP LAG. 
  14340  * Returns:
  14341  *      BCM_X_XXX
  14342  */
  14343 int
  14344 bcm_td2_vxlan_port_source_vp_lag_clear(int unit, bcm_gport_t gport,
  14345         int vp_lag_vp)
  14346 {
  14347     int vp, old_vp;
  14348 
  14349     if (!BCM_GPORT_IS_VXLAN_PORT(gport)) {
  14350         return BCM_E_PARAM;
  14351     }
  14352     vp = BCM_GPORT_VXLAN_PORT_ID_GET(gport);
  14353     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  14354         return BCM_E_PARAM;
  14355     }
  14356 
  14357     /* Clear source VP LAG by replacing the SVP field in VXLAN VP's
  14358      * match entry with the VP value.
  14359      */
  14360     BCM_IF_ERROR_RETURN
  14361         (_bcm_td2_vxlan_match_vp_replace(unit, vp, vp, &old_vp));
  14362 
  14363     return BCM_E_NONE;
  14364 }
  14365 
  14366 /*
  14367  * Function:
  14368  *      bcm_td2_vxlan_port_source_vp_lag_get
  14369  * Purpose:
  14370  *      Get source VP LAG for a VXLAN virtual port.
  14371  * Parameters:
  14372  *      unit - (IN) SOC unit number. 
  14373  *      gport - (IN) VXLAN virtual port GPORT ID. 
  14374  *      vp_lag_vp - (OUT) VP representing the VP LAG. 
  14375  * Returns:
  14376  *      BCM_X_XXX
  14377  */
  14378 int
  14379 bcm_td2_vxlan_port_source_vp_lag_get(int unit, bcm_gport_t gport,
  14380         int *vp_lag_vp)
  14381 {
  14382     int                rv = BCM_E_NONE;
  14383     soc_mem_t          mem;
  14384     int                key_type = bcmVlanTranslateKeyInvalid;
  14385     bcm_gport_t        vp;
  14386     uint32             svp_valid, tunnel_index, tunnel_sip;
  14387     int                entry_index;
  14388     int                port, my_modid, stm_idx;
  14389     int                local_port[SOC_MAX_NUM_PORTS];
  14390     int                local_port_count = 0;
  14391     uint32 vent[SOC_MAX_MEM_WORDS];
  14392     uint32 ment[SOC_MAX_MEM_WORDS];
  14393     source_trunk_map_table_entry_t stm_entry;
  14394     _bcm_vxlan_match_port_info_t *mkey = NULL;
  14395     int d = 0;
  14396 
  14397     if (!BCM_GPORT_IS_VXLAN_PORT(gport)) {
  14398         return BCM_E_PARAM;
  14399     }
  14400 
  14401     vp = BCM_GPORT_VXLAN_PORT_ID_GET(gport);
  14402     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVxlan)) {
  14403         return BCM_E_PARAM;
  14404     }
  14405 
  14406     mkey = &(VXLAN_INFO(unit)->match_key[vp]);
  14407 
  14408 #define _BCM_VLXLT_KTYPE_ASSIGN(_ktype, _k) \
  14409         do { \
  14410             if (_ktype == bcmVlanTranslateKeyInvalid) { \
  14411                 _ktype = _k; \
  14412             } \
  14413         } while(0)
  14414     
  14415     switch(mkey->flags) {
  14416         case _BCM_VXLAN_PORT_MATCH_TYPE_VLAN:
  14417             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortOuter);
  14418             /* Fall through */
  14419         case _BCM_VXLAN_PORT_MATCH_TYPE_INNER_VLAN:
  14420             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortInner);
  14421             /* Fall through */
  14422         case _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_STACKED:
  14423             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortDouble);
  14424             /* Fall through */
  14425         case _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_PRI:
  14426             _BCM_VLXLT_KTYPE_ASSIGN(key_type, bcmVlanTranslateKeyPortOuterPri);
  14427 
  14428             sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  14429 #if defined(BCM_TRIDENT3_SUPPORT)
  14430             if (soc_feature(unit, soc_feature_base_valid)) {
  14431                 mem = VLAN_XLATE_1_DOUBLEm;
  14432 
  14433                 soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
  14434                 soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
  14435             } else
  14436 #endif
  14437             {
  14438                 mem = VLAN_XLATEm;
  14439 
  14440                 soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1);
  14441             }
  14442 
  14443             if (mkey->modid != -1) {
  14444                 BCM_GPORT_MODPORT_SET(port, mkey->modid, mkey->port);
  14445             } else {
  14446                 BCM_GPORT_TRUNK_SET(port, mkey->trunk_id);
  14447             }
  14448             /* Construct lookup key */
  14449             BCM_IF_ERROR_RETURN(
  14450                 _bcm_trx_vlan_translate_entry_assemble(unit, vent,
  14451                                                        port, key_type,
  14452                                                        mkey->match_inner_vlan,
  14453                                                        mkey->match_vlan));
  14454             soc_mem_lock(unit, mem);
  14455             /* Lookup existing entry */
  14456             rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL,
  14457                                 &entry_index, vent, vent, 0);
  14458             soc_mem_unlock(unit, mem);
  14459             if (BCM_FAILURE(rv)) {
  14460                 return rv;
  14461             }
  14462             /* Get VP value representing VP LAG */
  14463             *vp_lag_vp = soc_mem_field32_get(unit, mem, vent, SOURCE_VPf);
  14464             break;
  14465         case _BCM_VXLAN_PORT_MATCH_TYPE_PORT:
  14466             mem = SOURCE_TRUNK_MAP_TABLEm;
  14467 
  14468             soc_mem_lock(unit, mem);
  14469 
  14470             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, 
  14471                               mkey->index, &stm_entry);
  14472             soc_mem_unlock(unit, mem);
  14473             if (BCM_FAILURE(rv)) {
  14474                 return rv;
  14475             }
  14476             /* Resolve SVP Mode */
  14477             if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) {
  14478                 svp_valid = soc_mem_field32_get(unit, mem, 
  14479                                                 &stm_entry, SVP_VALIDf);
  14480                 if (svp_valid == 0) {
  14481                     return BCM_E_INTERNAL;
  14482                 }
  14483             }
  14484             /* Get VP value representing VP LAG */
  14485             *vp_lag_vp = soc_mem_field32_get(unit, mem, 
  14486                                              &stm_entry, SOURCE_VPf);
  14487             break;
  14488         case _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK:
  14489             mem = SOURCE_TRUNK_MAP_TABLEm;
  14490 
  14491             /* Get module id for unit. */
  14492             BCM_IF_ERROR_RETURN(
  14493                 bcm_esw_stk_my_modid_get(unit, &my_modid));
  14494 
  14495             BCM_IF_ERROR_RETURN(
  14496                 _bcm_esw_trunk_local_members_get(unit, mkey->trunk_id,
  14497                                                  SOC_MAX_NUM_PORTS,
  14498                                                  local_port,
  14499                                                  &local_port_count));
  14500 
  14501             /* Get index to source trunk map table,
  14502              * Only get it from the first member in LAG
  14503              */
  14504             rv = _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
  14505                                                        local_port[0],
  14506                                                        &stm_idx);
  14507             if (BCM_FAILURE(rv)) {
  14508                 return rv;
  14509             }
  14510 
  14511             soc_mem_lock(unit, mem);
  14512             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, 
  14513                               stm_idx, &stm_entry);
  14514             soc_mem_unlock(unit, mem);
  14515             if (BCM_FAILURE(rv)) {
  14516                 return rv;
  14517             }
  14518 
  14519             /* Resolve SVP Mode */
  14520             if (soc_mem_field_valid(unit, mem, SVP_VALIDf)) {
  14521                 svp_valid = soc_mem_field32_get(unit, mem, 
  14522                                                 &stm_entry, SVP_VALIDf);
  14523                 if (svp_valid == 0) {
  14524                     return BCM_E_INTERNAL;
  14525                 }
  14526             }
  14527             /* Get VP value representing VP LAG */
  14528             *vp_lag_vp = soc_mem_field32_get(unit, mem, 
  14529                                              &stm_entry, SOURCE_VPf);
  14530             break;
  14531         case _BCM_VXLAN_PORT_MATCH_TYPE_VNID:
  14532             tunnel_index = mkey->match_tunnel_index;
  14533             tunnel_sip = VXLAN_INFO(unit)->vxlan_tunnel_term[tunnel_index].sip;
  14534 
  14535             sal_memset(ment, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  14536             mem = MPLS_ENTRYm;
  14537 #if defined(BCM_TRIDENT3_SUPPORT)
  14538             if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  14539                 mem = MPLS_ENTRY_SINGLEm;
  14540                 d = 1;
  14541                 soc_mem_field32_set(unit, mem, ment, BASE_VALIDf, 1);
  14542                 soc_mem_field32_set(unit, mem, &ment,
  14543                     DATA_TYPEf, _BCM_VXLAN_FLEX_DATA_TYPE_IPV4_SIP);
  14544             } else
  14545 #endif
  14546             {
  14547                 soc_mem_field32_set(unit, mem, &ment, VALIDf, 1);
  14548             }
  14549 
  14550             soc_mem_field32_set(unit, mem, &ment, BCM_VXLAN_SIP_FIELD(d, SIPf), tunnel_sip);
  14551 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  14552             if (soc_feature(unit, soc_feature_vrf_aware_vxlan_termination)) {
  14553                 soc_mem_field32_set(unit, mem, &ment, VXLAN_SIP__OVIDf,
  14554                     VXLAN_INFO(unit)->vxlan_tunnel_term[tunnel_index].vlan);
  14555             }
  14556 #endif
  14557             soc_mem_field32_set(unit, mem, &ment,
  14558                 KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_TUNNEL);
  14559             soc_mem_lock(unit, mem);
  14560             rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &entry_index, &ment, &ment, 0);
  14561             soc_mem_unlock(unit, mem);
  14562             if (rv == BCM_E_NOT_FOUND) {
  14563                 rv = BCM_E_PARAM;
  14564             }
  14565 
  14566             if (BCM_FAILURE(rv)) {
  14567                 return rv;
  14568             }
  14569 
  14570             /* Get VP value representing VP LAG */
  14571             *vp_lag_vp = soc_mem_field32_get(unit, mem, &ment, BCM_VXLAN_SIP_FIELD(d, SVPf));
  14572             break;
  14573         default:
  14574             return BCM_E_PARAM;
  14575     }
  14576 
  14577 #undef _BCM_VLXLT_KTYPE_ASSIGN
  14578 
  14579     if (!_bcm_vp_used_get(unit, *vp_lag_vp, _bcmVpTypeVpLag)) {
  14580         return BCM_E_INTERNAL;
  14581     }
  14582 
  14583     return BCM_E_NONE;
  14584 }
  14585 
  14586 int
  14587 _bcm_td2_vxlan_svp_field_set(int unit, bcm_gport_t vp,
  14588     soc_field_t field, int value)
  14589 {
  14590     int rv = BCM_E_NONE;
  14591     source_vp_entry_t svp;
  14592 
  14593     rv = bcm_td2_vxlan_lock(unit);
  14594     if (BCM_FAILURE(rv)) {
  14595         return rv;
  14596     }
  14597     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
  14598     if (rv < 0) {
  14599         bcm_td2_vxlan_unlock(unit);
  14600         return rv;
  14601     }
  14602     if (SOC_MEM_FIELD_VALID(unit, SOURCE_VPm, field)) {
  14603         soc_SOURCE_VPm_field32_set(unit, &svp, field, value);
  14604     }
  14605     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
  14606     bcm_td2_vxlan_unlock(unit);
  14607     return rv;
  14608 }
  14609 
  14610 #ifndef BCM_SW_STATE_DUMP_DISABLE
  14611 /*
  14612  * Function:
  14613  *     _bcm_td2_vxlan_sw_dump
  14614  * Purpose:
  14615  *     Displays VXLAN information maintained by software.
  14616  * Parameters:
  14617  *     unit - Device unit number
  14618  * Returns:
  14619  *     None
  14620  */
  14621 void
  14622 _bcm_td2_vxlan_sw_dump(int unit)
  14623 {
  14624     int i, num_vp;
  14625     _bcm_td2_vxlan_bookkeeping_t *vxlan_info = VXLAN_INFO(unit);
  14626 
  14627     LOG_CLI((BSL_META_U(unit,
  14628                         "Tunnel Initiator Endpoints:\n")));
  14629     for (i = 0; i < _BCM_MAX_NUM_VXLAN_TUNNEL; i++) {
  14630         if (VXLAN_INFO(unit)->vxlan_tunnel_init[i].dip != 0 &&
  14631             VXLAN_INFO(unit)->vxlan_tunnel_init[i].sip != 0 ) {
  14632             LOG_CLI((BSL_META_U(unit,
  14633                                 "Tunnel idx:%d, sip:%x, dip:%x, vlan:%x \n"), i,
  14634                      vxlan_info->vxlan_tunnel_init[i].sip, 
  14635                      vxlan_info->vxlan_tunnel_init[i].dip,
  14636                      vxlan_info->vxlan_tunnel_init[i].vlan));
  14637         }
  14638     }
  14639 
  14640     LOG_CLI((BSL_META_U(unit,
  14641                         "\nTunnel Terminator Endpoints:\n")));
  14642     for (i = 0; i < _BCM_MAX_NUM_VXLAN_TUNNEL; i++) {
  14643         if (VXLAN_INFO(unit)->vxlan_tunnel_term[i].dip != 0 &&
  14644             VXLAN_INFO(unit)->vxlan_tunnel_term[i].sip != 0 ) {
  14645             LOG_CLI((BSL_META_U(unit,
  14646                                 "Tunnel idx:%d, sip:%x, dip:%x, vlan:%x\n"), i,
  14647                      vxlan_info->vxlan_tunnel_term[i].sip, 
  14648                      vxlan_info->vxlan_tunnel_term[i].dip,
  14649                      vxlan_info->vxlan_tunnel_term[i].vlan));
  14650         }
  14651     }
  14652     
  14653     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
  14654 
  14655     LOG_CLI((BSL_META_U(unit,
  14656                         "\n  Match Info    : \n")));
  14657     for (i = 0; i < num_vp; i++) {
  14658         if ((vxlan_info->match_key[i].trunk_id == 0 || 
  14659              vxlan_info->match_key[i].trunk_id == -1) && 
  14660             (vxlan_info->match_key[i].modid == 0 || 
  14661              vxlan_info->match_key[i].modid == -1) &&
  14662             (vxlan_info->match_key[i].port == 0) &&
  14663             (vxlan_info->match_key[i].flags == 0)) {
  14664             continue;
  14665         }
  14666         LOG_CLI((BSL_META_U(unit,
  14667                             "\n  VXLAN port vp = %d\n"), i));
  14668         LOG_CLI((BSL_META_U(unit,
  14669                             "Flags = %x\n"), vxlan_info->match_key[i].flags));
  14670         LOG_CLI((BSL_META_U(unit,
  14671                             "Index = %x\n"), vxlan_info->match_key[i].index));
  14672         LOG_CLI((BSL_META_U(unit,
  14673                             "TGID = %d\n"), vxlan_info->match_key[i].trunk_id));
  14674         LOG_CLI((BSL_META_U(unit,
  14675                             "Modid = %d\n"), vxlan_info->match_key[i].modid));
  14676         LOG_CLI((BSL_META_U(unit,
  14677                             "Port = %d\n"), vxlan_info->match_key[i].port));
  14678         LOG_CLI((BSL_META_U(unit,
  14679                             "Match VLAN = %d\n"), 
  14680                  vxlan_info->match_key[i].match_vlan));
  14681         LOG_CLI((BSL_META_U(unit,
  14682                             "Match Inner VLAN = %d\n"), 
  14683                  vxlan_info->match_key[i].match_inner_vlan));
  14684         LOG_CLI((BSL_META_U(unit,
  14685                             "Match tunnel Index = %x\n"), 
  14686                  vxlan_info->match_key[i].match_tunnel_index));
  14687         LOG_CLI((BSL_META_U(unit,
  14688                             "Match count = %x\n"), 
  14689                  vxlan_info->match_key[i].match_count));
  14690         LOG_CLI((BSL_META_U(unit,
  14691                             "Related VFI = %d\n"), 
  14692                  vxlan_info->match_key[i].vfi));         
  14693     }
  14694     
  14695     LOG_CLI((BSL_META_U(unit,
  14696                         "\nVxlan VPN INFO:\n")));
  14697     for (i = 0; i < soc_mem_index_count(unit, VFIm); i++) {
  14698         if (vxlan_info->vxlan_vpn_info[i].vnid != 0 || 
  14699             vxlan_info->vxlan_vpn_info[i].vxlan_vpn_type != 0 || 
  14700             vxlan_info->vxlan_vpn_info[i].sip != 0) {
  14701             LOG_CLI((BSL_META_U(unit,
  14702                                 "\nVxlan VPN VFI %d:\n"), i));            
  14703             LOG_CLI((BSL_META_U(unit,
  14704                                 "VXLAN VPN TYPE = %d \n"), vxlan_info->vxlan_vpn_info[i].vxlan_vpn_type));
  14705             LOG_CLI((BSL_META_U(unit,
  14706                                 "VXLAN VPN SIP = %x \n"), vxlan_info->vxlan_vpn_info[i].sip));
  14707             LOG_CLI((BSL_META_U(unit,
  14708                                 "VXLAN VPN VNID = %d \n"), vxlan_info->vxlan_vpn_info[i].vnid));
  14709         }
  14710     }
  14711 
  14712     for (i = 0; i < num_vp; i++) {
  14713         if (vxlan_info->vfi_vnid_map_count[i]) {
  14714             LOG_CLI((BSL_META_U(unit,
  14715                                 "\nVxlan VP %d: VP-based VFI-VNID mappings count = %d\n"), i,
  14716                                 vxlan_info->vfi_vnid_map_count[i]));
  14717         }
  14718     }
  14719 
  14720     return;
  14721 }
  14722 #endif /* BCM_SW_STATE_DUMP_DISABLE */
  14723 
  14724 /*
  14725  * Function:
  14726  *      _bcm_td2_vxlan_dip_entry_idx_get
  14727  * Purpose:
  14728  *      Get TD2 vxlan_dip_entry index by VxLAN DIP.
  14729  * Parameters:
  14730  *      unit      - (IN)SOC unit number.
  14731  *      vxlan_dip - (IN)VxLAN DIP.
  14732  *      index     - (OUT)vxlan_dip_entry index.
  14733  * Returns:
  14734  *    BCM_E_XXX
  14735  */
  14736 int
  14737 _bcm_td2_vxlan_dip_entry_idx_get(int unit, 
  14738                                  bcm_ip_t vxlan_dip,
  14739                                  int *index)
  14740 {
  14741     soc_mem_t mem;
  14742     uint32 vent[SOC_MAX_MEM_WORDS];
  14743     int d = 0; /*vxlan decoupled mode*/
  14744 
  14745     sal_memset(vent, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
  14746 
  14747 #if defined(BCM_TRIDENT3_SUPPORT)
  14748      if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  14749         bcm_tunnel_terminator_t tnl_info;
  14750 
  14751         mem = MPLS_ENTRY_SINGLEm;
  14752         d = 1;
  14753         bcm_tunnel_terminator_t_init(&tnl_info);
  14754         _bcm_td2_vxlan_tunnel_terminate_entry_key_set(unit, &tnl_info,
  14755                        vent, 0, 1);
  14756     } else
  14757 #endif
  14758     {
  14759         mem = VLAN_XLATEm;
  14760 
  14761         soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1);
  14762         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, _BCM_VXLAN_KEY_TYPE_LOOKUP_DIP);
  14763     }
  14764 
  14765     soc_mem_field32_set(unit, mem, vent, BCM_VXLAN_DIP_FIELD(d,DIPf), vxlan_dip);
  14766 
  14767     return soc_mem_search(unit, mem, MEM_BLOCK_ANY, index, vent, vent, 0);
  14768 }
  14769 
  14770 /*
  14771  * Function:
  14772  *      _bcm_esw_vxlan_dip_stat_get_table_info
  14773  * Description:
  14774  *      Provides relevant flex table information(table-name,index with
  14775  *      direction)  for given ingress interface.
  14776  *
  14777  * Parameters:
  14778  *      unit             - (IN) unit number
  14779  *      vxlan_dip     - (IN) vxlan dip
  14780  *      num_of_tables    - (OUT) Number of flex counter tables
  14781  *      table_info       - (OUT) Flex counter tables information
  14782  *
  14783  * Return Value:
  14784  *      BCM_E_XXX
  14785  * Notes:
  14786  */
  14787 
  14788 static 
  14789 bcm_error_t _bcm_td2_vxlan_dip_stat_get_table_info(
  14790             int                        unit,
  14791             bcm_ip_t                   vxlan_dip,
  14792             uint32                     *num_of_tables,
  14793             bcm_stat_flex_table_info_t *table_info)
  14794 {
  14795 
  14796     int index;
  14797     soc_mem_t mem;
  14798 
  14799     if (!soc_feature(unit,soc_feature_advanced_flex_counter)) {
  14800         return BCM_E_UNAVAIL;
  14801     }
  14802 
  14803 #if defined(BCM_TRIDENT3_SUPPORT)
  14804     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  14805         return BCM_E_UNAVAIL;
  14806     }
  14807 #endif
  14808 
  14809     /* Parameter validation checks */
  14810     if (!SOC_UNIT_VALID(unit)) {
  14811         return BCM_E_UNIT;
  14812     }
  14813 
  14814     BCM_IF_ERROR_RETURN
  14815         (_bcm_td2_vxlan_dip_entry_idx_get(unit, vxlan_dip, &index)); 
  14816 
  14817 #if defined(BCM_TRIDENT3_SUPPORT)
  14818     if (soc_feature(unit, soc_feature_vxlan_decoupled_mode)) {
  14819         mem = MPLS_ENTRY_SINGLEm;
  14820     } else
  14821 #endif
  14822     {
  14823         mem = VLAN_XLATEm;
  14824     }
  14825 
  14826     if (vxlan_dip != 0) { 
  14827         table_info[*num_of_tables].table = mem;
  14828         table_info[*num_of_tables].index = index;
  14829         table_info[*num_of_tables].direction = bcmStatFlexDirectionIngress;
  14830         (*num_of_tables)++;
  14831     }
  14832 
  14833     if (*num_of_tables == 0) {
  14834         return BCM_E_PARAM;
  14835     }
  14836 
  14837     return BCM_E_NONE;
  14838 }
  14839 
  14840 /*
  14841  * Function:
  14842  *      _bcm_td2_vxlan_dip_stat_counter_get
  14843  * Description:
  14844  *      Get counter statistic values for specific vxlan dip
  14845  *      if sync_mode is set, sync the sw accumulated count
  14846  *      with hw count value first, else return sw count.  
  14847  *
  14848  * Parameters:
  14849  *      unit             - (IN) unit number
  14850  *      sync_mode        - (IN) hwcount is to be synced to sw count 
  14851  *      vxlan_dip        - (IN) vxlan dip information
  14852  *      stat             - (IN) Type of the counter to retrieve
  14853  *                              I.e. ingress/egress byte/packet)
  14854  *      num_entries      - (IN) Number of counter Entries
  14855  *      counter_indexes  - (IN) Pointer to Counter indexes entries
  14856  *      counter_values   - (OUT) Pointer to counter values
  14857  *
  14858  * Return Value:
  14859  *      BCM_E_XXX
  14860  * Notes:
  14861  */
  14862 bcm_error_t 
  14863 _bcm_td2_vxlan_dip_stat_counter_get(
  14864             int unit,
  14865             int sync_mode,
  14866             bcm_ip_t vxlan_dip,
  14867             bcm_vxlan_dip_stat_t stat,
  14868             uint32 num_entries,
  14869             uint32 *counter_indexes,
  14870             bcm_stat_value_t *counter_values)
  14871 {
  14872     uint32                          table_count=0;
  14873     uint32                          index_count=0;
  14874     uint32                          num_of_tables=0;
  14875     bcm_stat_flex_direction_t       direction=bcmStatFlexDirectionIngress;
  14876     uint32                          byte_flag=0;
  14877     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
  14878 
  14879     if ((stat == bcmVxlanDipInPackets) ||
  14880         (stat == bcmVxlanDipInBytes)) {
  14881          direction = bcmStatFlexDirectionIngress;
  14882     } else {
  14883          /* direction = bcmStatFlexDirectionEgress; */
  14884          return BCM_E_PARAM;
  14885     }
  14886 
  14887     if ((num_entries > 0) && 
  14888         ((NULL == counter_indexes) || (NULL == counter_values))) {
  14889         return BCM_E_PARAM;
  14890     }
  14891 
  14892     if (stat == bcmVxlanDipInPackets) {
  14893         byte_flag=0;
  14894     } else {
  14895         byte_flag=1; 
  14896     }
  14897 
  14898     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_dip_stat_get_table_info(
  14899                    unit, vxlan_dip,&num_of_tables,&table_info[0]));
  14900 
  14901     for (table_count=0; table_count < num_of_tables; table_count++) {
  14902       if (table_info[table_count].direction == direction) {
  14903           for (index_count=0; index_count < num_entries ; index_count++) {
  14904                /*ctr_offset_info.offset_index = counter_indexes[index_count];*/
  14905             BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get(
  14906                          unit, sync_mode,
  14907                          table_info[table_count].index,
  14908                          table_info[table_count].table,
  14909                          0,
  14910                          byte_flag,
  14911                          counter_indexes[index_count],
  14912                          &counter_values[index_count]));
  14913           }
  14914       }
  14915     }
  14916     return BCM_E_NONE;
  14917 }
  14918 
  14919 /*
  14920  * Function:
  14921  *      _bcm_td2_vxlan_dip_stat_multi_get
  14922  *
  14923  * Description:
  14924  *  Get Multiple vxlan dip counter value for specified IPMC group index for multiple stat
  14925  *  types
  14926  *
  14927  * Parameters:
  14928  *      unit             - (IN) unit number
  14929  *      vxlan_dip     - (IN) vxlan dip
  14930  *      nstat            - (IN) Number of elements in stat array
  14931  *      stat_arr         - (IN) Collected statistics descriptors array
  14932  *      value_arr        - (OUT) Collected counters values
  14933  *
  14934  * Return Value:
  14935  *      BCM_E_XXX
  14936  * Notes:
  14937  */
  14938  bcm_error_t  _bcm_td2_vxlan_dip_stat_multi_get(
  14939                             int                   unit, 
  14940                             bcm_ip_t              vxlan_dip,
  14941                             int                   nstat, 
  14942                             bcm_vxlan_dip_stat_t  *stat_arr,
  14943                             uint64                *value_arr)
  14944 {
  14945     int              rv = BCM_E_NONE;
  14946     int              idx;
  14947     uint32           counter_indexes = 0;
  14948     bcm_stat_value_t counter_values = {0};
  14949     int              sync_mode = 0; 
  14950 
  14951     if ((nstat > 0) && ((NULL == stat_arr) || (NULL == value_arr))) {
  14952         return BCM_E_PARAM;
  14953     }
  14954 
  14955     /* Iterate of all stats array to retrieve flex counter values */
  14956     for (idx = 0; idx < nstat; idx++) {
  14957          BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_dip_stat_counter_get( 
  14958                              unit, sync_mode, vxlan_dip, stat_arr[idx], 
  14959                              1, &counter_indexes, &counter_values));
  14960          if ((stat_arr[idx] == bcmVxlanDipInPackets)) {
  14961              COMPILER_64_SET(value_arr[idx],
  14962                              COMPILER_64_HI(counter_values.packets64),
  14963                              COMPILER_64_LO(counter_values.packets64));
  14964          } else {
  14965              COMPILER_64_SET(value_arr[idx],
  14966                              COMPILER_64_HI(counter_values.bytes),
  14967                              COMPILER_64_LO(counter_values.bytes));
  14968          }
  14969     }
  14970     return rv;
  14971 }
  14972 
  14973 /*
  14974  * Function:
  14975  *      _bcm_td2_vxlan_dip_stat_multi_get32
  14976  *
  14977  * Description:
  14978  *  Get 32bit vxlan dip counter value for specified IPMC group index for multiple stat
  14979  *  types
  14980  *
  14981  * Parameters:
  14982  *      unit             - (IN) unit number
  14983  *      vxlan_dip     - (IN) vxlan dip
  14984  *      nstat            - (IN) Number of elements in stat array
  14985  *      stat_arr         - (IN) Collected statistics descriptors array
  14986  *      value_arr        - (OUT) Collected counters values
  14987  *
  14988  * Return Value:
  14989  *      BCM_E_XXX
  14990  * Notes:
  14991  */
  14992 bcm_error_t  _bcm_td2_vxlan_dip_stat_multi_get32(
  14993                             int                  unit, 
  14994                             bcm_ip_t             vxlan_dip,
  14995                             int                  nstat, 
  14996                             bcm_vxlan_dip_stat_t *stat_arr,
  14997                             uint32               *value_arr)
  14998 {
  14999     int              rv = BCM_E_NONE;
  15000     int              idx;
  15001     uint32           counter_indexes = 0;
  15002     bcm_stat_value_t counter_values = {0};
  15003     int              sync_mode = 0; 
  15004 
  15005     if ((nstat > 0) && ((NULL == stat_arr) || (NULL == value_arr))) {
  15006         return BCM_E_PARAM;
  15007     }
  15008 
  15009     /* Iterate of all stats array to retrieve flex counter values */
  15010     for (idx = 0; idx < nstat; idx++) {
  15011          BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_dip_stat_counter_get( 
  15012                              unit, sync_mode, vxlan_dip, stat_arr[idx], 
  15013                              1, &counter_indexes, &counter_values));
  15014          if ((stat_arr[idx] == bcmVxlanDipInPackets)) {
  15015                 value_arr[idx] = counter_values.packets;
  15016          } else {
  15017              value_arr[idx] = COMPILER_64_LO(counter_values.bytes);
  15018          }
  15019     }
  15020     return rv;
  15021 }
  15022 
  15023 /*
  15024  * Function:
  15025  *      _bcm_td2_vxlan_dip_stat_counter_set
  15026  * Description:
  15027  *      Set counter statistic values for specific vxlan dip
  15028  *
  15029  * Parameters:
  15030  *      unit             - (IN) unit number
  15031  *      vxlan_dip     - (IN) vxlan dip
  15032  *      stat             - (IN) Type of the counter to retrieve
  15033  *                              I.e. ingress/egress byte/packet)
  15034  *      num_entries      - (IN) Number of counter Entries
  15035  *      counter_indexes  - (IN) Pointer to Counter indexes entries
  15036  *      counter_values   - (IN) Pointer to counter values
  15037  *
  15038  * Return Value:
  15039  *      BCM_E_XXX
  15040  * Notes:
  15041  */
  15042 bcm_error_t 
  15043 _bcm_td2_vxlan_dip_stat_counter_set(
  15044             int unit,
  15045             bcm_ip_t vxlan_dip,
  15046             bcm_vxlan_dip_stat_t stat,
  15047             uint32 num_entries,
  15048             uint32 *counter_indexes,
  15049             bcm_stat_value_t *counter_values)
  15050 {
  15051     uint32                          table_count=0;
  15052     uint32                          index_count=0;
  15053     uint32                          num_of_tables=0;
  15054     bcm_stat_flex_direction_t       direction=bcmStatFlexDirectionIngress;
  15055     uint32                          byte_flag=0;
  15056     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
  15057     
  15058     if ((stat == bcmVxlanDipInPackets) ||
  15059         (stat == bcmVxlanDipInBytes)) {
  15060          direction = bcmStatFlexDirectionIngress;
  15061     } else {
  15062          /* direction = bcmStatFlexDirectionEgress; */
  15063          return BCM_E_PARAM;
  15064     }
  15065 
  15066     if ((num_entries > 0) &&
  15067         ((NULL == counter_indexes) || (NULL == counter_values))) {
  15068         return BCM_E_PARAM;
  15069     }
  15070 
  15071     if (stat == bcmVxlanDipInPackets) {
  15072         byte_flag=0;
  15073     } else {
  15074         byte_flag=1; 
  15075     }
  15076 
  15077     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_dip_stat_get_table_info(
  15078                    unit, vxlan_dip, &num_of_tables, &table_info[0]));
  15079 
  15080     for (table_count=0; table_count < num_of_tables; table_count++) {
  15081       if (table_info[table_count].direction == direction) {
  15082           for (index_count=0; index_count < num_entries; index_count++) {
  15083             BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set(
  15084                                 unit,
  15085                                 table_info[table_count].index,
  15086                                 table_info[table_count].table,
  15087                                 0,
  15088                                 byte_flag,
  15089                                 counter_indexes[index_count],
  15090                                 &counter_values[index_count]));
  15091           }
  15092       }
  15093     }
  15094     return BCM_E_NONE;
  15095 }
  15096 
  15097 /*
  15098  * Function:
  15099  *      _bcm_esw_vxlan_dip_stat_counter_get
  15100  * Description:
  15101  *      Get counter statistic values for specific vxlan dip
  15102  *
  15103  * Parameters:
  15104  *      unit             - (IN) unit number
  15105  *      sync_mode        - (IN) if 1 sync sw count value with hw count
  15106  *                              before retieving count else get
  15107  *                              sw accumulated count
  15108  *      vxlan_dip      - (IN) vxlan dip
  15109  *      stat             - (IN) Type of the counter to retrieve
  15110  *                              I.e. ingress/egress byte/packet)
  15111  *      num_entries      - (IN) Number of counter Entries
  15112  *      counter_indexes  - (IN) Pointer to Counter indexes entries
  15113  *      counter_values   - (OUT) Pointer to counter values
  15114  *
  15115  * Return Value:
  15116  *      BCM_E_XXX
  15117  * Notes:
  15118  */
  15119 bcm_error_t
  15120 _bcm_esw_vxlan_dip_stat_counter_get(
  15121                                int                unit,
  15122                                int                sync_mode,
  15123                                bcm_ip_t           vxlan_dip,
  15124                                bcm_vxlan_dip_stat_t  stat,
  15125                                uint32             num_entries,
  15126                                uint32             *counter_indexes,
  15127                                bcm_stat_value_t   *counter_values)
  15128 {
  15129 #if defined(BCM_TRIDENT2_SUPPORT)
  15130     if (SOC_IS_TD2_TT2(unit)) { 
  15131         return _bcm_td2_vxlan_dip_stat_counter_get(unit, sync_mode, vxlan_dip, stat, 
  15132                     num_entries, counter_indexes, counter_values);
  15133     } else
  15134 #endif
  15135     {
  15136         return BCM_E_UNAVAIL;
  15137     }
  15138 }
  15139 
  15140 
  15141 /*
  15142  * Function:
  15143  *     _bcm_td2_vxlan_dip_stat_multi_set
  15144  *
  15145  * Description:
  15146  *  Set vxlan dip counter value for specified IPMC group index for multiple stat
  15147  *  types
  15148  *
  15149  * Parameters:
  15150  *      unit             - (IN) unit number
  15151  *      vxlan_dip    - (IN) vxlan dip
  15152  *      stat             - (IN) IPMC group counter stat types
  15153  *      num_entries      - (IN) Number of counter Entries
  15154  *      counter_indexes  - (IN) Pointer to Counter indexes entries
  15155  *      counter_values   - (OUT) Pointer to counter values
  15156  *
  15157  * Return Value:
  15158  *      BCM_E_XXX
  15159  * Notes:
  15160  */
  15161 bcm_error_t  _bcm_td2_vxlan_dip_stat_multi_set(
  15162                             int                   unit, 
  15163                             bcm_ip_t              vxlan_dip,
  15164                             int                   nstat, 
  15165                             bcm_vxlan_dip_stat_t  *stat_arr,
  15166                             uint64                *value_arr)
  15167 {
  15168     int              rv = BCM_E_NONE;
  15169     int              idx;
  15170     uint32           counter_indexes = 0;
  15171     bcm_stat_value_t counter_values = {0};
  15172 
  15173     if ((nstat > 0) && ((NULL == stat_arr) || (NULL == value_arr))) {
  15174         return BCM_E_PARAM;
  15175     }
  15176 
  15177     /* Iterate f all stats array to retrieve flex counter values */
  15178     for (idx = 0; idx < nstat; idx++) {
  15179          if ((stat_arr[idx] == bcmVxlanDipInPackets)) {
  15180               counter_values.packets = COMPILER_64_LO(value_arr[idx]);
  15181          } else {
  15182               COMPILER_64_SET(counter_values.bytes,
  15183                               COMPILER_64_HI(value_arr[idx]),
  15184                               COMPILER_64_LO(value_arr[idx]));
  15185          }
  15186           BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_dip_stat_counter_set( 
  15187                              unit, vxlan_dip, stat_arr[idx], 
  15188                              1, &counter_indexes, &counter_values));
  15189     }
  15190     return rv;
  15191 
  15192 }
  15193 
  15194 
  15195 
  15196 
  15197 
  15198 /*
  15199  * Function:
  15200  *      _bcm_td2_vxlan_dip_stat_multi_set32
  15201  *
  15202  * Description:
  15203  *  Set 32biv xlan dip counter value for specified IPMC group index for multiple stat
  15204  *  types
  15205  *
  15206  * Parameters:
  15207  *      unit             - (IN) unit number
  15208  *     vxlan_dip     - (IN)vxlan dip
  15209  *      stat             - (IN) IPMC group counter stat types
  15210  *      num_entries      - (IN) Number of counter Entries
  15211  *      counter_indexes  - (IN) Pointer to Counter indexes entries
  15212  *      counter_values   - (OUT) Pointer to counter values
  15213  *
  15214  * Return Value:
  15215  *      BCM_E_XXX
  15216  * Notes:
  15217  */
  15218 
  15219  bcm_error_t  _bcm_td2_vxlan_dip_stat_multi_set32(
  15220                             int                   unit, 
  15221                             bcm_ip_t              vxlan_dip,
  15222                             int                   nstat, 
  15223                             bcm_vxlan_dip_stat_t  *stat_arr,
  15224                             uint32                *value_arr)
  15225 {
  15226     int              rv = BCM_E_NONE;
  15227     int              idx;
  15228     uint32           counter_indexes = 0;
  15229     bcm_stat_value_t counter_values = {0};
  15230 
  15231     if ((nstat > 0)  && ((NULL == stat_arr) || (NULL == value_arr))) {
  15232         return BCM_E_PARAM;
  15233     }
  15234 
  15235     /* Iterate of all stats array to retrieve flex counter values */
  15236     for (idx = 0; idx < nstat; idx++) {
  15237          if ((stat_arr[idx] == bcmVxlanDipInPackets)) {
  15238              counter_values.packets = value_arr[idx];
  15239          } else {
  15240              COMPILER_64_SET(counter_values.bytes,0,value_arr[idx]);
  15241          }
  15242 
  15243          BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_dip_stat_counter_set( 
  15244                              unit, vxlan_dip, stat_arr[idx], 
  15245                              1, &counter_indexes, &counter_values));
  15246     }
  15247     return rv;
  15248 }
  15249 
  15250 /*
  15251  * Function:
  15252  *      _bcm_td2_vxlan_dip_stat_id_get
  15253  * Description:
  15254  *   Retrieve associated stat counter for given VXLAN DIP
  15255  *
  15256  * Parameters:
  15257  *      unit             - (IN) unit number
  15258  *      vxlan_dip      - (IN) vxlan ip
  15259  *      stat             - (IN) Type of the counter to retrieve
  15260  *                              I.e. ingress/egress byte/packet)
  15261  *      Stat_counter_id  - (OUT) Stat Counter ID
  15262  * Return Value:
  15263  *      BCM_E_XXX
  15264  * Notes:
  15265  */
  15266 bcm_error_t 
  15267 _bcm_td2_vxlan_dip_stat_id_get(
  15268             int unit,
  15269             bcm_ip_t vxlan_dip,
  15270             bcm_vxlan_dip_stat_t stat,
  15271             uint32 *stat_counter_id)
  15272 {
  15273     bcm_stat_flex_direction_t  direction=bcmStatFlexDirectionIngress;
  15274     uint32                     num_of_tables=0;
  15275     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
  15276     uint32                     index=0;
  15277     uint32                     num_stat_counter_ids=0;
  15278 
  15279     if ((stat == bcmVxlanDipInPackets) ||
  15280         (stat == bcmVxlanDipInBytes)) {
  15281          direction = bcmStatFlexDirectionIngress;
  15282     } else {
  15283          /* direction = bcmStatFlexDirectionEgress; */
  15284          return BCM_E_PARAM;
  15285     }
  15286 
  15287     if (NULL == stat_counter_id) {
  15288         return BCM_E_PARAM;
  15289     }
  15290 
  15291     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_dip_stat_get_table_info(
  15292                         unit,vxlan_dip,&num_of_tables,&table_info[0]));
  15293     for (index=0; index < num_of_tables; index++) {
  15294          if (table_info[index].direction == direction)
  15295              return _bcm_esw_stat_flex_get_counter_id(
  15296                                   unit, 1, &table_info[index],
  15297                                   &num_stat_counter_ids,stat_counter_id);
  15298     }
  15299     return BCM_E_NOT_FOUND;
  15300 }
  15301 
  15302 /*
  15303  * Function:
  15304  *      _bcm_td2_vxlan_dip_stat_detach
  15305  * Description:
  15306  *      Detach counters entries to the given vxlan dip
  15307  *
  15308  * Parameters:
  15309  *      unit             - (IN) unit number
  15310  *      vxlan_dip     - (IN) vxlan dip
  15311  *
  15312  * Return Value:
  15313  *      BCM_E_XXX
  15314  * Notes:
  15315  */
  15316 bcm_error_t
  15317 _bcm_td2_vxlan_dip_stat_detach(
  15318             int unit,
  15319             bcm_ip_t vxlan_dip)
  15320 {
  15321     uint32                     count=0;
  15322     uint32                     num_of_tables=0;
  15323     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
  15324     bcm_error_t                rv = BCM_E_NONE;
  15325     bcm_error_t                err_code[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {BCM_E_NONE};
  15326 
  15327     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_dip_stat_get_table_info(
  15328                    unit, vxlan_dip,&num_of_tables,&table_info[0]));
  15329 
  15330     for (count=0; count < num_of_tables; count++) {
  15331       if (table_info[count].direction == bcmStatFlexDirectionIngress) {
  15332            rv = _bcm_esw_stat_flex_detach_ingress_table_counters(
  15333                          unit,
  15334                          table_info[count].table,
  15335                          table_info[count].index);
  15336            if (BCM_E_NONE != rv &&
  15337                 BCM_E_NONE == err_code[bcmStatFlexDirectionIngress]) {
  15338                 err_code[bcmStatFlexDirectionIngress] = rv;
  15339            }
  15340       } else {
  15341          return BCM_E_INTERNAL;
  15342       }
  15343     }
  15344     
  15345     BCM_STAT_FLEX_DETACH_RETURN(err_code)
  15346 }
  15347 
  15348 /*
  15349  * Function:
  15350  *      _bcm_td2_vxlan_dip_stat_attach
  15351  * Description:
  15352  *      Attach counters entries to the given vxlan dip
  15353  *
  15354  * Parameters:
  15355  *      unit             - (IN) unit number
  15356  *      vxlan_dip      - (IN) vxlan dip 
  15357  *      stat_counter_id  - (IN) Stat Counter ID.
  15358  *
  15359  * Return Value:
  15360  *      BCM_E_XXX
  15361  */
  15362 bcm_error_t
  15363 _bcm_td2_vxlan_dip_stat_attach(
  15364             int unit,
  15365             bcm_ip_t vxlan_dip,
  15366             uint32 stat_counter_id)
  15367 {
  15368     soc_mem_t                 table[4]={0};
  15369     uint32                    flex_table_index=0;
  15370     bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress;
  15371     uint32                    pool_number=0;
  15372     uint32                    base_index=0;
  15373     bcm_stat_flex_mode_t      offset_mode=0;
  15374     bcm_stat_object_t         object=bcmStatObjectIngPort;
  15375     bcm_stat_group_mode_t     group_mode= bcmStatGroupModeSingle;
  15376     uint32                    count=0;
  15377     uint32                     actual_num_tables=0;
  15378     uint32                     num_of_tables=0;
  15379     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
  15380 
  15381     _bcm_esw_stat_get_counter_id_info(
  15382                   unit, stat_counter_id,
  15383                   &group_mode,&object,&offset_mode,&pool_number,&base_index);
  15384 
  15385     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_object(unit,object,&direction));
  15386     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit,group_mode));
  15387 
  15388     BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info(
  15389                         unit,object,4,&actual_num_tables,&table[0],&direction));
  15390 
  15391     BCM_IF_ERROR_RETURN(_bcm_td2_vxlan_dip_stat_get_table_info(
  15392                    unit, vxlan_dip,&num_of_tables,&table_info[0]));
  15393     for (count=0; count < num_of_tables; count++) {
  15394          for (flex_table_index=0; 
  15395               flex_table_index < actual_num_tables ; 
  15396               flex_table_index++) {
  15397               if ((table_info[count].direction == direction) &&
  15398                   (table_info[count].table == table[flex_table_index]) ) {
  15399                   if (direction == bcmStatFlexDirectionIngress) {
  15400                       return _bcm_esw_stat_flex_attach_ingress_table_counters(
  15401                              unit,
  15402                              table_info[count].table,
  15403                              table_info[count].index,
  15404                              offset_mode,
  15405                              base_index,
  15406                              pool_number);
  15407                   } else {
  15408                       return BCM_E_INTERNAL;
  15409                   }
  15410               }
  15411          }
  15412     }
  15413     return BCM_E_NOT_FOUND;
  15414 }
  15415 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
  15416