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


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * VXLAN API
      8  */
      9 
     10 #include <shared/bsl.h>
     11 #include <soc/defs.h>
     12 #include <sal/core/libc.h>
     13 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(INCLUDE_L3)
     14 #include <soc/drv.h>
     15 #include <soc/scache.h>
     16 #include <soc/util.h>
     17 #include <soc/hash.h>
     18 #include <soc/debug.h>
     19 #include <soc/greyhound2.h>
     20 #include <bcm/types.h>
     21 #include <bcm/error.h>
     22 #include <bcm/l3.h>
     23 #include <bcm_int/esw/mbcm.h>
     24 #include <bcm_int/esw_dispatch.h>
     25 #include <bcm_int/esw/trx.h>
     26 #include <bcm_int/esw/triumph2.h>
     27 #include <bcm_int/esw/hurricane3.h>
     28 #include <bcm_int/esw/greyhound2.h>
     29 #include <bcm_int/esw/vlan.h>
     30 #include <bcm_int/esw/vxlan.h>
     31 #include <bcm_int/esw/stack.h>
     32 #include <bcm_int/esw/switch.h>
     33 #include <bcm_int/esw/l3.h>
     34 #include <bcm_int/esw/port.h>
     35 #include <bcm_int/common/multicast.h>
     36 
     37 /*
     38  * GH2 VXLAN VFI info data structure
     39  */
     40 typedef struct gh2_vxlan_vpn_info_s {
     41     int valid;   /* VFI is valid */
     42     uint32 vnid; /* VNID */
     43 } gh2_vxlan_vpn_info_t;
     44 
     45 /* GH2 VXLAN DVP Type definition */
     46 #define GH2_VXLAN_DEST_VP_TYPE_INVALID   0x0
     47 #define GH2_VXLAN_DEST_VP_TYPE_ACCESS    0x1
     48 #define GH2_VXLAN_DEST_VP_TYPE_TUNNEL    0x2
     49 
     50 /*
     51  * GH2 VXLAN VP info data structure
     52  */
     53 typedef struct gh2_vxlan_vp_info_s {
     54     uint32 vp_type;           /* VP type (GH2_VXLAN_DEST_VP_TYPE_XXX) */
     55     int vfi;                  /* VFI domain */
     56     int ecmp;                 /* ECMP type */
     57     int nh_ecmp_index;        /* Next Hop or ECMP index */
     58     int tpid_valid;           /* TPID is valid */
     59     uint16 tpid_value;        /* The value of outer TPID */
     60     bcm_if_t ch_encap_id;     /* Custom Header encap ID */
     61     int ch_match_id_ipmc;     /* Custom Header Match ID for IPMC */
     62     int ch_match_id_non_ipmc; /* Custom Header Match ID for non-IPMC */
     63 } gh2_vxlan_vp_info_t;
     64 
     65 /*
     66  * GH2 VXLAN Outer TPID info data structure (per system)
     67  */
     68 typedef struct gh2_vxlan_outer_tpid_info_s {
     69     uint16 tpid_value; /* The value of outer TPID */
     70     int ref_count;     /* Reference count */
     71 } gh2_vxlan_outer_tpid_info_t;
     72 
     73 /*
     74  * GH2 VXLAN Ingress VLAN XLATE info data structure
     75  */
     76 typedef struct gh2_vxlan_vlan_xlate_info_s {
     77     int ref_count;     /* Reference count */
     78 } gh2_vxlan_vlan_xlate_info_t;
     79 
     80 typedef struct bcmi_gh2_vxlan_tunnel_endpoint_s {
     81      bcm_ip_t      dip;  /* Tunnel DIP */
     82      bcm_ip_t      sip;  /* Tunnel SIP */
     83      bcm_ip6_t     dip6; /* Tunnel DIP6 */
     84      bcm_ip6_t     sip6; /* Tunnel SIP6 */
     85      uint16        tunnel_state;  /* Multicast Reference Count */
     86      int           activate_flag; /* Tunnel terminator is deactivated or activated */
     87      bcm_vlan_t    vlan; /* Out vlan for tunnel termination */
     88 } COMPILER_ATTRIBUTE((packed)) bcmi_gh2_vxlan_tunnel_endpoint_t;
     89 
     90 /*
     91  * Software book keeping for GH2's VXLAN-LITE related information
     92  */
     93 typedef struct bcmi_gh2_vxlan_bookkeeping_s {
     94     int initialized;  /* Set to TRUE when VXLAN module initialized */
     95     sal_mutex_t vxlan_mutex;                 /* Protection mutex. */
     96     SHR_BITDCL *vxlan_ip_tnl_bitmap;         /* EGR_IP_TUNNEL index bitmap */
     97     _bcm_vxlan_match_port_info_t *match_key; /* Match Key */
     98     bcmi_gh2_vxlan_tunnel_endpoint_t *vxlan_tunnel_term;
     99     bcmi_gh2_vxlan_tunnel_endpoint_t *vxlan_tunnel_init;
    100     int num_vxlan_tnl;
    101     SHR_BITDCL *vxlan_vfi_bitmap;            /* VXLAN VFI bitmap */
    102     gh2_vxlan_vpn_info_t *vxlan_vpn_info;    /* VXLAN per VFI info */
    103     int num_vxlan_vfi;
    104     SHR_BITDCL *vxlan_vp_bitmap;             /* VXLAN Virtual Port bitmap */
    105     SHR_BITDCL *vxlan_network_vp_bitmap;     /* VXLAN Network VP bitmap */
    106     gh2_vxlan_outer_tpid_info_t *vxlan_outer_tpid; /* VXLAN Outer TPID info */
    107     int num_vxlan_outer_tpid;                /* Number of VXLAN outer TPIDs */
    108     gh2_vxlan_vlan_xlate_info_t *vxlan_vlan_xlate; /* VXLAN VLAN XLATE info */
    109     gh2_vxlan_vp_info_t *vxlan_vp_info;      /* VXLAN per VP info */
    110     int num_vxlan_vp;
    111     int riot_enable;                         /* VXLAN RIOT enabled status */
    112     SHR_BITDCL *vxlan_loopback_vp_bitmap;    /* VXLAN Loopback VP bitmap */
    113     int riot_custom_header_index0_ref_count; /* Reference count of
    114                                                 Custom Header index0 */
    115 } bcmi_gh2_vxlan_bookkeeping_t;
    116 
    117 STATIC bcmi_gh2_vxlan_bookkeeping_t
    118     *bcmi_gh2_vxlan_bk_info[BCM_MAX_NUM_UNITS];
    119 
    120 /* Global initialized parameter for VXLAN bookkeeping info */
    121 STATIC uint8 gh2_vxlan_initialized = FALSE;
    122 
    123 #define GH2_VXLAN_INFO(_unit_) (bcmi_gh2_vxlan_bk_info[_unit_])
    124 #define GH2_L3_INFO(_unit_) (&_bcm_l3_bk_info[_unit_])
    125 
    126 /* VXLAN-LITE RIOT enable info (only support for GH2-B0) */
    127 #define GH2_VXLAN_RIOT_ENABLE(_unit_) \
    128     (bcmi_gh2_vxlan_bk_info[_unit_]->riot_enable)
    129 
    130 /*
    131  * VXLAN-LITE VFI usage bitmap operations
    132  */
    133 #define GH2_VXLAN_VFI_USED_GET(_u_, _vfi_)     \
    134     ((GH2_VXLAN_INFO(_u_)->vxlan_vfi_bitmap) ? \
    135     SHR_BITGET(GH2_VXLAN_INFO(_u_)->vxlan_vfi_bitmap, (_vfi_)) : 0)
    136 #define GH2_VXLAN_VFI_USED_SET(_u_, _vfi_)     \
    137     SHR_BITSET(GH2_VXLAN_INFO((_u_))->vxlan_vfi_bitmap, (_vfi_))
    138 #define GH2_VXLAN_VFI_USED_CLR(_u_, _vfi_)     \
    139     SHR_BITCLR(GH2_VXLAN_INFO((_u_))->vxlan_vfi_bitmap, (_vfi_))
    140 
    141 /*
    142  * VXLAN-LITE Virtual Port usage bitmap operations
    143  */
    144 #define GH2_VXLAN_VP_USED_GET(_u_, _vp_)       \
    145     ((GH2_VXLAN_INFO(_u_)->vxlan_vp_bitmap) ?  \
    146     SHR_BITGET(GH2_VXLAN_INFO(_u_)->vxlan_vp_bitmap, (_vp_)) : 0)
    147 #define GH2_VXLAN_VP_USED_SET(_u_, _vp_)       \
    148     SHR_BITSET(GH2_VXLAN_INFO((_u_))->vxlan_vp_bitmap, (_vp_))
    149 #define GH2_VXLAN_VP_USED_CLR(_u_, _vp_)       \
    150     SHR_BITCLR(GH2_VXLAN_INFO((_u_))->vxlan_vp_bitmap, (_vp_))
    151 
    152 /*
    153  * Network Port bit-map for VXLAN-LITE usage bitmap operations
    154  */
    155 #define GH2_VXLAN_NETWORK_VP_USED_GET(_u_, _vp_)      \
    156     ((GH2_VXLAN_INFO(_u_)->vxlan_network_vp_bitmap) ? \
    157     SHR_BITGET(GH2_VXLAN_INFO(_u_)->vxlan_network_vp_bitmap, (_vp_)) : 0)
    158 #define GH2_VXLAN_NETWORK_VP_USED_SET(_u_, _vp_)      \
    159     SHR_BITSET(GH2_VXLAN_INFO((_u_))->vxlan_network_vp_bitmap, (_vp_))
    160 #define GH2_VXLAN_NETWORK_VP_USED_CLR(_u_, _vp_)      \
    161     SHR_BITCLR(GH2_VXLAN_INFO((_u_))->vxlan_network_vp_bitmap, (_vp_))
    162 
    163 /*
    164  * Loopback Port bit-map for VXLAN-LITE RIOT usage bitmap operations
    165  */
    166 #define GH2_VXLAN_LOOPBACK_VP_USED_GET(_u_, _vp_)      \
    167     ((GH2_VXLAN_INFO(_u_)->vxlan_loopback_vp_bitmap) ? \
    168     SHR_BITGET(GH2_VXLAN_INFO(_u_)->vxlan_loopback_vp_bitmap, (_vp_)) : 0)
    169 #define GH2_VXLAN_LOOPBACK_VP_USED_SET(_u_, _vp_)      \
    170     SHR_BITSET(GH2_VXLAN_INFO((_u_))->vxlan_loopback_vp_bitmap, (_vp_))
    171 #define GH2_VXLAN_LOOPBACK_VP_USED_CLR(_u_, _vp_)      \
    172     SHR_BITCLR(GH2_VXLAN_INFO((_u_))->vxlan_loopback_vp_bitmap, (_vp_))
    173 
    174 /* VP applications */
    175 #define GH2_VXLAN_VP_INFO_NETWORK_PORT  0x00000001 /* Network side port */
    176 #define GH2_VXLAN_VP_INFO_SHARED_PORT   0x00000002 /* Shared virtual port */
    177 #define GH2_VXLAN_VP_INFO_LOOPBACK_PORT 0x00000004 /* Loopback side port */
    178 
    179 /* Port Operations */
    180 #define GH2_VXLAN_PORT_OPERATION_NORMAL 0x0 /* Port Operation for normal */
    181 #define GH2_VXLAN_PORT_OPERATION_VFI    0x5 /* Port Operation for VFI */
    182 
    183 /*
    184  * Definitions for VXLAN RIOT port's Custom Header(32 bits)
    185  *  +-------------------------------+
    186  *  |      Ethertype (16 bits)      |
    187  *  +--------------+----------------+
    188  *  | IPMC Flag    | SGPP (15 bits) |
    189  *  +--------------+----------------+
    190  *
    191  *  Field location :
    192  *  - SGPP : b0~b14
    193  *  - IPMC Flag : b15
    194  *  - Ethertype : b16~b31
    195  *
    196  *  Note :
    197  *  - Macros defined below for the term of "CH" means "Custom Header"
    198  */
    199 #define GH2_VXLAN_RIOT_CH_HEADER_MASK        0xffffffff
    200 #define GH2_VXLAN_RIOT_CH_ETHERTYPE_MASK     0xffff
    201 #define GH2_VXLAN_RIOT_CH_ETHERTYPE_OFFSET   16
    202 #define GH2_VXLAN_RIOT_CH_IPMC_OFFSET        15
    203 #define GH2_VXLAN_RIOT_CH_MODID_MASK         0xff
    204 #define GH2_VXLAN_RIOT_CH_MODID_OFFSET       7
    205 #define GH2_VXLAN_RIOT_CH_PORT_MASK          0x7f
    206 #define GH2_VXLAN_RIOT_CH_PORT_OFFSET        0
    207 
    208 /* SW defined a non-common value for VXLAN RIOT usage */
    209 #define GH2_VXLAN_RIOT_CH_ETHERTYPE          0x21cd
    210 
    211 #define GH2_VXLAN_RIOT_CH_ENCAP_VALUE(_ipmc_, _modid_, _port_)             \
    212     ((GH2_VXLAN_RIOT_CH_ETHERTYPE << GH2_VXLAN_RIOT_CH_ETHERTYPE_OFFSET) | \
    213     (((_ipmc_) ? 1 : 0) << GH2_VXLAN_RIOT_CH_IPMC_OFFSET) |                \
    214     (((_modid_) & GH2_VXLAN_RIOT_CH_MODID_MASK) <<                         \
    215      GH2_VXLAN_RIOT_CH_MODID_OFFSET) |                                     \
    216     (((_port_) & GH2_VXLAN_RIOT_CH_PORT_MASK) <<                           \
    217      GH2_VXLAN_RIOT_CH_PORT_OFFSET))
    218 
    219 /* QoS mapping Operations for Custom Header usage */
    220 #define GH2_VXLAN_RIOT_CH_COS_REMAP_NONE 0x0         /* Don't use internal
    221                                                         Priority from CH */
    222 #define GH2_VXLAN_RIOT_CH_COS_REMAP_INT_PRI 0x1      /* Use internal Priority
    223                                                         from CH */
    224 #define GH2_VXLAN_RIOT_CH_COS_REMAP_INT_PRI_MAP 0x2  /* Use L2 QoS mapping
    225                                                         pointer from CH */
    226 #define GH2_VXLAN_RIOT_CH_COS_REMAP_DSCP_QOS_MAP 0x3 /* Use L3 QoS mapping
    227                                                         pointer from CH  */
    228 
    229 typedef struct bcmi_vxlan_vp_info_s {
    230     uint32 flags;
    231 } bcmi_vxlan_vp_info_t;
    232 
    233 #define GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(_unit_, _id_)     \
    234     do {                                                        \
    235         if (((_id_) < 0) ||                                     \
    236             (_id_) >= (GH2_VXLAN_INFO(_unit_)->num_vxlan_tnl)) {\
    237             return BCM_E_BADID;                                 \
    238         }                                                       \
    239     } while (0)
    240 
    241 typedef struct bcmi_gh2_vxlan_nh_info_s {
    242     int entry_type;
    243     int vnid;
    244     int intf_num;
    245     int tunnel_index;
    246     int udp_src_port_range_enable;
    247     int apply_evxlt_modify_to_payload;
    248     int use_nhi_in_evxlt_key;
    249     int payload_otag_delete;
    250     int tunnel_otag_delete;
    251     int tunnel_itag_delete;
    252     int qos_map_id;
    253     int tunnel_pkt_pri;
    254     int tunnel_pkt_cfi;
    255     int custom_header_ipmc;
    256 } bcmi_gh2_vxlan_nh_info_t;
    257 
    258 STATIC int
    259 bcmi_gh2_vxlan_port_vp_get(
    260     int unit,
    261     bcm_vpn_t vpn,
    262     int vp,
    263     bcm_vxlan_port_t *vxlan_port);
    264 
    265 STATIC void
    266 bcmi_gh2_vxlan_match_clear(int unit, int vp);
    267 
    268 STATIC int
    269 bcmi_gh2_vxlan_riot_custom_header_add(
    270     int unit,
    271     bcm_vxlan_port_t *vxlan_port,
    272     bcm_vxlan_port_t *old_vxlan_port,
    273     int vp);
    274 STATIC int
    275 bcmi_gh2_vxlan_riot_custom_header_delete(
    276     int unit,
    277     bcm_vxlan_port_t *vxlan_port,
    278     int vp);
    279 
    280 /*
    281  * Function:
    282  *    gh2_vxlan_bk_info_instance_get
    283  * Description:
    284  *    Helper function to retrieve VXLAN bookkeeping info pointer
    285  * Parameters:
    286  *    unit          - (IN) Device Number
    287  *    vxlan_bk_info - (OUT) VXLAN bookkeeping info data structure
    288  * Returns:
    289  *    BCM_E_XXX
    290  */
    291 STATIC int
    292 gh2_vxlan_bk_info_instance_get(
    293     int unit,
    294     bcmi_gh2_vxlan_bookkeeping_t **vxlan_bk_info)
    295 {
    296     /* Input parameter check */
    297     if (NULL == vxlan_bk_info) {
    298         return BCM_E_PARAM;
    299     }
    300     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
    301         return BCM_E_UNIT;
    302     }
    303 
    304     /* Check if VXLAN-LITE supported and initialized */
    305     if (!soc_feature(unit, soc_feature_vxlan_lite)) {
    306         return BCM_E_UNAVAIL;
    307     }
    308     if (NULL == bcmi_gh2_vxlan_bk_info[unit]) {
    309         LOG_ERROR(BSL_LS_BCM_VXLAN,
    310                   (BSL_META_U(unit,
    311                               "VXLAN bookkeeping info Error: "
    312                               "not initialized\n")));
    313         return BCM_E_INIT;
    314     }
    315     if (!bcmi_gh2_vxlan_bk_info[unit]->initialized) {
    316         LOG_ERROR(BSL_LS_BCM_VXLAN,
    317                   (BSL_META_U(unit,
    318                               "VXLAN module not initialized\n")));
    319         return BCM_E_INIT;
    320     }
    321 
    322     /* Fill info structure. */
    323     *vxlan_bk_info = bcmi_gh2_vxlan_bk_info[unit];
    324 
    325     return BCM_E_NONE;
    326 }
    327 
    328 /*
    329  * Function:
    330  *    bcmi_gh2_vxlan_check_init
    331  * Purpose:
    332  *    Check if VXLAN is initialized
    333  * Parameters:
    334  *    unit - (IN) Device Number
    335  * Returns:
    336  *    BCM_E_XXX
    337  */
    338 STATIC int
    339 bcmi_gh2_vxlan_check_init(int unit)
    340 {
    341     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
    342 
    343     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
    344         return BCM_E_UNIT;
    345     }
    346 
    347     vxlan_info = GH2_VXLAN_INFO(unit);
    348 
    349     if ((vxlan_info == NULL) || (vxlan_info->initialized == FALSE)) {
    350         return BCM_E_INIT;
    351     } else {
    352         return BCM_E_NONE;
    353     }
    354 }
    355 
    356 /*
    357  * Function:
    358  *    bcmi_gh2_vxlan_lock
    359  * Purpose:
    360  *    Take VXLAN Lock Semaphore
    361  * Parameters:
    362  *    unit - (IN) Device Number
    363  * Returns:
    364  *    BCM_E_XXX
    365  */
    366 int
    367 bcmi_gh2_vxlan_lock(int unit)
    368 {
    369     int rv = BCM_E_NONE;
    370 
    371     rv = bcmi_gh2_vxlan_check_init(unit);
    372 
    373     if (rv == BCM_E_NONE) {
    374         sal_mutex_take(GH2_VXLAN_INFO(unit)->vxlan_mutex, sal_mutex_FOREVER);
    375     }
    376 
    377     return rv;
    378 }
    379 
    380 /*
    381  * Function:
    382  *    bcmi_gh2_vxlan_unlock
    383  * Purpose:
    384  *    Release VXLAN Lock Semaphore
    385  * Parameters:
    386  *    unit - (IN) Device Number
    387  * Returns:
    388  *    BCM_E_XXX
    389  */
    390 void
    391 bcmi_gh2_vxlan_unlock(int unit)
    392 {
    393     int rv = BCM_E_NONE;
    394 
    395     rv = bcmi_gh2_vxlan_check_init(unit);
    396 
    397     if (rv == BCM_E_NONE) {
    398         sal_mutex_give(GH2_VXLAN_INFO(unit)->vxlan_mutex);
    399     }
    400 }
    401 
    402 /*
    403  * Function:
    404  *    bcmi_gh2_vxlan_udp_dest_port_set
    405  * Purpose:
    406  *    Set UDP Dest port for VXLAN
    407  * Parameters:
    408  *    unit - (IN) Device Number
    409  *    type - (IN) The desired configuration parameter to modify
    410  *    udp_destport - (IN) UDP Dest port (Non-zero value)
    411  * Returns:
    412  *    BCM_E_XXX.
    413  */
    414 int
    415 bcmi_gh2_vxlan_udp_dest_port_set(
    416     int unit,
    417     bcm_switch_control_t type,
    418     int udp_destport)
    419 {
    420     soc_reg_t reg = INVALIDr ;
    421     soc_field_t reg_field = INVALIDf;
    422     uint64 regval64;
    423     uint32 fieldval;
    424 
    425     COMPILER_64_ZERO(regval64);
    426 
    427     /* Given control type select register. */
    428     switch (type) {
    429         case bcmSwitchVxlanUdpDestPortSet:
    430             reg = ING_VXLAN_CONTROLr;
    431             reg_field = UDP_DST_PORT_NUMBER_1f;
    432             break;
    433         case bcmSwitchVxlanUdpDestPortSet1:
    434             reg = ING_VXLAN_CONTROLr;
    435             reg_field = UDP_DST_PORT_NUMBER_2f;
    436             break;
    437         default:
    438             return BCM_E_PARAM;
    439     }
    440 
    441     if (!SOC_REG_FIELD_VALID(unit, reg, reg_field)) {
    442         return BCM_E_UNAVAIL;
    443     }
    444 
    445     /* input parameter range check */
    446     if ((udp_destport < 0) || (udp_destport > 0xFFFF)) {
    447          return BCM_E_PARAM;
    448     }
    449 
    450     BCM_IF_ERROR_RETURN(
    451         soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &regval64));
    452     fieldval = soc_reg64_field32_get(unit, reg, regval64, reg_field);
    453     if (udp_destport != fieldval) {
    454         soc_reg64_field32_set(unit, reg, &regval64, reg_field, udp_destport);
    455         BCM_IF_ERROR_RETURN(
    456             soc_reg64_set(unit, reg, REG_PORT_ANY, 0, regval64));
    457     }
    458 
    459     return BCM_E_NONE;
    460 }
    461 
    462 /*
    463  * Function:
    464  *    bcmi_gh2_vxlan_udp_dest_port_get
    465  * Purpose:
    466  *    Get UDP Dest port for VXLAN
    467  * Parameters:
    468  *    unit - (IN) Device Number
    469  *    type - (IN) The desired configuration parameter to modify
    470  *    udp_destport - (OUT) UDP Dest port (Non-zero value)
    471  * Returns:
    472  *    BCM_E_XXX.
    473  */
    474 int
    475 bcmi_gh2_vxlan_udp_dest_port_get(
    476     int unit,
    477     bcm_switch_control_t type,
    478     int *udp_destport)
    479 {
    480     soc_reg_t reg = INVALIDr ;
    481     soc_field_t reg_field = INVALIDf;
    482     uint64 regval64;
    483     uint32 fieldval;
    484 
    485     COMPILER_64_ZERO(regval64);
    486 
    487     /* Given control type select register. */
    488     switch (type) {
    489         case bcmSwitchVxlanUdpDestPortSet:
    490             reg = ING_VXLAN_CONTROLr;
    491             reg_field = UDP_DST_PORT_NUMBER_1f;
    492             break;
    493         case bcmSwitchVxlanUdpDestPortSet1:
    494             reg = ING_VXLAN_CONTROLr;
    495             reg_field = UDP_DST_PORT_NUMBER_2f;
    496             break;
    497         default:
    498             return BCM_E_PARAM;
    499     }
    500 
    501     if (!SOC_REG_FIELD_VALID(unit, reg, reg_field)) {
    502         return BCM_E_UNAVAIL;
    503     }
    504 
    505     BCM_IF_ERROR_RETURN(
    506         soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &regval64));
    507     fieldval = soc_reg64_field32_get(unit, reg, regval64, reg_field);
    508 
    509     *udp_destport = fieldval;
    510 
    511     return BCM_E_NONE;
    512 }
    513 
    514 /*
    515  * Function:
    516  *    bcmi_gh2_vxlan_udp_source_port_set
    517  * Purpose:
    518  *    Enable UDP Source port based HASH for VXLAN
    519  * Parameters:
    520  *    unit - (IN) Device Number
    521  *    type - (IN) The desired configuration parameter to modify
    522  *    hash_enable - (IN) Enable Hash for UDP SourcePort
    523  * Returns:
    524  *    BCM_E_XXX.
    525  */
    526 int
    527 bcmi_gh2_vxlan_udp_source_port_set(
    528     int unit,
    529     bcm_switch_control_t type,
    530     int hash_enable)
    531 {
    532     soc_reg_t reg = INVALIDr ;
    533     soc_field_t reg_field = INVALIDf;
    534     uint32 regval, fieldval;
    535 
    536     /* Given control type select register. */
    537     switch (type) {
    538         case bcmSwitchVxlanEntropyEnable:
    539             reg = EGR_VXLAN_CONTROLr;
    540             reg_field = UDP_SOURCE_PORT_SELf;
    541             break;
    542         case bcmSwitchVxlanEntropyEnableIP6:
    543             reg = EGR_VXLAN_CONTROLr;
    544             reg_field = IPV6_FLOW_LABEL_SELf;
    545             break;
    546         default:
    547             return BCM_E_PARAM;
    548     }
    549 
    550     if (!SOC_REG_FIELD_VALID(unit, reg, reg_field)) {
    551         return BCM_E_UNAVAIL;
    552     }
    553 
    554     if ((hash_enable < 0) || (hash_enable > 1)) {
    555          return BCM_E_PARAM;
    556     }
    557 
    558     BCM_IF_ERROR_RETURN(
    559         soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &regval));
    560     fieldval = soc_reg_field_get(unit, reg, regval, reg_field);
    561     if (hash_enable != fieldval) {
    562         soc_reg_field_set(unit, reg, &regval, reg_field, hash_enable);
    563         BCM_IF_ERROR_RETURN(
    564             soc_reg32_set(unit, reg, REG_PORT_ANY, 0, regval));
    565     }
    566 
    567     return BCM_E_NONE;
    568 }
    569 
    570 /*
    571  * Function:
    572  *    bcmi_gh2_vxlan_udp_source_port_get
    573  * Purpose:
    574  *    Get UDP Source port based HASH for VXLAN
    575  * Parameters:
    576  *    unit - (IN) Device Number
    577  *    type - (IN) The desired configuration parameter to modify
    578  *    hash_enable - (OUT) Enable Hash for UDP SourcePort
    579  * Returns:
    580  *    BCM_E_XXX.
    581  */
    582 int
    583 bcmi_gh2_vxlan_udp_source_port_get(
    584     int unit,
    585     bcm_switch_control_t type,
    586     int *hash_enable)
    587 {
    588     soc_reg_t reg = INVALIDr ;
    589     soc_field_t reg_field = INVALIDf;
    590     uint32 regval, fieldval;
    591 
    592     /* Given control type select register. */
    593     switch (type) {
    594         case bcmSwitchVxlanEntropyEnable:
    595             reg = EGR_VXLAN_CONTROLr;
    596             reg_field = UDP_SOURCE_PORT_SELf;
    597             break;
    598         case bcmSwitchVxlanEntropyEnableIP6:
    599             reg = EGR_VXLAN_CONTROLr;
    600             reg_field = IPV6_FLOW_LABEL_SELf;
    601             break;
    602         default:
    603             return BCM_E_PARAM;
    604     }
    605 
    606     if (!SOC_REG_FIELD_VALID(unit, reg, reg_field)) {
    607         return BCM_E_UNAVAIL;
    608     }
    609 
    610     BCM_IF_ERROR_RETURN(
    611         soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &regval));
    612     fieldval = soc_reg_field_get(unit, reg, regval, reg_field);
    613 
    614     *hash_enable = fieldval;
    615 
    616     return BCM_E_NONE;
    617 }
    618 
    619 /*
    620  * Function:
    621  *    bcmi_gh2_vxlan_free_resource
    622  * Purpose:
    623  *    Free all allocated software resources
    624  * Parameters:
    625  *    unit - (IN) Device Number
    626  * Returns:
    627  *    Nothing
    628  */
    629 STATIC void
    630 bcmi_gh2_vxlan_free_resource(int unit)
    631 {
    632     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
    633 
    634     /* If software tables were not allocated we are done. */
    635     if (NULL == GH2_VXLAN_INFO(unit)) {
    636         return;
    637     }
    638 
    639     vxlan_info = GH2_VXLAN_INFO(unit);
    640 
    641     if (vxlan_info->vxlan_mutex != NULL) {
    642         sal_mutex_destroy(vxlan_info->vxlan_mutex);
    643         vxlan_info->vxlan_mutex = NULL;
    644     }
    645 
    646     /* Destroy EGR_IP_TUNNEL usage bitmap */
    647     if (vxlan_info->vxlan_ip_tnl_bitmap) {
    648         sal_free(vxlan_info->vxlan_ip_tnl_bitmap);
    649         vxlan_info->vxlan_ip_tnl_bitmap = NULL;
    650     }
    651 
    652     if (vxlan_info->match_key) {
    653         sal_free(vxlan_info->match_key);
    654         vxlan_info->match_key = NULL;
    655     }
    656 
    657     if (vxlan_info->vxlan_tunnel_init) {
    658         sal_free(vxlan_info->vxlan_tunnel_init);
    659         vxlan_info->vxlan_tunnel_init = NULL;
    660     }
    661 
    662     if (vxlan_info->vxlan_tunnel_term) {
    663         sal_free(vxlan_info->vxlan_tunnel_term);
    664         vxlan_info->vxlan_tunnel_term = NULL;
    665     }
    666 
    667     /* Destroy VXLAN VFI usage bitmap */
    668     if (vxlan_info->vxlan_vfi_bitmap) {
    669         sal_free(vxlan_info->vxlan_vfi_bitmap);
    670         vxlan_info->vxlan_vfi_bitmap = NULL;
    671     }
    672 
    673     /* Destroy VXLAN VFI info */
    674     if (vxlan_info->vxlan_vpn_info) {
    675         sal_free(vxlan_info->vxlan_vpn_info);
    676         vxlan_info->vxlan_vpn_info = NULL;
    677     }
    678 
    679     /* Destroy VXLAN Virtual Port usage bitmap */
    680     if (vxlan_info->vxlan_vp_bitmap) {
    681         sal_free(vxlan_info->vxlan_vp_bitmap);
    682         vxlan_info->vxlan_vp_bitmap = NULL;
    683     }
    684 
    685     /* Destroy Network VXLAN Virtual Port usage bitmap */
    686     if (vxlan_info->vxlan_network_vp_bitmap) {
    687         sal_free(vxlan_info->vxlan_network_vp_bitmap);
    688         vxlan_info->vxlan_network_vp_bitmap = NULL;
    689     }
    690 
    691     /* Destroy VXLAN Outer TPID info */
    692     if (vxlan_info->vxlan_outer_tpid) {
    693         sal_free(vxlan_info->vxlan_outer_tpid);
    694         vxlan_info->vxlan_outer_tpid = NULL;
    695     }
    696 
    697     /* Destroy VXLAN Ingress VLAN XLATE info */
    698     if (vxlan_info->vxlan_vlan_xlate) {
    699         sal_free(vxlan_info->vxlan_vlan_xlate);
    700         vxlan_info->vxlan_vlan_xlate = NULL;
    701     }
    702 
    703     /* Destroy VXLAN VP info */
    704     if (vxlan_info->vxlan_vp_info) {
    705         sal_free(vxlan_info->vxlan_vp_info);
    706         vxlan_info->vxlan_vp_info = NULL;
    707     }
    708 
    709     /* Destroy Loopback VXLAN Virtual Port usage bitmap (used for RIOT) */
    710     if (vxlan_info->vxlan_loopback_vp_bitmap) {
    711         sal_free(vxlan_info->vxlan_loopback_vp_bitmap);
    712         vxlan_info->vxlan_loopback_vp_bitmap = NULL;
    713     }
    714 
    715     /* Free module data. */
    716     sal_free(GH2_VXLAN_INFO(unit));
    717     GH2_VXLAN_INFO(unit) = NULL;
    718 }
    719 
    720 /*
    721  * Function:
    722  *    bcmi_gh2_vxlan_allocate_bk
    723  * Purpose:
    724  *    Initialize VXLAN software book-kepping
    725  * Parameters:
    726  *    unit - (IN) Device Number
    727  * Returns:
    728  *    BCM_E_XXX
    729  */
    730 STATIC int
    731 bcmi_gh2_vxlan_allocate_bk(int unit)
    732 {
    733     /* Allocate/Init unit software tables. */
    734     if (NULL == GH2_VXLAN_INFO(unit)) {
    735         BCMI_VXLAN_ALLOC(GH2_VXLAN_INFO(unit),
    736                          sizeof(bcmi_gh2_vxlan_bookkeeping_t),
    737                          "vxlan_bk_module_data");
    738         if (NULL == GH2_VXLAN_INFO(unit)) {
    739             return BCM_E_MEMORY;
    740         } else {
    741             GH2_VXLAN_INFO(unit)->initialized = FALSE;
    742         }
    743     }
    744 
    745     return BCM_E_NONE;
    746 }
    747 
    748 /*
    749  * Function:
    750  *    bcmi_gh2_vxlan_outer_tpid_ref_inc
    751  * Purpose:
    752  *    Increase reference count for the specified VXLAN outer TPID (per system)
    753  * Parameters:
    754  *    unit       - (IN) unit number
    755  *    tpid_value - (IN) TPID value
    756  * Returns:
    757  *    BCM_E_XXX
    758  * Notes:
    759  */
    760 STATIC int
    761 bcmi_gh2_vxlan_outer_tpid_ref_inc(int unit, uint16 tpid_value)
    762 {
    763     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
    764     gh2_vxlan_outer_tpid_info_t *vxlan_outer_tpid;
    765     int num_tpid, i;
    766 
    767     vxlan_info = GH2_VXLAN_INFO(unit);
    768     if (NULL == vxlan_info) {
    769         LOG_ERROR(BSL_LS_BCM_VXLAN,
    770                   (BSL_META_U(unit,
    771                               "VXLAN bookkeeping info Error: "
    772                               "not initialized\n")));
    773         return BCM_E_INIT;
    774     }
    775 
    776     /* Get total number of VXLAN outer TPID */
    777     num_tpid = vxlan_info->num_vxlan_outer_tpid;
    778 
    779     for (i = 0; i < num_tpid; i++) {
    780         vxlan_outer_tpid = &(vxlan_info->vxlan_outer_tpid[i]);
    781         if (vxlan_outer_tpid->ref_count == 0) {
    782             /* Find free index */
    783             vxlan_outer_tpid->tpid_value = tpid_value;
    784             /* Update the reference count */
    785             vxlan_outer_tpid->ref_count++;
    786             break;
    787         } else {
    788             if (tpid_value == vxlan_outer_tpid->tpid_value) {
    789                 /* Update the reference count */
    790                 vxlan_outer_tpid->ref_count++;
    791                 break;
    792             }
    793         }
    794     }
    795 
    796     if (i == num_tpid) {
    797         return BCM_E_RESOURCE;
    798     }
    799 
    800     return BCM_E_NONE;
    801 }
    802 
    803 /*
    804  * Function:
    805  *    bcmi_gh2_vxlan_outer_tpid_ref_dec
    806  * Purpose:
    807  *    Decrease reference count for the specified VXLAN outer TPID (per system)
    808  * Parameters:
    809  *    unit       - (IN) unit number
    810  *    tpid_value - (IN) TPID value
    811  * Returns:
    812  *    BCM_E_XXX
    813  * Notes:
    814  */
    815 STATIC int
    816 bcmi_gh2_vxlan_outer_tpid_ref_dec(int unit, uint16 tpid_value)
    817 {
    818     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
    819     gh2_vxlan_outer_tpid_info_t *vxlan_outer_tpid;
    820     int num_tpid, i;
    821     bcm_switch_tpid_info_t tpid_info;
    822 
    823     vxlan_info = GH2_VXLAN_INFO(unit);
    824     if (NULL == vxlan_info) {
    825         LOG_ERROR(BSL_LS_BCM_VXLAN,
    826                   (BSL_META_U(unit,
    827                               "VXLAN bookkeeping info Error: "
    828                               "not initialized\n")));
    829         return BCM_E_INIT;
    830     }
    831 
    832     /* Get total number of VXLAN outer TPID */
    833     num_tpid = vxlan_info->num_vxlan_outer_tpid;
    834 
    835     for (i = 0; i < num_tpid; i++) {
    836         vxlan_outer_tpid = &(vxlan_info->vxlan_outer_tpid[i]);
    837         if (vxlan_outer_tpid->ref_count > 0) {
    838             if (tpid_value == vxlan_outer_tpid->tpid_value) {
    839                 /* Update the reference count */
    840                 vxlan_outer_tpid->ref_count--;
    841                 if (vxlan_outer_tpid->ref_count == 0) {
    842                     sal_memset(&tpid_info, 0, sizeof(tpid_info));
    843                     tpid_info.tpid_type = bcmTpidTypeVxlanPayloadOuter;
    844                     tpid_info.tpid_value = tpid_value;
    845                     (void)bcm_esw_switch_tpid_delete(unit, &tpid_info);
    846                 }
    847                 break;
    848             }
    849         }
    850     }
    851 
    852     if (i == num_tpid) {
    853         return BCM_E_NOT_FOUND;
    854     }
    855 
    856     return BCM_E_NONE;
    857 }
    858 
    859 /*
    860  * Function:
    861  *    bcmi_gh2_vxlan_vlan_xlate_ref_inc
    862  * Purpose:
    863  *    Increase reference count for the specified VXLAN Vlan XLATE entry.
    864  * Parameters:
    865  *    unit        - (IN) unit number
    866  *    entry_index - (IN) Entry index
    867  * Returns:
    868  *    BCM_E_XXX
    869  * Notes:
    870  */
    871 STATIC int
    872 bcmi_gh2_vxlan_vlan_xlate_ref_inc(int unit, int entry_index)
    873 {
    874     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
    875     gh2_vxlan_vlan_xlate_info_t *vxlan_vlan_xlate;
    876     int num_vfi;
    877 
    878     vxlan_info = GH2_VXLAN_INFO(unit);
    879     if (NULL == vxlan_info) {
    880         LOG_ERROR(BSL_LS_BCM_VXLAN,
    881                   (BSL_META_U(unit,
    882                               "VXLAN bookkeeping info Error: "
    883                               "not initialized\n")));
    884         return BCM_E_INIT;
    885     }
    886 
    887     /* Input parameter check */
    888     num_vfi = vxlan_info->num_vxlan_vfi;
    889     if (entry_index >= num_vfi) {
    890         return BCM_E_RESOURCE;
    891     }
    892 
    893     /* Get VXLAN VLAN XLATE entry pointer with specified entry_index */
    894     vxlan_vlan_xlate = &(vxlan_info->vxlan_vlan_xlate[entry_index]);
    895 
    896     /* Update the reference count */
    897     vxlan_vlan_xlate->ref_count++;
    898 
    899     return BCM_E_NONE;
    900 }
    901 
    902 /*
    903  * Function:
    904  *    bcmi_gh2_vxlan_vlan_xlate_ref_dec
    905  * Purpose:
    906  *    Decrease reference count for the specified VXLAN Vlan XLATE entry.
    907  * Parameters:
    908  *    unit        - (IN) unit number
    909  *    entry_index - (IN) Entry index
    910  *    ref_cnt     - (OUT) Reference Count
    911  * Returns:
    912  *    BCM_E_XXX
    913  * Notes:
    914  */
    915 STATIC int
    916 bcmi_gh2_vxlan_vlan_xlate_ref_dec(int unit, int entry_index, int *ref_cnt)
    917 {
    918     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
    919     gh2_vxlan_vlan_xlate_info_t *vxlan_vlan_xlate;
    920     int num_vfi;
    921 
    922     vxlan_info = GH2_VXLAN_INFO(unit);
    923     if (NULL == vxlan_info) {
    924         LOG_ERROR(BSL_LS_BCM_VXLAN,
    925                   (BSL_META_U(unit,
    926                               "VXLAN bookkeeping info Error: "
    927                               "not initialized\n")));
    928         return BCM_E_INIT;
    929     }
    930 
    931     /* Input parameter check */
    932     num_vfi = vxlan_info->num_vxlan_vfi;
    933     if (entry_index >= num_vfi) {
    934         return BCM_E_RESOURCE;
    935     }
    936 
    937     if (NULL == ref_cnt) {
    938         return BCM_E_PARAM;
    939     }
    940 
    941     /* Get VXLAN VLAN XLATE entry pointer with specified entry_index */
    942     vxlan_vlan_xlate = &(vxlan_info->vxlan_vlan_xlate[entry_index]);
    943     if (vxlan_vlan_xlate->ref_count > 0) {
    944         /* Update the reference count */
    945         vxlan_vlan_xlate->ref_count--;
    946     }
    947 
    948     *ref_cnt = vxlan_vlan_xlate->ref_count;
    949 
    950     return BCM_E_NONE;
    951 }
    952 
    953 #ifdef BCM_WARM_BOOT_SUPPORT
    954 
    955 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1, 0)
    956 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_0
    957 
    958 STATIC int bcmi_gh2_vxlan_wb_alloc(int unit);
    959 
    960 /*
    961  * Function:
    962  *    bcmi_gh2_vxlan_ecmp_nexthop_entry_recover
    963  * Purpose:
    964  *    WB recovery for vxlan ecmp member object's Egress next hop entry
    965  * Parameters:
    966  *    unit           - (IN) Device Number
    967  *    ecmp_nh_index - (IN) ecmp group number
    968  * Returns:
    969  *    BCM_E_XXX
    970  */
    971 STATIC int
    972 bcmi_gh2_vxlan_egr_mac_da_recover(int unit)
    973 {
    974     int rv = BCM_E_NONE;
    975     int min, max, i;
    976     egr_l3_next_hop_entry_t nh_entry;
    977     int macda_idx;
    978 
    979     min = soc_mem_index_min(unit, EGR_L3_NEXT_HOPm);
    980     max = soc_mem_index_max(unit, EGR_L3_NEXT_HOPm);
    981 
    982     for (i = min; i < max; i++) {
    983 
    984         /* Recover MAC_DA profile count */
    985         SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
    986                                          i, &nh_entry));
    987         if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &nh_entry,
    988                                              ENTRY_TYPEf) == 0xa) {
    989             macda_idx = soc_EGR_L3_NEXT_HOPm_field32_get
    990                              (unit, &nh_entry,
    991                               VXLAN__MAC_DA_PROFILE_INDEXf);
    992             _bcm_common_profile_mem_ref_cnt_update(
    993                 unit, EGR_MAC_DA_PROFILEm, macda_idx, 1);
    994         }
    995     }
    996 
    997     return rv;
    998 }
    999 
   1000 /*
   1001  * Function:
   1002  *    bcmi_gh2_vxlan_wb_recover
   1003  * Purpose:
   1004  *    Recover VXLAN module info for Level 2 Warm Boot from persisitent memory
   1005  * Warm Boot Version Map:
   1006  *    see _bcm_esw_vxlan_sync definition
   1007  * Parameters:
   1008  *    unit - (IN) Device Number
   1009  * Returns:
   1010  *    BCM_E_XXX
   1011  */
   1012 STATIC int
   1013 bcmi_gh2_vxlan_wb_recover(int unit)
   1014 {
   1015     int rv = BCM_E_NONE;
   1016     int i;
   1017     int num_tnl = 0, num_vp = 0;
   1018     int stable_size;
   1019     int add_sz = 0;
   1020     bcm_gport_t gport;
   1021     uint8 *vxlan_state = NULL;
   1022     soc_scache_handle_t scache_handle;
   1023     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   1024     int num_vfi = 0;
   1025     int intf;
   1026     uint32 flag = 0;
   1027     int index = -1;
   1028     uint16 tpid_value;
   1029 
   1030     vxlan_info = GH2_VXLAN_INFO(unit);
   1031 
   1032     BCM_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   1033 
   1034     /* Requires extended scache support level-2 warmboot */
   1035     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
   1036         return BCM_E_NONE;
   1037     }
   1038 
   1039     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_VXLAN, 0);
   1040     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
   1041                                  0, &vxlan_state,
   1042                                  BCM_WB_DEFAULT_VERSION, NULL);
   1043     if (BCM_FAILURE(rv)) {
   1044         return rv;
   1045     }
   1046 
   1047     if (vxlan_state != NULL) {
   1048         num_vp = vxlan_info->num_vxlan_vp;
   1049         num_tnl = vxlan_info->num_vxlan_tnl;
   1050         num_vfi = vxlan_info->num_vxlan_vfi;
   1051 
   1052         /* Version_1_0: bcmi_gh2_vxlan_tunnel_endpoint_t in vxlan_bookkeeping_t
   1053          * bcm_ip_t dip + bcm_ip_t sip + bcm_ip6_t dip6 + bcm_ip6_t sip6 +
   1054          * uin16 tunnel_state + int activate_flag + bcm_vlan_t vlan.
   1055          */
   1056         /* size of (bcmi_gh2_vxlan_tunnel_endpoint_t) */
   1057         add_sz = sizeof(bcmi_gh2_vxlan_tunnel_endpoint_t);
   1058 
   1059         /*
   1060          * Recover Vxlan Tunnel Terminator
   1061          * (DIP, SIP, DIP6, SIP6, Tunnel State(uint16), activate_flag, vlan)
   1062          * To correspond with the sync actions in Version_1_0
   1063          */
   1064         for (i = 0; i < num_tnl; i++) {
   1065             sal_memcpy(&(vxlan_info->vxlan_tunnel_term[i]),
   1066                        vxlan_state, add_sz);
   1067             vxlan_state += add_sz;
   1068         }
   1069 
   1070         /*
   1071          * Recover Vxlan Tunnel Initiator
   1072          * (DIP, SIP, DIP6, SIP6, Tunnel State(uint16), activate_flag, vlan)
   1073          * To correspond with the sync actions in Version_1_0
   1074          */
   1075         for (i = 0; i < num_tnl; i++) {
   1076             sal_memcpy(&(vxlan_info->vxlan_tunnel_init[i]),
   1077                        vxlan_state, add_sz);
   1078             vxlan_state += add_sz;
   1079         }
   1080 
   1081         /* Recover the BITMAP of Vxlan Tunnel usage */
   1082         sal_memcpy(vxlan_info->vxlan_ip_tnl_bitmap, vxlan_state,
   1083                    SHR_BITALLOCSIZE(num_tnl));
   1084         vxlan_state += SHR_BITALLOCSIZE(num_tnl);
   1085 
   1086         /* Recover the flags & match_tunnel_index of each Match Key */
   1087         for (i = 0; i < num_vp; i++) {
   1088             sal_memcpy(&(vxlan_info->match_key[i].flags),
   1089                        vxlan_state, sizeof(uint32));
   1090             vxlan_state += sizeof(uint32);
   1091             sal_memcpy(&(vxlan_info->match_key[i].match_tunnel_index),
   1092                        vxlan_state, sizeof(uint32));
   1093             vxlan_state += sizeof(uint32);
   1094         }
   1095 
   1096         /*
   1097          * Recover the index && gport(trunk_id, modid, port) && match_vlan &&
   1098          * match_inner_vlan of each Match Key
   1099          */
   1100         for (i = 0; i < num_vp; i++) {
   1101             sal_memcpy(&(vxlan_info->match_key[i].index), vxlan_state,
   1102                        sizeof(uint32));
   1103             vxlan_state += sizeof(uint32);
   1104             sal_memcpy(&gport, vxlan_state, sizeof(bcm_gport_t));
   1105             if (BCM_GPORT_IS_TRUNK(gport)) {
   1106                 vxlan_info->match_key[i].trunk_id =
   1107                     BCM_GPORT_TRUNK_GET(gport);
   1108             } else if (BCM_GPORT_IS_MODPORT(gport)) {
   1109                 vxlan_info->match_key[i].modid =
   1110                     BCM_GPORT_MODPORT_MODID_GET(gport);
   1111                 vxlan_info->match_key[i].port =
   1112                     BCM_GPORT_MODPORT_PORT_GET(gport);
   1113                 vxlan_info->match_key[i].trunk_id = -1;
   1114             }
   1115             vxlan_state += sizeof(bcm_gport_t);
   1116             sal_memcpy(&(vxlan_info->match_key[i].match_vlan), vxlan_state,
   1117                        sizeof(bcm_vlan_t));
   1118             vxlan_state += sizeof(bcm_vlan_t);
   1119             sal_memcpy(&(vxlan_info->match_key[i].match_inner_vlan),
   1120                        vxlan_state, sizeof(bcm_vlan_t));
   1121             vxlan_state += sizeof(bcm_vlan_t);
   1122         }
   1123 
   1124         /* Recover the BITMAP of Vxlan VFI usage */
   1125         sal_memcpy(vxlan_info->vxlan_vfi_bitmap, vxlan_state,
   1126                    SHR_BITALLOCSIZE(num_vfi));
   1127         vxlan_state += SHR_BITALLOCSIZE(num_vfi);
   1128 
   1129         /* Recover the type of each vxlan vpn */
   1130         for (i = 0; i < num_vfi; i++) {
   1131             sal_memcpy(&(vxlan_info->vxlan_vpn_info[i].valid),
   1132                        vxlan_state, sizeof(int));
   1133             vxlan_state += sizeof(int);
   1134             sal_memcpy(&(vxlan_info->vxlan_vpn_info[i].vnid),
   1135                        vxlan_state, sizeof(uint32));
   1136             vxlan_state += sizeof(uint32);
   1137         }
   1138 
   1139         /* Recover the vfi index of each vxlan vp */
   1140         for (i = 0; i < num_vp; i++) {
   1141             sal_memcpy(&(vxlan_info->match_key[i].vfi),
   1142                        vxlan_state, sizeof(int));
   1143             vxlan_state += sizeof(int);
   1144         }
   1145 
   1146         /* Recover the BITMAP of Vxlan VP usage */
   1147         sal_memcpy(vxlan_info->vxlan_vp_bitmap, vxlan_state,
   1148                    SHR_BITALLOCSIZE(num_vp));
   1149         vxlan_state += SHR_BITALLOCSIZE(num_vp);
   1150 
   1151         /* Recover the BITMAP of Vxlan VP usage for Network side */
   1152         sal_memcpy(vxlan_info->vxlan_network_vp_bitmap, vxlan_state,
   1153                    SHR_BITALLOCSIZE(num_vp));
   1154         vxlan_state += SHR_BITALLOCSIZE(num_vp);
   1155 
   1156         /* Recover per VP info */
   1157         for (i = 0; i < num_vp; i++) {
   1158             sal_memcpy(&(vxlan_info->vxlan_vp_info[i].vp_type),
   1159                        vxlan_state, sizeof(uint32));
   1160             vxlan_state += sizeof(uint32);
   1161             sal_memcpy(&(vxlan_info->vxlan_vp_info[i].vfi),
   1162                        vxlan_state, sizeof(int));
   1163             vxlan_state += sizeof(int);
   1164             sal_memcpy(&(vxlan_info->vxlan_vp_info[i].ecmp),
   1165                        vxlan_state, sizeof(int));
   1166             vxlan_state += sizeof(int);
   1167             sal_memcpy(&(vxlan_info->vxlan_vp_info[i].nh_ecmp_index),
   1168                        vxlan_state, sizeof(int));
   1169             vxlan_state += sizeof(int);
   1170             /* Recovering EgrObj ref_count (NextHop/ECMP) */
   1171             if (vxlan_info->vxlan_vp_info[i].ecmp) {
   1172                 intf = vxlan_info->vxlan_vp_info[i].nh_ecmp_index +
   1173                        BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit);
   1174             } else {
   1175                 intf = vxlan_info->vxlan_vp_info[i].nh_ecmp_index +
   1176                        BCM_XGS3_EGRESS_IDX_MIN(unit);
   1177             }
   1178             rv = bcm_xgs3_get_nh_from_egress_object(unit, intf, &flag, 1,
   1179                                                     &index);
   1180             BCM_IF_ERROR_RETURN(rv);
   1181 
   1182             sal_memcpy(&(vxlan_info->vxlan_vp_info[i].tpid_valid),
   1183                        vxlan_state, sizeof(int));
   1184             vxlan_state += sizeof(int);
   1185             sal_memcpy(&(vxlan_info->vxlan_vp_info[i].tpid_value),
   1186                        vxlan_state, sizeof(uint16));
   1187             vxlan_state += sizeof(uint16);
   1188 
   1189             /* Recovering VXLAN Outer TPID reference count */
   1190             if (vxlan_info->vxlan_vp_info[i].tpid_valid) {
   1191                 tpid_value = vxlan_info->vxlan_vp_info[i].tpid_value;
   1192                 BCM_IF_ERROR_RETURN(
   1193                     bcmi_gh2_vxlan_outer_tpid_ref_inc(unit, tpid_value));
   1194             }
   1195         }
   1196 
   1197         /* Recover the reference count of each vxlan vlan xlate entry */
   1198         for (i = 0; i < num_vfi; i++) {
   1199             sal_memcpy(&(vxlan_info->vxlan_vlan_xlate[i].ref_count),
   1200                        vxlan_state, sizeof(int));
   1201             vxlan_state += sizeof(int);
   1202         }
   1203 
   1204         /* Recover Custom Header info per VP info (used for RIOT) */
   1205         for (i = 0; i < num_vp; i++) {
   1206             sal_memcpy(&(vxlan_info->vxlan_vp_info[i].ch_encap_id),
   1207                        vxlan_state, sizeof(bcm_if_t));
   1208             vxlan_state += sizeof(bcm_if_t);
   1209             sal_memcpy(&(vxlan_info->vxlan_vp_info[i].ch_match_id_ipmc),
   1210                        vxlan_state, sizeof(int));
   1211             vxlan_state += sizeof(int);
   1212             sal_memcpy(&(vxlan_info->vxlan_vp_info[i].ch_match_id_non_ipmc),
   1213                        vxlan_state, sizeof(int));
   1214             vxlan_state += sizeof(int);
   1215         }
   1216 
   1217         /*
   1218          * Recover the BITMAP of Vxlan VP usage for Loopback side
   1219          * (used for RIOT)
   1220          */
   1221         sal_memcpy(vxlan_info->vxlan_loopback_vp_bitmap, vxlan_state,
   1222                    SHR_BITALLOCSIZE(num_vp));
   1223         vxlan_state += SHR_BITALLOCSIZE(num_vp);
   1224 
   1225         /*
   1226          * Recover Reference count of Custom Header index0
   1227          * (used for RIOT)
   1228          */
   1229         sal_memcpy(&(vxlan_info->riot_custom_header_index0_ref_count),
   1230                    vxlan_state, sizeof(int));
   1231         vxlan_state += sizeof(int);
   1232 
   1233     }
   1234 
   1235     return BCM_E_NONE;
   1236 }
   1237 
   1238 /*
   1239  * Function:
   1240  *    bcmi_gh2_vxlan_wb_alloc
   1241  * Purpose:
   1242  *    Alloc persisitent memory for Level 2 Warm Boot scache.
   1243  * Parameters:
   1244  *    unit - (IN) Device Number
   1245  * Returns:
   1246  *    BCM_E_XXX
   1247  */
   1248 STATIC int
   1249 bcmi_gh2_vxlan_wb_alloc(int unit)
   1250 {
   1251     int rv = BCM_E_NONE;
   1252     int alloc_sz = 0;
   1253     soc_scache_handle_t scache_handle;
   1254     int num_tnl = 0, num_vp = 0;
   1255     int num_vfi = 0;
   1256     uint8 *vxlan_state;
   1257     int stable_size;
   1258     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   1259 
   1260     vxlan_info = GH2_VXLAN_INFO(unit);
   1261 
   1262     BCM_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   1263 
   1264     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
   1265         return BCM_E_NONE;
   1266     }
   1267 
   1268     /* Size of Tunnel Terminator & Initiator */
   1269     num_tnl = vxlan_info->num_vxlan_tnl;
   1270     alloc_sz += num_tnl * sizeof(bcmi_gh2_vxlan_tunnel_endpoint_t) * 2;
   1271 
   1272     /* Size of EGR_IP_TUNNEL index bitmap */
   1273     alloc_sz += SHR_BITALLOCSIZE(num_tnl);
   1274 
   1275     /* Size of All match_key's flags & match_tunnel_index */
   1276     num_vp = vxlan_info->num_vxlan_vp;
   1277     alloc_sz += num_vp * sizeof(uint32) * 2;
   1278 
   1279     /*
   1280      * Size of All match_key's index && gport(trunk_id, modid, port) &&
   1281      * match_vlan && match_inner_vlan
   1282      */
   1283     alloc_sz += num_vp * (sizeof(uint32) + sizeof(bcm_gport_t) +
   1284                           sizeof(bcm_vlan_t) * 2);
   1285 
   1286     /* Size of VXLAN VFI bitmap */
   1287     num_vfi = vxlan_info->num_vxlan_vfi;
   1288     alloc_sz += SHR_BITALLOCSIZE(num_vfi);
   1289 
   1290     /* Size of VXLAN VFI info data structure */
   1291     alloc_sz += num_vfi * sizeof(gh2_vxlan_vpn_info_t);
   1292     /* Size of match_key's vfi related with vp */
   1293     alloc_sz += num_vp * sizeof(int);
   1294 
   1295     /* Size of VXLAN Virtual Port bitmap & Network Virtual Port bitmap */
   1296     alloc_sz += SHR_BITALLOCSIZE(num_vp);
   1297     alloc_sz += SHR_BITALLOCSIZE(num_vp);
   1298 
   1299     /* Size of VXLAN per VLAN XLATE entry info */
   1300     alloc_sz += num_vfi * sizeof(gh2_vxlan_vlan_xlate_info_t);
   1301 
   1302     /* Size of VXLAN per VP info */
   1303     alloc_sz += num_vp * sizeof(gh2_vxlan_vp_info_t);
   1304 
   1305     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_VXLAN, 0);
   1306     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
   1307                                  alloc_sz, (uint8**)&vxlan_state,
   1308                                  BCM_WB_DEFAULT_VERSION, NULL);
   1309     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1310         return rv;
   1311     }
   1312 
   1313     return BCM_E_NONE;
   1314 }
   1315 
   1316 /*
   1317  * Function:
   1318  *    bcmi_gh2_vxlan_tunnel_initiator_reinit
   1319  * Purpose:
   1320  *    Tunnel initiator hash and ref-count recovery.
   1321  * Parameters:
   1322  *    unit - (IN) Device Number
   1323  * Returns:
   1324  *    BCM_E_XXX
   1325  */
   1326 STATIC int
   1327 bcmi_gh2_vxlan_tunnel_initiator_reinit(int unit)
   1328 {
   1329     bcm_tunnel_initiator_t tnl_init_info;
   1330     soc_mem_t mem, mem_ip6;
   1331     int i = 0;
   1332     int idx_min = 0;
   1333     int idx_max = 0;
   1334     uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry */
   1335     int entry_type = 0; /* Entry type (IPv4 or IPv6). */
   1336     int tnl_type = 0; /* Tunnel type. */
   1337     _bcm_l3_tbl_t *tbl_ptr; /* Tunnel init table pointer. */
   1338 
   1339     mem = BCM_XGS3_L3_MEM(unit, tnl_init_v4);
   1340     mem_ip6 = BCM_XGS3_L3_MEM(unit, tnl_init_v6);
   1341     idx_min = soc_mem_index_min(unit, mem);
   1342     idx_max = soc_mem_index_max(unit, mem);
   1343     tbl_ptr = BCM_XGS3_L3_TBL_PTR(unit, tnl_init);
   1344     for (i = idx_min; i <= idx_max; i++) {
   1345         /* Initialize the buffer */
   1346         sal_memset(tnl_entry, 0, sizeof(tnl_entry));
   1347         BCM_IF_ERROR_RETURN(
   1348             soc_mem_read(unit, mem, MEM_BLOCK_ANY, i, tnl_entry));
   1349 
   1350         tnl_type = soc_mem_field32_get(unit, mem, tnl_entry, TUNNEL_TYPEf);
   1351         entry_type = soc_mem_field32_get(unit, mem, tnl_entry, ENTRY_TYPEf);
   1352 
   1353         if (tnl_type == _BCM_VXLAN_TUNNEL_TYPE) {
   1354             if (entry_type == BCM_XGS3_TUNNEL_INIT_V6) {
   1355                 /* Initialize the buffer */
   1356                 sal_memset(tnl_entry, 0, sizeof(tnl_entry));
   1357                 BCM_IF_ERROR_RETURN(
   1358                     soc_mem_read(unit, mem_ip6, MEM_BLOCK_ANY,
   1359                                  (i / 2), tnl_entry));
   1360 
   1361                 bcm_tunnel_initiator_t_init(&tnl_init_info);
   1362 
   1363                 /* Tunnel for IPv6 */
   1364                 tnl_init_info.type = bcmTunnelTypeVxlan6;
   1365 
   1366                 /* Extract IPv6 SIP/DIP address */
   1367                 soc_mem_ip6_addr_get(unit, mem_ip6, tnl_entry, SIPf,
   1368                                      tnl_init_info.sip6,
   1369                                      SOC_MEM_IP6_FULL_ADDR);
   1370                 soc_mem_ip6_addr_get(unit, mem_ip6, tnl_entry, DIPf,
   1371                                      tnl_init_info.dip6,
   1372                                      SOC_MEM_IP6_FULL_ADDR);
   1373 
   1374                 tnl_init_info.udp_dst_port =
   1375                     soc_mem_field32_get(unit, mem_ip6,
   1376                                         tnl_entry, L4_DST_PORTf);
   1377                 BCM_IF_ERROR_RETURN(bcmi_gh2_vxlan_tunnel_initiator_hash_calc
   1378                     (unit, &tnl_init_info,
   1379                     &BCM_XGS3_L3_ENT_HASH(tbl_ptr, i)));
   1380                 BCM_IF_ERROR_RETURN(bcmi_gh2_vxlan_tunnel_initiator_hash_calc
   1381                     (unit, &tnl_init_info,
   1382                     &BCM_XGS3_L3_ENT_HASH(tbl_ptr, (i + 1))));
   1383                 BCM_XGS3_L3_ENT_REF_CNT_INC(
   1384                     tbl_ptr, i,
   1385                     ((_BCM_TUNNEL_OUTER_HEADER_IPV6(tnl_init_info.type)) ?
   1386                     _BCM_DOUBLE_WIDE : _BCM_SINGLE_WIDE));
   1387                 /* Update Maximum used index */
   1388                 tbl_ptr->idx_maxused = i;
   1389             } else if (entry_type == BCM_XGS3_TUNNEL_INIT_V4) {
   1390                 bcm_tunnel_initiator_t_init(&tnl_init_info);
   1391 
   1392                 /* Tunnel for IPv4 */
   1393                 tnl_init_info.type = bcmTunnelTypeVxlan;
   1394 
   1395                 /* Get IPv4 SIP/DIP address */
   1396                 tnl_init_info.sip =
   1397                     soc_mem_field32_get(unit, mem, tnl_entry, SIPf);
   1398                 tnl_init_info.dip =
   1399                     soc_mem_field32_get(unit, mem, tnl_entry, DIPf);
   1400 
   1401                 tnl_init_info.udp_dst_port =
   1402                     soc_mem_field32_get(unit, mem, tnl_entry, L4_DST_PORTf);
   1403                 BCM_IF_ERROR_RETURN(bcmi_gh2_vxlan_tunnel_initiator_hash_calc
   1404                     (unit, &tnl_init_info,
   1405                      &BCM_XGS3_L3_ENT_HASH(tbl_ptr, i)));
   1406                 BCM_XGS3_L3_ENT_REF_CNT_INC(
   1407                     tbl_ptr, i,
   1408                     ((_BCM_TUNNEL_OUTER_HEADER_IPV6(tnl_init_info.type)) ?
   1409                     _BCM_DOUBLE_WIDE : _BCM_SINGLE_WIDE));
   1410                 /* Update Maximum used index */
   1411                 tbl_ptr->idx_maxused = i;
   1412             }
   1413         }
   1414     }
   1415 
   1416     return BCM_E_NONE;
   1417 }
   1418 
   1419 /*
   1420  * Function:
   1421  *    bcmi_gh2_vxlan_reinit
   1422  * Purpose:
   1423  *    Warm boot recovery for the VXLAN software module
   1424  * Parameters:
   1425  *    unit - (IN) Device Number
   1426  * Returns:
   1427  *    BCM_E_XXX
   1428  */
   1429 STATIC int
   1430 bcmi_gh2_vxlan_reinit(int unit)
   1431 {
   1432 
   1433     /* Tunnel initiator hash and ref-count recovery */
   1434     BCM_IF_ERROR_RETURN(
   1435         bcmi_gh2_vxlan_tunnel_initiator_reinit(unit));
   1436 
   1437     /* Recover L2 scache */
   1438     BCM_IF_ERROR_RETURN(bcmi_gh2_vxlan_wb_recover(unit));
   1439 
   1440     /* Recover EGR_MAC_DA reference count */
   1441     BCM_IF_ERROR_RETURN(bcmi_gh2_vxlan_egr_mac_da_recover(unit));
   1442 
   1443     return BCM_E_NONE;
   1444 }
   1445 
   1446 /*
   1447  * Function:
   1448  *    bcmi_gh2_vxlan_sync
   1449  * Purpose:
   1450  *    This routine extracts the state that needs to be stored from the
   1451  *    book-keeping structs and stores it in the allocated scache location.
   1452  * Parameters:
   1453  *    unit - (IN) Device Number
   1454  * Returns:
   1455  *    BCM_E_XXX
   1456  */
   1457 int
   1458 bcmi_gh2_vxlan_sync(int unit)
   1459 {
   1460     int rv = BCM_E_NONE;
   1461     int i, num_tnl = 0, num_vp = 0;
   1462     int num_vfi = 0;
   1463     int size;
   1464     int stable_size;
   1465     bcm_gport_t gport;
   1466     uint8 *vxlan_state;
   1467     soc_scache_handle_t scache_handle;
   1468     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   1469 
   1470     if (!soc_feature(unit, soc_feature_vxlan_lite)) {
   1471         return BCM_E_UNAVAIL;
   1472     }
   1473 
   1474     /* Parameter validation checks */
   1475     if (!SOC_UNIT_VALID(unit)) {
   1476         return BCM_E_UNIT;
   1477     }
   1478 
   1479     vxlan_info = GH2_VXLAN_INFO(unit);
   1480 
   1481     BCM_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   1482 
   1483     /* Requires extended scache support level-2 warmboot */
   1484     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
   1485         return BCM_E_NONE;
   1486     }
   1487 
   1488     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_VXLAN, 0);
   1489     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
   1490                                  0, &vxlan_state,
   1491                                  BCM_WB_DEFAULT_VERSION, NULL);
   1492     if (BCM_FAILURE(rv) && (rv != BCM_E_INTERNAL)) {
   1493         return rv;
   1494     }
   1495 
   1496     num_vp = vxlan_info->num_vxlan_vp;
   1497     num_tnl = vxlan_info->num_vxlan_tnl;
   1498     size = num_tnl * sizeof(bcmi_gh2_vxlan_tunnel_endpoint_t);
   1499 
   1500     /* Store each Vxlan Tunnnel Terminator entry (SIP, DIP, Tunnel State) */
   1501     /*
   1502      * vxlan_tunnel_term points to a struct array with a base type of
   1503      * bcmi_gh2_vxlan_tunnel_endpoint_t, sized to hold the info of each
   1504      * virtual port tunnel.
   1505      *
   1506      * EGR_IP_TUNNELm hw index equals to array index, related to the IP & state
   1507      * info of each VP.
   1508      *
   1509      * bcmi_gh2_vxlan_tunnel_endpoint_t[size of (EGR_IP_TUNNELm)] *
   1510      * vxlan_tunnel_term
   1511      */
   1512     sal_memcpy(vxlan_state, vxlan_info->vxlan_tunnel_term, size);
   1513     vxlan_state += size;
   1514 
   1515     /* Store each Vxlan Tunnel Initiator entry (SIP, DIP, Tunnel State) */
   1516     /*
   1517      * Same as vxlan_tunnel_term.
   1518      */
   1519     sal_memcpy(vxlan_state, vxlan_info->vxlan_tunnel_init, size);
   1520     vxlan_state += size;
   1521 
   1522     /* Store the BITMAP of Vxlan Tunnel usage */
   1523     /*
   1524      * vxlan_ip_tnl_bitmap points to a struct array with a base type of uint32.
   1525      * sized to hold the maximum number of Egress IP Tunnel.
   1526      *
   1527      * EGR_IP_TUNNELm hw index used as offset of this wide bitmap.
   1528      *
   1529      * uint32[(size of (EGR_IP_TUNNELm) + 31) / 32] * vxlan_ip_tnl_bitmap
   1530      */
   1531     sal_memcpy(vxlan_state, vxlan_info->vxlan_ip_tnl_bitmap,
   1532                SHR_BITALLOCSIZE(num_tnl));
   1533     vxlan_state += SHR_BITALLOCSIZE(num_tnl);
   1534 
   1535     /* Store the flags & match_tunnel_index of each Match Key */
   1536     /*
   1537      * Since we can't recover flags & match_tunnel_index from HW,
   1538      * so we need to store it for warmboot recovery.
   1539      */
   1540     for (i = 0; i < num_vp; i++) {
   1541         sal_memcpy(vxlan_state, &(vxlan_info->match_key[i].flags),
   1542                    sizeof(uint32));
   1543         vxlan_state += sizeof(uint32);
   1544         sal_memcpy(vxlan_state, &(vxlan_info->match_key[i].match_tunnel_index),
   1545                    sizeof(uint32));
   1546         vxlan_state += sizeof(uint32);
   1547     }
   1548 
   1549     /*
   1550      * Store the index & gport(trunk_id, modid, port) & match_vlan &
   1551      * match_inner_vlan of each Match Key
   1552      *
   1553      * Since we can't recover index & gport(trunk_id, modid, port) &
   1554      * match_vlan & match_inner_vlan from HW, so we need to store it
   1555      * for warmboot recovery.
   1556      */
   1557     for (i = 0; i < num_vp; i++) {
   1558         sal_memcpy(vxlan_state, &(vxlan_info->match_key[i].index),
   1559                    sizeof(uint32));
   1560         vxlan_state += sizeof(uint32);
   1561         if (vxlan_info->match_key[i].trunk_id != -1) {
   1562             BCM_GPORT_TRUNK_SET(gport, vxlan_info->match_key[i].trunk_id);
   1563         } else if (vxlan_info->match_key[i].modid != -1) {
   1564             BCM_GPORT_MODPORT_SET(gport,
   1565                                   vxlan_info->match_key[i].modid,
   1566                                   vxlan_info->match_key[i].port);
   1567         } else {
   1568             gport = BCM_GPORT_INVALID;
   1569         }
   1570         sal_memcpy(vxlan_state, &gport, sizeof(bcm_gport_t));
   1571         vxlan_state += sizeof(bcm_gport_t);
   1572         sal_memcpy(vxlan_state, &(vxlan_info->match_key[i].match_vlan),
   1573                    sizeof(bcm_vlan_t));
   1574         vxlan_state += sizeof(bcm_vlan_t);
   1575         sal_memcpy(vxlan_state, &(vxlan_info->match_key[i].match_inner_vlan),
   1576                    sizeof(bcm_vlan_t));
   1577         vxlan_state += sizeof(bcm_vlan_t);
   1578     }
   1579 
   1580     num_vfi = vxlan_info->num_vxlan_vfi;
   1581 
   1582     /* Store the BITMAP of Vxlan VFI usage */
   1583     /*
   1584      * vxlan_vfi_bitmap points to a struct array with a base type of uint32.
   1585      * sized to hold the maximum number of Vxlan VFI.
   1586      *
   1587      * VFI sw index used as offset of this wide bitmap.
   1588      *
   1589      * uint32[(size of (VLAN_XLATEm or VFIm) + 31) / 32] * vxlan_vfi_bitmap
   1590      * VFIm is support for GH2-B0. VLAN_XLATEm is used for GH2-A0.
   1591      */
   1592     sal_memcpy(vxlan_state, vxlan_info->vxlan_vfi_bitmap,
   1593                SHR_BITALLOCSIZE(num_vfi));
   1594     vxlan_state += SHR_BITALLOCSIZE(num_vfi);
   1595 
   1596     /* Store the type of each vxlan vpn */
   1597     for (i = 0; i < num_vfi; i++) {
   1598         sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vpn_info[i].valid),
   1599                    sizeof(int));
   1600         vxlan_state += sizeof(int);
   1601         sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vpn_info[i].vnid),
   1602                    sizeof(uint32));
   1603         vxlan_state += sizeof(uint32);
   1604     }
   1605 
   1606     /* Store the vfi index for vp */
   1607     for (i = 0; i < num_vp; i++) {
   1608         sal_memcpy(vxlan_state, &(vxlan_info->match_key[i].vfi),
   1609                    sizeof(int));
   1610         vxlan_state += sizeof(int);
   1611     }
   1612 
   1613     /* Store the BITMAP of Vxlan VP usage */
   1614     /*
   1615      * vxlan_vp_bitmap points to a struct array with a base type of uint32.
   1616      * sized to hold the maximum number of Vxlan VP.
   1617      *
   1618      * VP sw index used as offset of this wide bitmap.
   1619      *
   1620      * uint32[(size of (VLAN_XLATEm) + 31) / 32] * vxlan_vp_bitmap
   1621      */
   1622     sal_memcpy(vxlan_state, vxlan_info->vxlan_vp_bitmap,
   1623                SHR_BITALLOCSIZE(num_vp));
   1624     vxlan_state += SHR_BITALLOCSIZE(num_vp);
   1625 
   1626     /* Store the BITMAP of Vxlan VP usage for Network side */
   1627     /*
   1628      * Same as vxlan_vp_bitmap.
   1629      */
   1630     sal_memcpy(vxlan_state, vxlan_info->vxlan_network_vp_bitmap,
   1631                SHR_BITALLOCSIZE(num_vp));
   1632     vxlan_state += SHR_BITALLOCSIZE(num_vp);
   1633 
   1634     /* Store per VP info */
   1635     for (i = 0; i < num_vp; i++) {
   1636         sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vp_info[i].vp_type),
   1637                    sizeof(uint32));
   1638         vxlan_state += sizeof(uint32);
   1639         sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vp_info[i].vfi),
   1640                    sizeof(int));
   1641         vxlan_state += sizeof(int);
   1642         sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vp_info[i].ecmp),
   1643                    sizeof(int));
   1644         vxlan_state += sizeof(int);
   1645         sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vp_info[i].nh_ecmp_index),
   1646                    sizeof(int));
   1647         vxlan_state += sizeof(int);
   1648         sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vp_info[i].tpid_valid),
   1649                    sizeof(int));
   1650         vxlan_state += sizeof(int);
   1651         sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vp_info[i].tpid_value),
   1652                    sizeof(uint16));
   1653         vxlan_state += sizeof(uint16);
   1654     }
   1655 
   1656     /* Store the ref_cnt of each vxlan vlan xlate entry */
   1657     for (i = 0; i < num_vfi; i++) {
   1658         sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vlan_xlate[i].ref_count),
   1659                    sizeof(int));
   1660         vxlan_state += sizeof(int);
   1661     }
   1662 
   1663     /* Store Cstom Header info per VP info (used for RIOT) */
   1664     for (i = 0; i < num_vp; i++) {
   1665         sal_memcpy(vxlan_state, &(vxlan_info->vxlan_vp_info[i].ch_encap_id),
   1666                    sizeof(bcm_if_t));
   1667         vxlan_state += sizeof(bcm_if_t);
   1668         sal_memcpy(vxlan_state,
   1669                    &(vxlan_info->vxlan_vp_info[i].ch_match_id_ipmc),
   1670                    sizeof(int));
   1671         vxlan_state += sizeof(int);
   1672         sal_memcpy(vxlan_state,
   1673                    &(vxlan_info->vxlan_vp_info[i].ch_match_id_non_ipmc),
   1674                    sizeof(int));
   1675         vxlan_state += sizeof(int);
   1676     }
   1677 
   1678     /* Store the BITMAP of Vxlan VP usage for Loopback side (used for RIOT) */
   1679     sal_memcpy(vxlan_state, vxlan_info->vxlan_loopback_vp_bitmap,
   1680                SHR_BITALLOCSIZE(num_vp));
   1681     vxlan_state += SHR_BITALLOCSIZE(num_vp);
   1682 
   1683     /* Store Reference count of Custom Header index0 (used for RIOT) */
   1684     sal_memcpy(vxlan_state, &(vxlan_info->riot_custom_header_index0_ref_count),
   1685                sizeof(int));
   1686     vxlan_state += sizeof(int);
   1687 
   1688     return rv;
   1689 
   1690 }
   1691 
   1692 #endif /* BCM_WARM_BOOT_SUPPORT */
   1693 
   1694 /*
   1695  * Function:
   1696  *    bcmi_gh2_vxlan_hw_clear
   1697  * Purpose:
   1698  *    Perform hw tables clean up for VXLAN module.
   1699  * Parameters:
   1700  *    unit - (IN) Device Number
   1701  * Returns:
   1702  *    BCM_E_XXX
   1703  */
   1704 STATIC int
   1705 bcmi_gh2_vxlan_hw_clear(int unit)
   1706 {
   1707     int rv = BCM_E_NONE, rv_error = BCM_E_NONE;
   1708 
   1709     rv = bcmi_gh2_vxlan_tunnel_terminator_destroy_all(unit);
   1710     if (BCM_FAILURE(rv)) {
   1711         rv_error = rv;
   1712     }
   1713 
   1714     rv = bcmi_gh2_vxlan_tunnel_initiator_destroy_all(unit);
   1715     if (BCM_FAILURE(rv) && (rv_error == BCM_E_NONE)) {
   1716         rv_error = rv;
   1717     }
   1718 
   1719     rv = bcmi_gh2_vxlan_vpn_destroy_all(unit);
   1720     if (BCM_FAILURE(rv) && (rv_error == BCM_E_NONE)) {
   1721         rv_error = rv;
   1722     }
   1723 
   1724     return rv_error;
   1725 }
   1726 
   1727 /*
   1728  * Function:
   1729  *    bcmi_gh2_vxlan_vfi_alloc
   1730  * Purpose:
   1731  *    Internal function for allocating a VFI
   1732  * Parameters:
   1733  *    unit - (IN) Device Number
   1734  *    vfi  - (OUT) VFI index
   1735  * Returns:
   1736  *    BCM_X_XXX
   1737  */
   1738 STATIC int
   1739 bcmi_gh2_vxlan_vfi_alloc(int unit, int *vfi)
   1740 {
   1741     int i, num_vfi;
   1742     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit);
   1743 
   1744     if (NULL == vfi) {
   1745         return BCM_E_PARAM;
   1746     }
   1747 
   1748     num_vfi = vxlan_info->num_vxlan_vfi;
   1749 
   1750     for (i = 0; i < num_vfi; i++) {
   1751         if (!GH2_VXLAN_VFI_USED_GET(unit, i)) {
   1752             break;
   1753         }
   1754     }
   1755 
   1756     if (i == num_vfi) {
   1757         return BCM_E_RESOURCE;
   1758     }
   1759 
   1760     GH2_VXLAN_VFI_USED_SET(unit, i);
   1761     *vfi = i;
   1762 
   1763     return BCM_E_NONE;
   1764 }
   1765 
   1766 /*
   1767  * Function:
   1768  *    bcmi_gh2_vxlan_vfi_alloc_with_id
   1769  * Purpose:
   1770  *    Internal function for allocating a VFI with a given ID
   1771  * Parameters:
   1772  *    unit - (IN) Device Number
   1773  *    vfi  - (IN) VFI index
   1774  * Returns:
   1775  *    BCM_X_XXX
   1776  */
   1777 STATIC int
   1778 bcmi_gh2_vxlan_vfi_alloc_with_id(int unit, int vfi)
   1779 {
   1780     int num_vfi;
   1781     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit);
   1782 
   1783     num_vfi = vxlan_info->num_vxlan_vfi;
   1784 
   1785     /* Check Valid range of VFI */
   1786     if (vfi < 0 || vfi >= num_vfi) {
   1787          return BCM_E_RESOURCE;
   1788     }
   1789 
   1790     if (GH2_VXLAN_VFI_USED_GET(unit, vfi)) {
   1791         return BCM_E_EXISTS;
   1792     }
   1793 
   1794     GH2_VXLAN_VFI_USED_SET(unit, vfi);
   1795 
   1796     return BCM_E_NONE;
   1797 }
   1798 
   1799 
   1800 /*
   1801  * Function:
   1802  *    bcmi_gh2_vxlan_vfi_free
   1803  * Purpose:
   1804  *    Internal function for freeing a VFI
   1805  * Parameters:
   1806  *    unit - (IN) Device Number
   1807  *    vfi  - (IN) VFI index
   1808  * Returns:
   1809  *    None
   1810  */
   1811 STATIC int
   1812 bcmi_gh2_vxlan_vfi_free(int unit, int vfi)
   1813 {
   1814     int num_vfi;
   1815     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit);
   1816     vfi_entry_t vfi_entry;
   1817 
   1818     num_vfi = vxlan_info->num_vxlan_vfi;
   1819 
   1820     /* Check Valid range of VFI */
   1821     if (vfi < 0 || vfi >= num_vfi) {
   1822          return BCM_E_RESOURCE;
   1823     }
   1824 
   1825     GH2_VXLAN_VFI_USED_CLR(unit, vfi);
   1826 
   1827     if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   1828         /* Only support for GH2-B0 with new VFI table */
   1829         sal_memset(&vfi_entry, 0, sizeof(vfi_entry_t));
   1830         SOC_IF_ERROR_RETURN(
   1831             soc_mem_write(unit, VFIm, MEM_BLOCK_ALL, vfi, &vfi_entry));
   1832     }
   1833 
   1834     return BCM_E_NONE;
   1835 }
   1836 
   1837 /*
   1838  * Function:
   1839  *    bcmi_gh2_vxlan_vfi_used_get
   1840  * Purpose:
   1841  *    Check whether a VFI is used or not
   1842  * Parameters:
   1843  *    unit - (IN) Device Number
   1844  *    vfi  - (IN) VFI index
   1845  * Returns:
   1846  *    Boolean
   1847  */
   1848 int
   1849 bcmi_gh2_vxlan_vfi_used_get(int unit, int vfi)
   1850 {
   1851     int rv;
   1852     int num_vfi;
   1853     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit);
   1854 
   1855     num_vfi = vxlan_info->num_vxlan_vfi;
   1856 
   1857     /* Check Valid range of VFI */
   1858     if (vfi < 0 || vfi >= num_vfi) {
   1859          return BCM_E_RESOURCE;
   1860     }
   1861 
   1862     rv = GH2_VXLAN_VFI_USED_GET(unit, vfi);
   1863 
   1864     return rv;
   1865 }
   1866 
   1867 /*
   1868  * Function:
   1869  *    bcmi_gh2_vxlan_vp_info_init
   1870  * Purpose:
   1871  *    Internal function to initialize bcmi_vxlan_vp_info_t structure
   1872  * Parameters:
   1873  *    vxlan_vp_info - (IN/OUT) variable
   1874  * Returns:
   1875  *    void
   1876  */
   1877 STATIC void
   1878 bcmi_gh2_vxlan_vp_info_init(bcmi_vxlan_vp_info_t *vxlan_vp_info)
   1879 {
   1880     if (vxlan_vp_info != NULL) {
   1881         sal_memset(vxlan_vp_info, 0, sizeof(*vxlan_vp_info));
   1882     }
   1883 
   1884     return;
   1885 }
   1886 
   1887 /*
   1888  * Function:
   1889  *    bcmi_gh2_vxlan_vp_alloc
   1890  * Purpose:
   1891  *    Internal function for allocating a group of VPs
   1892  * Parameters:
   1893  *    unit  - (IN) Device Number
   1894  *    start - (IN) First VP index to allocate from
   1895  *    end   - (IN) Last VP index to allocate from
   1896  *    count - (IN) How many consecutive VPs to allocate
   1897  *    vxlan_vp_info - (IN) VXLAN VP information
   1898  *    base_vp - (OUT) Base VP index
   1899  * Returns:
   1900  *    BCM_X_XXX
   1901  */
   1902 STATIC int
   1903 bcmi_gh2_vxlan_vp_alloc(
   1904     int unit,
   1905     int start,
   1906     int end,
   1907     int count,
   1908     bcmi_vxlan_vp_info_t vxlan_vp_info,
   1909     int *base_vp)
   1910 {
   1911     int num_vp;
   1912     int i, j;
   1913     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit);
   1914 
   1915     num_vp = vxlan_info->num_vxlan_vp;
   1916 
   1917     /* Input parameter check */
   1918     if (NULL == base_vp) {
   1919         return BCM_E_PARAM;
   1920     }
   1921     if ((end < 0) || (start < 0) || (end < start) ||
   1922         (end >= num_vp) || (start >= num_vp)) {
   1923         return BCM_E_PARAM;
   1924     }
   1925 
   1926     if (vxlan_vp_info.flags) {
   1927         /* Loopback VP is only support when VXLAN RIOT is enabled */
   1928         if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   1929             if (!(vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_NETWORK_PORT) &&
   1930                 !(vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_LOOPBACK_PORT)) {
   1931                 return BCM_E_UNAVAIL;
   1932             }
   1933         } else {
   1934             if (!(vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_NETWORK_PORT)) {
   1935                 return BCM_E_UNAVAIL;
   1936             }
   1937         }
   1938     }
   1939 
   1940     for (i = start; (i + count - 1) <= end; i += (j + 1)) {
   1941         for (j = 0; j < count; j++) {
   1942             if (GH2_VXLAN_VP_USED_GET(unit, (i + j))) {
   1943                 break;
   1944             }
   1945         }
   1946         if (j == count) {
   1947             break;
   1948         }
   1949     }
   1950 
   1951     if ((i + count - 1) <= end) {
   1952         *base_vp = i;
   1953         for (j = 0; j < count; j++) {
   1954             GH2_VXLAN_VP_USED_SET(unit, i + j);
   1955             if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_NETWORK_PORT) {
   1956                 GH2_VXLAN_NETWORK_VP_USED_SET(unit, (i + j));
   1957             } else if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_LOOPBACK_PORT) {
   1958                 GH2_VXLAN_LOOPBACK_VP_USED_SET(unit, (i + j));
   1959             }
   1960         }
   1961         return BCM_E_NONE;
   1962     }
   1963 
   1964     return BCM_E_RESOURCE;
   1965 }
   1966 
   1967 /*
   1968  * Function:
   1969  *    bcmi_gh2_vxlan_vp_free
   1970  * Purpose:
   1971  *    Internal function for freeing a group of VPs
   1972  * Parameters:
   1973  *    unit  - (IN) Device Number
   1974  *    count   -  (IN) How many consecutive VPs to free
   1975  *    base_vp -  (IN) Base VP index
   1976  * Returns:
   1977  *    BCM_X_XXX
   1978  */
   1979 STATIC int
   1980 bcmi_gh2_vxlan_vp_free(int unit, int count, int base_vp)
   1981 {
   1982     int i;
   1983 
   1984     for (i = 0; i < count; i++) {
   1985         GH2_VXLAN_VP_USED_CLR(unit, (base_vp + i));
   1986         GH2_VXLAN_NETWORK_VP_USED_CLR(unit, (base_vp + i));
   1987         /* Loopback VP is only support when VXLAN RIOT is enabled */
   1988         if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   1989             GH2_VXLAN_LOOPBACK_VP_USED_CLR(unit, (base_vp + i));
   1990         }
   1991     }
   1992 
   1993     return BCM_E_NONE;
   1994 }
   1995 
   1996 /*
   1997  * Function:
   1998  *    bcmi_gh2_vxlan_vp_used_set
   1999  * Purpose:
   2000  *    Mark the VP as used
   2001  * Parameters:
   2002  *    unit - (IN) Device Number
   2003  *    vp   - (IN) VP
   2004  *    vxlan_vp_info - (IN) VXLAN VP info
   2005  * Returns:
   2006  *    Boolean
   2007  */
   2008 STATIC int
   2009 bcmi_gh2_vxlan_vp_used_set(
   2010     int unit,
   2011     int vp,
   2012     bcmi_vxlan_vp_info_t vxlan_vp_info)
   2013 {
   2014     if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_SHARED_PORT) {
   2015         return BCM_E_UNAVAIL;
   2016     }
   2017 
   2018     GH2_VXLAN_VP_USED_SET(unit, vp);
   2019 
   2020     if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_NETWORK_PORT) {
   2021         GH2_VXLAN_NETWORK_VP_USED_SET(unit, vp);
   2022     } else {
   2023         GH2_VXLAN_NETWORK_VP_USED_CLR(unit, vp);
   2024     }
   2025 
   2026     /* Loopback VP is only support when VXLAN RIOT is enabled */
   2027     if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   2028         if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_LOOPBACK_PORT) {
   2029             GH2_VXLAN_LOOPBACK_VP_USED_SET(unit, vp);
   2030         } else {
   2031             GH2_VXLAN_LOOPBACK_VP_USED_CLR(unit, vp);
   2032         }
   2033     }
   2034 
   2035     return BCM_E_NONE;
   2036 }
   2037 
   2038 /*
   2039  * Function:
   2040  *    bcmi_gh2_vxlan_vp_used_get
   2041  * Purpose:
   2042  *    Check whether a VP is used or not
   2043  * Parameters:
   2044  *    unit - (IN) Device Number
   2045  *    vp   - (IN) VP
   2046  * Returns:
   2047  *    Boolean
   2048  */
   2049 int
   2050 bcmi_gh2_vxlan_vp_used_get(int unit, int vp)
   2051 {
   2052     int rv = BCM_E_NONE;
   2053     int num_vp;
   2054     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit);
   2055 
   2056     num_vp = vxlan_info->num_vxlan_vp;
   2057 
   2058     /* Check Valid range of VFI */
   2059     if ((vp < 0) || (vp >= num_vp)) {
   2060          return rv;
   2061     }
   2062 
   2063     rv = GH2_VXLAN_VP_USED_GET(unit, vp);
   2064 
   2065     return rv;
   2066 }
   2067 
   2068 /*
   2069  * Function:
   2070  *    bcmi_gh2_vxlan_vp_info_get
   2071  * Purpose:
   2072  *    Get the VP Type of a VP, given its Id
   2073  * Parameters:
   2074  *    unit  - (IN) Device Number
   2075  *    vp   -  (IN) VP
   2076  *    vp_info - (OUT) VP info structure
   2077  * Returns:
   2078  *    BCM_E_XXX
   2079  */
   2080 int
   2081 bcmi_gh2_vxlan_vp_info_get(int unit, int vp, bcmi_vxlan_vp_info_t *vp_info)
   2082 {
   2083     if (NULL == vp_info) {
   2084         return BCM_E_PARAM;
   2085     }
   2086 
   2087     bcmi_gh2_vxlan_vp_info_init(vp_info);
   2088 
   2089     if (bcmi_gh2_vxlan_vp_used_get(unit, vp)) {
   2090         if (GH2_VXLAN_NETWORK_VP_USED_GET(unit, vp)) {
   2091             vp_info->flags |= GH2_VXLAN_VP_INFO_NETWORK_PORT;
   2092         } else {
   2093             /* Loopback VP is only support when VXLAN RIOT is enabled */
   2094             if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   2095                 if (GH2_VXLAN_LOOPBACK_VP_USED_GET(unit, vp)) {
   2096                     vp_info->flags |= GH2_VXLAN_VP_INFO_LOOPBACK_PORT;
   2097                 }
   2098             }
   2099         }
   2100 
   2101         return BCM_E_NONE;
   2102     }
   2103 
   2104     return BCM_E_NOT_FOUND;
   2105 }
   2106 
   2107 /*
   2108  * Function:
   2109  *    bcmi_gh2_vxlan_port_match_count_adjust
   2110  * Purpose:
   2111  *    Obtain ref-count for a VXLAN port
   2112  * Parameters:
   2113  *    unit - (IN) Device Number
   2114  *    vp   - (IN) VP
   2115  *    step - (IN) number for rer-count increment
   2116  * Returns:
   2117  *    None
   2118  */
   2119 
   2120 STATIC void
   2121 bcmi_gh2_vxlan_port_match_count_adjust(int unit, int vp, int step)
   2122 {
   2123     int num_vp;
   2124     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit);
   2125 
   2126     num_vp = vxlan_info->num_vxlan_vp;
   2127 
   2128     /* Check Valid range of VFI */
   2129     if ((vp < 0) || (vp >= num_vp)) {
   2130          return;
   2131     }
   2132 
   2133     vxlan_info->match_key[vp].match_count += step;
   2134 }
   2135 
   2136 /*
   2137  * Function:
   2138  *    bcmi_gh2_vxlan_cleanup
   2139  * Purpose:
   2140  *    DeInit VXLAN software module
   2141  * Parameters:
   2142  *    unit - (IN) Device Number
   2143  * Returns:
   2144  *    BCM_E_XXX
   2145  */
   2146 int
   2147 bcmi_gh2_vxlan_cleanup(int unit)
   2148 {
   2149     int rv = BCM_E_UNAVAIL;
   2150     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   2151 
   2152     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   2153          return BCM_E_UNIT;
   2154     }
   2155 
   2156     vxlan_info = GH2_VXLAN_INFO(unit);
   2157 
   2158     if (vxlan_info->initialized == FALSE) {
   2159         return BCM_E_NONE;
   2160     }
   2161 
   2162     rv = bcmi_gh2_vxlan_lock(unit);
   2163     if (BCM_FAILURE(rv)) {
   2164         return rv;
   2165     }
   2166 
   2167     if (0 == SOC_HW_ACCESS_DISABLE(unit)) {
   2168         rv = bcmi_gh2_vxlan_hw_clear(unit);
   2169     }
   2170 
   2171     bcmi_gh2_vxlan_unlock(unit);
   2172 
   2173     /* Mark the state as uninitialized */
   2174     vxlan_info->initialized = FALSE;
   2175 
   2176     /* Free software resources */
   2177     (void)bcmi_gh2_vxlan_free_resource(unit);
   2178 
   2179     return rv;
   2180 }
   2181 
   2182 /*
   2183  * Function:
   2184  *    bcmi_gh2_vxlan_header_init
   2185  * Purpose:
   2186  *    Initialize the VXLAN header info
   2187  * Parameters:
   2188  *    unit - (IN) Device Number
   2189  * Returns:
   2190  *    BCM_E_XXX
   2191  */
   2192 STATIC int
   2193 bcmi_gh2_vxlan_header_init(int unit)
   2194 {
   2195     uint32 mem_entry[SOC_MAX_MEM_WORDS];
   2196     soc_mem_t mem;
   2197 
   2198     if (soc_feature(unit, soc_feature_vxlan_lite)) {
   2199         sal_memset(mem_entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS));
   2200 
   2201         /*
   2202          * Ingress VXLAN class selection:
   2203          * only support one class (VXLAN_FLAGS = 0x08, others are all zero)
   2204          * the VXLAN_CLASS_ID hit will be one condition of VXLAN-LITE decap
   2205          */
   2206         /* ING_VXLAN_CLASS_ID_TCAMm */
   2207         mem = ING_VXLAN_CLASS_ID_TCAMm;
   2208         sal_memset(mem_entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS));
   2209         BCM_IF_ERROR_RETURN(
   2210             soc_mem_read(unit, mem, MEM_BLOCK_ANY, 0, mem_entry));
   2211         soc_mem_field32_set(unit, mem, mem_entry, VALIDf, 0x1);
   2212         soc_mem_field32_set(unit, mem, mem_entry, VXLAN_FLAGSf, 0x8);
   2213         soc_mem_field32_set(unit, mem, mem_entry, VXLAN_FLAGS_MASKf, 0xff);
   2214         /* Write buffer to hw. */
   2215         BCM_IF_ERROR_RETURN(
   2216             soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, mem_entry));
   2217 
   2218         /* ING_VXLAN_CLASS_ID_POLICY_TABLE */
   2219         mem = ING_VXLAN_CLASS_ID_POLICY_TABLEm;
   2220         sal_memset(mem_entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS));
   2221         BCM_IF_ERROR_RETURN(
   2222             soc_mem_read(unit, mem, MEM_BLOCK_ANY, 0, mem_entry));
   2223         soc_mem_field32_set(unit, mem, mem_entry, VALIDf, 0x1);
   2224         soc_mem_field32_set(unit, mem, mem_entry, CLASS_IDf, 0x0);
   2225         /* Write buffer to hw. */
   2226         BCM_IF_ERROR_RETURN(
   2227             soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, mem_entry));
   2228 
   2229         /* Egress VXLAN header */
   2230         mem = EGR_VXLAN_HEADERm;
   2231         sal_memset(mem_entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS));
   2232         BCM_IF_ERROR_RETURN(
   2233             soc_mem_read(unit, mem, MEM_BLOCK_ANY, 0, mem_entry));
   2234         soc_mem_field32_set(unit, mem, mem_entry, VXLAN_FLAGSf, 0x8);
   2235         /* Write buffer to hw. */
   2236         BCM_IF_ERROR_RETURN(
   2237             soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, mem_entry));
   2238     }
   2239 
   2240     return BCM_E_NONE;
   2241 }
   2242 
   2243 /*
   2244  * Function:
   2245  *    bcmi_gh2_vxlan_init
   2246  * Purpose:
   2247  *    Initialize the VXLAN software module
   2248  * Parameters:
   2249  *    unit - (IN) Device Number
   2250  * Returns:
   2251  *    BCM_E_XXX
   2252  */
   2253 int
   2254 bcmi_gh2_vxlan_init(int unit)
   2255 {
   2256     int rv = BCM_E_NONE;
   2257     int i, num_tnl = 0, num_vp = 0, num_vfi = 0, num_tpid = 0;
   2258     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   2259     int riot_enable = 0;
   2260 
   2261     if (!GH2_L3_INFO(unit)->l3_initialized) {
   2262         LOG_ERROR(BSL_LS_BCM_VXLAN,
   2263                   (BSL_META_U(unit,
   2264                               "L3 module must be initialized" \
   2265                               "prior to VXLAN Init\n")));
   2266         return BCM_E_CONFIG;
   2267     }
   2268 
   2269     /* VXLAN-Lite RIOT is only support for GH2-B0 */
   2270     riot_enable = soc_property_get(unit, spn_RIOT_ENABLE, 0);
   2271     if (riot_enable && !soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   2272         LOG_ERROR(BSL_LS_BCM_VXLAN,
   2273                   (BSL_META_U(unit,
   2274                               "VXLAN RIOT is not supported\n")));
   2275         return BCM_E_CONFIG;
   2276     }
   2277 
   2278     /* Global initialization flag setup */
   2279     if (gh2_vxlan_initialized == FALSE) {
   2280         for (i = 0; i < BCM_MAX_NUM_UNITS; i++) {
   2281             bcmi_gh2_vxlan_bk_info[i] = NULL;
   2282         }
   2283         gh2_vxlan_initialized = TRUE;
   2284     }
   2285 
   2286     /* Allocate BK Info */
   2287     BCM_IF_ERROR_RETURN(
   2288         bcmi_gh2_vxlan_allocate_bk(unit));
   2289     vxlan_info = GH2_VXLAN_INFO(unit);
   2290 
   2291     /*
   2292      * Allocate Resources
   2293      */
   2294     if (vxlan_info->initialized) {
   2295         BCM_IF_ERROR_RETURN(
   2296             bcmi_gh2_vxlan_cleanup(unit));
   2297         BCM_IF_ERROR_RETURN(
   2298             bcmi_gh2_vxlan_allocate_bk(unit));
   2299         vxlan_info = GH2_VXLAN_INFO(unit);
   2300     }
   2301 
   2302     num_vp = soc_mem_index_count(unit, VLAN_XLATEm);
   2303 
   2304     /* VXLAN Virtual Port store */
   2305     BCMI_VXLAN_ALLOC(vxlan_info->match_key,
   2306                      sizeof(_bcm_vxlan_match_port_info_t) * num_vp,
   2307                      "match_key");
   2308     if (vxlan_info->match_key == NULL) {
   2309         bcmi_gh2_vxlan_free_resource(unit);
   2310         return BCM_E_MEMORY;
   2311     }
   2312 
   2313     /* Stay same after recover */
   2314     for (i = 0; i < num_vp; i++) {
   2315         bcmi_gh2_vxlan_match_clear(unit, i);
   2316     }
   2317 
   2318     num_tnl = soc_mem_index_count(unit, BCM_XGS3_L3_MEM(unit, tnl_init_v4));
   2319 
   2320     /* Create EGR_IP_TUNNEL usage bitmap */
   2321     BCMI_VXLAN_ALLOC(vxlan_info->vxlan_ip_tnl_bitmap,
   2322                      SHR_BITALLOCSIZE(num_tnl), "vxlan_ip_tnl_bitmap");
   2323     if (vxlan_info->vxlan_ip_tnl_bitmap == NULL) {
   2324         bcmi_gh2_vxlan_free_resource(unit);
   2325         return BCM_E_MEMORY;
   2326     }
   2327 
   2328     /* Create VXLAN protection mutex. */
   2329     vxlan_info->vxlan_mutex = sal_mutex_create("vxlan_mutex");
   2330     if (!vxlan_info->vxlan_mutex) {
   2331          bcmi_gh2_vxlan_free_resource(unit);
   2332          return BCM_E_MEMORY;
   2333     }
   2334 
   2335     /* VXLAN tunnel termination store */
   2336     BCMI_VXLAN_ALLOC(vxlan_info->vxlan_tunnel_term,
   2337                      sizeof(bcmi_gh2_vxlan_tunnel_endpoint_t) * num_tnl,
   2338                      "vxlan tunnel term store");
   2339     if (vxlan_info->vxlan_tunnel_term == NULL) {
   2340         bcmi_gh2_vxlan_free_resource(unit);
   2341         return BCM_E_MEMORY;
   2342     }
   2343 
   2344     /* VXLAN tunnel initialization store */
   2345     BCMI_VXLAN_ALLOC(vxlan_info->vxlan_tunnel_init,
   2346                      sizeof(bcmi_gh2_vxlan_tunnel_endpoint_t) * num_tnl,
   2347                      "vxlan tunnel init store");
   2348     if (vxlan_info->vxlan_tunnel_init == NULL) {
   2349         bcmi_gh2_vxlan_free_resource(unit);
   2350         return BCM_E_MEMORY;
   2351     }
   2352 
   2353     vxlan_info->num_vxlan_tnl = num_tnl;
   2354 
   2355     if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   2356         /* GH2-B0 support hardware VFI table */
   2357         num_vfi = soc_mem_index_count(unit, VFIm);
   2358     } else {
   2359         /* GH2-A0 support software VFI table (depends on VLAN_XLATEm) */
   2360         num_vfi = soc_mem_index_count(unit, VLAN_XLATEm);
   2361     }
   2362 
   2363     /* VXLAN VFI bitmap initialization store */
   2364     BCMI_VXLAN_ALLOC(vxlan_info->vxlan_vfi_bitmap,
   2365                      SHR_BITALLOCSIZE(num_vfi), "vxlan_vfi_bitmap");
   2366     if (vxlan_info->vxlan_vfi_bitmap == NULL) {
   2367         bcmi_gh2_vxlan_free_resource(unit);
   2368         return BCM_E_MEMORY;
   2369     }
   2370 
   2371     /* VXLAN VFI info initialization store */
   2372     BCMI_VXLAN_ALLOC(vxlan_info->vxlan_vpn_info,
   2373                      sizeof(gh2_vxlan_vpn_info_t) * num_vfi, "vxlan_vpn_info");
   2374     if (vxlan_info->vxlan_vpn_info == NULL) {
   2375         bcmi_gh2_vxlan_free_resource(unit);
   2376         return BCM_E_MEMORY;
   2377     }
   2378     vxlan_info->num_vxlan_vfi = num_vfi;
   2379 
   2380     /* VXLAN Virtual Port bitmap initialization store */
   2381     BCMI_VXLAN_ALLOC(vxlan_info->vxlan_vp_bitmap,
   2382                      SHR_BITALLOCSIZE(num_vp), "vxlan_vp_bitmap");
   2383     if (vxlan_info->vxlan_vp_bitmap == NULL) {
   2384         bcmi_gh2_vxlan_free_resource(unit);
   2385         return BCM_E_MEMORY;
   2386     }
   2387 
   2388     /* Network VXLAN Virtual Port bitmap initialization store */
   2389     BCMI_VXLAN_ALLOC(vxlan_info->vxlan_network_vp_bitmap,
   2390                      SHR_BITALLOCSIZE(num_vp), "vxlan_network_vp_bitmap");
   2391     if (vxlan_info->vxlan_network_vp_bitmap == NULL) {
   2392         bcmi_gh2_vxlan_free_resource(unit);
   2393         return BCM_E_MEMORY;
   2394     }
   2395 
   2396     /* VXLAN Outer TPID info initialization store */
   2397     num_tpid = soc_reg_field_length(unit, ING_VXLAN_CONTROLr,
   2398                                     PAYLOAD_OUTER_TPID_ENABLEf);
   2399     BCMI_VXLAN_ALLOC(vxlan_info->vxlan_outer_tpid,
   2400                      sizeof(gh2_vxlan_outer_tpid_info_t) * num_tpid,
   2401                      "vxlan_outer_tpid");
   2402     if (vxlan_info->vxlan_outer_tpid == NULL) {
   2403         bcmi_gh2_vxlan_free_resource(unit);
   2404         return BCM_E_MEMORY;
   2405     }
   2406     vxlan_info->num_vxlan_outer_tpid = num_tpid;
   2407 
   2408     /* VXLAN Ingress VLAN XLATE info initialization store */
   2409     BCMI_VXLAN_ALLOC(vxlan_info->vxlan_vlan_xlate,
   2410                      sizeof(gh2_vxlan_vlan_xlate_info_t) * num_vfi,
   2411                      "vxlan_vlan_xlate");
   2412     if (vxlan_info->vxlan_vlan_xlate == NULL) {
   2413         bcmi_gh2_vxlan_free_resource(unit);
   2414         return BCM_E_MEMORY;
   2415     }
   2416 
   2417     /* VXLAN VP info initialization store */
   2418     BCMI_VXLAN_ALLOC(vxlan_info->vxlan_vp_info,
   2419                      sizeof(gh2_vxlan_vp_info_t) * num_vp, "vxlan_vp_info");
   2420     if (vxlan_info->vxlan_vp_info == NULL) {
   2421         bcmi_gh2_vxlan_free_resource(unit);
   2422         return BCM_E_MEMORY;
   2423     }
   2424     vxlan_info->num_vxlan_vp = num_vp;
   2425 
   2426     /* RIOT is Enabled/Disabled on this device (for GH2-B0 only) */
   2427     vxlan_info->riot_enable = riot_enable;
   2428 
   2429     /*
   2430      * Loopback VXLAN Virtual Port bitmap initialization store
   2431      * (used for RIOT)
   2432      */
   2433     BCMI_VXLAN_ALLOC(vxlan_info->vxlan_loopback_vp_bitmap,
   2434                      SHR_BITALLOCSIZE(num_vp), "vxlan_loopback_vp_bitmap");
   2435     if (vxlan_info->vxlan_loopback_vp_bitmap == NULL) {
   2436         bcmi_gh2_vxlan_free_resource(unit);
   2437         return BCM_E_MEMORY;
   2438     }
   2439 
   2440     /* Reference count of Custom Header index0 initialization store */
   2441     vxlan_info->riot_custom_header_index0_ref_count = 0;
   2442 
   2443     /* Initialize the VXLAN header info */
   2444     rv = bcmi_gh2_vxlan_header_init(unit);
   2445     if (BCM_FAILURE(rv)) {
   2446         bcmi_gh2_vxlan_free_resource(unit);
   2447         return rv;
   2448     }
   2449 
   2450 #ifdef BCM_WARM_BOOT_SUPPORT
   2451     if (SOC_WARM_BOOT(unit)) {
   2452         rv = bcmi_gh2_vxlan_reinit(unit);
   2453     } else {
   2454         rv = bcmi_gh2_vxlan_wb_alloc(unit);
   2455     }
   2456     /* clean up the bookkeeping resource if any errors */
   2457     if (BCM_FAILURE(rv)) {
   2458         bcmi_gh2_vxlan_free_resource(unit);
   2459         return rv;
   2460     }
   2461 #endif /* BCM_WARM_BOOT_SUPPORT */
   2462 
   2463     /* Mark the state as initialized */
   2464     vxlan_info->initialized = TRUE;
   2465 
   2466     return rv;
   2467 }
   2468 
   2469 /*
   2470  * Function:
   2471  *    bcmi_gh2_vxlan_vpn_is_valid
   2472  * Purpose:
   2473  *    Find if given VXLAN VPN is Valid
   2474  * Parameters:
   2475  *    unit  - (IN) Device Number
   2476  *    l2vpn - (IN) VXLAN VPN
   2477  * Returns:
   2478  *    BCM_E_XXXX
   2479  */
   2480 STATIC int
   2481 bcmi_gh2_vxlan_vpn_is_valid(int unit, bcm_vpn_t l2vpn)
   2482 {
   2483     bcm_vpn_t vxlan_vpn_min = 0;
   2484     int vfi_index = -1, num_vfi = 0;
   2485     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   2486 
   2487     /* Get VXLAN bookkeeping info instance */
   2488     BCM_IF_ERROR_RETURN(
   2489         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   2490 
   2491     num_vfi = vxlan_info->num_vxlan_vfi;
   2492 
   2493     /* Check for Valid vpn */
   2494     _BCM_VXLAN_VPN_SET(vxlan_vpn_min, _BCM_VPN_TYPE_VFI, 0);
   2495     if (l2vpn < vxlan_vpn_min || l2vpn > (vxlan_vpn_min + num_vfi - 1)) {
   2496         return BCM_E_PARAM;
   2497     }
   2498 
   2499     _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, l2vpn);
   2500 
   2501     if (!bcmi_gh2_vxlan_vfi_used_get(unit, vfi_index)) {
   2502         return BCM_E_NOT_FOUND;
   2503     }
   2504 
   2505     return BCM_E_NONE;
   2506 }
   2507 
   2508 /*
   2509  * Function:
   2510  *    bcmi_gh2_vxlan_vpn_is_eline
   2511  * Purpose:
   2512  *    Find if given VXLAN VPN is ELINE
   2513  * Parameters:
   2514  *    unit  - (IN) Device Number
   2515  *    l2vpn   - VXLAN VPN
   2516  *    is_eline  - Flag
   2517  * Returns:
   2518  *    BCM_E_XXXX
   2519  */
   2520 STATIC int
   2521 bcmi_gh2_vxlan_vpn_is_eline(int unit, bcm_vpn_t l2vpn, uint8 *is_eline)
   2522 {
   2523     /* Input parameter check */
   2524     if (NULL == is_eline) {
   2525         return BCM_E_PARAM;
   2526     }
   2527 
   2528     BCM_IF_ERROR_RETURN(
   2529         bcmi_gh2_vxlan_vpn_is_valid(unit, l2vpn));
   2530 
   2531     /* Currently, VXLAN-LITE only support ELAN */
   2532     *is_eline = 0;
   2533 
   2534     return BCM_E_NONE;
   2535 }
   2536 
   2537 /*
   2538  * Function:
   2539  *    bcmi_gh2_vxlan_vp_is_eline
   2540  * Purpose:
   2541  *    Find if given VXLAN VP is ELINE
   2542  * Parameters:
   2543  *    unit     - (IN) Device Number
   2544  *    vp       - (IN) VXLAN VP
   2545  *    is_eline - (IN) Flag
   2546  * Returns:
   2547  *    BCM_E_XXXX
   2548  * Assumes:
   2549  *    l2vpn is valid
   2550  */
   2551 STATIC int
   2552 bcmi_gh2_vxlan_vp_is_eline( int unit, int vp, uint8 *is_eline)
   2553 {
   2554     /* Input parameter check */
   2555     if (NULL == is_eline) {
   2556         return BCM_E_PARAM;
   2557     }
   2558     if (vp == -1) {
   2559         return BCM_E_PARAM;
   2560     }
   2561 
   2562     if (!bcmi_gh2_vxlan_vp_used_get(unit, vp)) {
   2563         return BCM_E_NOT_FOUND;
   2564     }
   2565 
   2566    *is_eline = 0x0;
   2567 
   2568    return BCM_E_NONE;
   2569 }
   2570 
   2571 /*
   2572  * Function:
   2573  *    bcmi_gh2_vxlan_match_vnid_entry_reset
   2574  * Purpose:
   2575  *    Reset VXLAN Match VNID Entry
   2576  * Parameters:
   2577  *    unit  - (IN) Device Number
   2578  *    IN :  Vnid
   2579  * Returns:
   2580  *    BCM_E_XXX
   2581  */
   2582 STATIC int
   2583 bcmi_gh2_vxlan_match_vnid_entry_reset(int unit, uint32 vnid)
   2584 {
   2585     soc_mem_t mem;
   2586     uint32 vxlate_entry[SOC_MAX_MEM_WORDS];
   2587 
   2588     sal_memset(vxlate_entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS));
   2589 
   2590     mem = VLAN_XLATEm;
   2591 
   2592     soc_mem_field32_set(unit, mem, vxlate_entry, VALIDf, 0x1);
   2593     soc_mem_field32_set(unit, mem, vxlate_entry, XLATE__VNIDf, vnid);
   2594     /* incoming port not used in lookup key, set field to all 1's */
   2595     soc_mem_field32_set(unit, mem, vxlate_entry, XLATE__GLPf,
   2596                         SOC_VLAN_XLATE_GLP_WILDCARD(unit));
   2597     soc_mem_field32_set(unit, mem, vxlate_entry, KEY_TYPEf,
   2598                         GH2_VLXLT_HASH_KEY_TYPE_VNID);
   2599 
   2600     BCM_IF_ERROR_RETURN(
   2601         soc_mem_delete(unit, mem, MEM_BLOCK_ALL, vxlate_entry));
   2602 
   2603     return BCM_E_NONE;
   2604 }
   2605 
   2606  /*
   2607  * Function:
   2608  *    bcmi_gh2_vxlan_vfi_to_vpn_get
   2609  * Purpose:
   2610  *    Get L2-VPN instance for VXLAN
   2611  * Parameters:
   2612  *    unit - (IN) Device Number
   2613  *    vfi_index - (IN) vfi_index
   2614  *    vid  - (OUT) VLAN Id (l2vpn id)
   2615  * Returns:
   2616  *    BCM_E_XXXX
   2617  */
   2618 int
   2619 bcmi_gh2_vxlan_vfi_to_vpn_get(int unit, int vfi_index, bcm_vlan_t *vid)
   2620 {
   2621     /* Input parameter check */
   2622     if (NULL == vid) {
   2623         return BCM_E_PARAM;
   2624     }
   2625 
   2626     if (!bcmi_gh2_vxlan_vfi_used_get(unit, vfi_index)) {
   2627         return BCM_E_NOT_FOUND;
   2628     }
   2629 
   2630     _BCM_VXLAN_VPN_SET(*vid, _BCM_VXLAN_VPN_TYPE_ELAN, vfi_index);
   2631 
   2632     return BCM_E_NONE;
   2633 }
   2634 
   2635 /*
   2636  * Function:
   2637  *    bcmi_gh2_vxlan_vpn_create
   2638  * Purpose:
   2639  *    Create a VPN instance
   2640  * Parameters:
   2641  *    unit - (IN) Device Number
   2642  *    info - (IN/OUT) VPN configuration info
   2643  * Returns:
   2644  *    BCM_E_XXX
   2645  */
   2646 int
   2647 bcmi_gh2_vxlan_vpn_create(int unit, bcm_vxlan_vpn_config_t *info)
   2648 {
   2649     int rv, rv2;
   2650     int vfi_index = -1;
   2651     uint32 vnid = 0;
   2652     uint8 vpn_alloc_flag = 0;
   2653     bcm_vlan_protocol_packet_ctrl_t protocol_pkt;
   2654     soc_mem_t mem;
   2655     uint32 vxlate_entry[SOC_MAX_MEM_WORDS];
   2656     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   2657     gh2_vxlan_vpn_info_t *vfi_info;
   2658     vfi_entry_t vfi_entry;
   2659     int uuc_umc_bc_group = 0;
   2660     int uuc_umc_bc_group_type = 0;
   2661 
   2662     /* Input parameter check */
   2663     if (NULL == info) {
   2664         return BCM_E_PARAM;
   2665     }
   2666 
   2667     /* Get VXLAN bookkeeping info instance */
   2668     BCM_IF_ERROR_RETURN(
   2669         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   2670 
   2671     sal_memset(vxlate_entry, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS));
   2672 
   2673     /* Allocate VFI */
   2674     if (info->flags & BCM_VXLAN_VPN_REPLACE) {
   2675         BCM_IF_ERROR_RETURN(
   2676             bcmi_gh2_vxlan_vpn_is_valid(unit, info->vpn));
   2677         _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, info->vpn);
   2678     } else if (info->flags & BCM_VXLAN_VPN_WITH_ID) {
   2679         rv = bcmi_gh2_vxlan_vpn_is_valid(unit, info->vpn);
   2680         if (rv == BCM_E_NONE) {
   2681             return BCM_E_EXISTS;
   2682         } else if (rv != BCM_E_NOT_FOUND) {
   2683             return rv;
   2684         }
   2685         _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, info->vpn);
   2686         BCM_IF_ERROR_RETURN(
   2687             bcmi_gh2_vxlan_vfi_alloc_with_id(unit, vfi_index));
   2688         vpn_alloc_flag = 1;
   2689     } else {
   2690         BCM_IF_ERROR_RETURN(
   2691             bcmi_gh2_vxlan_vfi_alloc(unit, &vfi_index));
   2692         _BCM_VXLAN_VPN_SET(info->vpn, _BCM_VPN_TYPE_VFI, vfi_index);
   2693         vpn_alloc_flag = 1;
   2694     }
   2695 
   2696     /* Initial and configure VFI */
   2697     if (info->flags & BCM_VXLAN_VPN_ELINE) {
   2698         /* Currently, VXLAN-LITE doesn't support ELINE on VPN */
   2699         return BCM_E_UNAVAIL;
   2700     } else if (info->flags & BCM_VXLAN_VPN_ELAN) {
   2701         /* Configure unknown UC/MC/BC packets forwarding on the VFI */
   2702         if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   2703             /* Only support for GH2-B0 with new VFI table */
   2704 
   2705             /* Check that the groups are valid */
   2706             /* Unknown UC/MC/BC group share the same field for GH2-B0 */
   2707             if ((info->unknown_unicast_group !=
   2708                 info->unknown_multicast_group) ||
   2709                 (info->unknown_multicast_group !=
   2710                 info->broadcast_group)) {
   2711                 if (vpn_alloc_flag) {
   2712                     rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index);
   2713                     if (BCM_FAILURE(rv)) {
   2714                         return rv;
   2715                     }
   2716                 }
   2717                 return BCM_E_PARAM;
   2718             }
   2719 
   2720             /* Select one of groups (suppose they should be the same) */
   2721             if (info->unknown_unicast_group != 0) {
   2722                 uuc_umc_bc_group_type =
   2723                     _BCM_MULTICAST_TYPE_GET(info->unknown_unicast_group);
   2724                 uuc_umc_bc_group =
   2725                     _BCM_MULTICAST_ID_GET(info->unknown_unicast_group);
   2726 
   2727                 if ((uuc_umc_bc_group_type != _BCM_MULTICAST_TYPE_VXLAN) ||
   2728                     (uuc_umc_bc_group >= soc_mem_index_count(unit,
   2729                                                              L3_IPMCm))) {
   2730                     if (vpn_alloc_flag) {
   2731                         rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index);
   2732                         if (BCM_FAILURE(rv)) {
   2733                             return rv;
   2734                         }
   2735                     }
   2736                     return BCM_E_PARAM;
   2737                 }
   2738 
   2739                 /* Commit the entry to HW */
   2740                 rv = soc_mem_read(unit, VFIm, MEM_BLOCK_ANY,
   2741                                   vfi_index, &vfi_entry);
   2742                 if (SOC_FAILURE(rv)) {
   2743                     if (vpn_alloc_flag) {
   2744                         rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index);
   2745                         if (BCM_FAILURE(rv)) {
   2746                             return rv;
   2747                         }
   2748                     }
   2749                     return rv;
   2750                 }
   2751                 soc_mem_field32_set(unit, VFIm, &vfi_entry,
   2752                                     UUC_UMC_BC_INDEXf, uuc_umc_bc_group);
   2753                 rv = soc_mem_write(unit, VFIm, MEM_BLOCK_ALL,
   2754                                    vfi_index, &vfi_entry);
   2755                 if (SOC_FAILURE(rv)) {
   2756                     if (vpn_alloc_flag) {
   2757                         rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index);
   2758                         if (BCM_FAILURE(rv)) {
   2759                             return rv;
   2760                         }
   2761                     }
   2762                     return rv;
   2763                 }
   2764             }
   2765         } else {
   2766             /* Not support for GH2-A0 (no VFI table) */
   2767             if ((info->broadcast_group != 0) ||
   2768                 (info->unknown_multicast_group != 0) ||
   2769                 (info->unknown_unicast_group != 0)) {
   2770                 if (vpn_alloc_flag) {
   2771                     rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index);
   2772                     if (BCM_FAILURE(rv)) {
   2773                         return rv;
   2774                     }
   2775                 }
   2776                 return BCM_E_PARAM;
   2777             }
   2778         }
   2779     }
   2780 
   2781     /* Configure protocol packet control (not support for VXLAN-LITE) */
   2782     sal_memset(&protocol_pkt, 0, sizeof(protocol_pkt));
   2783     if (0 != sal_memcmp(&(info->protocol_pkt), &protocol_pkt,
   2784                         sizeof(bcm_vlan_protocol_packet_ctrl_t))) {
   2785         if (vpn_alloc_flag) {
   2786             rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index);
   2787             if (BCM_FAILURE(rv)) {
   2788                 return rv;
   2789             }
   2790         }
   2791         return BCM_E_UNAVAIL;
   2792     }
   2793 
   2794     if (info->flags & BCM_VXLAN_VPN_WITH_VPNID) {
   2795         /* VXLAN-LITE doesn't support BCM_VXLAN_VPN_SERVICE_XXX */
   2796         if ((info->flags & BCM_VXLAN_VPN_SERVICE_TAGGED) ||
   2797             (info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_ADD) ||
   2798             (info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_REPLACE) ||
   2799             (info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_DELETE) ||
   2800             (info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_TPID_REPLACE) ||
   2801             (info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_PRI_TPID_REPLACE) ||
   2802             (info->flags & BCM_VXLAN_VPN_SERVICE_VLAN_PRI_REPLACE) ||
   2803             (info->flags & BCM_VXLAN_VPN_SERVICE_PRI_REPLACE) ||
   2804             (info->flags & BCM_VXLAN_VPN_SERVICE_TPID_REPLACE)) {
   2805             if (vpn_alloc_flag) {
   2806                 rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index);
   2807                 if (BCM_FAILURE(rv)) {
   2808                     return rv;
   2809                 }
   2810             }
   2811             return BCM_E_UNAVAIL;
   2812         }
   2813 
   2814         /* Valid check for VNID value */
   2815         if ((info->vnid > 0xFFFFFF) ||
   2816             (info->flags & BCM_VXLAN_VPN_TUNNEL_BASED_VNID)) {
   2817             if (vpn_alloc_flag) {
   2818                 rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index);
   2819                 if (BCM_FAILURE(rv)) {
   2820                     return rv;
   2821                 }
   2822             }
   2823             return BCM_E_PARAM;
   2824         }
   2825 
   2826         /* Configure Ingress VNID (use VLAN_XLATE) */
   2827         mem = VLAN_XLATEm;
   2828 
   2829         soc_mem_field32_set(unit, mem, vxlate_entry, VALIDf, 0x1);
   2830         soc_mem_field32_set(unit, mem, vxlate_entry, XLATE__MPLS_ACTIONf, 0x5);
   2831         soc_mem_field32_set(unit, mem, vxlate_entry,
   2832                             XLATE__DISABLE_VLAN_CHECKSf, 0x1);
   2833         soc_mem_field32_set(unit, mem, vxlate_entry, XLATE__VFI_VALIDf, 0x1);
   2834         soc_mem_field32_set(unit, mem, vxlate_entry, XLATE__VFIf, vfi_index);
   2835 
   2836         soc_mem_field32_set(unit, mem, vxlate_entry, KEY_TYPEf,
   2837                             GH2_VLXLT_HASH_KEY_TYPE_VNID);
   2838         /* incoming port not used in lookup key, set field to all 1's */
   2839         soc_mem_field32_set(unit, mem, vxlate_entry, XLATE__GLPf,
   2840                             SOC_VLAN_XLATE_GLP_WILDCARD(unit));
   2841 
   2842         vfi_info = &(vxlan_info->vxlan_vpn_info[vfi_index]);
   2843         if (info->flags & BCM_VXLAN_VPN_REPLACE) {
   2844             /* Delete old match vnid entry */
   2845             vnid = vfi_info->vnid;
   2846             if (vfi_info->valid) {
   2847                 if (info->vnid == vnid) {
   2848                     /* Return when the vnid is not changed */
   2849                     return BCM_E_NONE;
   2850                 }
   2851 
   2852                 soc_mem_field32_set(unit, mem, vxlate_entry,
   2853                                     XLATE__VNIDf, vnid);
   2854                 rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, vxlate_entry);
   2855                 if (BCM_FAILURE(rv)) {
   2856                     if (vpn_alloc_flag) {
   2857                         rv2 = bcmi_gh2_vxlan_vfi_free(unit, vfi_index);
   2858                         if (BCM_FAILURE(rv2)) {
   2859                             return rv2;
   2860                         }
   2861                     }
   2862                     return rv;
   2863                 }
   2864             }
   2865         }
   2866         soc_mem_field32_set(unit, mem, vxlate_entry,
   2867                             XLATE__VNIDf, info->vnid);
   2868         rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, vxlate_entry);
   2869         if (BCM_FAILURE(rv)) {
   2870             if (vpn_alloc_flag) {
   2871                 rv2 = bcmi_gh2_vxlan_vfi_free(unit, vfi_index);
   2872                 if (BCM_FAILURE(rv2)) {
   2873                     return rv2;
   2874                 }
   2875             }
   2876             return rv;
   2877         }
   2878 
   2879         /* Update vnid for VXLAN VFI */
   2880         vfi_info->valid = 1;
   2881         vfi_info->vnid = info->vnid;
   2882 
   2883         /* Configure Egress VNID (use EGR_L3_NEXT_HOPm) */
   2884         /* Will be programmed with bcm_vxlan_port_add */
   2885     } else {
   2886         if (info->flags & BCM_VXLAN_VPN_TUNNEL_BASED_VNID) {
   2887             if (vpn_alloc_flag) {
   2888                 rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index);
   2889                 if (BCM_FAILURE(rv)) {
   2890                     return rv;
   2891                 }
   2892             }
   2893             return BCM_E_PARAM;
   2894         }
   2895 
   2896         /* Reset match vnid table */
   2897         vfi_info = &(vxlan_info->vxlan_vpn_info[vfi_index]);
   2898         if (vfi_info->valid) {
   2899             vnid = vfi_info->vnid;
   2900             /* Delete vxlate_entry */
   2901             rv = bcmi_gh2_vxlan_match_vnid_entry_reset(unit, vnid);
   2902             if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) {
   2903                 return rv;
   2904             }
   2905 
   2906             /* Update vnid for VXLAN VFI */
   2907             vfi_info->valid = 0;
   2908             vfi_info->vnid = 0;
   2909         }
   2910     }
   2911 
   2912     return BCM_E_NONE;
   2913 }
   2914 
   2915 /*
   2916  * Function:
   2917  *    bcmi_gh2_vxlan_vpn_destroy
   2918  * Purpose:
   2919  *    Delete a VPN instance
   2920  * Parameters:
   2921  *    unit  - (IN) Device Number
   2922  *    l2vpn - (IN) VPN instance ID
   2923  * Returns:
   2924  *    BCM_E_XXX
   2925  */
   2926 int
   2927 bcmi_gh2_vxlan_vpn_destroy(int unit, bcm_vpn_t l2vpn)
   2928 {
   2929     int rv = 0;
   2930     int vfi_index = 0;
   2931     uint8 is_eline = 0;
   2932     uint32 vnid = 0;
   2933     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   2934     gh2_vxlan_vpn_info_t *vfi_info;
   2935 
   2936     /* Get VXLAN bookkeeping info instance */
   2937     BCM_IF_ERROR_RETURN(
   2938         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   2939 
   2940     /* Get vfi index */
   2941     BCM_IF_ERROR_RETURN(
   2942         bcmi_gh2_vxlan_vpn_is_eline(unit, l2vpn, &is_eline));
   2943     if (is_eline != 0x0) {
   2944         /* VXLAN-LITE doesn't support ELINE */
   2945         return BCM_E_INTERNAL;
   2946     } else {
   2947         _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, l2vpn);
   2948     }
   2949 
   2950     /* Reset match vnid table */
   2951     vfi_info = &(vxlan_info->vxlan_vpn_info[vfi_index]);
   2952     if (vfi_info->valid) {
   2953         vnid = vfi_info->vnid;
   2954         /* Delete vxlate_entry */
   2955         rv = bcmi_gh2_vxlan_match_vnid_entry_reset(unit, vnid);
   2956         if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) {
   2957             return rv;
   2958         }
   2959 
   2960         /* Update vnid for VXLAN VFI */
   2961         vfi_info->valid = 0;
   2962         vfi_info->vnid = 0;
   2963     }
   2964 
   2965     /* Delete all VXLAN ports on this VPN */
   2966     BCM_IF_ERROR_RETURN(
   2967         bcmi_gh2_vxlan_port_delete_all(unit, l2vpn));
   2968 
   2969     /* Reset VFI table */
   2970     rv = bcmi_gh2_vxlan_vfi_free(unit, vfi_index);
   2971 
   2972     return rv;
   2973 }
   2974 
   2975 /*
   2976  * Function:
   2977  *    bcmi_gh2_vxlan_vpn_id_destroy_all
   2978  * Purpose:
   2979  *    Delete all L2-VPN instances
   2980  * Parameters:
   2981  *    unit - (IN) Device Number
   2982  * Returns:
   2983  *    BCM_E_XXXX
   2984  */
   2985 int
   2986 bcmi_gh2_vxlan_vpn_destroy_all(int unit)
   2987 {
   2988     int num_vfi = 0, idx = 0;
   2989     bcm_vpn_t l2vpn = 0;
   2990     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   2991 
   2992     /* Get VXLAN bookkeeping info instance */
   2993     BCM_IF_ERROR_RETURN(
   2994         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   2995 
   2996     /* Destroy all VXLAN VPNs */
   2997     num_vfi = vxlan_info->num_vxlan_vfi;
   2998     for (idx = 0; idx < num_vfi; idx++) {
   2999         if (bcmi_gh2_vxlan_vfi_used_get(unit, idx)) {
   3000             _BCM_VXLAN_VPN_SET(l2vpn, _BCM_VPN_TYPE_VFI, idx);
   3001             BCM_IF_ERROR_RETURN(
   3002                 bcmi_gh2_vxlan_vpn_destroy(unit, l2vpn));
   3003         }
   3004     }
   3005 
   3006     return BCM_E_NONE;
   3007 }
   3008 
   3009 /*
   3010  * Function:
   3011  *    bcmi_gh2_vxlan_vpn_get
   3012  * Purpose:
   3013  *    Get L2-VPN instance
   3014  * Parameters:
   3015  *    unit  - (IN) Device Number
   3016  *    l2vpn - (IN) VXLAN VPN
   3017  *    info  - (OUT) VXLAN VPN Config
   3018  * Returns:
   3019  *    BCM_E_XXXX
   3020  */
   3021 int
   3022 bcmi_gh2_vxlan_vpn_get(
   3023     int unit,
   3024     bcm_vpn_t l2vpn,
   3025     bcm_vxlan_vpn_config_t *info)
   3026 {
   3027     int vfi_index = -1;
   3028     uint8 is_eline = 0;
   3029     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   3030     gh2_vxlan_vpn_info_t *vfi_info;
   3031     vfi_entry_t vfi_entry;
   3032     int uuc_umc_bc_group = 0;
   3033 
   3034     /* Input parameter check */
   3035     if (NULL == info) {
   3036         return BCM_E_PARAM;
   3037     }
   3038 
   3039     /* Get VXLAN bookkeeping info instance */
   3040     BCM_IF_ERROR_RETURN(
   3041         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   3042 
   3043     /* Get vfi table */
   3044     BCM_IF_ERROR_RETURN(
   3045         bcmi_gh2_vxlan_vpn_is_eline(unit, l2vpn, &is_eline));
   3046     if (is_eline != 0x0) {
   3047         /* VXLAN-LITE doesn't support ELINE */
   3048         return BCM_E_INTERNAL;
   3049     } else {
   3050         _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VXLAN_VPN_TYPE_ELAN, l2vpn);
   3051         /* Get info associated with vfi table */
   3052         info->flags =  BCM_VXLAN_VPN_ELAN;
   3053 
   3054         if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   3055             /* Only support for GH2-B0 with new VFI table */
   3056             SOC_IF_ERROR_RETURN(
   3057                 soc_mem_read(unit, VFIm, MEM_BLOCK_ANY,
   3058                              vfi_index, &vfi_entry));
   3059 
   3060             /* Unknown UC/MC/BC group share the same field for GH2-B0 */
   3061             uuc_umc_bc_group =
   3062                 soc_mem_field32_get(unit, VFIm, &vfi_entry, UUC_UMC_BC_INDEXf);
   3063             if (uuc_umc_bc_group != 0) {
   3064                 _BCM_MULTICAST_GROUP_SET(info->broadcast_group,
   3065                                          _BCM_MULTICAST_TYPE_VXLAN,
   3066                                          uuc_umc_bc_group);
   3067                 _BCM_MULTICAST_GROUP_SET(info->unknown_unicast_group,
   3068                                          _BCM_MULTICAST_TYPE_VXLAN,
   3069                                          uuc_umc_bc_group);
   3070                 _BCM_MULTICAST_GROUP_SET(info->unknown_multicast_group,
   3071                                          _BCM_MULTICAST_TYPE_VXLAN,
   3072                                          uuc_umc_bc_group);
   3073             }
   3074         }
   3075     }
   3076 
   3077     _BCM_VXLAN_VPN_SET(info->vpn, _BCM_VPN_TYPE_VFI, vfi_index);
   3078 
   3079     /* Get VNID */
   3080     vfi_info = &(vxlan_info->vxlan_vpn_info[vfi_index]);
   3081     if (vfi_info->valid) {
   3082         info->flags |= BCM_VXLAN_VPN_WITH_VPNID;
   3083         info->vnid = vfi_info->vnid;
   3084     }
   3085 
   3086     return BCM_E_NONE;
   3087 }
   3088 
   3089 /*
   3090  * Function:
   3091  *    bcmi_gh2_vxlan_vpn_traverse
   3092  * Purpose:
   3093  *    Get information about a VPN instance
   3094  * Parameters:
   3095  *    unit - (IN) Device Number
   3096  *    cb   - (IN)  User-provided callback
   3097  *    user_data  - (IN/OUT) callback user data
   3098  * Returns:
   3099  *    BCM_E_XXX
   3100  */
   3101 int
   3102 bcmi_gh2_vxlan_vpn_traverse(
   3103     int unit,
   3104     bcm_vxlan_vpn_traverse_cb cb,
   3105     void *user_data)
   3106 {
   3107     int rv = BCM_E_NONE;
   3108     int idx, num_vfi;
   3109     int vpn;
   3110     bcm_vxlan_vpn_config_t info;
   3111     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   3112 
   3113     /* Input parameter check */
   3114     if (NULL == cb) {
   3115         return BCM_E_PARAM;
   3116     }
   3117 
   3118     /* Get VXLAN bookkeeping info instance */
   3119     BCM_IF_ERROR_RETURN(
   3120         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   3121 
   3122     num_vfi = vxlan_info->num_vxlan_vfi;
   3123     for (idx = 0; idx < num_vfi; idx++) {
   3124         if (bcmi_gh2_vxlan_vfi_used_get(unit, idx)) {
   3125             _BCM_VXLAN_VPN_SET(vpn, _BCM_VPN_TYPE_VFI, idx);
   3126             bcm_vxlan_vpn_config_t_init(&info);
   3127             rv = bcmi_gh2_vxlan_vpn_get(unit, vpn, &info);
   3128             if (BCM_SUCCESS(rv)) {
   3129                 BCM_IF_ERROR_RETURN(
   3130                     cb(unit, &info, user_data));
   3131             }
   3132         }
   3133     }
   3134 
   3135     return rv;
   3136 }
   3137 
   3138 /*
   3139  * Function:
   3140  *    bcmi_gh2_vxlan_tunnel_ip6_is_zero
   3141  * Purpose:
   3142  *    Helper function to check input IPv6 address is zero or not
   3143  * Parameters:
   3144  *    ip6  - (IN) IPv6 address
   3145  * Returns:
   3146  *    TRUE: IPv6 address is all zero, FALSE: IPv6 address is not zero
   3147  */
   3148 STATIC int
   3149 bcmi_gh2_vxlan_tunnel_ip6_is_zero(bcm_ip6_t ip6)
   3150 {
   3151     bcm_ip6_t ip6_zero;
   3152     int is_zero = FALSE;
   3153 
   3154     sal_memset(ip6_zero, 0, BCM_IP6_ADDRLEN);
   3155 
   3156     if (sal_memcmp(ip6, ip6_zero, BCM_IP6_ADDRLEN) == 0) {
   3157         is_zero = TRUE;
   3158     }
   3159 
   3160     return is_zero;
   3161 }
   3162 
   3163 /*
   3164  * Function:
   3165  *    bcmi_gh2_vxlan_tunnel_terminator_create
   3166  * Purpose:
   3167  *    Set VXLAN Tunnel terminator
   3168  * Parameters:
   3169  *    unit - (IN) Device Number
   3170  *    tnl_info - (IN) Tunnel terminator info data structure
   3171  * Returns:
   3172  *    BCM_E_XXX
   3173  */
   3174 int
   3175 bcmi_gh2_vxlan_tunnel_terminator_create(
   3176     int unit,
   3177     bcm_tunnel_terminator_t *tnl_info)
   3178 {
   3179     int tunnel_idx = -1;
   3180     bcm_ip6_t tnl_ip6;
   3181     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   3182 
   3183     /* Input parameter check */
   3184     if (NULL == tnl_info) {
   3185         return BCM_E_PARAM;
   3186     }
   3187 
   3188     /* Get VXLAN bookkeeping info instance */
   3189     BCM_IF_ERROR_RETURN(
   3190         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   3191 
   3192     /* Input Tunnel Type check */
   3193     if (tnl_info->type == bcmTunnelTypeVxlan6) {
   3194         /* Tunnel for IPv6 */
   3195         if (bcmi_gh2_vxlan_tunnel_ip6_is_zero(tnl_info->dip6) ||
   3196             bcmi_gh2_vxlan_tunnel_ip6_is_zero(tnl_info->sip6)) {
   3197             return BCM_E_PARAM;
   3198         }
   3199     } else if (tnl_info->type == bcmTunnelTypeVxlan) {
   3200         /* Tunnel for IPv4 */
   3201         if ((tnl_info->dip == 0) || (tnl_info->sip == 0)) {
   3202             return BCM_E_PARAM;
   3203         }
   3204     } else {
   3205         /* Others are not supported */
   3206         return BCM_E_PARAM;
   3207     }
   3208 
   3209     /* GH2 doesn't support below tunnel flags */
   3210     if (tnl_info->flags & BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE ||
   3211         tnl_info->flags & BCM_TUNNEL_TERM_USE_OUTER_DSCP ||
   3212         tnl_info->flags & BCM_TUNNEL_TERM_USE_OUTER_PCP) {
   3213         return BCM_E_PARAM;
   3214     }
   3215 
   3216     /* Program tunnel id */
   3217     if (tnl_info->flags & BCM_TUNNEL_TERM_TUNNEL_WITH_ID) {
   3218         if (!BCM_GPORT_IS_TUNNEL(tnl_info->tunnel_id)) {
   3219             return BCM_E_PARAM;
   3220         }
   3221 
   3222         tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(tnl_info->tunnel_id);
   3223         GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx);
   3224     } else {
   3225         /* Only BCM_TUNNEL_TERM_TUNNEL_WITH_ID supported */
   3226         /* Use tunnel_id which is got by _create */
   3227         return BCM_E_PARAM;
   3228     }
   3229 
   3230     if (tnl_info->type == bcmTunnelTypeVxlan6) {
   3231         /* Tunnel for IPv6 */
   3232         sal_memcpy(tnl_ip6,
   3233                    vxlan_info->vxlan_tunnel_term[tunnel_idx].dip6,
   3234                    BCM_IP6_ADDRLEN);
   3235         if (!bcmi_gh2_vxlan_tunnel_ip6_is_zero(tnl_ip6)) {
   3236             /*
   3237              * Entry exists with the same idx no matter the dip6
   3238              * is the same or not
   3239              */
   3240             return BCM_E_EXISTS;
   3241         }
   3242     } else {
   3243         /* Tunnel for IPv4 */
   3244         if (vxlan_info->vxlan_tunnel_term[tunnel_idx].dip != 0) {
   3245             /*
   3246              * Entry exists with the same idx no matter the dip
   3247              * is the same or not
   3248              */
   3249             return BCM_E_EXISTS;
   3250         }
   3251     }
   3252 
   3253     sal_memset(&(vxlan_info->vxlan_tunnel_term[tunnel_idx]),
   3254                0, sizeof(bcmi_gh2_vxlan_tunnel_endpoint_t));
   3255     if (tunnel_idx != -1) {
   3256         if (tnl_info->type == bcmTunnelTypeVxlan6) {
   3257             /* Tunnel for IPv6 */
   3258             sal_memcpy(vxlan_info->vxlan_tunnel_term[tunnel_idx].sip6,
   3259                        tnl_info->sip6, BCM_IP6_ADDRLEN);
   3260             sal_memcpy(vxlan_info->vxlan_tunnel_term[tunnel_idx].dip6,
   3261                        tnl_info->dip6, BCM_IP6_ADDRLEN);
   3262         } else {
   3263             /* Tunnel for IPv4 */
   3264             vxlan_info->vxlan_tunnel_term[tunnel_idx].sip = tnl_info->sip;
   3265             vxlan_info->vxlan_tunnel_term[tunnel_idx].dip = tnl_info->dip;
   3266         }
   3267         vxlan_info->vxlan_tunnel_term[tunnel_idx].vlan = tnl_info->vlan;
   3268         vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state =
   3269             _BCM_VXLAN_TUNNEL_TERM_MULTICAST_LEAF;
   3270         vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag |=
   3271             _BCM_VXLAN_TUNNEL_TERM_ENABLE;
   3272     }
   3273 
   3274     return BCM_E_NONE;
   3275 }
   3276 
   3277 /*
   3278  * Function:
   3279  *    bcmi_gh2_vxlan_tunnel_terminator_update
   3280  * Purpose:
   3281  *    Update VXLAN Tunnel terminator multicast state
   3282  * Parameters:
   3283  *    unit - (IN) Device Number
   3284  *    tnl_info - (IN) Tunnel terminator info data structure
   3285  * Returns:
   3286  *    BCM_E_XXX
   3287  */
   3288 int
   3289 bcmi_gh2_vxlan_tunnel_terminator_update(
   3290     int unit,
   3291     bcm_tunnel_terminator_t *tnl_info)
   3292 {
   3293     int tunnel_idx = -1;
   3294     bcm_ip_t tunnel_dip = 0;
   3295     bcm_ip6_t tunnel_dip6;
   3296     uint16 tunnel_multicast_state = 0;
   3297     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   3298 
   3299     /* Input parameter check */
   3300     if (NULL == tnl_info) {
   3301         return BCM_E_PARAM;
   3302     }
   3303 
   3304     /* Get VXLAN bookkeeping info instance */
   3305     BCM_IF_ERROR_RETURN(
   3306         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   3307 
   3308     /* Program tunnel id */
   3309     if (tnl_info->flags & BCM_TUNNEL_TERM_TUNNEL_WITH_ID) {
   3310         if (!BCM_GPORT_IS_TUNNEL(tnl_info->tunnel_id)) {
   3311             return BCM_E_PARAM;
   3312         }
   3313         tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(tnl_info->tunnel_id);
   3314         GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx);
   3315     } else {
   3316         /* Only BCM_TUNNEL_TERM_TUNNEL_WITH_ID supported */
   3317         /* Use tunnel_id which is got by _create */
   3318         return BCM_E_PARAM;
   3319     }
   3320 
   3321     tunnel_dip = vxlan_info->vxlan_tunnel_term[tunnel_idx].dip;
   3322     sal_memcpy(tunnel_dip6,
   3323                vxlan_info->vxlan_tunnel_term[tunnel_idx].dip6,
   3324                BCM_IP6_ADDRLEN);
   3325 
   3326     if (tnl_info->flags & BCM_TUNNEL_TERM_TUNNEL_DEACTIVATE) {
   3327         vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag &=
   3328             (~_BCM_VXLAN_TUNNEL_TERM_ENABLE);
   3329         return BCM_E_NONE;
   3330     } else if (!(vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag &
   3331         _BCM_VXLAN_TUNNEL_TERM_ENABLE)) {
   3332         if ((tunnel_dip != 0) ||
   3333             (!bcmi_gh2_vxlan_tunnel_ip6_is_zero(tunnel_dip6))) {
   3334             /*
   3335              * Below tunnel flags are not supported for GH2:
   3336              * - _BCM_VXLAN_TUNNEL_TERM_UDP_CHECKSUM_ENABLE
   3337              * - _BCM_VXLAN_TUNNEL_TERM_USE_OUTER_DSCP
   3338              * - _BCM_VXLAN_TUNNEL_TERM_USE_OUTER_PCP
   3339              */
   3340             vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag |=
   3341                 _BCM_VXLAN_TUNNEL_TERM_ENABLE;
   3342         }
   3343     }
   3344 
   3345     /* Set (SIP, DIP) based Software State */
   3346     tunnel_multicast_state =
   3347         vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state;
   3348 
   3349     if (tnl_info->multicast_flag ==
   3350         BCM_VXLAN_MULTICAST_TUNNEL_STATE_BUD_DISABLE) {
   3351         if (tunnel_multicast_state != _BCM_VXLAN_TUNNEL_TERM_MULTICAST_LEAF) {
   3352              vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state =
   3353                  _BCM_VXLAN_TUNNEL_TERM_MULTICAST_LEAF;
   3354         }
   3355     } else {
   3356         /* GH2 doesn't support BUD node */
   3357         return BCM_E_PARAM;
   3358     }
   3359 
   3360     return BCM_E_NONE;
   3361 }
   3362 
   3363 /*
   3364  * Function:
   3365  *    bcmi_gh2_vxlan_tunnel_terminate_destroy
   3366  * Purpose:
   3367  *    Destroy VXLAN tunnel_terminate Entry
   3368  * Parameters:
   3369  *    unit - (IN) Device Number
   3370  *    vxlan_tunnel_id - (IN) vxlan_tunnel_id
   3371  * Returns:
   3372  *    BCM_E_XXX
   3373  */
   3374 int
   3375 bcmi_gh2_vxlan_tunnel_terminator_destroy(
   3376     int unit,
   3377     bcm_gport_t vxlan_tunnel_id)
   3378 {
   3379     int tunnel_idx = -1;
   3380     bcm_ip_t tunnel_dip = 0;
   3381     bcm_ip6_t tunnel_dip6;
   3382     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   3383 
   3384     /* Get VXLAN bookkeeping info instance */
   3385     BCM_IF_ERROR_RETURN(
   3386         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   3387 
   3388     /* Input parameter check */
   3389     if (!BCM_GPORT_IS_TUNNEL(vxlan_tunnel_id)) {
   3390         return BCM_E_PARAM;
   3391     }
   3392 
   3393     tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(vxlan_tunnel_id);
   3394     GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx);
   3395 
   3396     tunnel_dip = vxlan_info->vxlan_tunnel_term[tunnel_idx].dip;
   3397     sal_memcpy(tunnel_dip6,
   3398                vxlan_info->vxlan_tunnel_term[tunnel_idx].dip6,
   3399                BCM_IP6_ADDRLEN);
   3400 
   3401     if ((tunnel_dip == 0) &&
   3402         (bcmi_gh2_vxlan_tunnel_ip6_is_zero(tunnel_dip6))) {
   3403         return BCM_E_NOT_FOUND;
   3404     }
   3405 
   3406     if (!(_BCM_VXLAN_TUNNEL_TERM_ENABLE &
   3407         vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag)) {
   3408         /* Deactivated tunnel terminator can not be destroyed */
   3409         return BCM_E_DISABLED;
   3410     }
   3411 
   3412     /* Remove Tunnel term-entry for given DIP from Software based */
   3413     if (tunnel_idx != -1) {
   3414             vxlan_info->vxlan_tunnel_term[tunnel_idx].dip = 0;
   3415             sal_memset(vxlan_info->vxlan_tunnel_term[tunnel_idx].dip6,
   3416                        0, BCM_IP6_ADDRLEN);
   3417             vxlan_info->vxlan_tunnel_term[tunnel_idx].vlan = 0;
   3418             vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state = 0;
   3419             vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag = 0;
   3420     }
   3421 
   3422     return BCM_E_NONE;
   3423 }
   3424 
   3425 /*
   3426  * Function:
   3427  *    bcmi_gh2_vxlan_tunnel_terminator_destroy_all
   3428  * Purpose:
   3429  *    Destroy all incoming VXLAN tunnel
   3430  * Parameters:
   3431  *    unit - (IN) Device Number
   3432  * Returns:
   3433  *    BCM_E_XXX
   3434  */
   3435 int
   3436 bcmi_gh2_vxlan_tunnel_terminator_destroy_all(int unit)
   3437 {
   3438     int rv = BCM_E_NONE;
   3439     int tnl_idx = 0, num_tnl = 0;
   3440     bcm_gport_t vxlan_tunnel_id;
   3441     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   3442 
   3443     /* Get VXLAN bookkeeping info instance */
   3444     BCM_IF_ERROR_RETURN(
   3445         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   3446 
   3447     /* Remove all Tunnel term-entry from Software based */
   3448     num_tnl = vxlan_info->num_vxlan_tnl;
   3449     for (tnl_idx = 0; tnl_idx < num_tnl; tnl_idx++) {
   3450         BCM_GPORT_TUNNEL_ID_SET(vxlan_tunnel_id, tnl_idx);
   3451         rv = bcmi_gh2_vxlan_tunnel_terminator_destroy(unit, vxlan_tunnel_id);
   3452         if (BCM_FAILURE(rv)) {
   3453             if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_DISABLED)) {
   3454                 return rv;
   3455             }
   3456         }
   3457     }
   3458 
   3459     return BCM_E_NONE;
   3460 }
   3461 
   3462 /*
   3463  * Function:
   3464  *    bcmi_gh2_vxlan_tunnel_terminator_get
   3465  * Purpose:
   3466  *    Get VXLAN tunnel_terminate Entry
   3467  * Parameters:
   3468  *    unit - (IN) Device Number
   3469  *    info - (IN/OUT) Tunnel terminator structure
   3470  * Returns:
   3471  *    BCM_E_XXX
   3472  */
   3473 int
   3474 bcmi_gh2_vxlan_tunnel_terminator_get(
   3475     int unit,
   3476     bcm_tunnel_terminator_t *tnl_info)
   3477 {
   3478     int tunnel_idx = -1;
   3479     bcm_ip_t tunnel_dip = 0;
   3480     bcm_ip6_t tunnel_dip6;
   3481     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   3482 
   3483     /* Input parameter check */
   3484     if (NULL == tnl_info) {
   3485         return BCM_E_PARAM;
   3486     }
   3487 
   3488     /* Get VXLAN bookkeeping info instance */
   3489     BCM_IF_ERROR_RETURN(
   3490         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   3491 
   3492     /* Program tunnel id */
   3493     if (!BCM_GPORT_IS_TUNNEL(tnl_info->tunnel_id)) {
   3494         return BCM_E_PARAM;
   3495     }
   3496 
   3497     tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(tnl_info->tunnel_id);
   3498     GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx);
   3499 
   3500     tunnel_dip = vxlan_info->vxlan_tunnel_term[tunnel_idx].dip;
   3501     sal_memcpy(tunnel_dip6,
   3502                vxlan_info->vxlan_tunnel_term[tunnel_idx].dip6,
   3503                BCM_IP6_ADDRLEN);
   3504 
   3505     if (tunnel_dip != 0) {
   3506         /* Tunnel for IPv4 */
   3507         tnl_info->sip = vxlan_info->vxlan_tunnel_term[tunnel_idx].sip;
   3508         tnl_info->dip = vxlan_info->vxlan_tunnel_term[tunnel_idx].dip;
   3509         tnl_info->type = bcmTunnelTypeVxlan;
   3510     } else if (!bcmi_gh2_vxlan_tunnel_ip6_is_zero(tunnel_dip6)) {
   3511         /* Tunnel for IPv6 */
   3512         sal_memcpy(tnl_info->sip6,
   3513                    vxlan_info->vxlan_tunnel_term[tunnel_idx].sip6,
   3514                    BCM_IP6_ADDRLEN);
   3515         sal_memcpy(tnl_info->dip6,
   3516                    vxlan_info->vxlan_tunnel_term[tunnel_idx].dip6,
   3517                    BCM_IP6_ADDRLEN);
   3518         tnl_info->type = bcmTunnelTypeVxlan6;
   3519     } else {
   3520         /* not exist */
   3521         return BCM_E_NOT_FOUND;
   3522     }
   3523 
   3524     /* De-activated */
   3525     if (!(vxlan_info->vxlan_tunnel_term[tunnel_idx].activate_flag &
   3526         _BCM_VXLAN_TUNNEL_TERM_ENABLE)) {
   3527         tnl_info->flags |= BCM_TUNNEL_TERM_TUNNEL_DEACTIVATE;
   3528     }
   3529 
   3530     tnl_info->vlan = vxlan_info->vxlan_tunnel_term[tunnel_idx].vlan;
   3531     if (vxlan_info->vxlan_tunnel_term[tunnel_idx].tunnel_state ==
   3532         _BCM_VXLAN_TUNNEL_TERM_MULTICAST_LEAF) {
   3533         tnl_info->multicast_flag =
   3534             BCM_VXLAN_MULTICAST_TUNNEL_STATE_BUD_DISABLE;
   3535     } else {
   3536         tnl_info->multicast_flag = 0;
   3537     }
   3538 
   3539     /*
   3540      * Below tunnel flags are not supported for GH2:
   3541      * - BCM_TUNNEL_TERM_UDP_CHECKSUM_ENABLE
   3542      * - BCM_TUNNEL_TERM_USE_OUTER_DSCP
   3543      * - BCM_TUNNEL_TERM_USE_OUTER_PCP
   3544      */
   3545 
   3546     return BCM_E_NONE;
   3547 }
   3548 
   3549 /*
   3550  * Function:
   3551  *    bcmi_gh2_vxlan_tunnel_terminator_traverse
   3552  * Purpose:
   3553  *    Traverse VXLAN tunnel terminator entries
   3554  * Parameters:
   3555  *    unit - (IN) Device Number
   3556  *    cb   - (IN) User callback function, called once per entry
   3557  *    user_data - (IN) User supplied cookie used in callback function
   3558  * Returns:
   3559  *    BCM_E_XXX
   3560  */
   3561 int
   3562 bcmi_gh2_vxlan_tunnel_terminator_traverse(
   3563     int unit,
   3564     bcm_tunnel_terminator_traverse_cb cb,
   3565     void *user_data)
   3566 {
   3567     int rv = BCM_E_NONE;
   3568     int num_tnl = 0, idx = 0;
   3569     bcm_tunnel_terminator_t info;
   3570     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   3571 
   3572     /* Input parameter check */
   3573     if (NULL == cb) {
   3574         return BCM_E_PARAM;
   3575     }
   3576 
   3577     /* Get VXLAN bookkeeping info instance */
   3578     BCM_IF_ERROR_RETURN(
   3579         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   3580 
   3581     num_tnl = vxlan_info->num_vxlan_tnl;
   3582 
   3583     /* Iterate over all the entries - search valid ones */
   3584     for (idx = 0; idx < num_tnl; idx++) {
   3585         /* Check a valid entry */
   3586         if ((vxlan_info->vxlan_tunnel_term[idx].dip) ||
   3587             (vxlan_info->vxlan_tunnel_term[idx].sip) ||
   3588             (!bcmi_gh2_vxlan_tunnel_ip6_is_zero(
   3589             vxlan_info->vxlan_tunnel_term[idx].dip6)) ||
   3590             (!bcmi_gh2_vxlan_tunnel_ip6_is_zero(
   3591             vxlan_info->vxlan_tunnel_term[idx].sip6))) {
   3592             /* Reset buffer before read */
   3593             bcm_tunnel_terminator_t_init(&info);
   3594 
   3595             BCM_GPORT_TUNNEL_ID_SET(info.tunnel_id, idx);
   3596             rv = bcmi_gh2_vxlan_tunnel_terminator_get(unit, &info);
   3597 
   3598             /* search failure */
   3599             if (BCM_FAILURE(rv)) {
   3600                 if (rv != BCM_E_NOT_FOUND) {
   3601                     break;
   3602                 }
   3603                 continue;
   3604             }
   3605 
   3606             rv = (*cb)(unit, &info, user_data);
   3607 #ifdef BCM_CB_ABORT_ON_ERR
   3608             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   3609                 break;
   3610             }
   3611 #endif
   3612         }
   3613     }
   3614 
   3615     /* Reset last read status */
   3616     if (rv == BCM_E_NOT_FOUND) {
   3617         rv = BCM_E_NONE;
   3618     }
   3619 
   3620     return rv;
   3621 }
   3622 
   3623 /*
   3624  * Function:
   3625  *    bcmi_gh2_vxlan_tunnel_initiator_add
   3626  * Purpose:
   3627  *    Add tunnel initiator entry to hw.
   3628  * Parameters:
   3629  *    unit - (IN) Device Number
   3630  *    idx  - (IN) Index to insert tunnel initiator.
   3631  *    info - (IN) Tunnel initiator entry info.
   3632  * Returns:
   3633  *    BCM_E_XXX
   3634  */
   3635 STATIC int
   3636 bcmi_gh2_vxlan_tunnel_initiator_add(
   3637     int unit,
   3638     int idx,
   3639     bcm_tunnel_initiator_t *info)
   3640 {
   3641     int rv = BCM_E_NONE;
   3642     uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to write hw entry */
   3643     soc_mem_t mem; /* Tunnel initiator table memory */
   3644     int ipv6; /* IPv6 tunnel initiator */
   3645     int df_val = 0; /* Don't fragment encoding */
   3646     int hw_map_idx = 0;
   3647     int entry_type = 0;
   3648     int val;
   3649     uint16 random;
   3650     egr_fragment_id_table_entry_t entry;
   3651 
   3652     /* Input parameters check */
   3653     if (NULL == info) {
   3654         return BCM_E_PARAM;
   3655     }
   3656 
   3657     ipv6 = _BCM_TUNNEL_OUTER_HEADER_IPV6(info->type);
   3658 
   3659     /* Get table memory. */
   3660     if (ipv6) {
   3661         /* Tunnel for IPv6 */
   3662         idx >>= 1;
   3663         mem = BCM_XGS3_L3_MEM(unit, tnl_init_v6);
   3664         entry_type = BCM_XGS3_TUNNEL_INIT_V6;
   3665     } else {
   3666         /* Tunnel for IPv4 */
   3667         mem = BCM_XGS3_L3_MEM(unit, tnl_init_v4);
   3668         entry_type = BCM_XGS3_TUNNEL_INIT_V4;
   3669     }
   3670 
   3671     /* Zero write buffer. */
   3672     sal_memset(tnl_entry, 0, sizeof(tnl_entry));
   3673 
   3674     /*
   3675      * If replacing existing entry, first read the entry to get old
   3676      * profile pointer and TPID
   3677      */
   3678     if (info->flags & BCM_TUNNEL_REPLACE) {
   3679         BCM_IF_ERROR_RETURN(
   3680             soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, tnl_entry));
   3681     }
   3682 
   3683     if (info->type == bcmTunnelTypeVxlan6) {
   3684         /* Tunnel for IPv6 */
   3685         /* Set source address within Tunnel Table */
   3686         soc_mem_ip6_addr_set(unit, mem, tnl_entry, SIPf, info->sip6,
   3687                              SOC_MEM_IP6_FULL_ADDR);
   3688 
   3689         /* Set destination address within Tunnel Table */
   3690         soc_mem_ip6_addr_set(unit, mem, tnl_entry, DIPf, info->dip6,
   3691                              SOC_MEM_IP6_FULL_ADDR);
   3692 
   3693         /* Set FLOW_LABEL. */
   3694         soc_mem_field32_set(unit, mem, tnl_entry,
   3695                             FLOW_LABELf, info->flow_label);
   3696 
   3697         /* Set HOP_LIMIT. */
   3698         soc_mem_field32_set(unit, mem, tnl_entry, HOP_LIMITf, info->ttl);
   3699     } else {
   3700         /* Tunnel for IPv4 */
   3701         /* Set source address within Tunnel Table */
   3702         soc_mem_field_set(unit, mem, tnl_entry, SIPf, (uint32 *)&info->sip);
   3703 
   3704         /* Set destination address within Tunnel Table */
   3705         soc_mem_field_set(unit, mem, tnl_entry, DIPf, (uint32 *)&info->dip);
   3706 
   3707         /* IP tunnel hdr DF bit for IPv4. */
   3708         df_val = 0;
   3709         if (info->flags & BCM_TUNNEL_INIT_USE_INNER_DF) {
   3710             df_val |= 0x2;
   3711         } else if (info->flags & BCM_TUNNEL_INIT_IPV4_SET_DF) {
   3712             df_val |= 0x1;
   3713         }
   3714         soc_mem_field32_set(unit, mem, tnl_entry, IPV4_DF_SELf, df_val);
   3715 
   3716         /* IP tunnel hdr DF bit for IPv6. */
   3717         if (info->flags & BCM_TUNNEL_INIT_IPV6_SET_DF) {
   3718             soc_mem_field32_set(unit, mem, tnl_entry, IPV6_DF_SELf, 1);
   3719         }
   3720 
   3721         /* Set TTL. */
   3722         soc_mem_field32_set(unit, mem, tnl_entry, TTLf, info->ttl);
   3723     }
   3724 
   3725     /* Tunnel header DSCP select. */
   3726     soc_mem_field32_set(unit, mem, tnl_entry, DSCP_SELf, info->dscp_sel);
   3727 
   3728     if (info->dscp_sel == bcmTunnelDscpMap) {
   3729         /* Set DSCP_MAP value. */
   3730         if (SOC_MEM_FIELD_VALID(unit, mem, DSCP_MAPPING_PTRf)) {
   3731             BCM_IF_ERROR_RETURN(
   3732                 _bcm_tr2_qos_id2idx(unit, info->dscp_map, &hw_map_idx));
   3733             soc_mem_field32_set(unit, mem, tnl_entry,
   3734                                 DSCP_MAPPING_PTRf, hw_map_idx);
   3735         } else {
   3736             return BCM_E_PARAM;
   3737         }
   3738     } else if (info->dscp_sel == bcmTunnelDscpAssign) {
   3739         /* Set DSCP value. */
   3740         if (SOC_MEM_FIELD_VALID(unit, mem, DSCPf)) {
   3741             soc_mem_field32_set(unit, mem, tnl_entry,
   3742                                 DSCPf, info->dscp);
   3743         } else {
   3744             return BCM_E_PARAM;
   3745         }
   3746     }
   3747 
   3748     /* Set UDP Dest Port */
   3749     soc_mem_field32_set(unit, mem, tnl_entry,
   3750                         L4_DST_PORTf, info->udp_dst_port);
   3751 
   3752     /* Set UDP Src Port */
   3753     soc_mem_field32_set(unit, mem, tnl_entry,
   3754                         L4_SRC_PORTf, info->udp_src_port);
   3755 
   3756     /* Set Tunnel type = VXLAN */
   3757     soc_mem_field32_set(unit, mem, tnl_entry,
   3758                         TUNNEL_TYPEf, _BCM_VXLAN_TUNNEL_TYPE);
   3759 
   3760     /*
   3761       * Set entry type:
   3762       * IPv4: BCM_XGS3_TUNNEL_INIT_V4 = 0x1
   3763       * IPv6: BCM_XGS3_TUNNEL_INIT_V6 = 0x2
   3764       */
   3765     soc_mem_field32_set(unit, mem, tnl_entry, ENTRY_TYPEf, entry_type);
   3766 
   3767     if ((info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_FIXED) ||
   3768         (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_RANDOM)) {
   3769         if (info->type != bcmTunnelTypeVxlan) {
   3770             return BCM_E_PARAM;
   3771         }
   3772         BCM_IF_ERROR_RETURN(
   3773             bcm_esw_switch_control_get(unit,
   3774                                        bcmSwitchTunnelIp4IdShared, &val));
   3775         if (val == 0) {
   3776             sal_memset(&entry, 0, sizeof(egr_fragment_id_table_entry_t));
   3777 
   3778             if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_FIXED) {
   3779                 soc_EGR_FRAGMENT_ID_TABLEm_field32_set(unit, &entry,
   3780                                                        FRAGMENT_IDf,
   3781                                                        info->ip4_id);
   3782             } else if (info->flags & BCM_TUNNEL_INIT_IP4_ID_SET_RANDOM) {
   3783                 random = (uint16)(sal_time_usecs() & 0xFFFF);
   3784                 soc_EGR_FRAGMENT_ID_TABLEm_field32_set(unit, &entry,
   3785                                                        FRAGMENT_IDf, random);
   3786             }
   3787             BCM_IF_ERROR_RETURN(
   3788                 soc_mem_write(unit, EGR_FRAGMENT_ID_TABLEm,
   3789                               SOC_BLOCK_ALL, idx, &entry));
   3790         }
   3791     }
   3792 
   3793     /* Write buffer to hw */
   3794     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, tnl_entry);
   3795 
   3796     return rv;
   3797 }
   3798 
   3799 /*
   3800  * Function:
   3801  *    bcmi_gh2_vxlan_tnl_init_del
   3802  * Purpose:
   3803  *    Delete tunnels initiator entry. Entry kept if reference count
   3804  *    not equals to 1 (Other tunnels reference the same entry).
   3805  * Parameters:
   3806  *    unit      - (IN) Device Number
   3807  *    flags     - (IN) Table shared flags
   3808  *    info      - (IN) The informaton of tunnel initiator
   3809  *    ent_index - (IN) Entry index
   3810  * Returns:
   3811  *    BCM_E_XXX
   3812  */
   3813 STATIC int
   3814 bcmi_gh2_vxlan_tnl_init_del(
   3815     int unit,
   3816     uint32 flags,
   3817     bcm_tunnel_initiator_t *info,
   3818     int ent_index)
   3819 {
   3820     _bcm_l3_tbl_op_t data; /* Delete operation info. */
   3821 
   3822     /* Initialization */
   3823     sal_memset(&data, 0, sizeof(_bcm_l3_tbl_op_t));
   3824 
   3825     /* Check hw call is defined. */
   3826     if (!BCM_XGS3_L3_HWCALL_CHECK(unit, tnl_init_del)) {
   3827         return BCM_E_UNAVAIL;
   3828     }
   3829 
   3830     if(_BCM_EGR_IP_TUNNEL_DOUBLE_WIDE_ENTRY(unit, info->type)) {
   3831         /* IPv6 tunnel is double table entry operation (occupy 2 slots). */
   3832         data.width = _BCM_DOUBLE_WIDE;
   3833     } else {
   3834         /* IPv4 tunnel is single table entry operation.*/
   3835         data.width = _BCM_SINGLE_WIDE;
   3836     }
   3837 
   3838     data.tbl_ptr =  BCM_XGS3_L3_TBL_PTR(unit, tnl_init);
   3839     data.entry_index = ent_index;
   3840     data.oper_flags = flags;
   3841     data.delete_func = BCM_XGS3_L3_HWCALL(unit, tnl_init_del);
   3842 
   3843     /* Delete tunnel initiator table entry. */
   3844     return _bcm_xgs3_tbl_del(unit, &data);
   3845 }
   3846 
   3847 /*
   3848  * Function:
   3849  *    bcmi_gh2_vxlan_tunnel_initiator_entry_add
   3850  * Purpose:
   3851  *    Configure VXLAN Tunnel initiator hardware Entry
   3852  * Parameters:
   3853  *    unit  - (IN) Device Number
   3854  *    flags - (IN) the flags of tunnel initiator
   3855  *    info  - (IN) the informaton of tunnel initiator
   3856  *    tnl_idx - (OUT) Tunnel id for tunnel initiator
   3857  * Returns:
   3858  *    BCM_E_XXX
   3859  */
   3860 STATIC int
   3861 bcmi_gh2_vxlan_tunnel_initiator_entry_add(
   3862     int unit,
   3863     uint32 flags,
   3864     bcm_tunnel_initiator_t *info,
   3865     int *tnl_idx)
   3866 {
   3867     int rv = BCM_E_NONE;
   3868 
   3869     /* Input parameters check */
   3870     if ((NULL == info) || (NULL == tnl_idx)) {
   3871         return BCM_E_PARAM;
   3872     }
   3873 
   3874     rv = bcm_xgs3_tnl_init_add(unit, flags, info, tnl_idx);
   3875     if (BCM_FAILURE(rv)) {
   3876         return rv;
   3877     }
   3878 
   3879     /* Write the entry to HW */
   3880     rv = bcmi_gh2_vxlan_tunnel_initiator_add(unit, *tnl_idx, info);
   3881     if (BCM_FAILURE(rv)) {
   3882         flags = _BCM_L3_SHR_WRITE_DISABLE;
   3883         (void)bcmi_gh2_vxlan_tnl_init_del(unit, flags, info, *tnl_idx);
   3884     }
   3885 
   3886     return rv;
   3887 }
   3888 
   3889 /*
   3890  * Function:
   3891  *    bcmi_gh2_vxlan_tunnel_initiator_get_tunnel_id
   3892  * Purpose:
   3893  *    Get an available tunnel id for vxlan tunnel initiator
   3894  * Parameters:
   3895  *    unit - (IN) Device Number
   3896  *    info - (IN) the informaton of tunnel initiator
   3897  *    hw_match_flag - (IN) Indicate if an existing EGR_IP_TUNNEL entry
   3898  *    soft_tnl_idx  - (OUT) Tunnel id for tunnel initiator
   3899  *    new_id_flag   - (OUT) Indicate if a new free tunnel id
   3900  * Returns:
   3901  *    BCM_E_XXX
   3902  */
   3903 STATIC int
   3904 bcmi_gh2_vxlan_tunnel_initiator_get_tunnel_id(
   3905     int unit,
   3906     bcm_tunnel_initiator_t *info,
   3907     int hw_match_flag,
   3908     int *soft_tnl_idx,
   3909     int *new_id_flag)
   3910 {
   3911     int rv = BCM_E_NONE;
   3912     int idx = 0, num_tnl = 0;
   3913     int free_index = -1, free_entry_found = 0;
   3914     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   3915 
   3916     if ((NULL == info) || (NULL == soft_tnl_idx) || (NULL == new_id_flag)) {
   3917         return BCM_E_PARAM;
   3918     }
   3919 
   3920     /* Get VXLAN bookkeeping info instance */
   3921     BCM_IF_ERROR_RETURN(
   3922         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   3923 
   3924     num_tnl = vxlan_info->num_vxlan_tnl;
   3925     *new_id_flag = FALSE;
   3926 
   3927     for (idx = 0; idx < num_tnl; idx++) {
   3928         if (info->type == bcmTunnelTypeVxlan6) {
   3929             /* Tunnel for IPv6 */
   3930             if (((sal_memcmp(vxlan_info->vxlan_tunnel_init[idx].sip6,
   3931                              info->sip6, BCM_IP6_ADDRLEN) == 0)) &&
   3932                 ((sal_memcmp(vxlan_info->vxlan_tunnel_init[idx].dip6,
   3933                              info->dip6, BCM_IP6_ADDRLEN) == 0)) &&
   3934                 (vxlan_info->vxlan_tunnel_init[idx].tunnel_state ==
   3935                              info->udp_dst_port)) {
   3936                 /* Obtain existed index */
   3937                 *soft_tnl_idx = idx;
   3938                 return BCM_E_NONE;
   3939             }
   3940         } else {
   3941             /* Tunnel for IPv4 */
   3942             if ((vxlan_info->vxlan_tunnel_init[idx].sip == info->sip) &&
   3943                 (vxlan_info->vxlan_tunnel_init[idx].dip == info->dip) &&
   3944                 (vxlan_info->vxlan_tunnel_init[idx].tunnel_state ==
   3945                 info->udp_dst_port)) {
   3946                 /* Obtain existed index */
   3947                 *soft_tnl_idx = idx;
   3948                 return BCM_E_NONE;
   3949             }
   3950         }
   3951 
   3952         if ((vxlan_info->vxlan_tunnel_init[idx].sip == 0) &&
   3953             (bcmi_gh2_vxlan_tunnel_ip6_is_zero(
   3954             vxlan_info->vxlan_tunnel_init[idx].sip6)) &&
   3955             !free_entry_found) {
   3956             /* Obtain Free index */
   3957             free_index = idx;
   3958             free_entry_found = 1;
   3959             if (!hw_match_flag) {
   3960                 break;
   3961             }
   3962         }
   3963     }
   3964 
   3965     if (free_entry_found) {
   3966         *new_id_flag = TRUE;
   3967         *soft_tnl_idx = free_index;
   3968     } else {
   3969         /* No free resource */
   3970         return BCM_E_RESOURCE;
   3971     }
   3972 
   3973     return rv;
   3974 }
   3975 
   3976 /*
   3977  * Function:
   3978  *    bcmi_gh2_vxlan_tunnel_initiator_idx_translate
   3979  * Purpose:
   3980  *    Translate the index of software object to the index
   3981  *    of hw entry for tunnel initiator
   3982  * Parameters:
   3983  *    unit - (IN) Device Number
   3984  *    soft_idx - (IN) The index of software object
   3985  *    hw_idx   - (OUT) The index of hw entry
   3986  * Returns:
   3987  *    BCM_E_XXX
   3988  */
   3989 STATIC int
   3990 bcmi_gh2_vxlan_tunnel_initiator_idx_translate(
   3991     int unit,
   3992     int soft_idx,
   3993     int *hw_idx)
   3994 {
   3995     int rv = BCM_E_NONE;
   3996     bcm_tunnel_initiator_t init_tnl_info;
   3997     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   3998 
   3999     /* Input parameter check */
   4000     if (NULL == hw_idx) {
   4001         return BCM_E_PARAM;
   4002     }
   4003 
   4004     /* Get VXLAN bookkeeping info instance */
   4005     BCM_IF_ERROR_RETURN(
   4006         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   4007 
   4008     bcm_tunnel_initiator_t_init(&init_tnl_info);
   4009 
   4010     if (vxlan_info->vxlan_tunnel_init[soft_idx].sip != 0) {
   4011         /* Tunnel for IPv4 */
   4012         init_tnl_info.type = bcmTunnelTypeVxlan;
   4013         init_tnl_info.sip = vxlan_info->vxlan_tunnel_init[soft_idx].sip;
   4014     } else {
   4015         /* Tunnel for IPv6 */
   4016         init_tnl_info.type = bcmTunnelTypeVxlan6;
   4017         sal_memcpy(init_tnl_info.sip6,
   4018                    vxlan_info->vxlan_tunnel_init[soft_idx].sip6,
   4019                    BCM_IP6_ADDRLEN);
   4020     }
   4021 
   4022     init_tnl_info.udp_dst_port =
   4023         vxlan_info->vxlan_tunnel_init[soft_idx].tunnel_state;
   4024 
   4025     rv = _bcm_xgs3_l3_tnl_init_find(unit, &init_tnl_info, hw_idx);
   4026 
   4027     return rv;
   4028 }
   4029 
   4030 /*
   4031  * Function:
   4032  *    bcmi_gh2_vxlan_tunnel_initiator_cmp
   4033  * Purpose:
   4034  *    Routine compares vxlan tunnel initiator entry with entry in the chip
   4035  *    with specified index.
   4036  * Parameters:
   4037  *    unit - (IN) Device Number
   4038  *    buf  - (IN) Tunnel initiator entry to compare.
   4039  *    index- (IN) Entry index in the chip to compare.
   4040  *    cmp_result - (OUT) Compare result.
   4041  * Returns:
   4042  *    BCM_E_XXX
   4043  */
   4044 int
   4045 bcmi_gh2_vxlan_tunnel_initiator_cmp(
   4046     int unit,
   4047     void *buf,
   4048     int index,
   4049     int *cmp_result)
   4050 {
   4051     int rv = BCM_E_NONE;
   4052     bcm_tunnel_initiator_t hw_entry;   /* Entry read from hw */
   4053     bcm_tunnel_initiator_t *tnl_entry; /* Api passed buffer */
   4054 
   4055     if ((NULL == buf) || (NULL == cmp_result)) {
   4056         return BCM_E_PARAM;
   4057     }
   4058 
   4059     *cmp_result = BCM_L3_CMP_NOT_EQUAL;
   4060 
   4061     /* Copy buffer to structure */
   4062     tnl_entry = (bcm_tunnel_initiator_t *)buf;
   4063 
   4064     /* Initialization */
   4065     bcm_tunnel_initiator_t_init(&hw_entry);
   4066 
   4067     /* Get tunnel initiator entry from hw */
   4068     if (BCM_XGS3_L3_HWCALL_CHECK(unit, tnl_init_get)) {
   4069         BCM_XGS3_L3_MODULE_LOCK(unit);
   4070         rv = (BCM_XGS3_L3_HWCALL_EXEC
   4071             (unit, tnl_init_get)(unit, index, &hw_entry));
   4072         BCM_XGS3_L3_MODULE_UNLOCK(unit);
   4073         BCM_IF_ERROR_RETURN(rv);
   4074     } else {
   4075         return BCM_E_UNAVAIL;
   4076     }
   4077 
   4078     /* Compare source ip */
   4079     if ((tnl_entry->sip != hw_entry.sip) ||
   4080         (sal_memcmp(tnl_entry->sip6, hw_entry.sip6,
   4081                     BCM_IP6_ADDRLEN) != 0)) {
   4082         return BCM_E_NONE;
   4083     }
   4084 
   4085     /* Compare udp dst port */
   4086     if (tnl_entry->udp_dst_port != hw_entry.udp_dst_port) {
   4087         return BCM_E_NONE;
   4088     }
   4089 
   4090     *cmp_result = BCM_L3_CMP_EQUAL;
   4091 
   4092     return BCM_E_NONE;
   4093 }
   4094 
   4095 /*
   4096  * Function:
   4097  *    bcmi_gh2_vxlan_tunnel_initiator_hash_calc
   4098  * Purpose:
   4099  *    Calculate tunnel initiator entry hash (signature).
   4100  * Parameters:
   4101  *    unit - (IN) Device Number
   4102  *    buf  - (IN) Tunnel initiator entry information.
   4103  *    hash - (OUT) Hash (signature) calculated value.
   4104  * Returns:
   4105  *    BCM_X_XXX
   4106  */
   4107 int
   4108 bcmi_gh2_vxlan_tunnel_initiator_hash_calc(int unit, void *buf, uint16 *hash)
   4109 {
   4110     bcm_tunnel_initiator_t tnl_entry;
   4111 
   4112     if ((NULL == buf) || (NULL == hash)) {
   4113         return (BCM_E_PARAM);
   4114     }
   4115 
   4116     bcm_tunnel_initiator_t_init(&tnl_entry);
   4117     tnl_entry.type = ((bcm_tunnel_initiator_t *)buf)->type;
   4118 
   4119     /* Set source ip */
   4120     if (tnl_entry.type == bcmTunnelTypeVxlan6) {
   4121         /* Tunnel for IPv6 */
   4122         sal_memcpy(tnl_entry.sip6,
   4123                    ((bcm_tunnel_initiator_t *)buf)->sip6, BCM_IP6_ADDRLEN);
   4124     } else {
   4125         /* Tunnel for IPv4 */
   4126         tnl_entry.sip = ((bcm_tunnel_initiator_t *)buf)->sip;
   4127     }
   4128 
   4129     tnl_entry.udp_dst_port = ((bcm_tunnel_initiator_t *)buf)->udp_dst_port;
   4130 
   4131     /* Calculate hash */
   4132     *hash = _shr_crc16(0, (uint8 *)&tnl_entry, sizeof(bcm_tunnel_initiator_t));
   4133 
   4134     return BCM_E_NONE;
   4135 }
   4136 
   4137 /*
   4138  * Function:
   4139  *    bcmi_gh2_vxlan_tunnel_initiator_create
   4140  * Purpose:
   4141  *    Set VXLAN Tunnel initiator
   4142  * Parameters:
   4143  *    unit - (IN) Device Number
   4144  * Returns:
   4145  *    BCM_E_XXX
   4146  */
   4147 int
   4148 bcmi_gh2_vxlan_tunnel_initiator_create(int unit, bcm_tunnel_initiator_t *info)
   4149 {
   4150     int tnl_idx = -1, ref_count = 0;
   4151     uint32 flags = 0;
   4152     int idx = 0, num_tnl = 0;
   4153     uint8 match_entry_present = 0;
   4154     int soft_tnl_idx = -1, tunnel_idx = -1;
   4155     int new_idx_flag = FALSE;
   4156     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   4157 
   4158     /* Input parameter check */
   4159     if (NULL == info) {
   4160         return BCM_E_PARAM;
   4161     }
   4162 
   4163     /* Input Tunnel Type check */
   4164     if (info->type == bcmTunnelTypeVxlan6) {
   4165         /* Tunnel for IPv6 */
   4166         if (bcmi_gh2_vxlan_tunnel_ip6_is_zero(info->dip6) ||
   4167             bcmi_gh2_vxlan_tunnel_ip6_is_zero(info->sip6)) {
   4168             return BCM_E_PARAM;
   4169         }
   4170 
   4171         /* IPv6 doesn't support DSCP value. */
   4172         if (info->dscp_sel == bcmTunnelDscpAssign) {
   4173             return BCM_E_PARAM;
   4174         }
   4175     } else if (info->type == bcmTunnelTypeVxlan) {
   4176         /* Tunnel for IPv4 */
   4177         if ((info->dip == 0) || (info->sip == 0)) {
   4178             return BCM_E_PARAM;
   4179         }
   4180     } else {
   4181         return BCM_E_PARAM;
   4182     }
   4183 
   4184     /* Input TTL valid range check */
   4185     if (!BCM_TTL_VALID(info->ttl)) {
   4186         return BCM_E_PARAM;
   4187     }
   4188     /* Input DSCP selection valid range check */
   4189     if (info->dscp_sel > bcmTunnelDscpMap || info->dscp_sel < 0) {
   4190         return BCM_E_PARAM;
   4191     }
   4192     /* Validate IP tunnel DSCP value. */
   4193     if (info->dscp > 63 || info->dscp < 0) {
   4194         return BCM_E_PARAM;
   4195     }
   4196     /* Validate flow label value. */
   4197     if (_BCM_TUNNEL_OUTER_HEADER_IPV6(info->type)) {
   4198         if (info->flow_label >= (1 << 20)) {
   4199             return BCM_E_PARAM;
   4200         }
   4201     }
   4202 
   4203     /* Get VXLAN bookkeeping info instance */
   4204     BCM_IF_ERROR_RETURN(
   4205         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   4206 
   4207     num_tnl = vxlan_info->num_vxlan_tnl;
   4208     if (info->flags & BCM_TUNNEL_REPLACE) {
   4209         tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id);
   4210         GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx);
   4211         if (info->type == bcmTunnelTypeVxlan6) {
   4212             /* Tunnel for IPv6 */
   4213             if ((sal_memcmp(info->sip6,
   4214                             vxlan_info->vxlan_tunnel_init[tunnel_idx].sip6,
   4215                             BCM_IP6_ADDRLEN) != 0) ||
   4216                 (sal_memcmp(info->dip6,
   4217                             vxlan_info->vxlan_tunnel_init[tunnel_idx].dip6,
   4218                             BCM_IP6_ADDRLEN) != 0) ||
   4219                 (info->udp_dst_port !=
   4220                     vxlan_info->vxlan_tunnel_init[tunnel_idx].tunnel_state)) {
   4221                 return BCM_E_UNAVAIL;
   4222             }
   4223         } else {
   4224             /* Tunnel for IPv4 */
   4225             if ((info->sip !=
   4226                     vxlan_info->vxlan_tunnel_init[tunnel_idx].sip) ||
   4227                 (info->udp_dst_port !=
   4228                     vxlan_info->vxlan_tunnel_init[tunnel_idx].tunnel_state) ||
   4229                 (info->dip !=
   4230                     vxlan_info->vxlan_tunnel_init[tunnel_idx].dip)) {
   4231                 return BCM_E_UNAVAIL;
   4232             }
   4233         }
   4234     }
   4235 
   4236     /* Allocate either existing or new tunnel initiator entry */
   4237     flags = _BCM_L3_SHR_MATCH_DISABLE |
   4238             _BCM_L3_SHR_WRITE_DISABLE |
   4239             _BCM_L3_SHR_SKIP_INDEX_ZERO;
   4240 
   4241     if (_bcm_xgs3_l3_tnl_init_find(unit, info, &tnl_idx) == BCM_E_NONE) {
   4242         match_entry_present = 1;
   4243     }
   4244 
   4245     /* Get an available tunnel id */
   4246     BCM_IF_ERROR_RETURN(
   4247         bcmi_gh2_vxlan_tunnel_initiator_get_tunnel_id(
   4248             unit, info, match_entry_present, &soft_tnl_idx, &new_idx_flag));
   4249 
   4250     if (match_entry_present) {
   4251         if (info->flags & BCM_TUNNEL_REPLACE) {
   4252             if (new_idx_flag) {
   4253                 return BCM_E_UNAVAIL;
   4254             }
   4255 
   4256             /* Check for Ref-count in (SIP, multi-DIP) situation */
   4257             for (idx = 0; idx < num_tnl; idx++) {
   4258                 if (info->type == bcmTunnelTypeVxlan6) {
   4259                     /* Tunnel for IPv6 */
   4260                     if ((sal_memcmp(info->sip6,
   4261                                     vxlan_info->vxlan_tunnel_init[idx].sip6,
   4262                                     BCM_IP6_ADDRLEN) == 0) &&
   4263                         (info->udp_dst_port ==
   4264                         vxlan_info->vxlan_tunnel_init[idx].tunnel_state)) {
   4265                         if (++ref_count > 1) {
   4266                             return BCM_E_RESOURCE;
   4267                         }
   4268                     }
   4269                 } else {
   4270                     /* Tunnel for IPv4 */
   4271                     if ((info->sip ==
   4272                         vxlan_info->vxlan_tunnel_init[idx].sip) &&
   4273                         (info->udp_dst_port ==
   4274                         vxlan_info->vxlan_tunnel_init[idx].tunnel_state)) {
   4275                         if (++ref_count > 1) {
   4276                             return BCM_E_RESOURCE;
   4277                         }
   4278                     }
   4279                 }
   4280             }
   4281 
   4282             flags |= _BCM_L3_SHR_UPDATE | _BCM_L3_SHR_WITH_ID;
   4283             BCM_IF_ERROR_RETURN(
   4284                 bcmi_gh2_vxlan_tunnel_initiator_entry_add(unit, flags,
   4285                                                           info, &tnl_idx));
   4286         }
   4287     } else {
   4288          /* Parse tunnel replace flag */
   4289          if (info->flags & BCM_TUNNEL_REPLACE) {
   4290              /* replace an inexistent tunnel initiator */
   4291              return BCM_E_NOT_FOUND;
   4292          }
   4293          BCM_IF_ERROR_RETURN(
   4294              bcmi_gh2_vxlan_tunnel_initiator_entry_add(unit, flags,
   4295                                                        info, &tnl_idx));
   4296     }
   4297 
   4298     if (soft_tnl_idx != -1) {
   4299         if (info->type == bcmTunnelTypeVxlan6) {
   4300             /* Tunnel for IPv6 */
   4301             sal_memcpy(vxlan_info->vxlan_tunnel_init[soft_tnl_idx].sip6,
   4302                        info->sip6, BCM_IP6_ADDRLEN);
   4303             sal_memcpy(vxlan_info->vxlan_tunnel_init[soft_tnl_idx].dip6,
   4304                        info->dip6, BCM_IP6_ADDRLEN);
   4305         } else {
   4306             /* Tunnel for IPv4 */
   4307             vxlan_info->vxlan_tunnel_init[soft_tnl_idx].sip = info->sip;
   4308             vxlan_info->vxlan_tunnel_init[soft_tnl_idx].dip = info->dip;
   4309         }
   4310         vxlan_info->vxlan_tunnel_init[soft_tnl_idx].tunnel_state =
   4311             info->udp_dst_port;
   4312         BCM_GPORT_TUNNEL_ID_SET(info->tunnel_id, soft_tnl_idx);
   4313     } else {
   4314         return BCM_E_NOT_FOUND;
   4315     }
   4316 
   4317     return BCM_E_NONE;
   4318 }
   4319 
   4320 /*
   4321  * Function:
   4322  *    bcmi_gh2_vxlan_tunnel_initiator_destroy
   4323  * Purpose:
   4324  *    Destroy outgoing VXLAN tunnel
   4325  * Parameters:
   4326  *    unit - (IN) Device Number
   4327  *    vxlan_tunnel_id - (IN) Tunnel ID (Gport)
   4328  * Returns:
   4329  *    BCM_E_XXX
   4330  */
   4331 int
   4332 bcmi_gh2_vxlan_tunnel_initiator_destroy(
   4333     int unit,
   4334     bcm_gport_t vxlan_tunnel_id)
   4335 {
   4336     int rv = BCM_E_NONE;
   4337     int tnl_idx = -1, temp_tnl_idx = -1, ref_count = 0, idx = 0;
   4338     uint32 flags = 0;
   4339     int num_tnl = 0;
   4340     bcm_ip_t sip = 0;       /* Tunnel header SIP (IPv4). */
   4341     bcm_ip6_t sip6;         /* Tunnel header SIP (IPv6). */
   4342     uint16 udp_dst_port;    /* Destination UDP port */
   4343     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   4344 
   4345     /* Input parameters check */
   4346     if (!BCM_GPORT_IS_TUNNEL(vxlan_tunnel_id)) {
   4347         return BCM_E_PARAM;
   4348     }
   4349 
   4350     /* Get VXLAN bookkeeping info instance */
   4351     BCM_IF_ERROR_RETURN(
   4352         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   4353 
   4354     tnl_idx = BCM_GPORT_TUNNEL_ID_GET(vxlan_tunnel_id);
   4355     GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tnl_idx);
   4356 
   4357     /* Tunnel for IPv4/IPv6 */
   4358     sip = vxlan_info->vxlan_tunnel_init[tnl_idx].sip;
   4359     sal_memcpy(sip6, vxlan_info->vxlan_tunnel_init[tnl_idx].sip6,
   4360                BCM_IP6_ADDRLEN);
   4361     udp_dst_port =  vxlan_info->vxlan_tunnel_init[tnl_idx].tunnel_state;
   4362 
   4363     if ((sip == 0) && (bcmi_gh2_vxlan_tunnel_ip6_is_zero(sip6))) {
   4364         return BCM_E_NOT_FOUND;
   4365     }
   4366 
   4367     /*
   4368      * Remove HW TNL entry only if all matching SIP, UDP_DEST_PORT
   4369      * gets removed
   4370      */
   4371     num_tnl = vxlan_info->num_vxlan_tnl;
   4372     for (idx = 0; idx < num_tnl; idx++) {
   4373         if (sip != 0) {
   4374             /* Tunnel for IPv4 */
   4375             if ((vxlan_info->vxlan_tunnel_init[idx].sip == sip) &&
   4376                 (vxlan_info->vxlan_tunnel_init[idx].tunnel_state ==
   4377                 udp_dst_port)) {
   4378                 ref_count++;
   4379             }
   4380         } else {
   4381             /* Tunnel for IPv6 */
   4382             if ((sal_memcmp(vxlan_info->vxlan_tunnel_init[idx].sip6,
   4383                             sip6, BCM_IP6_ADDRLEN) == 0) &&
   4384                 (vxlan_info->vxlan_tunnel_init[idx].tunnel_state ==
   4385                 udp_dst_port)) {
   4386                 ref_count++;
   4387             }
   4388         }
   4389     }
   4390 
   4391     if (ref_count == 1) {
   4392         /* Get the entry first */
   4393         temp_tnl_idx = tnl_idx;
   4394         BCM_IF_ERROR_RETURN(
   4395             bcmi_gh2_vxlan_tunnel_initiator_idx_translate(unit, temp_tnl_idx,
   4396                                                           &tnl_idx));
   4397         /* Destroy the tunnel entry */
   4398         (void)bcm_xgs3_tnl_init_del(unit, flags, tnl_idx);
   4399         vxlan_info->vxlan_tunnel_init[temp_tnl_idx].sip = 0;
   4400         vxlan_info->vxlan_tunnel_init[temp_tnl_idx].dip = 0;
   4401         sal_memset(vxlan_info->vxlan_tunnel_init[temp_tnl_idx].sip6,
   4402                    0, BCM_IP6_ADDRLEN);
   4403         sal_memset(vxlan_info->vxlan_tunnel_init[temp_tnl_idx].dip6,
   4404                    0, BCM_IP6_ADDRLEN);
   4405         vxlan_info->vxlan_tunnel_init[temp_tnl_idx].tunnel_state = 0;
   4406     } else if (ref_count > 1) {
   4407         vxlan_info->vxlan_tunnel_init[tnl_idx].sip = 0;
   4408         vxlan_info->vxlan_tunnel_init[tnl_idx].dip = 0;
   4409         sal_memset(vxlan_info->vxlan_tunnel_init[tnl_idx].sip6,
   4410                    0, BCM_IP6_ADDRLEN);
   4411         sal_memset(vxlan_info->vxlan_tunnel_init[tnl_idx].dip6,
   4412                    0, BCM_IP6_ADDRLEN);
   4413         vxlan_info->vxlan_tunnel_init[tnl_idx].tunnel_state = 0;
   4414     }
   4415 
   4416     return rv;
   4417 }
   4418 
   4419 /*
   4420  * Function:
   4421  *    bcmi_gh2_vxlan_tunnel_initiator_destroy_all
   4422  * Purpose:
   4423  *    Destroy all outgoing VXLAN tunnel
   4424  * Parameters:
   4425  *    unit - (IN) Device Number
   4426  * Returns:
   4427  *    BCM_E_XXX
   4428  */
   4429 int
   4430 bcmi_gh2_vxlan_tunnel_initiator_destroy_all(int unit)
   4431 {
   4432     int rv = BCM_E_NONE;
   4433     soc_mem_t mem; /* Tunnel initiator table memory */
   4434     egr_ip_tunnel_entry_t *tnl_entry, *tnl_entries;
   4435     int tnl_idx, num_entries, num_tnl;
   4436     int tnl_type = 0;   /* Tunnel type. */
   4437     uint32 entry_type;  /* Entry type (IPv4/IPv6) */
   4438     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   4439 
   4440     /* Get VXLAN bookkeeping info instance */
   4441     BCM_IF_ERROR_RETURN(
   4442         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   4443 
   4444     num_tnl = vxlan_info->num_vxlan_tnl;
   4445 
   4446     /* Destroy VXLAN IPv4/IPv6 Tunnel from hardware */
   4447     mem =  BCM_XGS3_L3_MEM(unit, tnl_init_v4);
   4448     num_entries = soc_mem_index_count(unit, mem);
   4449     tnl_entries = soc_cm_salloc(unit, num_entries * sizeof(*tnl_entries),
   4450                                 "egr_ip_tunnel");
   4451     if (tnl_entries == NULL) {
   4452         return BCM_E_MEMORY;
   4453     }
   4454     sal_memset(tnl_entries, 0, num_entries * sizeof(*tnl_entries));
   4455 
   4456     soc_mem_lock(unit, mem);
   4457     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   4458                             0, (num_entries - 1), tnl_entries);
   4459     if (BCM_FAILURE(rv)) {
   4460         soc_mem_unlock(unit, mem);
   4461         soc_cm_sfree(unit, tnl_entries);
   4462         return rv;
   4463     }
   4464 
   4465     for (tnl_idx = 0; tnl_idx < num_entries; tnl_idx++) {
   4466         tnl_entry =
   4467             soc_mem_table_idx_to_pointer(unit, mem,
   4468                                          egr_ip_tunnel_entry_t *,
   4469                                          tnl_entries, tnl_idx);
   4470         tnl_type = soc_mem_field32_get(unit, mem, tnl_entry, TUNNEL_TYPEf);
   4471         entry_type = soc_mem_field32_get(unit, mem, tnl_entry, ENTRY_TYPEf);
   4472         if (tnl_type == _BCM_VXLAN_TUNNEL_TYPE) {
   4473             if ((entry_type == BCM_XGS3_TUNNEL_INIT_V4) ||
   4474                 (entry_type == BCM_XGS3_TUNNEL_INIT_V6)) {
   4475                 /* Delete the entry from HW */
   4476                 /* Destroy the tunnel entry */
   4477                 (void)bcm_xgs3_tnl_init_del(unit, 0, tnl_idx);
   4478             }
   4479         }
   4480     }
   4481     soc_mem_unlock(unit, mem);
   4482     soc_cm_sfree(unit, tnl_entries);
   4483 
   4484     /* Clear all VXLAN IPv4/IPv6 Tunnel from software */
   4485     for (tnl_idx = 0; tnl_idx < num_tnl; tnl_idx++) {
   4486         vxlan_info->vxlan_tunnel_init[tnl_idx].sip = 0;
   4487         vxlan_info->vxlan_tunnel_init[tnl_idx].dip = 0;
   4488         sal_memset(vxlan_info->vxlan_tunnel_init[tnl_idx].sip6,
   4489                    0, BCM_IP6_ADDRLEN);
   4490         sal_memset(vxlan_info->vxlan_tunnel_init[tnl_idx].dip6,
   4491                    0, BCM_IP6_ADDRLEN);
   4492         vxlan_info->vxlan_tunnel_init[tnl_idx].tunnel_state = 0;
   4493     }
   4494 
   4495     return BCM_E_NONE;
   4496 }
   4497 
   4498 /*
   4499  * Function:
   4500  *    bcmi_gh2_vxlan_tunnel_initiator_get
   4501  * Purpose:
   4502  *    Get an outgong VXLAN tunnel info
   4503  * Parameters:
   4504  *    unit - (IN) Device Number
   4505  *    info - (IN/OUT) Tunnel initiator structure
   4506  * Returns:
   4507  *    BCM_E_XXX
   4508  */
   4509 int
   4510 bcmi_gh2_vxlan_tunnel_initiator_get(int unit, bcm_tunnel_initiator_t *info)
   4511 {
   4512     int rv = BCM_E_NONE;
   4513     int soft_idx = -1, hw_idx = -1;
   4514     egr_fragment_id_table_entry_t entry;
   4515     uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry */
   4516     soc_mem_t mem;      /* Tunnel initiator table memory.*/
   4517     int df_val = 0;     /* Don't fragment encoded value. */
   4518     int tnl_type = 0;   /* Tunnel type. */
   4519     uint32 entry_type;  /* Entry type (IPv4/IPv6) */
   4520     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   4521 
   4522     /* Input parameters check */
   4523     if (NULL == info) {
   4524         return BCM_E_PARAM;
   4525     }
   4526 
   4527     /* Get VXLAN bookkeeping info instance */
   4528     BCM_IF_ERROR_RETURN(
   4529         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   4530 
   4531     if (!BCM_GPORT_IS_TUNNEL(info->tunnel_id)) {
   4532         return BCM_E_PARAM;
   4533     }
   4534 
   4535     soft_idx = BCM_GPORT_TUNNEL_ID_GET(info->tunnel_id);
   4536     GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, soft_idx);
   4537 
   4538     /* Get SIP/DIP info from hardware */
   4539     BCM_IF_ERROR_RETURN(
   4540         bcmi_gh2_vxlan_tunnel_initiator_idx_translate(unit, soft_idx,
   4541                                                       &hw_idx));
   4542 
   4543     /* Get table memory for IPv4 */
   4544     mem = BCM_XGS3_L3_MEM(unit, tnl_init_v4);
   4545     /* Initialize the buffer */
   4546     sal_memset(tnl_entry, 0, sizeof(tnl_entry));
   4547     BCM_IF_ERROR_RETURN(
   4548         soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, tnl_entry));
   4549 
   4550     /* Get entry_type. */
   4551     entry_type = soc_mem_field32_get(unit, mem, tnl_entry, ENTRY_TYPEf);
   4552     if (entry_type == BCM_XGS3_TUNNEL_INIT_V6) {
   4553         /* Tunnel for IPv6 */
   4554         mem = BCM_XGS3_L3_MEM(unit, tnl_init_v6);
   4555         hw_idx >>= 1;    /* Each record takes two slots. */
   4556 
   4557         /* Initialize the buffer */
   4558         sal_memset(tnl_entry, 0, sizeof(tnl_entry));
   4559         BCM_IF_ERROR_RETURN(
   4560             soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, tnl_entry));
   4561     }
   4562 
   4563     /* Get tunnel type. */
   4564     tnl_type = soc_mem_field32_get(unit, mem, tnl_entry, TUNNEL_TYPEf);
   4565     if (tnl_type != _BCM_VXLAN_TUNNEL_TYPE) {
   4566         return BCM_E_NOT_FOUND;
   4567     }
   4568 
   4569     if (entry_type == BCM_XGS3_TUNNEL_INIT_V6) {
   4570         /* Tunnel for IPv6 */
   4571 
   4572         /* Extract IPv6 SIP/DIP address */
   4573         soc_mem_ip6_addr_get(unit, mem, tnl_entry, SIPf, info->sip6,
   4574                              SOC_MEM_IP6_FULL_ADDR);
   4575         sal_memcpy(info->dip6, vxlan_info->vxlan_tunnel_init[soft_idx].dip6,
   4576                    BCM_IP6_ADDRLEN);
   4577 
   4578         /* Get FLOW_LABEL. */
   4579         info->flow_label = soc_mem_field32_get(unit, mem,
   4580                                                tnl_entry, FLOW_LABELf);
   4581 
   4582         /* Get HOP_LIMIT. */
   4583         info->ttl = soc_mem_field32_get(unit, mem, tnl_entry, HOP_LIMITf);
   4584     } else if (entry_type == BCM_XGS3_TUNNEL_INIT_V4) {
   4585         /* Tunnel for IPv4 */
   4586 
   4587         /* Extract IPv4 SIP/DIP address */
   4588         info->sip = soc_mem_field32_get(unit, mem, tnl_entry, SIPf);
   4589         info->dip = vxlan_info->vxlan_tunnel_init[soft_idx].dip;
   4590 
   4591         /* IP tunnel hdr DF bit for IPv4 */
   4592         df_val = soc_mem_field32_get(unit, mem, tnl_entry, IPV4_DF_SELf);
   4593         if (0x2 <= df_val) {
   4594             info->flags |= BCM_TUNNEL_INIT_USE_INNER_DF;
   4595         } else if (0x1 == df_val) {
   4596             info->flags |= BCM_TUNNEL_INIT_IPV4_SET_DF;
   4597         }
   4598 
   4599         df_val = soc_mem_field32_get(unit, mem, tnl_entry, IPV6_DF_SELf);
   4600         if (0x1 == df_val) {
   4601             info->flags |= BCM_TUNNEL_INIT_IPV6_SET_DF;
   4602         }
   4603 
   4604         /* Get TTL. */
   4605         info->ttl = soc_mem_field32_get(unit, mem, tnl_entry, TTLf);
   4606     } else {
   4607         return BCM_E_NOT_FOUND;
   4608     }
   4609 
   4610     /* Tunnel header DSCP select. */
   4611     info->dscp_sel = soc_mem_field32_get(unit, mem, tnl_entry, DSCP_SELf);
   4612     if (info->dscp_sel == bcmTunnelDscpMap) {
   4613         /* Tunnel header DSCP_MAP value. */
   4614         if (SOC_MEM_FIELD_VALID(unit, mem, DSCP_MAPPING_PTRf)) {
   4615             BCM_IF_ERROR_RETURN(
   4616                 _bcm_tr2_qos_idx2id
   4617                     (unit, soc_mem_field32_get(unit, mem, tnl_entry,
   4618                                                DSCP_MAPPING_PTRf),
   4619                      _BCM_QOS_MAP_TYPE_EGR_DSCP_TABLE,
   4620                      &info->dscp_map));
   4621         } else {
   4622             return BCM_E_INTERNAL;
   4623         }
   4624     } else if (info->dscp_sel == bcmTunnelDscpAssign) {
   4625         /* Tunnel header DSCP value. */
   4626         if (SOC_MEM_FIELD_VALID(unit, mem, DSCPf)) {
   4627             info->dscp = soc_mem_field32_get(unit, mem, tnl_entry, DSCPf);
   4628         } else {
   4629             return BCM_E_INTERNAL;
   4630         }
   4631     }
   4632 
   4633     /* Get UDP Dest Port */
   4634     info->udp_dst_port =
   4635         soc_mem_field32_get(unit, mem, tnl_entry, L4_DST_PORTf);
   4636 
   4637     /* Get UDP Src Port */
   4638     info->udp_src_port =
   4639         soc_mem_field32_get(unit, mem, tnl_entry, L4_SRC_PORTf);
   4640 
   4641     /*
   4642      * Translate hw tunnel type into API encoding:
   4643      * - bcmTunnelTypeVxlan (IPv4) or bcmTunnelTypeVxlan6 (IPv6)
   4644      */
   4645     BCM_IF_ERROR_RETURN(
   4646         _bcm_trx_tnl_hw_code_to_type(unit,
   4647                                      tnl_type, entry_type, &info->type));
   4648 
   4649     BCM_IF_ERROR_RETURN(
   4650         soc_mem_read(unit, EGR_FRAGMENT_ID_TABLEm,
   4651                      MEM_BLOCK_ANY, hw_idx, &entry));
   4652     info->ip4_id = soc_mem_field32_get(
   4653         unit, EGR_FRAGMENT_ID_TABLEm, &entry, FRAGMENT_IDf);
   4654 
   4655     return rv;
   4656 }
   4657 
   4658 /*
   4659  * Function:
   4660  *    bcmi_gh2_vxlan_tunnel_initiator_traverse
   4661  * Purpose:
   4662  *    Traverse VXLAN tunnel initiator entries
   4663  * Parameters:
   4664  *    unit - (IN) Device Number
   4665  *    cb   - (IN) User callback function, called once per entry
   4666  *    user_data - (IN) User supplied cookie used in parameter
   4667  *                           in callback function
   4668  * Returns:
   4669  *    BCM_E_XXX
   4670  */
   4671 int
   4672 bcmi_gh2_vxlan_tunnel_initiator_traverse(
   4673     int unit,
   4674     bcm_tunnel_initiator_traverse_cb cb,
   4675     void *user_data)
   4676 {
   4677     int rv = BCM_E_NONE;
   4678     int num_tnl = 0, idx = 0;
   4679     bcm_tunnel_initiator_t info;
   4680     bcm_ip6_t sip6;
   4681     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   4682 
   4683     /* Input parameter check */
   4684     if (NULL == cb) {
   4685         return BCM_E_PARAM;
   4686     }
   4687 
   4688     /* Get VXLAN bookkeeping info instance */
   4689     BCM_IF_ERROR_RETURN(
   4690         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   4691 
   4692     num_tnl = vxlan_info->num_vxlan_tnl;
   4693 
   4694     sal_memset(sip6, 0, BCM_IP6_ADDRLEN);
   4695 
   4696     /* Iterate over all the entries - search valid ones */
   4697     for (idx = 0; idx < num_tnl; idx++) {
   4698         /* Check a valid entry */
   4699         sal_memcpy(sip6, vxlan_info->vxlan_tunnel_init[idx].sip6,
   4700                    BCM_IP6_ADDRLEN);
   4701         if ((vxlan_info->vxlan_tunnel_init[idx].sip != 0) ||
   4702             (!bcmi_gh2_vxlan_tunnel_ip6_is_zero(sip6))) {
   4703             /* Reset buffer before read */
   4704             bcm_tunnel_initiator_t_init(&info);
   4705 
   4706             BCM_GPORT_TUNNEL_ID_SET(info.tunnel_id, idx);
   4707             rv = bcmi_gh2_vxlan_tunnel_initiator_get(unit, &info);
   4708 
   4709             /* search failure */
   4710             if (BCM_FAILURE(rv)) {
   4711                 if (rv != BCM_E_NOT_FOUND) {
   4712                     break;
   4713                 }
   4714                 continue;
   4715             }
   4716 
   4717             rv = (*cb)(unit, &info, user_data);
   4718 #ifdef BCM_CB_ABORT_ON_ERR
   4719             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   4720                 break;
   4721             }
   4722 #endif
   4723         }
   4724     }
   4725 
   4726     /* Reset last read status */
   4727     if (rv == BCM_E_NOT_FOUND) {
   4728         rv = BCM_E_NONE;
   4729     }
   4730 
   4731     return rv;
   4732 }
   4733 
   4734 /*
   4735  * Function:
   4736  *    bcmi_gh2_vxlan_port_resolve
   4737  * Purpose:
   4738  *    Get the modid, port, trunk values for a VXLAN port
   4739  * Parameters:
   4740  *    unit - (IN) Device Number
   4741  * Returns:
   4742  *    BCM_E_XXX
   4743  */
   4744 int
   4745 bcmi_gh2_vxlan_port_resolve(
   4746     int unit,
   4747     bcm_gport_t vxlan_port_id,
   4748     bcm_if_t encap_id,
   4749     bcm_module_t *modid,
   4750     bcm_port_t *port,
   4751     bcm_trunk_t *trunk_id,
   4752     int *id)
   4753 
   4754 {
   4755     int rv = BCM_E_NONE;
   4756     ing_l3_next_hop_entry_t ing_nh;
   4757     egr_l3_next_hop_entry_t egr_nh;
   4758     int ecmp = 0, nh_index = -1, nh_ecmp_index = -1, vp = -1;
   4759     uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry */
   4760     int idx, max_ent_count, base_idx;
   4761 
   4762     /* Input parameter check */
   4763     if ((NULL == modid) || (NULL == port) ||
   4764         (NULL == trunk_id) || (NULL == id)) {
   4765        return BCM_E_PARAM;
   4766     }
   4767     if (!BCM_GPORT_IS_VXLAN_PORT(vxlan_port_id)) {
   4768         return BCM_E_BADID;
   4769     }
   4770 
   4771     vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port_id);
   4772     if (vp == -1) {
   4773        return BCM_E_PARAM;
   4774     }
   4775 
   4776     if (!bcmi_gh2_vxlan_vp_used_get(unit, vp)) {
   4777         return BCM_E_NOT_FOUND;
   4778     }
   4779 
   4780     /* GH2 requires to retrieve vp to ecmp or nhi from software database */
   4781     BCM_IF_ERROR_RETURN(
   4782         bcmi_gh2_vxlan_port_to_nh_ecmp_index(unit, vp,
   4783                                              &ecmp, &nh_ecmp_index));
   4784 
   4785     if (!ecmp) {
   4786         nh_index = nh_ecmp_index;
   4787         BCM_IF_ERROR_RETURN(
   4788             soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   4789                          nh_index, &ing_nh));
   4790 
   4791         if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
   4792             *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit,
   4793                                                          &ing_nh, TGIDf);
   4794         } else {
   4795             /* Only add this to replication set if destination is local */
   4796             *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit,
   4797                                                       &ing_nh, MODULE_IDf);
   4798             *port = soc_ING_L3_NEXT_HOPm_field32_get(unit,
   4799                                                      &ing_nh, PORT_NUMf);
   4800         }
   4801     } else {
   4802         /* Select the desired next hop from ECMP group - pointed by encap_id */
   4803         BCM_IF_ERROR_RETURN(
   4804              soc_mem_read(unit, L3_ECMP_COUNTm, MEM_BLOCK_ANY,
   4805                           nh_ecmp_index, hw_buf));
   4806 
   4807         max_ent_count = soc_mem_field32_get(unit, L3_ECMP_COUNTm,
   4808                                             hw_buf, COUNTf);
   4809         base_idx = soc_mem_field32_get(unit, L3_ECMP_COUNTm,
   4810                                        hw_buf, BASE_PTRf);
   4811         max_ent_count++; /* Count is zero based */
   4812 
   4813         if (encap_id == -1) {
   4814             BCM_IF_ERROR_RETURN(
   4815                  soc_mem_read(unit, L3_ECMPm, MEM_BLOCK_ANY,
   4816                               base_idx, hw_buf));
   4817 
   4818             nh_index = soc_mem_field32_get(unit, L3_ECMPm,
   4819                                            hw_buf, NEXT_HOP_INDEXf);
   4820 
   4821             BCM_IF_ERROR_RETURN (
   4822                 soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   4823                              nh_index, &ing_nh));
   4824 
   4825             if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
   4826                 *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit,
   4827                                                              &ing_nh, TGIDf);
   4828             } else {
   4829                 /* Only add this to replication set if destination is local */
   4830                 *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit,
   4831                                                           &ing_nh, MODULE_IDf);
   4832                 *port = soc_ING_L3_NEXT_HOPm_field32_get(unit,
   4833                                                          &ing_nh, PORT_NUMf);
   4834            }
   4835         } else {
   4836             for (idx = 0; idx < max_ent_count; idx++) {
   4837                 BCM_IF_ERROR_RETURN(
   4838                      soc_mem_read(unit, L3_ECMPm, MEM_BLOCK_ANY,
   4839                                   (base_idx + idx), hw_buf));
   4840                 nh_index = soc_mem_field32_get(unit, L3_ECMPm,
   4841                                                hw_buf, NEXT_HOP_INDEXf);
   4842                 BCM_IF_ERROR_RETURN(
   4843                      soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   4844                                   nh_index, &egr_nh));
   4845                 if (encap_id == soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
   4846                                                     &egr_nh, INTF_NUMf)) {
   4847                     BCM_IF_ERROR_RETURN(
   4848                         soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   4849                                      nh_index, &ing_nh));
   4850                     if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
   4851                         *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit,
   4852                                                                      &ing_nh,
   4853                                                                      TGIDf);
   4854                     } else {
   4855                         /*
   4856                          * Only add this to replication set
   4857                          * if destination is local
   4858                          */
   4859                         *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit,
   4860                                                                   &ing_nh,
   4861                                                                   MODULE_IDf);
   4862                         *port = soc_ING_L3_NEXT_HOPm_field32_get(unit,
   4863                                                                  &ing_nh,
   4864                                                                  PORT_NUMf);
   4865                     }
   4866                     break;
   4867                 }
   4868             }
   4869         }
   4870     }
   4871 
   4872     *id = vp;
   4873 
   4874     return rv;
   4875 }
   4876 
   4877 /*
   4878  * Function:
   4879  *    bcmi_gh2_vxlan_port_cnt_update
   4880  * Purpose:
   4881  *    Update port's VP count.
   4882  * Parameters:
   4883  *    unit - (IN) Device Number
   4884  *    gport- (IN) GPORT ID
   4885  *    vp   - (IN) Virtual port number
   4886  *    incr - (IN) If TRUE, increment VP count, else decrease VP count
   4887  * Returns:
   4888  *    BCM_X_XXX
   4889  */
   4890 STATIC int
   4891 bcmi_gh2_vxlan_port_cnt_update(
   4892     int unit,
   4893     bcm_gport_t gport,
   4894     int vp,
   4895     int incr_decr_flag)
   4896 {
   4897     int mod_out = -1, port_out = -1, tgid_out = -1, vp_out = -1;
   4898     bcm_port_t local_member_array[SOC_MAX_NUM_PORTS];
   4899     int local_member_count = 0;
   4900     int idx = -1;
   4901     int mod_local = -1;
   4902     _bcm_port_info_t *port_info;
   4903     uint32 port_flags;
   4904 
   4905     BCM_IF_ERROR_RETURN(
   4906         bcmi_gh2_vxlan_port_resolve(unit, gport, -1, &mod_out,
   4907                                     &port_out, &tgid_out, &vp_out));
   4908 
   4909     if (vp_out == -1) {
   4910         return BCM_E_PARAM;
   4911     }
   4912 
   4913     /*
   4914      * Update the physical port's SW state. If associated with a trunk,
   4915      * update each local physical port's SW state.
   4916      */
   4917     if (BCM_TRUNK_INVALID != tgid_out) {
   4918         BCM_IF_ERROR_RETURN(
   4919             _bcm_esw_trunk_local_members_get(unit, tgid_out,
   4920                                              SOC_MAX_NUM_PORTS,
   4921                                              local_member_array,
   4922                                              &local_member_count));
   4923 
   4924         for (idx = 0; idx < local_member_count; idx++) {
   4925             _bcm_port_info_access(unit, local_member_array[idx], &port_info);
   4926             if (incr_decr_flag) {
   4927                 port_info->vp_count++;
   4928             } else {
   4929                 if (port_info->vp_count > 0) {
   4930                     port_info->vp_count--;
   4931                 }
   4932             }
   4933             BCM_IF_ERROR_RETURN(
   4934                 bcm_esw_port_vlan_member_get(unit,
   4935                                              local_member_array[idx],
   4936                                              &port_flags));
   4937             BCM_IF_ERROR_RETURN(
   4938                 bcm_esw_port_vlan_member_set(unit,
   4939                                              local_member_array[idx],
   4940                                              port_flags));
   4941         }
   4942     } else {
   4943         BCM_IF_ERROR_RETURN(
   4944             _bcm_esw_modid_is_local(unit, mod_out, &mod_local));
   4945 
   4946         if (mod_local) {
   4947             _bcm_port_info_access(unit, port_out, &port_info);
   4948 
   4949             if (incr_decr_flag) {
   4950                 port_info->vp_count++;
   4951             } else {
   4952                 port_info->vp_count--;
   4953             }
   4954 
   4955             BCM_IF_ERROR_RETURN(
   4956                 bcm_esw_port_vlan_member_get(unit, port_out, &port_flags));
   4957             BCM_IF_ERROR_RETURN(
   4958                 bcm_esw_port_vlan_member_set(unit, port_out, port_flags));
   4959         }
   4960     }
   4961 
   4962     return BCM_E_NONE;
   4963 }
   4964 
   4965 /*
   4966  * Function:
   4967  *    bcmi_gh2_vxlan_ingress_dvp_set
   4968  * Purpose:
   4969  *    Set Ingress DVP to Next Hop info
   4970  * Parameters:
   4971  *    unit - (IN) Device Number
   4972  *    vp   - (IN) Virtual port number
   4973  *    mpath_flag       - (IN) Multiple Path flag
   4974  *    vp_nh_ecmp_index - (IN) nhi or ecmp index
   4975  *    vxlan_port       - (IN) vxlan_port information
   4976  * Returns:
   4977  *    BCM_E_XXX
   4978  */
   4979 STATIC int
   4980 bcmi_gh2_vxlan_ingress_dvp_set(
   4981     int unit,
   4982     int vp,
   4983     uint32 mpath_flag,
   4984     int vp_nh_ecmp_index,
   4985     bcm_vxlan_port_t *vxlan_port)
   4986 {
   4987     int rv = BCM_E_NONE;
   4988     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   4989     gh2_vxlan_vp_info_t *vp_info;
   4990 
   4991     /* Input parameter check */
   4992     if (NULL == vxlan_port) {
   4993         return BCM_E_PARAM;
   4994     }
   4995 
   4996     /* Get VXLAN bookkeeping info instance */
   4997     BCM_IF_ERROR_RETURN(
   4998         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   4999 
   5000     vp_info = &(vxlan_info->vxlan_vp_info[vp]);
   5001 
   5002     if (!(vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) {
   5003         if (mpath_flag) {
   5004              vp_info->ecmp = 1; /* ECMP */
   5005         } else {
   5006              vp_info->ecmp = 0; /* Next Hop */
   5007         }
   5008         vp_info->nh_ecmp_index = vp_nh_ecmp_index;
   5009     }
   5010 
   5011     if (vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) {
   5012         vp_info->vp_type = GH2_VXLAN_DEST_VP_TYPE_TUNNEL;
   5013     } else {
   5014         vp_info->vp_type = GH2_VXLAN_DEST_VP_TYPE_ACCESS;
   5015     }
   5016 
   5017     return rv;
   5018 }
   5019 
   5020 /*
   5021  * Function:
   5022  *    bcmi_gh2_vxlan_egress_tunnel_set
   5023  * Purpose:
   5024  *    Set Egress Tunnel index for Egress Next Hop Info
   5025  * Parameters:
   5026  *    unit        - (IN) Device Number
   5027  *    vxlan_port  - (IN) vxlan_port information
   5028  *    egr_nh_info - (OUT) Egress Next Hop Info
   5029  * Returns:
   5030  *    BCM_E_XXX
   5031  */
   5032 STATIC int
   5033 bcmi_gh2_vxlan_egress_tunnel_set(
   5034     int unit,
   5035     bcm_vxlan_port_t *vxlan_port,
   5036     bcmi_gh2_vxlan_nh_info_t  *egr_nh_info)
   5037 {
   5038     int rv = BCM_E_NONE;
   5039     int tunnel_index = -1, hw_idx = -1;
   5040     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   5041 
   5042     /* Input parameter check */
   5043     if ((NULL == vxlan_port) || (NULL == egr_nh_info)) {
   5044         return BCM_E_PARAM;
   5045     }
   5046 
   5047     /* Get VXLAN bookkeeping info instance */
   5048     BCM_IF_ERROR_RETURN(
   5049         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   5050 
   5051     tunnel_index = BCM_GPORT_TUNNEL_ID_GET(vxlan_port->egress_tunnel_id);
   5052     GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_index);
   5053 
   5054     /* Got HW tunnel index */
   5055     BCM_IF_ERROR_RETURN(
   5056            bcmi_gh2_vxlan_tunnel_initiator_idx_translate(unit, tunnel_index,
   5057                                                          &hw_idx));
   5058     egr_nh_info->tunnel_index = hw_idx;
   5059 
   5060     if (vxlan_port->flags & BCM_VXLAN_PORT_UDP_SRC_PORT_RANGE_ENABLE) {
   5061         egr_nh_info->udp_src_port_range_enable = 1;
   5062     }
   5063 
   5064     return rv;
   5065 }
   5066 
   5067 /*
   5068  * Function:
   5069  *    bcmi_gh2_vxlan_egress_tunnel_get
   5070  * Purpose:
   5071  *    Get Egress Tunnel index Info
   5072  * Parameters:
   5073  *    unit         - (IN) Device Number
   5074  *    vxlan_port   - (IN/OUT) vxlan_port information
   5075  *    tunnel_index - (IN) Tunnel index
   5076  * Returns:
   5077  *    BCM_E_XXX
   5078  */
   5079 STATIC int
   5080 bcmi_gh2_vxlan_egress_tunnel_get(
   5081     int unit,
   5082     bcm_vxlan_port_t *vxlan_port,
   5083     int tunnel_index)
   5084 {
   5085     int idx = 0, num_tnl = 0;
   5086     soc_mem_t mem; /* Tunnel initiator table memory */
   5087     uint32 tnl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry */
   5088     uint32 entry_type;  /* Entry type (IPv4/IPv6) */
   5089     bcm_ip_t dip = 0;       /* Tunnel header DIP (IPv4). */
   5090     bcm_ip6_t dip6;         /* Tunnel header DIP (IPv6). */
   5091     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   5092 
   5093     /* Input parameter check */
   5094     if (NULL == vxlan_port) {
   5095         return BCM_E_PARAM;
   5096     }
   5097 
   5098     /* Get VXLAN bookkeeping info instance */
   5099     BCM_IF_ERROR_RETURN(
   5100         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   5101 
   5102     num_tnl = vxlan_info->num_vxlan_tnl;
   5103 
   5104     /* First to read for IPv4 */
   5105     mem = BCM_XGS3_L3_MEM(unit, tnl_init_v4);
   5106     BCM_IF_ERROR_RETURN(
   5107         soc_mem_read(unit, mem, MEM_BLOCK_ANY, tunnel_index, tnl_entry));
   5108     entry_type = soc_mem_field32_get(unit, mem, tnl_entry, ENTRY_TYPEf);
   5109     if (entry_type != BCM_XGS3_TUNNEL_INIT_V4) {
   5110         mem = BCM_XGS3_L3_MEM(unit, tnl_init_v6);
   5111         BCM_IF_ERROR_RETURN(
   5112             soc_mem_read(unit, mem, MEM_BLOCK_ANY, tunnel_index, tnl_entry));
   5113         entry_type = soc_mem_field32_get(unit, mem, tnl_entry, ENTRY_TYPEf);
   5114     }
   5115 
   5116     if (entry_type == BCM_XGS3_TUNNEL_INIT_V6) {
   5117         /* Extract IPv6 address. */
   5118         soc_mem_ip6_addr_get(unit, mem, tnl_entry, DIPf, dip6,
   5119                              SOC_MEM_IP6_FULL_ADDR);
   5120 
   5121         /* Find DIP within Softare State */
   5122         for (idx = 0; idx < num_tnl; idx++) {
   5123             if (sal_memcmp(dip6, vxlan_info->vxlan_tunnel_init[idx].dip6,
   5124                            BCM_IP6_ADDRLEN) == 0) {
   5125                 break;
   5126             }
   5127         }
   5128     } else if (entry_type == BCM_XGS3_TUNNEL_INIT_V4) {
   5129         /* Extract IPv4 address. */
   5130         dip = soc_mem_field32_get(unit, mem, tnl_entry, DIPf);
   5131 
   5132         /* Find DIP within Softare State */
   5133         for (idx = 0; idx < num_tnl; idx++) {
   5134             if (vxlan_info->vxlan_tunnel_init[idx].dip == dip) {
   5135                 break;
   5136             }
   5137         }
   5138     }
   5139 
   5140     if (idx == num_tnl) {
   5141         return BCM_E_NOT_FOUND;
   5142     }
   5143 
   5144     BCM_GPORT_TUNNEL_ID_SET(vxlan_port->egress_tunnel_id, idx);
   5145 
   5146     return BCM_E_NONE;
   5147 }
   5148 
   5149 /*
   5150  * Function:
   5151  *    bcmi_gh2_vxlan_vlan_tag_set
   5152  * Purpose:
   5153  *    Program inner payload/outer tunnel VLAN TAG settings
   5154  * Parameters:
   5155  *    unit            - (IN) Device Number
   5156  *    vxlan_port      - (IN) VXLAN port info
   5157  *    egr_nh_info     - (IN/OUT) Egress Next Hop Info
   5158  *    nh_index        - (IN) Egress Next Hop Index
   5159  * Returns:
   5160  *    BCM_E_XXX
   5161  */
   5162 STATIC int
   5163 bcmi_gh2_vxlan_vlan_tag_set(
   5164     int unit,
   5165     bcm_vxlan_port_t *vxlan_port,
   5166     bcmi_gh2_vxlan_nh_info_t *egr_nh_info,
   5167     int nh_index)
   5168 {
   5169     int rv = BCM_E_NONE;
   5170     bcm_vlan_action_set_t action;
   5171     egr_vlan_xlate_entry_t egr_vent, return_vent;
   5172     int index = -1;
   5173     uint32 egr_profile_idx;
   5174     soc_mem_t hw_mem = EGR_VLAN_XLATEm;
   5175 
   5176     /* Input parameter check */
   5177     if ((NULL == vxlan_port) || (NULL == egr_nh_info)) {
   5178         return BCM_E_PARAM;
   5179     }
   5180 
   5181     /* VXLAN-LITE doesn't support replace TPID related actions */
   5182     if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TPID_REPLACE ||
   5183         vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE ||
   5184         vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_TPID_REPLACE) {
   5185         return BCM_E_UNAVAIL;
   5186     }
   5187 
   5188     /* Common setting for below flags */
   5189     if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD ||
   5190         vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_REPLACE ||
   5191         vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_REPLACE ||
   5192         vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_PRI_REPLACE ||
   5193         (!(vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) &&
   5194         vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_DELETE)) {
   5195         bcm_vlan_action_set_t_init(&action);
   5196         sal_memset(&egr_vent, 0, sizeof(egr_vent));
   5197         /* Valid Entry */
   5198         soc_mem_field32_set(unit, hw_mem, &egr_vent, VALIDf, 1);
   5199         /* Entry type = NHI */
   5200         soc_mem_field32_set(unit, hw_mem, &egr_vent, ENTRY_TYPEf, 0x07);
   5201         /* Key type = nh_index */
   5202         soc_mem_field32_set(unit, hw_mem, &egr_vent, NHI__NHIf, nh_index);
   5203 
   5204         /* Old Outer VID = match_vlan */
   5205         if (!BCM_VLAN_VALID(vxlan_port->match_vlan)) {
   5206             return BCM_E_PARAM;
   5207         }
   5208         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5209                             NHI__OLD_VLAN_IDf, vxlan_port->match_vlan);
   5210     }
   5211 
   5212     if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD) {
   5213         if (!BCM_VLAN_VALID(vxlan_port->egress_service_vlan)) {
   5214             return BCM_E_PARAM;
   5215         }
   5216 
   5217         if (vxlan_port->pkt_pri > BCM_PRIO_MAX) {
   5218             return BCM_E_PARAM;
   5219         }
   5220         if (vxlan_port->pkt_cfi != 0) {
   5221             return BCM_E_PARAM;
   5222         }
   5223 
   5224         action.ut_outer = bcmVlanActionAdd;
   5225         action.it_outer = bcmVlanActionAdd;
   5226         BCM_IF_ERROR_RETURN(
   5227             _bcm_trx_egr_vlan_action_profile_entry_add(unit, &action,
   5228                                                        &egr_profile_idx));
   5229 
   5230         /* Data */
   5231         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5232                             NHI__TAG_ACTION_PROFILE_PTRf, egr_profile_idx);
   5233         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5234                             NHI__NEW_OVIDf, vxlan_port->egress_service_vlan);
   5235         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5236                             NHI__NEW_OPRIf, vxlan_port->pkt_pri);
   5237         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5238                             NHI__NEW_ORPEf, 0x1);
   5239     }
   5240 
   5241     if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_REPLACE) {
   5242         if (!BCM_VLAN_VALID(vxlan_port->egress_service_vlan)) {
   5243             return BCM_E_PARAM;
   5244         }
   5245 
   5246         action.ot_outer = bcmVlanActionReplace;
   5247         action.dt_outer = bcmVlanActionReplace;
   5248         BCM_IF_ERROR_RETURN(
   5249             _bcm_trx_egr_vlan_action_profile_entry_add(unit, &action,
   5250                                                        &egr_profile_idx));
   5251 
   5252         /* Data */
   5253         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5254                             NHI__TAG_ACTION_PROFILE_PTRf, egr_profile_idx);
   5255         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5256                             NHI__NEW_OVIDf, vxlan_port->egress_service_vlan);
   5257     } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_REPLACE) {
   5258         if (!BCM_VLAN_VALID(vxlan_port->egress_service_vlan)) {
   5259             return BCM_E_PARAM;
   5260         }
   5261 
   5262         if (vxlan_port->pkt_pri > BCM_PRIO_MAX) {
   5263             return BCM_E_PARAM;
   5264         }
   5265         if (vxlan_port->pkt_cfi != 0) {
   5266             return BCM_E_PARAM;
   5267         }
   5268 
   5269         action.ot_outer = bcmVlanActionReplace;
   5270         action.ot_outer_prio = bcmVlanActionReplace;
   5271         action.dt_outer = bcmVlanActionReplace;
   5272         action.dt_outer_prio = bcmVlanActionReplace;
   5273         BCM_IF_ERROR_RETURN(
   5274             _bcm_trx_egr_vlan_action_profile_entry_add(unit, &action,
   5275                                                        &egr_profile_idx));
   5276 
   5277         /* Data */
   5278         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5279                             NHI__TAG_ACTION_PROFILE_PTRf, egr_profile_idx);
   5280         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5281                             NHI__NEW_OVIDf, vxlan_port->egress_service_vlan);
   5282         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5283                             NHI__NEW_OPRIf, vxlan_port->pkt_pri);
   5284         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5285                             NHI__NEW_ORPEf, 0x1);
   5286     } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_PRI_REPLACE) {
   5287         if (vxlan_port->pkt_pri > BCM_PRIO_MAX) {
   5288             return BCM_E_PARAM;
   5289         }
   5290         if (vxlan_port->pkt_cfi != 0) {
   5291             return BCM_E_PARAM;
   5292         }
   5293 
   5294         action.ot_outer_prio = bcmVlanActionReplace;
   5295         action.dt_outer_prio = bcmVlanActionReplace;
   5296         BCM_IF_ERROR_RETURN(
   5297             _bcm_trx_egr_vlan_action_profile_entry_add(unit, &action,
   5298                                                        &egr_profile_idx));
   5299 
   5300         /* Data */
   5301         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5302                             NHI__TAG_ACTION_PROFILE_PTRf, egr_profile_idx);
   5303         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5304                             NHI__NEW_OPRIf, vxlan_port->pkt_pri);
   5305         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5306                             NHI__NEW_ORPEf, 0x1);
   5307     } else if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_DELETE) {
   5308         if (vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) {
   5309             egr_nh_info->payload_otag_delete = 1;
   5310         } else {
   5311             action.ot_outer = bcmVlanActionDelete;
   5312             action.dt_outer = bcmVlanActionDelete;
   5313             BCM_IF_ERROR_RETURN(
   5314                 _bcm_trx_egr_vlan_action_profile_entry_add(unit, &action,
   5315                                                            &egr_profile_idx));
   5316 
   5317             /* Data */
   5318             soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5319                                 NHI__TAG_ACTION_PROFILE_PTRf, egr_profile_idx);
   5320         }
   5321     }
   5322 
   5323     /* Common memory write for below flags */
   5324     if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_ADD ||
   5325         vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_REPLACE ||
   5326         vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_PRI_REPLACE ||
   5327         vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_PRI_REPLACE ||
   5328         (!(vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) &&
   5329         vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_VLAN_DELETE)) {
   5330         rv = soc_mem_search(unit, hw_mem,
   5331                             MEM_BLOCK_ANY, &index, &egr_vent, &return_vent, 0);
   5332         if (BCM_SUCCESS(rv)) {
   5333             /* Replace the new egress vlan translate entry */
   5334             BCM_IF_ERROR_RETURN(
   5335                 soc_mem_write(unit, hw_mem, MEM_BLOCK_ALL, index, &egr_vent));
   5336             /* Delete the old vlan translate profile entry */
   5337             egr_profile_idx =
   5338                 soc_mem_field32_get(unit, hw_mem, &return_vent,
   5339                                     NHI__TAG_ACTION_PROFILE_PTRf);
   5340             BCM_IF_ERROR_RETURN(
   5341                 _bcm_trx_egr_vlan_action_profile_entry_delete
   5342                     (unit, egr_profile_idx));
   5343         } else if (rv == BCM_E_NOT_FOUND) {
   5344             BCM_IF_ERROR_RETURN(
   5345                 soc_mem_insert(unit, hw_mem, MEM_BLOCK_ALL, &egr_vent));
   5346         } else {
   5347             return rv;
   5348         }
   5349 
   5350         egr_nh_info->use_nhi_in_evxlt_key = 1;
   5351         /* Apply EVXLT modification to inner payload VLAN tag */
   5352         egr_nh_info->apply_evxlt_modify_to_payload = 1;
   5353     }
   5354 
   5355     if (vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) {
   5356         /* Use NHI as key for Egress VLAN Translation on Egress Tunnel */
   5357         egr_nh_info->use_nhi_in_evxlt_key = 1;
   5358 
   5359         /* Delete Tunnel Outer Tag */
   5360         if (vxlan_port->flags & BCM_VXLAN_PORT_TUNNEL_OUTER_VLAN_DELETE) {
   5361             egr_nh_info->tunnel_otag_delete = 1;
   5362         }
   5363         /* Delete Tunnel Inner Tag */
   5364         if (vxlan_port->flags & BCM_VXLAN_PORT_TUNNEL_INNER_VLAN_DELETE) {
   5365             egr_nh_info->tunnel_itag_delete = 1;
   5366         }
   5367 
   5368         /* DOT1P priority selection for Tunnel outer header */
   5369         if (vxlan_port->flags & BCM_VXLAN_PORT_TUNNEL_QOS_MAP) {
   5370             /* Apply qos_map_id to outer VXLAN header directly */
   5371             egr_nh_info->apply_evxlt_modify_to_payload = 1;
   5372             /* USE_MAPPING */
   5373             egr_nh_info->qos_map_id = vxlan_port->qos_map_id;
   5374         } else {
   5375             if ((vxlan_port->tunnel_pkt_pri) || (vxlan_port->tunnel_pkt_cfi)) {
   5376                 /* Apply NEW_PCP/NEW_CFI to outer VXLAN header directly */
   5377                 egr_nh_info->apply_evxlt_modify_to_payload = 1;
   5378                 /* USE_FIXED */
   5379                 egr_nh_info->tunnel_pkt_pri = vxlan_port->tunnel_pkt_pri;
   5380                 egr_nh_info->tunnel_pkt_cfi = vxlan_port->tunnel_pkt_cfi;
   5381             }
   5382         }
   5383     }
   5384 
   5385     /* Only support for GH2-B0 when VXLAN RIOT is enabled */
   5386     if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   5387         if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) {
   5388             /* Copied to Custom Header IPMC bit for encap */
   5389             if (vxlan_port->flags & BCM_VXLAN_PORT_MULTICAST) {
   5390                 egr_nh_info->custom_header_ipmc = 1;
   5391             } else {
   5392                 egr_nh_info->custom_header_ipmc = 0;
   5393             }
   5394         }
   5395     }
   5396 
   5397     return BCM_E_NONE;
   5398 }
   5399 
   5400 /*
   5401  * Function:
   5402  *    bcmi_gh2_vxlan_vlan_tag_get
   5403  * Purpose:
   5404  *    Program inner payload/outer tunnel VLAN TAG settings
   5405  * Parameters:
   5406  *    unit         - (IN) Device Number
   5407  *    vxlan_port   - (IN/OUT) VXLAN port info
   5408  *    egr_nh_entry - (IN) Egress L3 Next Hop entry
   5409  *    nh_index     - (IN) Egress Next Hop Index
   5410  * Returns:
   5411  *    BCM_E_XXX
   5412  */
   5413 STATIC int
   5414 bcmi_gh2_vxlan_vlan_tag_get(
   5415     int unit,
   5416     bcm_vxlan_port_t *vxlan_port,
   5417     egr_l3_next_hop_entry_t *egr_nh_entry,
   5418     int nh_index)
   5419 {
   5420     int rv = BCM_E_NONE;
   5421     bcm_vlan_action_set_t action;
   5422     egr_vlan_xlate_entry_t egr_vent;
   5423     egr_vlan_xlate_entry_t ret_egr_vent;
   5424     int index = -1, use_nhi_in_evxlt_key = 0;
   5425     uint32 entry_type, egr_profile_idx;
   5426     soc_mem_t hw_mem = EGR_VLAN_XLATEm;
   5427     uint32 value = 0, dot1p_pri_select = 0;
   5428     int custom_header_ipmc = 0;
   5429 
   5430     /* Input parameter check */
   5431     if ((NULL == vxlan_port) || (NULL == egr_nh_entry)) {
   5432         return BCM_E_PARAM;
   5433     }
   5434 
   5435     entry_type =
   5436         soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry, ENTRY_TYPEf);
   5437 
   5438     if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) {
   5439         use_nhi_in_evxlt_key =
   5440             soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   5441                                              VXLAN__USE_NHI_IN_EVXLT_KEYf);
   5442     } else if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) {
   5443         use_nhi_in_evxlt_key =
   5444             soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   5445                                              L3__USE_NHI_IN_EVXLT_KEYf);
   5446 
   5447         /* Only support for GH2-B0 when VXLAN RIOT is enabled */
   5448         if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   5449             custom_header_ipmc =
   5450                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   5451                                                  L3__CUSTOM_HEADER_IPMCf);
   5452         }
   5453     } else if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW) {
   5454         use_nhi_in_evxlt_key =
   5455             soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   5456                                              L3MC__USE_NHI_IN_EVXLT_KEYf);
   5457 
   5458         /* Only support for GH2-B0 when VXLAN RIOT is enabled */
   5459         if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   5460             custom_header_ipmc =
   5461                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   5462                                                  L3MC__CUSTOM_HEADER_IPMCf);
   5463         }
   5464     } else if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_IFP_ACTION_VIEW) {
   5465         /* Only support for GH2-B0 when VXLAN RIOT is enabled */
   5466         if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   5467             custom_header_ipmc =
   5468                 soc_EGR_L3_NEXT_HOPm_field32_get
   5469                     (unit, egr_nh_entry, IFP_ACTIONS__CUSTOM_HEADER_IPMCf);
   5470         }
   5471     }
   5472 
   5473     if (use_nhi_in_evxlt_key) {
   5474         /* Initialize */
   5475         sal_memset(&egr_vent, 0, sizeof(egr_vlan_xlate_entry_t));
   5476         sal_memset(&ret_egr_vent, 0, sizeof(egr_vlan_xlate_entry_t));
   5477         bcm_vlan_action_set_t_init(&action);
   5478 
   5479         /* Valid Entry */
   5480         soc_mem_field32_set(unit, hw_mem, &egr_vent, VALIDf, 1);
   5481         /* Entry type = NHI */
   5482         soc_mem_field32_set(unit, hw_mem, &egr_vent, ENTRY_TYPEf, 0x07);
   5483         /* Key type = nh_index */
   5484         soc_mem_field32_set(unit, hw_mem, &egr_vent, NHI__NHIf, nh_index);
   5485         /* Old Outer VID = match_vlan */
   5486         VLAN_CHK_ID(unit, vxlan_port->match_vlan);
   5487         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   5488                             NHI__OLD_VLAN_IDf, vxlan_port->match_vlan);
   5489         rv = soc_mem_search(unit, hw_mem, MEM_BLOCK_ANY, &index,
   5490                             &egr_vent, &ret_egr_vent, 0);
   5491         if (BCM_SUCCESS(rv)) {
   5492             egr_profile_idx = soc_mem_field32_get(unit, hw_mem, &ret_egr_vent,
   5493                                                   NHI__TAG_ACTION_PROFILE_PTRf);
   5494 
   5495             _bcm_trx_egr_vlan_action_profile_entry_get(unit, &action,
   5496                                                        egr_profile_idx);
   5497 
   5498             if (action.ut_outer == bcmVlanActionAdd &&
   5499                 action.it_outer == bcmVlanActionAdd) {
   5500                 vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_ADD;
   5501                 vxlan_port->egress_service_vlan =
   5502                     soc_mem_field32_get(unit, hw_mem, &ret_egr_vent,
   5503                                         NHI__NEW_OVIDf);
   5504                 vxlan_port->pkt_pri =
   5505                     soc_mem_field32_get(unit, hw_mem, &ret_egr_vent,
   5506                                         NHI__NEW_OPRIf);
   5507             }
   5508 
   5509             if (action.ot_outer == bcmVlanActionReplace &&
   5510                 action.ot_outer_prio == bcmVlanActionReplace &&
   5511                 action.dt_outer == bcmVlanActionReplace &&
   5512                 action.dt_outer_prio == bcmVlanActionReplace) {
   5513                 vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_PRI_REPLACE;
   5514                 vxlan_port->egress_service_vlan =
   5515                     soc_mem_field32_get(unit, hw_mem, &ret_egr_vent,
   5516                                         NHI__NEW_OVIDf);
   5517                 vxlan_port->pkt_pri =
   5518                     soc_mem_field32_get(unit, hw_mem, &ret_egr_vent,
   5519                                         NHI__NEW_OPRIf);
   5520             } else if (action.ot_outer == bcmVlanActionReplace &&
   5521                        action.dt_outer == bcmVlanActionReplace) {
   5522                 vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_REPLACE;
   5523                 vxlan_port->egress_service_vlan =
   5524                     soc_mem_field32_get(unit, hw_mem, &ret_egr_vent,
   5525                                         NHI__NEW_OVIDf);
   5526             } else if (action.ot_outer_prio == bcmVlanActionReplace &&
   5527                        action.dt_outer_prio == bcmVlanActionReplace) {
   5528                 vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_PRI_REPLACE;
   5529                 vxlan_port->pkt_pri =
   5530                     soc_mem_field32_get(unit, hw_mem, &ret_egr_vent,
   5531                                         NHI__NEW_OPRIf);
   5532             } else if (action.ot_outer == bcmVlanActionDelete &&
   5533                        action.dt_outer == bcmVlanActionDelete) {
   5534                 vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_DELETE;
   5535                 vxlan_port->egress_service_vlan = BCM_VLAN_INVALID;
   5536             }
   5537 
   5538             vxlan_port->match_vlan =
   5539                 soc_mem_field32_get(unit, hw_mem, &ret_egr_vent,
   5540                                     NHI__OLD_VLAN_IDf);
   5541         }
   5542     }
   5543 
   5544     if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) {
   5545         /* Delete Payload Outer Tag */
   5546         value = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   5547                                                  egr_nh_entry,
   5548                                                  VXLAN__DELETE_PAYLOAD_OTAGf);
   5549         if (value) {
   5550             vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_VLAN_DELETE;
   5551         }
   5552 
   5553         /* Delete Tunnel Outer Tag */
   5554         value = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   5555                                                  egr_nh_entry,
   5556                                                  VXLAN__DELETE_TUNNEL_OTAGf);
   5557         if (value) {
   5558             vxlan_port->flags |= BCM_VXLAN_PORT_TUNNEL_OUTER_VLAN_DELETE;
   5559         }
   5560 
   5561         /* Delete Tunnel Inner Tag */
   5562         value = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   5563                                                  egr_nh_entry,
   5564                                                  VXLAN__DELETE_TUNNEL_ITAGf);
   5565         if (value) {
   5566             vxlan_port->flags |= BCM_VXLAN_PORT_TUNNEL_INNER_VLAN_DELETE;
   5567         }
   5568 
   5569         /* DOT1P priority selection for Tunnel outer header */
   5570         dot1p_pri_select =
   5571             soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   5572                                              VXLAN__DOT1P_PRI_SELECTf);
   5573         if (dot1p_pri_select == 0x1) {
   5574             /* USE_MAPPING */
   5575             value = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   5576                                                      VXLAN__DOT1P_MAPPING_PTRf);
   5577             BCM_IF_ERROR_RETURN(
   5578                 _bcm_tr2_qos_idx2id(unit, value,
   5579                 _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS, &vxlan_port->qos_map_id));
   5580             vxlan_port->flags |=  BCM_VXLAN_PORT_TUNNEL_QOS_MAP;
   5581         } else {
   5582             /* USE_FIXED */
   5583             vxlan_port->tunnel_pkt_pri =
   5584                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   5585                                                  VXLAN__NEW_PCPf);
   5586             vxlan_port->tunnel_pkt_cfi =
   5587                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   5588                                                  VXLAN__NEW_CFIf);
   5589         }
   5590     }
   5591 
   5592     /* Only support for GH2-B0 when VXLAN RIOT is enabled */
   5593     if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   5594         if (custom_header_ipmc) {
   5595             vxlan_port->flags |= BCM_VXLAN_PORT_MULTICAST;
   5596         }
   5597     }
   5598 
   5599     return rv;
   5600 }
   5601 
   5602 /*
   5603  * Function:
   5604  *    bcmi_gh2_vxlan_nexthop_entry_modify
   5605  * Purpose:
   5606  *    Modify Egress entry
   5607  * Parameters:
   5608  *    unit           - (IN) Device Number
   5609  *    nh_index       - (IN) Next Hop Index
   5610  *    egr_nh_info    - (IN) Egress Next Hop info
   5611  *    new_entry_type - (IN) New Entry type
   5612  * Returns:
   5613  *    BCM_E_XXX
   5614  */
   5615 STATIC int
   5616 bcmi_gh2_vxlan_nexthop_entry_modify(
   5617     int unit,
   5618     int nh_index,
   5619     bcmi_gh2_vxlan_nh_info_t *egr_nh_info,
   5620     int new_entry_type)
   5621 {
   5622     int rv = BCM_E_NONE;
   5623     soc_mem_t mem;
   5624     egr_l3_next_hop_entry_t egr_nh_entry;
   5625     uint32 old_entry_type = 0, intf_num = 0;
   5626     bcm_mac_t mac_addr; /* Next hop forwarding destination mac. */
   5627     uint32 macda_index;
   5628     void *entries[1];
   5629     egr_mac_da_profile_entry_t macda_entry;
   5630     int pri_field_len = 0;
   5631     int max_pri = 0;
   5632     int hw_idx = 0;
   5633     uint32 value;
   5634 
   5635     /* Input parameter check */
   5636     if (NULL == egr_nh_info) {
   5637         return BCM_E_PARAM;
   5638     }
   5639 
   5640     mem = EGR_L3_NEXT_HOPm;
   5641 
   5642     sal_memset(&mac_addr, 0, sizeof(mac_addr));
   5643     BCM_IF_ERROR_RETURN(
   5644         soc_mem_read(unit, mem, MEM_BLOCK_ANY, nh_index, &egr_nh_entry));
   5645 
   5646     old_entry_type = soc_mem_field32_get(unit, mem, &egr_nh_entry,
   5647                                          ENTRY_TYPEf);
   5648 
   5649     if ((new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) &&
   5650         ((old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) ||
   5651          (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW))) {
   5652 
   5653         if (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) {
   5654             /* Get mac address for L3 (Normal view) */
   5655             soc_mem_mac_addr_get(unit, mem, &egr_nh_entry,
   5656                              L3__MAC_ADDRESSf, mac_addr);
   5657 
   5658             /* Get int_num for L3 (Normal view) */
   5659             intf_num = soc_mem_field32_get(unit, mem, &egr_nh_entry,
   5660                                            L3__INTF_NUMf);
   5661 
   5662             /* Zero buffers for new Entry Type (VXLAN) */
   5663             sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry));
   5664 
   5665             /* Add mac_addr (MAC_DA) into EGR_MAC_DA_PROFILEm */
   5666             sal_memset(&macda_entry, 0, sizeof(macda_entry));
   5667             soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, &macda_entry,
   5668                                  MAC_ADDRESSf, mac_addr);
   5669             entries[0] = &macda_entry;
   5670             BCM_IF_ERROR_RETURN(
   5671                 _bcm_mac_da_profile_entry_add(unit, entries, 1, &macda_index));
   5672 
   5673             /* Set MAC_DA_PROFILE_INDEX */
   5674             soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5675                                 VXLAN__MAC_DA_PROFILE_INDEXf, macda_index);
   5676 
   5677             /* Set INTF_NUM */
   5678             soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5679                                 VXLAN__INTF_NUMf, intf_num);
   5680         }
   5681 
   5682         /* Set Tunnel Index */
   5683         if (egr_nh_info->tunnel_index != -1) {
   5684             soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5685                                 VXLAN__TUNNEL_INDEXf,
   5686                                 egr_nh_info->tunnel_index);
   5687         }
   5688 
   5689         /* Set UDP source port range checking for Entropy */
   5690         value = 0;
   5691         if (egr_nh_info->udp_src_port_range_enable != -1) {
   5692             value = egr_nh_info->udp_src_port_range_enable;
   5693         }
   5694         soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5695                             VXLAN__UDP_SRC_PORT_RANGE_ENf, value);
   5696 
   5697         /* Set VXLAN_CLASS_ID (currently use index = 0 for GH2) */
   5698         value = 0;
   5699         soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5700                             VXLAN__VXLAN_CLASS_IDf, value);
   5701 
   5702         /* Set UDP source port range checking for Entropy */
   5703         value = 0;
   5704         if (egr_nh_info->vnid != -1) {
   5705             value = egr_nh_info->vnid;
   5706         }
   5707         soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5708                             VXLAN__VN_IDf, value);
   5709 
   5710         /* Use NHI as key in EGR_VLAN_XLATE */
   5711         value = 0;
   5712         if (egr_nh_info->use_nhi_in_evxlt_key != -1) {
   5713             value = egr_nh_info->use_nhi_in_evxlt_key;
   5714         }
   5715         soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5716                             VXLAN__USE_NHI_IN_EVXLT_KEYf, value);
   5717 
   5718         /* Set for Egress VLAN XLATE modify to Payload/Tunnel */
   5719         value = 0;
   5720         if (egr_nh_info->apply_evxlt_modify_to_payload != -1) {
   5721             value = egr_nh_info->apply_evxlt_modify_to_payload;
   5722         }
   5723         soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5724                             VXLAN__DO_EVXLT_BEFORE_TUNNEL_ENCAPf, value);
   5725 
   5726         /* Delete payload OTAG */
   5727         value = 0;
   5728         if (egr_nh_info->payload_otag_delete != -1) {
   5729             value = egr_nh_info->payload_otag_delete;
   5730         }
   5731         soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5732                             VXLAN__DELETE_PAYLOAD_OTAGf, value);
   5733 
   5734         /* Delete Tunnel OTAG */
   5735         value = 0;
   5736         if (egr_nh_info->tunnel_otag_delete != -1) {
   5737             value = egr_nh_info->tunnel_otag_delete;
   5738         }
   5739         soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5740                             VXLAN__DELETE_TUNNEL_OTAGf, value);
   5741 
   5742         /* Delete Tunnel ITAG */
   5743         value = 0;
   5744         if (egr_nh_info->tunnel_itag_delete != -1) {
   5745             value = egr_nh_info->tunnel_itag_delete;
   5746         }
   5747         soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5748                             VXLAN__DELETE_TUNNEL_ITAGf, value);
   5749 
   5750         /* DOT1P priority selection for Tunnel outer header */
   5751         if (egr_nh_info->qos_map_id != -1) {
   5752             /* USE_MAPPING */
   5753             BCM_IF_ERROR_RETURN(
   5754                 _bcm_tr2_qos_id2idx(unit, egr_nh_info->qos_map_id, &hw_idx));
   5755             soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5756                                 VXLAN__DOT1P_PRI_SELECTf, 0x1);
   5757             soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5758                                 VXLAN__DOT1P_MAPPING_PTRf, hw_idx);
   5759         } else if ((egr_nh_info->tunnel_pkt_pri != -1) &&
   5760                    (egr_nh_info->tunnel_pkt_cfi != -1)) {
   5761             /* USE_FIXED */
   5762             pri_field_len = soc_mem_field_length(unit, mem, VXLAN__NEW_PCPf);
   5763             max_pri = (1 << pri_field_len) - 1;
   5764 
   5765             if ((egr_nh_info->tunnel_pkt_pri > max_pri) ||
   5766                 (egr_nh_info->tunnel_pkt_cfi > 1)) {
   5767                 return BCM_E_PARAM;
   5768             }
   5769             soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5770                                 VXLAN__DOT1P_PRI_SELECTf, 0x0);
   5771             soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5772                                 VXLAN__NEW_PCPf, egr_nh_info->tunnel_pkt_pri);
   5773             soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5774                                 VXLAN__NEW_CFIf, egr_nh_info->tunnel_pkt_cfi);
   5775         }
   5776 
   5777         /* Set Entry Type */
   5778         soc_mem_field32_set(unit, mem, &egr_nh_entry, ENTRY_TYPEf,
   5779                             new_entry_type);
   5780     } else if ((new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW) &&
   5781         (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW)) {
   5782         /* Use NHI as key in EGR_VLAN_XLATE */
   5783         value = 0;
   5784         if (egr_nh_info->use_nhi_in_evxlt_key != -1) {
   5785             value = egr_nh_info->use_nhi_in_evxlt_key;
   5786         }
   5787         soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5788                             L3MC__USE_NHI_IN_EVXLT_KEYf, value);
   5789 
   5790         /* Only support for GH2-B0 when VXLAN RIOT is enabled */
   5791         if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   5792             /* Set to copied to Custom Header IPMC bit */
   5793             value = 0;
   5794             if (egr_nh_info->custom_header_ipmc != -1) {
   5795                 value = egr_nh_info->custom_header_ipmc;
   5796             }
   5797             soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5798                                 L3MC__CUSTOM_HEADER_IPMCf, value);
   5799         }
   5800     } else if ((new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) &&
   5801         (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW)) {
   5802         /* Use NHI as key in EGR_VLAN_XLATE */
   5803         value = 0;
   5804         if (egr_nh_info->use_nhi_in_evxlt_key != -1) {
   5805             value = egr_nh_info->use_nhi_in_evxlt_key;
   5806         }
   5807         soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5808                             L3__USE_NHI_IN_EVXLT_KEYf, value);
   5809 
   5810         /* Only support for GH2-B0 when VXLAN RIOT is enabled */
   5811         if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   5812             /* Set to copied to Custom Header IPMC bit */
   5813             value = 0;
   5814             if (egr_nh_info->custom_header_ipmc != -1) {
   5815                 value = egr_nh_info->custom_header_ipmc;
   5816             }
   5817             soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5818                                 L3__CUSTOM_HEADER_IPMCf, value);
   5819         }
   5820     } else if ((new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_IFP_ACTION_VIEW) &&
   5821         ((old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) ||
   5822          (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_IFP_ACTION_VIEW))) {
   5823         /* Only support for GH2-B0 when VXLAN RIOT is enabled */
   5824 
   5825         /* Set to copied to Custom Header IPMC bit */
   5826         value = 0;
   5827         if (egr_nh_info->custom_header_ipmc != -1) {
   5828             value = egr_nh_info->custom_header_ipmc;
   5829         }
   5830         soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5831                             IFP_ACTIONS__CUSTOM_HEADER_IPMCf, value);
   5832 
   5833         /* Disable the DA/SA replacement when unicast decap flow */
   5834         value = 1;
   5835         soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5836                             IFP_ACTIONS__L3_UC_DA_DISABLEf, value);
   5837         soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5838                             IFP_ACTIONS__L3_UC_SA_DISABLEf, value);
   5839 
   5840         /* Set Entry Type */
   5841         soc_mem_field32_set(unit, mem, &egr_nh_entry, ENTRY_TYPEf,
   5842                             new_entry_type);
   5843     } else if (new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) {
   5844         if (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) {
   5845             /* Get MAC_DA_PROFILE_INDEX for VXLAN view */
   5846             macda_index =
   5847                 soc_mem_field32_get(unit, mem, &egr_nh_entry,
   5848                                     VXLAN__MAC_DA_PROFILE_INDEXf);
   5849             /* Write MAC_DA from profile into NH table in L3 view */
   5850             sal_memset(&macda_entry, 0, sizeof(macda_entry));
   5851             BCM_IF_ERROR_RETURN(
   5852                 soc_mem_read(unit, EGR_MAC_DA_PROFILEm, MEM_BLOCK_ANY,
   5853                              macda_index, &macda_entry));
   5854             soc_mem_mac_addr_get(unit, EGR_MAC_DA_PROFILEm, &macda_entry,
   5855                                  MAC_ADDRESSf, mac_addr);
   5856             soc_mem_mac_addr_set(unit, mem, &egr_nh_entry, L3__MAC_ADDRESSf,
   5857                                  mac_addr);
   5858             /* Delete mac_addr (MAC_DA) from EGR_MAC_DA_PROFILEm */
   5859             BCM_IF_ERROR_RETURN(
   5860                 _bcm_mac_da_profile_entry_delete(unit, macda_index));
   5861         }
   5862 
   5863         /* Use NHI as key in EGR_VLAN_XLATE */
   5864         value = 0;
   5865         if (egr_nh_info->use_nhi_in_evxlt_key != -1) {
   5866             value = egr_nh_info->use_nhi_in_evxlt_key;
   5867         }
   5868         soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5869                             L3__USE_NHI_IN_EVXLT_KEYf, value);
   5870 
   5871         /* Only support for GH2-B0 when VXLAN RIOT is enabled */
   5872         if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   5873             /* Set to copied to Custom Header IPMC bit */
   5874             value = 0;
   5875             if (egr_nh_info->custom_header_ipmc != -1) {
   5876                 value = egr_nh_info->custom_header_ipmc;
   5877             }
   5878             soc_mem_field32_set(unit, mem, &egr_nh_entry,
   5879                                 L3__CUSTOM_HEADER_IPMCf, value);
   5880         }
   5881 
   5882         /* Set Entry Type */
   5883         soc_mem_field32_set(unit, mem, &egr_nh_entry, ENTRY_TYPEf,
   5884                             new_entry_type);
   5885     } else if ((new_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) &&
   5886         (old_entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW)) {
   5887         return BCM_E_PARAM;
   5888     }
   5889 
   5890     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, nh_index, &egr_nh_entry);
   5891 
   5892     return rv;
   5893 }
   5894 
   5895 /*
   5896  * Function:
   5897  *    bcmi_gh2_vxlan_ecmp_nexthop_entry_modify
   5898  * Purpose:
   5899  *    Modify vxlan ecmp member object's Egress next hop entry
   5900  * Parameters:
   5901  *    unit           - (IN) Device Number
   5902  *    vxlan_port - (IN) vxlan_port information
   5903  *    egr_nh_info    - (IN) Egress Next Hop info
   5904  *    new_entry_type - (IN) New Entry type
   5905  * Returns:
   5906  *    BCM_E_XXX
   5907  */
   5908 STATIC int
   5909 bcmi_gh2_vxlan_ecmp_nexthop_entry_modify(
   5910     int unit,
   5911     bcm_vxlan_port_t *vxlan_port,
   5912     bcmi_gh2_vxlan_nh_info_t *egr_nh_info,
   5913     int new_entry_type)
   5914 {
   5915     int rv = BCM_E_NONE;
   5916     int i = 0, ecmp_member_count = 0;
   5917     int ecmp_index;
   5918     int alloc_size, index;
   5919     bcm_l3_egress_ecmp_t ecmp_info;
   5920     bcm_if_t *ecmp_member_array = NULL;
   5921 
   5922     if ((NULL == vxlan_port) || (NULL == egr_nh_info) ) {
   5923         return BCM_E_PARAM;
   5924     }
   5925 
   5926     ecmp_index = vxlan_port->egress_if;
   5927     if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_index)) {
   5928         return BCM_E_PARAM;
   5929     }
   5930 
   5931     ecmp_info.ecmp_intf = ecmp_index;
   5932     alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit);
   5933     ecmp_member_array = sal_alloc(alloc_size, "ecmp member array");
   5934     if (NULL == ecmp_member_array) {
   5935         return BCM_E_MEMORY;
   5936     }
   5937     sal_memset(ecmp_member_array, 0, alloc_size);
   5938 
   5939     rv = bcm_esw_l3_egress_ecmp_get(unit, &ecmp_info,
   5940                                     BCM_XGS3_L3_ECMP_MAX(unit),
   5941                                     ecmp_member_array, &ecmp_member_count);
   5942     if (BCM_FAILURE(rv)) {
   5943         sal_free(ecmp_member_array);
   5944         ecmp_member_array = NULL;
   5945         return rv;
   5946     }
   5947 
   5948     while (i < ecmp_member_count) {
   5949         if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, ecmp_member_array[i])) {
   5950             index = (ecmp_member_array[i] - BCM_XGS3_EGRESS_IDX_MIN(unit));
   5951         } else {
   5952             sal_free(ecmp_member_array);
   5953             ecmp_member_array = NULL;
   5954             return BCM_E_PARAM;
   5955         }
   5956 
   5957         /* Configure inner payload/outer tunnel VLAN TAG setting */
   5958         rv = bcmi_gh2_vxlan_vlan_tag_set(unit, vxlan_port,
   5959                                          egr_nh_info, index);
   5960         if (BCM_FAILURE(rv)) {
   5961             sal_free(ecmp_member_array);
   5962             ecmp_member_array = NULL;
   5963             return rv;
   5964         }
   5965 
   5966         rv = bcmi_gh2_vxlan_nexthop_entry_modify(unit, index,
   5967                                                  egr_nh_info, new_entry_type);
   5968         if (BCM_FAILURE(rv)) {
   5969             sal_free(ecmp_member_array);
   5970             ecmp_member_array = NULL;
   5971             return rv;
   5972         }
   5973 
   5974         i++;
   5975     }
   5976 
   5977     if (ecmp_member_array) {
   5978         sal_free(ecmp_member_array);
   5979         ecmp_member_array = NULL;
   5980     }
   5981 
   5982     return rv;
   5983 }
   5984 
   5985 /*
   5986  * Function:
   5987  *    bcmi_gh2_vxlan_ecmp_member_egress_get_first
   5988  * Purpose:
   5989  *    Get ECMP first member nexthop index
   5990  * Parameters:
   5991  *    unit       - (IN) Device Number
   5992  *    ecmp_index - (IN) ECMP index
   5993  *    index      - (OUT) poiter to first next hop index
   5994  * Returns:
   5995  *      BCM_E_XXX
   5996  */
   5997 STATIC int
   5998 bcmi_gh2_vxlan_ecmp_member_egress_get_first(
   5999     int unit,
   6000     int ecmp_index,
   6001     int *index)
   6002 {
   6003     int rv = BCM_E_NONE;
   6004     int alloc_size;
   6005     int ecmp_member_count = 0;
   6006     bcm_l3_egress_ecmp_t ecmp_info;
   6007     bcm_if_t *ecmp_member_array = NULL;
   6008 
   6009     /* Input parameter check */
   6010     if (NULL == index) {
   6011         return BCM_E_PARAM;
   6012     }
   6013 
   6014     if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_index)) {
   6015         return BCM_E_PARAM;
   6016     }
   6017 
   6018     bcm_l3_egress_ecmp_t_init(&ecmp_info);
   6019     ecmp_info.ecmp_intf = ecmp_index;
   6020     alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit);
   6021     ecmp_member_array = sal_alloc(alloc_size, "ecmp member array");
   6022     if (NULL == ecmp_member_array) {
   6023         return BCM_E_MEMORY;
   6024     }
   6025     sal_memset(ecmp_member_array, 0, alloc_size);
   6026 
   6027     rv = bcm_esw_l3_egress_ecmp_get(unit, &ecmp_info,
   6028                                     BCM_XGS3_L3_ECMP_MAX(unit),
   6029                                     ecmp_member_array, &ecmp_member_count);
   6030     if (BCM_FAILURE(rv)) {
   6031         sal_free(ecmp_member_array);
   6032         ecmp_member_array = NULL;
   6033         return rv;
   6034     }
   6035 
   6036     if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, ecmp_member_array[0])) {
   6037         *index = (ecmp_member_array[0] - BCM_XGS3_EGRESS_IDX_MIN(unit));
   6038     } else {
   6039         rv = BCM_E_PARAM;
   6040     }
   6041 
   6042     if (ecmp_member_array) {
   6043         sal_free(ecmp_member_array);
   6044         ecmp_member_array = NULL;
   6045     }
   6046 
   6047     return rv;
   6048 }
   6049 
   6050 /*
   6051  * Function:
   6052  *    bcmi_gh2_vxlan_port_egress_nexthop_reset
   6053  * Purpose:
   6054  *    Reset VXLAN Egress NextHop
   6055  * Parameters:
   6056  *    unit     - (IN) Device Number
   6057  *    nh_index - (IN) Next Hop index
   6058  *    vp_type - (IN) VP type
   6059  *    vp       - (IN) vxlan virtual port
   6060  *    vpn      - (IN) VPN instance ID
   6061  * Returns:
   6062  *    BCM_E_XXX
   6063  */
   6064 STATIC int
   6065 bcmi_gh2_vxlan_port_egress_nexthop_reset(
   6066     int unit,
   6067     int nh_index,
   6068     int vp_type,
   6069     int vp,
   6070     bcm_vpn_t vpn)
   6071 {
   6072     int rv = BCM_E_NONE;
   6073     egr_l3_next_hop_entry_t egr_nh_entry;
   6074     uint32 entry_type = 0;
   6075     bcmi_gh2_vxlan_nh_info_t egr_nh_info;
   6076     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   6077     int index = -1, use_nhi_in_evxlt_key = 0;
   6078     egr_vlan_xlate_entry_t egr_vent;
   6079     egr_vlan_xlate_entry_t ret_egr_vent;
   6080     soc_mem_t hw_mem = EGR_VLAN_XLATEm;
   6081     uint32 egr_profile_idx;
   6082 
   6083     /* Get VXLAN bookkeeping info instance */
   6084     BCM_IF_ERROR_RETURN(
   6085         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   6086 
   6087     BCM_IF_ERROR_RETURN(
   6088         soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   6089                      nh_index, &egr_nh_entry));
   6090 
   6091     /* Egressing into a regular port */
   6092     entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   6093                                                   &egr_nh_entry, ENTRY_TYPEf);
   6094     if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) {
   6095         use_nhi_in_evxlt_key =
   6096             soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry,
   6097                                              VXLAN__USE_NHI_IN_EVXLT_KEYf);
   6098     } else if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) {
   6099         use_nhi_in_evxlt_key =
   6100             soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry,
   6101                                              L3__USE_NHI_IN_EVXLT_KEYf);
   6102     } else if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW) {
   6103         use_nhi_in_evxlt_key =
   6104             soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry,
   6105                                              L3MC__USE_NHI_IN_EVXLT_KEYf);
   6106     }
   6107 
   6108     if (use_nhi_in_evxlt_key) {
   6109         /* Initialize */
   6110         sal_memset(&egr_vent, 0, sizeof(egr_vlan_xlate_entry_t));
   6111         sal_memset(&ret_egr_vent, 0, sizeof(egr_vlan_xlate_entry_t));
   6112 
   6113         /* Valid Entry */
   6114         soc_mem_field32_set(unit, hw_mem, &egr_vent, VALIDf, 1);
   6115         /* Entry type = NHI */
   6116         soc_mem_field32_set(unit, hw_mem, &egr_vent, ENTRY_TYPEf, 0x07);
   6117         /* Key type = nh_index */
   6118         soc_mem_field32_set(unit, hw_mem, &egr_vent, NHI__NHIf, nh_index);
   6119         /* Old Outer VID = match_vlan */
   6120         soc_mem_field32_set(unit, hw_mem, &egr_vent,
   6121                             NHI__OLD_VLAN_IDf,
   6122                             vxlan_info->match_key[vp].match_vlan);
   6123         rv = soc_mem_search(unit, hw_mem, MEM_BLOCK_ANY, &index,
   6124                             &egr_vent, &ret_egr_vent, 0);
   6125         if (BCM_SUCCESS(rv)) {
   6126             /* Existing EGR_VLAN_XLATE entry is found */
   6127 
   6128             /* Delete the old vlan translate profile entry */
   6129             egr_profile_idx =
   6130                 soc_mem_field32_get(unit, hw_mem, &ret_egr_vent,
   6131                                     NHI__TAG_ACTION_PROFILE_PTRf);
   6132             BCM_IF_ERROR_RETURN(
   6133                 _bcm_trx_egr_vlan_action_profile_entry_delete
   6134                     (unit, egr_profile_idx));
   6135 
   6136             /* Delete the related EGR_VLAN_XLATE entry with nh_index */
   6137             BCM_IF_ERROR_RETURN(
   6138                 soc_mem_delete(unit, hw_mem, MEM_BLOCK_ALL, &egr_vent));
   6139         } else {
   6140             if (rv == BCM_E_NOT_FOUND) {
   6141                 rv = BCM_E_NONE;
   6142             } else {
   6143                 return rv;
   6144             }
   6145         }
   6146     }
   6147 
   6148     sal_memset(&egr_nh_info, 0, sizeof(egr_nh_info));
   6149     if (vp_type == GH2_VXLAN_DEST_VP_TYPE_ACCESS) {
   6150         /* Normalize Next-hop Entry - L3 View */
   6151         rv = bcmi_gh2_vxlan_nexthop_entry_modify
   6152                   (unit, nh_index, &egr_nh_info,
   6153                    _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW);
   6154 
   6155     } else if (vp_type == GH2_VXLAN_DEST_VP_TYPE_TUNNEL) {
   6156         /*
   6157          * Egressing into a tunnel, vp type should be
   6158          * GH2_VXLAN_DEST_VP_TYPE_TUNNEL
   6159          */
   6160         /* Normalize Next-hop Entry - L3 View */
   6161         if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) {
   6162             rv = bcmi_gh2_vxlan_nexthop_entry_modify
   6163                       (unit, nh_index, &egr_nh_info,
   6164                        _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW);
   6165         }
   6166     }
   6167 
   6168     return rv;
   6169 }
   6170 
   6171 /*
   6172  * Function:
   6173  *    bcmi_gh2_vxlan_ecmp_port_egress_nexthop_reset
   6174  * Purpose:
   6175  *    Reset VXLAN ecmp Egress NextHop
   6176  * Parameters:
   6177  *    unit       - (IN) Device Number
   6178  *    ecmp_index - (IN) ECMP index
   6179  *    vp_type    - (IN) VP type
   6180  *    vp         - (IN) vxlan virtual port
   6181  *    vpn        - (IN) VPN instance ID
   6182  * Returns:
   6183  *    BCM_E_XXX
   6184  */
   6185 STATIC int
   6186 bcmi_gh2_vxlan_ecmp_port_egress_nexthop_reset(
   6187     int unit,
   6188     int ecmp_index,
   6189     int vp_type,
   6190     int vp,
   6191     bcm_vpn_t vpn)
   6192 {
   6193     int rv = BCM_E_NONE;
   6194     int i = 0, ecmp_member_count = 0;
   6195     int alloc_size, index;
   6196     bcm_l3_egress_ecmp_t ecmp_info;
   6197     bcm_if_t *ecmp_member_array = NULL;
   6198     uint32 ref_count;
   6199 
   6200     if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, ecmp_index)) {
   6201         return BCM_E_PARAM;
   6202     }
   6203 
   6204     /* Initialize ecmp_info data structure */
   6205     bcm_l3_egress_ecmp_t_init(&ecmp_info);
   6206     ecmp_info.ecmp_intf = ecmp_index;
   6207     alloc_size = sizeof(bcm_if_t) * BCM_XGS3_L3_ECMP_MAX(unit);
   6208     ecmp_member_array = sal_alloc(alloc_size, "ecmp member array");
   6209     if (NULL == ecmp_member_array) {
   6210         return BCM_E_MEMORY;
   6211     }
   6212     sal_memset(ecmp_member_array, 0, alloc_size);
   6213 
   6214     rv = bcm_esw_l3_egress_ecmp_get(unit, &ecmp_info,
   6215                                     BCM_XGS3_L3_ECMP_MAX(unit),
   6216                                     ecmp_member_array, &ecmp_member_count);
   6217     if (BCM_FAILURE(rv)) {
   6218         sal_free(ecmp_member_array);
   6219         ecmp_member_array = NULL;
   6220         return rv;
   6221     }
   6222 
   6223     while (i < ecmp_member_count) {
   6224         if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, ecmp_member_array[i])) {
   6225             index = (ecmp_member_array[i] - BCM_XGS3_EGRESS_IDX_MIN(unit));
   6226         } else {
   6227             sal_free(ecmp_member_array);
   6228             ecmp_member_array = NULL;
   6229             return BCM_E_PARAM;
   6230         }
   6231 
   6232         /* Get current reference count */
   6233         _bcm_esw_l3_egress_reference_get(unit, index, 0, &ref_count);
   6234 
   6235         /*
   6236          * If (ref_count == 1), it means the NHI is used for
   6237          * ECMP group only, then we must reset VXLAN Egress NextHop.
   6238          */
   6239         if (ref_count == 1) {
   6240             if (index) {
   6241                 rv = bcmi_gh2_vxlan_port_egress_nexthop_reset
   6242                          (unit, index, vp_type, vp, vpn);
   6243             }
   6244         }
   6245 
   6246         if (BCM_FAILURE(rv)) {
   6247             sal_free(ecmp_member_array);
   6248             ecmp_member_array = NULL;
   6249             return rv;
   6250         }
   6251         i++;
   6252     }
   6253 
   6254     if (ecmp_member_array) {
   6255         sal_free(ecmp_member_array);
   6256         ecmp_member_array = NULL;
   6257     }
   6258 
   6259     return rv;
   6260 }
   6261 
   6262 /*
   6263  * Function:
   6264  *    bcmi_gh2_vxlan_nexthop_ecmp_find
   6265  * Purpose:
   6266  *    Find ECMP group with specified egress forwarding object and
   6267  *    reset VXLAN Egress NextHop when found
   6268  * Parameters:
   6269  *    unit       - (IN) Device Number
   6270  *    ecmp       - (IN) ECMP group info.
   6271  *    intf_count - (IN) Number of elements in intf_array.
   6272  *    intf_array - (IN) Array of Egress forwarding objects.
   6273  *    user_data  - (IN) User data to be passed to callback function.
   6274  * Returns:
   6275  *    BCM_E_XXX
   6276  */
   6277 STATIC int
   6278 bcmi_gh2_vxlan_nexthop_ecmp_find(
   6279     int unit,
   6280     bcm_l3_egress_ecmp_t *ecmp,
   6281     int intf_count,
   6282     bcm_if_t *intf_array,
   6283     void *user_data)
   6284 {
   6285     int rv = BCM_E_NONE;
   6286     int *nh_ecmp_index;
   6287     int idx, nh_ecmp_intf, found, nhi;
   6288     egr_l3_next_hop_entry_t egr_nh_entry;
   6289     bcmi_gh2_vxlan_nh_info_t egr_nh_info;
   6290     uint32 entry_type = 0;
   6291 
   6292     /* Input parameters check */
   6293     if ((NULL == ecmp) || (NULL == intf_array) || (NULL == user_data)) {
   6294         return BCM_E_PARAM;
   6295     }
   6296 
   6297     nh_ecmp_index = (int *)user_data;
   6298     nh_ecmp_intf = (*nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit));
   6299     found = 0;
   6300     for (idx = 0; idx < intf_count; idx++) {
   6301         if (*intf_array == nh_ecmp_intf) {
   6302             found = 1;
   6303             break;
   6304         }
   6305         intf_array++;
   6306     }
   6307 
   6308     if (found != 0) {
   6309         sal_memset(&egr_nh_info, 0, sizeof(egr_nh_info));
   6310 
   6311         nhi = (nh_ecmp_intf - BCM_XGS3_EGRESS_IDX_MIN(unit));
   6312         BCM_IF_ERROR_RETURN(
   6313             soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   6314                          nhi, &egr_nh_entry));
   6315 
   6316         /* Egressing into a regular port */
   6317         entry_type =
   6318             soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry,
   6319                                              ENTRY_TYPEf);
   6320 
   6321         /* Normalize Next-hop Entry - L3 View */
   6322         if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) {
   6323             rv = bcmi_gh2_vxlan_nexthop_entry_modify
   6324                       (unit, nhi, &egr_nh_info,
   6325                        _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW);
   6326         }
   6327     }
   6328 
   6329     return rv;
   6330 }
   6331 
   6332 /*
   6333  * Function:
   6334  *    bcmi_gh2_vxlan_port_nh_add
   6335  * Purpose:
   6336  *    Add VXLAN Next Hop entry
   6337  * Parameters:
   6338  *    unit - (IN) Device Number
   6339  *    vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id)
   6340  *    vp   - (IN) vxlan virtual port
   6341  *    vpn  - (IN) VPN instance ID
   6342  * Returns:
   6343  *    BCM_E_XXX
   6344  */
   6345 STATIC int
   6346 bcmi_gh2_vxlan_port_nh_add(
   6347     int unit,
   6348     bcm_vxlan_port_t *vxlan_port,
   6349     int vp,
   6350     bcm_vpn_t vpn)
   6351 {
   6352     int rv = BCM_E_NONE;
   6353     int vfi_index = -1;
   6354     int new_entry_type;
   6355     egr_l3_next_hop_entry_t egr_nh_entry;
   6356     bcmi_gh2_vxlan_nh_info_t egr_nh_info;
   6357     uint32 mpath_flag = 0;
   6358     int vp_nh_ecmp_index = -1;
   6359     int ref_count = 0;
   6360     int l3_flag = 0;
   6361     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   6362     gh2_vxlan_vpn_info_t *vfi_info;
   6363     gh2_vxlan_vp_info_t *vp_info;
   6364 
   6365     /* Input parameter check */
   6366     if (NULL == vxlan_port) {
   6367         return BCM_E_PARAM;
   6368     }
   6369 
   6370     /* Get VXLAN bookkeeping info instance */
   6371     BCM_IF_ERROR_RETURN(
   6372         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   6373 
   6374     _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
   6375     /* Get VFI info for VN_ID */
   6376     vfi_info = &(vxlan_info->vxlan_vpn_info[vfi_index]);
   6377 
   6378     /* Get VP info for vfi_index */
   6379     vp_info = &(vxlan_info->vxlan_vp_info[vp]);
   6380     vp_info->vfi = vfi_index;
   6381 
   6382     sal_memset(&egr_nh_info, 0, sizeof(egr_nh_info));
   6383     egr_nh_info.vnid = vfi_info->vnid;
   6384     egr_nh_info.entry_type = -1;
   6385     egr_nh_info.intf_num = -1;
   6386     egr_nh_info.tunnel_index = -1;
   6387     egr_nh_info.udp_src_port_range_enable = -1;
   6388     egr_nh_info.payload_otag_delete = -1;
   6389     egr_nh_info.use_nhi_in_evxlt_key = -1;
   6390     egr_nh_info.apply_evxlt_modify_to_payload = -1;
   6391     egr_nh_info.tunnel_otag_delete = -1;
   6392     egr_nh_info.tunnel_itag_delete = -1;
   6393     egr_nh_info.qos_map_id = -1;
   6394     egr_nh_info.tunnel_pkt_pri = -1;
   6395     egr_nh_info.tunnel_pkt_cfi = -1;
   6396     egr_nh_info.custom_header_ipmc = -1;
   6397 
   6398     /*
   6399      * Get egress next-hop index from egress object and
   6400      * increase egress object reference count.
   6401      */
   6402     if (!(vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) {
   6403         rv = bcm_xgs3_get_nh_from_egress_object(unit, vxlan_port->egress_if,
   6404                                                 &mpath_flag, 1,
   6405                                                 &vp_nh_ecmp_index);
   6406         BCM_IF_ERROR_RETURN(rv);
   6407 
   6408         /* Read the existing egress next_hop entry */
   6409         if (mpath_flag == 0) {
   6410             if (vxlan_port->flags & BCM_VXLAN_PORT_NETWORK) {
   6411                 l3_flag = BCM_XGS3_L3_ENT_FLAG(
   6412                     BCM_XGS3_L3_TBL_PTR(unit, next_hop), vp_nh_ecmp_index);
   6413                 if (l3_flag != _BCM_L3_VXLAN_ONLY) {
   6414                     if (vp_nh_ecmp_index != -1) {
   6415                         /* Decrement reference count */
   6416                         (void)bcm_xgs3_get_ref_count_from_nhi
   6417                                     (unit, mpath_flag, &ref_count,
   6418                                      vp_nh_ecmp_index);
   6419                     }
   6420                     return BCM_E_CONFIG;
   6421                 }
   6422             }
   6423         }
   6424 
   6425         sal_memset(&egr_nh_entry, 0, sizeof(egr_l3_next_hop_entry_t));
   6426         rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   6427                           vp_nh_ecmp_index, &egr_nh_entry);
   6428         if (BCM_FAILURE(rv)) {
   6429             if (vp_nh_ecmp_index != -1) {
   6430                 /* Decrement reference count */
   6431                 (void)bcm_xgs3_get_ref_count_from_nhi
   6432                             (unit, mpath_flag, &ref_count,
   6433                              vp_nh_ecmp_index);
   6434             }
   6435             return rv;
   6436         }
   6437     }
   6438 
   6439     if (vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL) {
   6440         /* Egress into Network - Tunnel */
   6441 
   6442         if (!(vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) {
   6443             if (vxlan_port->flags & BCM_VXLAN_PORT_MULTICAST) {
   6444                 /* GH2 doesn't support multicast VXLAN tunnel */
   6445                 rv = BCM_E_UNAVAIL;
   6446             }
   6447 
   6448             /*
   6449              * Select PPD type for Higig header:
   6450              * - Must be BCM_VXLAN_PORT_ENCAP_LOCAL for GH2
   6451              */
   6452             if (!(vxlan_port->flags & BCM_VXLAN_PORT_ENCAP_LOCAL)) {
   6453                 rv = BCM_E_PARAM;
   6454             }
   6455 
   6456             if (BCM_FAILURE(rv)) {
   6457                 if (vp_nh_ecmp_index != -1) {
   6458                     /* Decrement reference count */
   6459                     (void)bcm_xgs3_get_ref_count_from_nhi
   6460                                 (unit, mpath_flag, &ref_count,
   6461                                  vp_nh_ecmp_index);
   6462                 }
   6463                 return rv;
   6464             }
   6465         }
   6466 
   6467         /* Program software Egress Tunnel info */
   6468         rv = bcmi_gh2_vxlan_egress_tunnel_set(unit, vxlan_port, &egr_nh_info);
   6469         if (BCM_FAILURE(rv)) {
   6470             if (vp_nh_ecmp_index != -1) {
   6471                 /* Decrement reference count */
   6472                 (void)bcm_xgs3_get_ref_count_from_nhi
   6473                             (unit, mpath_flag, &ref_count,
   6474                              vp_nh_ecmp_index);
   6475             }
   6476             return rv;
   6477         }
   6478 
   6479         /* Program software DVP to NHI/ECMP */
   6480         rv = bcmi_gh2_vxlan_ingress_dvp_set(unit, vp, mpath_flag,
   6481                                             vp_nh_ecmp_index, vxlan_port);
   6482         if (BCM_FAILURE(rv)) {
   6483             if (vp_nh_ecmp_index != -1) {
   6484                 /* Decrement reference count */
   6485                 (void)bcm_xgs3_get_ref_count_from_nhi
   6486                             (unit, mpath_flag, &ref_count,
   6487                              vp_nh_ecmp_index);
   6488             }
   6489             return rv;
   6490         }
   6491 
   6492         new_entry_type = _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW;
   6493         if (mpath_flag == 0) {
   6494             /* Configure inner payload/outer tunnel VLAN TAG setting */
   6495             rv = bcmi_gh2_vxlan_vlan_tag_set(unit, vxlan_port,
   6496                                              &egr_nh_info, vp_nh_ecmp_index);
   6497             if (BCM_FAILURE(rv)) {
   6498                 if (vp_nh_ecmp_index != -1) {
   6499                     /* Decrement reference count */
   6500                     (void)bcm_xgs3_get_ref_count_from_nhi
   6501                                 (unit, mpath_flag, &ref_count,
   6502                                  vp_nh_ecmp_index);
   6503                 }
   6504                 return rv;
   6505             }
   6506 
   6507             rv = bcmi_gh2_vxlan_nexthop_entry_modify
   6508                 (unit, vp_nh_ecmp_index, &egr_nh_info, new_entry_type);
   6509             if (BCM_FAILURE(rv)) {
   6510                 if (vp_nh_ecmp_index != -1) {
   6511                     /* Decrement reference count */
   6512                     (void)bcm_xgs3_get_ref_count_from_nhi
   6513                                 (unit, mpath_flag, &ref_count,
   6514                                  vp_nh_ecmp_index);
   6515                 }
   6516                 return rv;
   6517             }
   6518         } else {
   6519             /* ECMP */
   6520             rv = bcmi_gh2_vxlan_ecmp_nexthop_entry_modify
   6521                 (unit, vxlan_port, &egr_nh_info, new_entry_type);
   6522             if (BCM_FAILURE(rv)) {
   6523                 if (vp_nh_ecmp_index != -1) {
   6524                     /* Decrement reference count */
   6525                     (void)bcm_xgs3_get_ref_count_from_nhi
   6526                                 (unit, mpath_flag, &ref_count,
   6527                                  vp_nh_ecmp_index);
   6528                 }
   6529                 return rv;
   6530             }
   6531         }
   6532     } else {
   6533         /* Egress into Access - Non Tunnel */
   6534 
   6535         /* Configure inner payload VLAN TAG setting */
   6536         rv = bcmi_gh2_vxlan_vlan_tag_set(unit, vxlan_port,
   6537                                          &egr_nh_info, vp_nh_ecmp_index);
   6538         if (BCM_FAILURE(rv)) {
   6539             if (vp_nh_ecmp_index != -1) {
   6540                 /* Decrement reference count */
   6541                 (void)bcm_xgs3_get_ref_count_from_nhi
   6542                             (unit, mpath_flag, &ref_count,
   6543                              vp_nh_ecmp_index);
   6544             }
   6545             return rv;
   6546         }
   6547 
   6548         egr_nh_info.entry_type =
   6549             soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, ENTRY_TYPEf);
   6550         if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) {
   6551             /* Loopback VP is only support when VXLAN RIOT is enabled */
   6552             if ((egr_nh_info.entry_type !=
   6553                  _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) &&
   6554                 (egr_nh_info.entry_type !=
   6555                  _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW) &&
   6556                 (egr_nh_info.entry_type !=
   6557                  _BCM_VXLAN_EGR_NEXT_HOP_IFP_ACTION_VIEW)) {
   6558                 if (vp_nh_ecmp_index != -1) {
   6559                     /* Decrement reference count */
   6560                     (void)bcm_xgs3_get_ref_count_from_nhi
   6561                                 (unit, mpath_flag, &ref_count,
   6562                                  vp_nh_ecmp_index);
   6563                 }
   6564                 return BCM_E_PARAM;
   6565             }
   6566 
   6567             new_entry_type = _BCM_VXLAN_EGR_NEXT_HOP_IFP_ACTION_VIEW;
   6568         } else {
   6569             if ((egr_nh_info.entry_type !=
   6570                  _BCM_VXLAN_EGR_NEXT_HOP_L3_VIEW) &&
   6571                 (egr_nh_info.entry_type !=
   6572                  _BCM_VXLAN_EGR_NEXT_HOP_L3MC_VIEW)) {
   6573                 if (vp_nh_ecmp_index != -1) {
   6574                     /* Decrement reference count */
   6575                     (void)bcm_xgs3_get_ref_count_from_nhi
   6576                                 (unit, mpath_flag, &ref_count,
   6577                                  vp_nh_ecmp_index);
   6578                 }
   6579                 return BCM_E_PARAM;
   6580             }
   6581 
   6582             new_entry_type = egr_nh_info.entry_type;
   6583         }
   6584 
   6585         /* Program software DVP to NHI/ECMP */
   6586         rv = bcmi_gh2_vxlan_ingress_dvp_set(unit, vp, mpath_flag,
   6587                                             vp_nh_ecmp_index, vxlan_port);
   6588         if (BCM_FAILURE(rv)) {
   6589             if (vp_nh_ecmp_index != -1) {
   6590                 /* Decrement reference count */
   6591                 (void)bcm_xgs3_get_ref_count_from_nhi
   6592                             (unit, mpath_flag, &ref_count,
   6593                              vp_nh_ecmp_index);
   6594             }
   6595             return rv;
   6596         }
   6597 
   6598         /* Configure EGR Next Hop entry - Normal or L3MC view */
   6599         rv = bcmi_gh2_vxlan_nexthop_entry_modify(unit, vp_nh_ecmp_index,
   6600                                                  &egr_nh_info, new_entry_type);
   6601         if (BCM_FAILURE(rv)) {
   6602             if (vp_nh_ecmp_index != -1) {
   6603                 /* Decrement reference count */
   6604                 (void)bcm_xgs3_get_ref_count_from_nhi
   6605                             (unit, mpath_flag, &ref_count,
   6606                              vp_nh_ecmp_index);
   6607             }
   6608             return rv;
   6609         }
   6610     }
   6611 
   6612     return rv;
   6613 }
   6614 
   6615 /*
   6616  * Function:
   6617  *    bcmi_gh2_vxlan_port_nh_delete
   6618  * Purpose:
   6619  *    Delete VXLAN Next Hop entry
   6620  * Parameters:
   6621  *    unit - (IN) Device Number
   6622  *    vpn  - (IN) VPN instance ID
   6623  *    vp   - (IN) vxlan virtual port
   6624  * Returns:
   6625  *    BCM_E_XXX
   6626  */
   6627 STATIC int
   6628 bcmi_gh2_vxlan_port_nh_delete(int unit, bcm_vpn_t vpn, int vp)
   6629 {
   6630     uint32 flags = 0;
   6631     int  ref_count = 0;
   6632     uint32 vp_type = 0;
   6633     int ecmp = -1;
   6634     int nh_ecmp_index = -1;
   6635     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   6636     gh2_vxlan_vp_info_t *vp_info;
   6637 
   6638     /* Get VXLAN bookkeeping info instance */
   6639     BCM_IF_ERROR_RETURN(
   6640         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   6641 
   6642     /* GH2 requires to retrieve vp to ecmp or nhi from software database */
   6643     vp_info = &(vxlan_info->vxlan_vp_info[vp]);
   6644     vp_type = vp_info->vp_type;
   6645     ecmp = vp_info->ecmp;
   6646     nh_ecmp_index = vp_info->nh_ecmp_index;
   6647 
   6648     if (ecmp) {
   6649         flags = BCM_L3_MULTIPATH;
   6650         /* Decrease reference count */
   6651         BCM_IF_ERROR_RETURN(
   6652             bcm_xgs3_get_ref_count_from_nhi(unit, flags,
   6653                                             &ref_count, nh_ecmp_index));
   6654         if (ref_count == 1) {
   6655             if (vp_type == GH2_VXLAN_DEST_VP_TYPE_TUNNEL) {
   6656                 /* support ecmp on network port only */
   6657                 BCM_IF_ERROR_RETURN(
   6658                     bcmi_gh2_vxlan_ecmp_port_egress_nexthop_reset
   6659                     (unit, (nh_ecmp_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit)),
   6660                      vp_type, vp, vpn));
   6661             }
   6662         }
   6663     } else {
   6664         if (nh_ecmp_index != 0) {
   6665             /* Decrease reference count */
   6666             BCM_IF_ERROR_RETURN(
   6667                 bcm_xgs3_get_ref_count_from_nhi(unit, flags,
   6668                                                 &ref_count, nh_ecmp_index));
   6669         }
   6670 
   6671         if (ref_count == 1) {
   6672             if (nh_ecmp_index) {
   6673                 BCM_IF_ERROR_RETURN(
   6674                     bcmi_gh2_vxlan_port_egress_nexthop_reset
   6675                         (unit, nh_ecmp_index, vp_type, vp, vpn));
   6676             }
   6677         } else if (ref_count == 2) {
   6678             /*
   6679              * Need to check if the NHI is used for ECMP group only when
   6680              * (ref_count == 2), if TRUE, we must reset VXLAN Egress NextHop.
   6681              */
   6682             if (nh_ecmp_index) {
   6683                 BCM_IF_ERROR_RETURN(
   6684                     bcm_esw_l3_egress_ecmp_traverse
   6685                         (unit, bcmi_gh2_vxlan_nexthop_ecmp_find,
   6686                          (void *)&nh_ecmp_index));
   6687             }
   6688         }
   6689     }
   6690 
   6691     /* Decrement VXLAN outer TPID ref count */
   6692     if (vp_info->tpid_valid) {
   6693         BCM_IF_ERROR_RETURN(
   6694             bcmi_gh2_vxlan_outer_tpid_ref_dec(unit, vp_info->tpid_value));
   6695     }
   6696 
   6697     /* Clear software database for vp_info */
   6698     vp_info->vp_type = GH2_VXLAN_DEST_VP_TYPE_INVALID;
   6699     vp_info->vfi = -1;
   6700     vp_info->ecmp = 0;
   6701     vp_info->nh_ecmp_index = 0;
   6702     vp_info->tpid_valid= 0;
   6703     vp_info->tpid_value = 0x0;
   6704 
   6705     return BCM_E_NONE;
   6706 }
   6707 
   6708 /*
   6709  * Function:
   6710  *    bcmi_gh2_vxlan_port_nh_get
   6711  * Purpose:
   6712  *    Get VXLAN Next Hop entry
   6713  * Parameters:
   6714  *    unit - (IN) Device Number
   6715  *    vpn  - (IN) VPN instance ID
   6716  *    vp   - (IN) vxlan virtual port
   6717  *    vxlan_port - (IN/OUT) vxlan_port information
   6718  * Returns:
   6719  *      BCM_E_XXX
   6720  */
   6721 STATIC int
   6722 bcmi_gh2_vxlan_port_nh_get(
   6723     int unit,
   6724     bcm_vpn_t vpn,
   6725     int vp,
   6726     bcm_vxlan_port_t *vxlan_port)
   6727 {
   6728     int nh_ecmp_index = 0, tunnel_index = 0, udp_src_port_range_enable = 0;
   6729     uint32 ecmp = 0;
   6730     uint32 entry_type;
   6731     egr_l3_next_hop_entry_t egr_nh_entry;
   6732     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   6733     gh2_vxlan_vp_info_t *vp_info;
   6734 
   6735     /* Input parameter check */
   6736     if (NULL == vxlan_port) {
   6737         return BCM_E_PARAM;
   6738     }
   6739 
   6740     /* Get VXLAN bookkeeping info instance */
   6741     BCM_IF_ERROR_RETURN(
   6742         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   6743 
   6744     /* Clear egr_nh_entry */
   6745     sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry));
   6746 
   6747     /* Get SW VP info */
   6748     vp_info = &(vxlan_info->vxlan_vp_info[vp]);
   6749 
   6750     if (vp_info->vp_type == GH2_VXLAN_DEST_VP_TYPE_TUNNEL) {
   6751         /* Egress into VXLAN tunnel, find the tunnel_if */
   6752         vxlan_port->flags |= BCM_VXLAN_PORT_EGRESS_TUNNEL;
   6753 
   6754         ecmp = vp_info->ecmp;
   6755         nh_ecmp_index = vp_info->nh_ecmp_index;
   6756         if (ecmp) {
   6757             /* Extract next hop index from multipath egress object */
   6758             vxlan_port->egress_if =
   6759                 (nh_ecmp_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit));
   6760 
   6761             /* Get ecmp's first member nexthop index */
   6762             BCM_IF_ERROR_RETURN(
   6763                 bcmi_gh2_vxlan_ecmp_member_egress_get_first
   6764                     (unit, vxlan_port->egress_if, &nh_ecmp_index));
   6765         } else {
   6766             /* Extract next hop index from unipath egress object */
   6767             vxlan_port->egress_if =
   6768                 (nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit));
   6769         }
   6770 
   6771         BCM_IF_ERROR_RETURN(
   6772             soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   6773                          nh_ecmp_index, &egr_nh_entry));
   6774 
   6775     } else if (vp_info->vp_type == GH2_VXLAN_DEST_VP_TYPE_ACCESS) {
   6776         /* Egress into Access-side, find the tunnel_if */
   6777         nh_ecmp_index = vp_info->nh_ecmp_index;
   6778 
   6779         /* Extract next hop index from unipath egress object. */
   6780         vxlan_port->egress_if =
   6781             (nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit));
   6782 
   6783         BCM_IF_ERROR_RETURN(
   6784             soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   6785                          nh_ecmp_index, &egr_nh_entry));
   6786     } else {
   6787         return BCM_E_NOT_FOUND;
   6788     }
   6789 
   6790     entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh_entry,
   6791                                      ENTRY_TYPEf);
   6792     if (entry_type == _BCM_VXLAN_EGR_NEXT_HOP_VXLAN_VIEW) {
   6793         /* Get Tunnel index */
   6794         tunnel_index =
   6795             soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
   6796                                 &egr_nh_entry, VXLAN__TUNNEL_INDEXf);
   6797 
   6798         BCM_IF_ERROR_RETURN(
   6799             bcmi_gh2_vxlan_egress_tunnel_get(unit, vxlan_port, tunnel_index));
   6800 
   6801         /* Get UDP source port range checking for Entropy */
   6802         udp_src_port_range_enable =
   6803             soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
   6804                                 &egr_nh_entry, VXLAN__UDP_SRC_PORT_RANGE_ENf);
   6805         if (udp_src_port_range_enable) {
   6806             vxlan_port->flags |= BCM_VXLAN_PORT_UDP_SRC_PORT_RANGE_ENABLE;
   6807         }
   6808     }
   6809 
   6810     if (vp_info->vp_type == GH2_VXLAN_DEST_VP_TYPE_TUNNEL) {
   6811         /* Must be BCM_VXLAN_PORT_ENCAP_LOCAL for GH2 */
   6812         vxlan_port->flags |= BCM_VXLAN_PORT_ENCAP_LOCAL;
   6813     }
   6814 
   6815     /* Get VXLAN vlan tag info */
   6816     (void)bcmi_gh2_vxlan_vlan_tag_get(unit, vxlan_port,
   6817                                       &egr_nh_entry, nh_ecmp_index);
   6818 
   6819     return BCM_E_NONE;
   6820 }
   6821 
   6822 /*
   6823  * Function:
   6824  *    bcmi_gh2_vxlan_port_untagged_profile_set
   6825  * Purpose:
   6826  *    Set  VLan profile per Physical port entry
   6827  * Parameters:
   6828  *    unit - (IN) Device Number
   6829  *    port - (IN) Physical port
   6830  * Returns:
   6831  *    BCM_E_XXX
   6832  */
   6833 STATIC int
   6834 bcmi_gh2_vxlan_port_untagged_profile_set(int unit, bcm_port_t port)
   6835 {
   6836     int rv = BCM_E_NONE;
   6837     bcm_vlan_action_set_t action;
   6838     uint32 ing_profile_idx = 0xffffffff;
   6839 
   6840     bcm_vlan_action_set_t_init(&action);
   6841     action.ut_outer = 0x0; /* No Op */
   6842     action.ut_inner = 0x0; /* No Op */
   6843 
   6844     rv = _bcm_trx_vlan_action_profile_entry_add(unit, &action,
   6845                                                 &ing_profile_idx);
   6846     if (BCM_FAILURE(rv)) {
   6847         return rv;
   6848     }
   6849 
   6850     rv = _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE,
   6851                                TAG_ACTION_PROFILE_PTRf, ing_profile_idx);
   6852 
   6853     return rv;
   6854 }
   6855 
   6856 /*
   6857  * Function:
   6858  *    bcmi_gh2_vxlan_port_untagged_profile_reset
   6859  * Purpose:
   6860  *    Reset  VLan profile per Physical port entry
   6861  * Parameters:
   6862  *    unit - (IN) Device Number
   6863  *    port  - (IN) Physical port
   6864  * Returns:
   6865  *    BCM_E_XXX
   6866  */
   6867 STATIC int
   6868 bcmi_gh2_vxlan_port_untagged_profile_reset(int unit, bcm_port_t port)
   6869 {
   6870     int rv = BCM_E_NONE;
   6871     int ing_profile_idx = -1;
   6872 
   6873     BCM_IF_ERROR_RETURN(
   6874         _bcm_esw_port_tab_get(unit, port, TAG_ACTION_PROFILE_PTRf,
   6875                               &ing_profile_idx));
   6876 
   6877     rv = _bcm_trx_vlan_action_profile_entry_delete(unit, ing_profile_idx);
   6878     if (BCM_FAILURE(rv)) {
   6879         return rv;
   6880     }
   6881 
   6882     rv = _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE,
   6883                                TAG_ACTION_PROFILE_PTRf, 0);
   6884 
   6885     return rv;
   6886 }
   6887 
   6888 /*
   6889  * Function:
   6890  *    bcmi_gh2_vxlan_match_vxlate_entry_set
   6891  * Purpose:
   6892  *    Set VXLAN Match Vxlate Entry
   6893  * Parameters:
   6894  *    unit - (IN) Device Number
   6895  *    vpn  - (IN) VPN instance ID
   6896  *    vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id)
   6897  *    vent - (IN) vlan xlate entry pointer
   6898  * Returns:
   6899  *    BCM_E_XXX
   6900  */
   6901 STATIC int
   6902 bcmi_gh2_vxlan_match_vxlate_entry_set(
   6903     int unit,
   6904     bcm_vpn_t vpn,
   6905     bcm_vxlan_port_t *vxlan_port,
   6906     uint32 *vent)
   6907 {
   6908     int rv = BCM_E_NONE;
   6909     int index = -1, added_index = -1;
   6910     soc_mem_t mem;
   6911     uint32 return_vent[SOC_MAX_MEM_WORDS];
   6912     int vfi = 0;
   6913 
   6914     mem = VLAN_XLATEm;
   6915 
   6916     soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1);
   6917     soc_mem_field32_set(unit, mem, vent, XLATE__MPLS_ACTIONf, 0x5); /* VFI */
   6918     soc_mem_field32_set(unit, mem, vent, XLATE__VFI_VALIDf, 0x1);
   6919     if (!(vxlan_port->flags & BCM_VXLAN_PORT_ENABLE_VLAN_CHECKS)) {
   6920         soc_mem_field32_set(unit, mem, vent, XLATE__DISABLE_VLAN_CHECKSf, 0x1);
   6921     }
   6922 
   6923     _BCM_VXLAN_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
   6924     soc_mem_field32_set(unit, mem, vent, XLATE__VFIf, vfi);
   6925 
   6926     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY,
   6927                         &index, vent, return_vent, 0);
   6928     if (BCM_SUCCESS(rv)) {
   6929         /* Existing VLAN_XLATE entry is found */
   6930         BCM_IF_ERROR_RETURN(
   6931             soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, vent));
   6932 
   6933         if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
   6934             added_index = index;
   6935         }
   6936     } else if (rv == BCM_E_NOT_FOUND) {
   6937         /* New VLAN_XLATE entry to be inserted */
   6938         if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
   6939             return BCM_E_NOT_FOUND;
   6940         }
   6941         BCM_IF_ERROR_RETURN(
   6942             soc_mem_insert(unit, mem, MEM_BLOCK_ALL, vent));
   6943 
   6944         /* Search inserted VLAN_XLATE entry index */
   6945         rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY,
   6946                             &index, vent, return_vent, 0);
   6947         added_index = index;
   6948     } else {
   6949         return rv;
   6950     }
   6951 
   6952     /* Increase ref_cnt for the specified VXLAN Vlan XLATE entry  */
   6953     if (added_index != -1) {
   6954         BCM_IF_ERROR_RETURN(
   6955             bcmi_gh2_vxlan_vlan_xlate_ref_inc(unit, added_index));
   6956     }
   6957 
   6958     return BCM_E_NONE;
   6959 }
   6960 
   6961 /*
   6962  * Function:
   6963  *    bcmi_gh2_vxlan_match_vxlate_entry_reset
   6964  * Purpose:
   6965  *    Reset VXLAN Match Vxlate Entry
   6966  * Parameters:
   6967  *    unit - (IN) Device Number
   6968  *    vpn  - (IN) VPN instance ID
   6969  *    vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id)
   6970  *    vent - (IN) vlan xlate entry pointer
   6971  * Returns:
   6972  *    BCM_E_XXX
   6973  */
   6974 STATIC int
   6975 bcmi_gh2_vxlan_match_vxlate_entry_reset(
   6976     int unit,
   6977     uint32 *vent)
   6978 {
   6979     int rv = BCM_E_NONE;
   6980     int index = -1, deleted_index = -1;
   6981     soc_mem_t mem;
   6982     uint32 return_vent[SOC_MAX_MEM_WORDS];
   6983     int ref_cnt = 0;
   6984 
   6985     mem = VLAN_XLATEm;
   6986 
   6987     soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1);
   6988     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY,
   6989                         &index, vent, return_vent, 0);
   6990     if (BCM_SUCCESS(rv)) {
   6991         /* Existing VLAN_XLATE entry is found */
   6992         deleted_index = index;
   6993     } else {
   6994         return rv;
   6995     }
   6996 
   6997     /* Decrease ref_cnt for the specified VXLAN Vlan XLATE entry  */
   6998     if (deleted_index != -1) {
   6999         BCM_IF_ERROR_RETURN(
   7000             bcmi_gh2_vxlan_vlan_xlate_ref_dec(unit, deleted_index, &ref_cnt));
   7001 
   7002         if (ref_cnt == 0) {
   7003             BCM_IF_ERROR_RETURN(
   7004                 soc_mem_delete(unit, mem, MEM_BLOCK_ALL, vent));
   7005         }
   7006     }
   7007 
   7008     return rv;
   7009 }
   7010 
   7011 /*
   7012  * Function:
   7013  *    bcmi_gh2_vxlan_trunk_table_set
   7014  * Purpose:
   7015  *    Configure VXLAN Trunk port entry
   7016  * Parameters:
   7017  *    unit - (IN) Device Number
   7018  *    port   - (IN) Trunk member port
   7019  *    tgid - (IN) Trunk group Id
   7020  *    vpn  - (IN) VPN instance ID
   7021  * Returns:
   7022  *    BCM_E_XXX
   7023  */
   7024 STATIC int
   7025 bcmi_gh2_vxlan_trunk_table_set(
   7026     int unit,
   7027     bcm_port_t port,
   7028     bcm_trunk_t tgid,
   7029     bcm_vpn_t vpn)
   7030 {
   7031     int rv = BCM_E_NONE;
   7032     source_trunk_map_table_entry_t trunk_map_entry;
   7033     bcm_module_t my_modid;
   7034     int src_trk_idx = -1;
   7035     int port_type;
   7036     int vfi = 0;
   7037 
   7038     if (tgid != BCM_TRUNK_INVALID) {
   7039         port_type = 1; /* TRUNK_PORT_TYPE */
   7040     } else {
   7041         return BCM_E_PARAM;
   7042     }
   7043 
   7044     if (vpn != BCM_VXLAN_VPN_INVALID) {
   7045         _BCM_VXLAN_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
   7046         if (!bcmi_gh2_vxlan_vfi_used_get(unit, vfi)) {
   7047             return BCM_E_NOT_FOUND;
   7048         }
   7049     } else {
   7050         return BCM_E_PARAM;
   7051     }
   7052 
   7053     /* Get module id for unit */
   7054     BCM_IF_ERROR_RETURN(
   7055         bcm_esw_stk_my_modid_get(unit, &my_modid));
   7056 
   7057     /* Get index to source trunk map table */
   7058     BCM_IF_ERROR_RETURN(
   7059         _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
   7060                                               port, &src_trk_idx));
   7061 
   7062     soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm);
   7063 
   7064     /* Read source trunk map table */
   7065     rv = soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY,
   7066                       src_trk_idx, &trunk_map_entry);
   7067     if (BCM_FAILURE(rv)) {
   7068         soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   7069         return rv;
   7070     }
   7071 
   7072     /* Set trunk group id */
   7073     soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry,
   7074                         TGIDf, tgid);
   7075 
   7076     /* Set port is part of Trunk group */
   7077     soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry,
   7078                         PORT_TYPEf, port_type);
   7079 
   7080     /* Set vfi to provide default VFI (for untag & ptag packets) */
   7081     soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry,
   7082                         VFIf, vfi);
   7083 
   7084     /* Disable VLAN check for SOURCE_TRUNK_MAP_TABLEm */
   7085     soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry,
   7086                         DISABLE_VLAN_CHECKSf, 1);
   7087 
   7088     /* Write entry to hw. */
   7089     rv = soc_mem_write(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ALL,
   7090                        src_trk_idx, &trunk_map_entry);
   7091 
   7092     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   7093 
   7094     return rv;
   7095 }
   7096 
   7097 
   7098 /*
   7099  * Function:
   7100  *    bcmi_gh2_vxlan_trunk_table_reset
   7101  * Purpose:
   7102  *    Reset VXLAN Trunk port entry
   7103  * Parameters:
   7104  *    unit    - (IN) Device Number
   7105  *    port   - (IN) Trunk member port
   7106  * Returns:
   7107  *    BCM_E_XXX
   7108  */
   7109 
   7110 STATIC int
   7111 bcmi_gh2_vxlan_trunk_table_reset(int unit, bcm_port_t port)
   7112 {
   7113     int rv = BCM_E_NONE;
   7114     source_trunk_map_table_entry_t trunk_map_entry;
   7115     bcm_module_t my_modid;
   7116     int src_trk_idx = -1;
   7117 
   7118     /* Get module id for unit. */
   7119     BCM_IF_ERROR_RETURN(
   7120         bcm_esw_stk_my_modid_get(unit, &my_modid));
   7121 
   7122     /* Get index to source trunk map table */
   7123     BCM_IF_ERROR_RETURN(
   7124         _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
   7125                                               port, &src_trk_idx));
   7126 
   7127     soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm);
   7128 
   7129     /* Read source trunk map table */
   7130     rv = soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY,
   7131                       src_trk_idx, &trunk_map_entry);
   7132     if (BCM_FAILURE(rv)) {
   7133         soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   7134         return rv;
   7135     }
   7136 
   7137     /* Set vfi */
   7138     soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry,
   7139                         VFIf, 0);
   7140 
   7141     soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry,
   7142                         DISABLE_VLAN_CHECKSf, 0);
   7143 
   7144     /* Write entry to hw */
   7145     rv = soc_mem_write(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ALL,
   7146                        src_trk_idx, &trunk_map_entry);
   7147 
   7148     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   7149 
   7150     return rv;
   7151 }
   7152 
   7153 /*
   7154  * Function:
   7155  *    bcmi_gh2_vxlan_trunk_member_delete
   7156  * Purpose:
   7157  *    Clear Trunk Port-membership when the members to be deleted.
   7158  * Parameters:
   7159  *    unit - (IN) Device Number
   7160  *    tgid - (IN)  Trunk Group ID
   7161  *    trunk_member_count - (IN) Count of Trunk members to be deleted
   7162  *    trunk_member_array - (IN) Trunk member gports to be deleted
   7163 */
   7164 int
   7165 bcmi_gh2_vxlan_trunk_member_delete(
   7166     int unit,
   7167     bcm_trunk_t trunk_id,
   7168     int trunk_member_count,
   7169     bcm_port_t *trunk_member_array)
   7170 {
   7171     int rv = BCM_E_NONE, rv2 = BCM_E_NONE;
   7172     int idx = 0;
   7173     int value;
   7174     bcm_port_t local_member;
   7175 
   7176     if (NULL == trunk_member_array) {
   7177         return BCM_E_PARAM;
   7178     }
   7179 
   7180     rv = _bcm_trunk_id_validate(unit, trunk_id);
   7181     if (BCM_FAILURE(rv)) {
   7182         return BCM_E_PORT;
   7183     }
   7184 
   7185     for (idx = 0; idx < trunk_member_count; idx++) {
   7186         rv2 = bcm_esw_port_local_get(unit, trunk_member_array[idx],
   7187                                      &local_member);
   7188         /* Only support trunk local ports for trunk match */
   7189         if (BCM_FAILURE(rv2)) {
   7190             continue;
   7191         }
   7192         (void)_bcm_esw_port_tab_get(unit, local_member,
   7193                                     PORT_OPERATIONf, &value);
   7194         if (value == GH2_VXLAN_PORT_OPERATION_VFI) {
   7195             (void)_bcm_esw_port_tab_set(unit, local_member,
   7196                                         _BCM_CPU_TABS_NONE, PORT_OPERATIONf,
   7197                                         GH2_VXLAN_PORT_OPERATION_NORMAL);
   7198             BCM_IF_ERROR_RETURN(
   7199                 bcmi_gh2_vxlan_trunk_table_reset(unit, local_member));
   7200         }
   7201     }
   7202 
   7203     return rv;
   7204 }
   7205 
   7206 /*
   7207  * Function:
   7208  *    bcmi_gh2_vxlan_riot_custom_header_add
   7209  * Purpose:
   7210  *    Add Custom Header entry for 2-Pass VXLAN RIOT support.
   7211  * Parameters:
   7212  *    unit           - (IN) Device Number
   7213  *    vxlan_port     - (IN) vxlan_port information
   7214  *    old_vxlan_port - (IN) old vxlan_port information (for replace)
   7215  *    vp             - (IN) Source Virtual Port
   7216  * Returns:
   7217  *    BCM_X_XXX
   7218  */
   7219 STATIC int
   7220 bcmi_gh2_vxlan_riot_custom_header_add(
   7221     int unit,
   7222     bcm_vxlan_port_t *vxlan_port,
   7223     bcm_vxlan_port_t *old_vxlan_port,
   7224     int vp)
   7225 {
   7226     int rv = BCM_E_NONE;
   7227     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   7228     gh2_vxlan_vp_info_t *vp_info;
   7229     bcm_switch_match_control_info_t match_control_info;
   7230     bcm_switch_encap_info_t encap_info;
   7231     bcm_module_t mod_out = -1;
   7232     bcm_port_t port_out = -1;
   7233     bcm_trunk_t trunk_id = -1;
   7234     int gport_id = -1;
   7235     int local_port_out[SOC_MAX_NUM_PORTS];
   7236     int local_member_count = 0;
   7237     int port_idx = 0;
   7238     bcm_if_t encap_id;
   7239     int index_array[2];
   7240     bcm_module_t lmodid;
   7241     int egr_gpp_index = 0;
   7242     egr_gpp_attributes_entry_t egr_gpp_entry;
   7243     int i;
   7244     int is_ipmc;
   7245     int match_id_ipmc, match_id_non_ipmc;
   7246     int *match_id_ptr;
   7247     bcm_switch_match_config_info_t match_info;
   7248     bcm_switch_match_service_t match_service;
   7249     uint32 match_id_hw;
   7250     custom_header_policy_table_entry_t policy_entry;
   7251     int mode = 0;
   7252     int qos_map_ptr = 0;
   7253 
   7254     /* Input parameter check */
   7255     if ((NULL == vxlan_port) || (NULL == old_vxlan_port)) {
   7256         return BCM_E_PARAM;
   7257     }
   7258 
   7259     /* Get VXLAN bookkeeping info instance */
   7260     BCM_IF_ERROR_RETURN(
   7261         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   7262 
   7263     if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
   7264         /* Delete old VP related Custom Header configurations */
   7265         BCM_IF_ERROR_RETURN(
   7266             bcmi_gh2_vxlan_riot_custom_header_delete(unit,
   7267                                                      old_vxlan_port, vp));
   7268     }
   7269 
   7270     /*
   7271      * Set Custom Header match mask value (global) when
   7272      * VXLAN RIOT enabled (for GH2-B0 only)
   7273      */
   7274     if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) {
   7275         /* Get current Custom Header match mask value (global) */
   7276         bcm_switch_match_control_info_t_init(&match_control_info);
   7277 
   7278         BCM_IF_ERROR_RETURN(
   7279             bcm_esw_switch_match_control_get(
   7280                 unit, bcmSwitchMatchServiceCustomHeader,
   7281                 bcmSwitchMatchControlMatchMask,
   7282                 0, &match_control_info));
   7283 
   7284         if (match_control_info.mask32 != GH2_VXLAN_RIOT_CH_HEADER_MASK) {
   7285             bcm_switch_match_control_info_t_init(&match_control_info);
   7286             match_control_info.mask32 = GH2_VXLAN_RIOT_CH_HEADER_MASK;
   7287 
   7288             BCM_IF_ERROR_RETURN(
   7289                 bcm_esw_switch_match_control_set(
   7290                     unit, bcmSwitchMatchServiceCustomHeader,
   7291                     bcmSwitchMatchControlMatchMask,
   7292                     0, &match_control_info));
   7293         }
   7294     } else {
   7295         /*
   7296          * Create one dummy Custom Header encap entry with index = 0 :
   7297          * - the Custom Header index could not be 0 when using
   7298          *   the EGR_GPP_ATTRIBUTES
   7299          */
   7300         index_array[0] = 0; /* hw index = 0 */
   7301         BCM_IF_ERROR_RETURN(
   7302             _bcm_hr3_switch_encap_idx2id(unit,
   7303                                          _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER,
   7304                                          1, index_array, &encap_id));
   7305 
   7306         bcm_switch_encap_info_t_init(&encap_info);
   7307         BCM_IF_ERROR_RETURN(
   7308             bcm_esw_switch_encap_get(unit, encap_id, &encap_info));
   7309 
   7310         if (encap_info.value32 == 0) {
   7311             bcm_switch_encap_info_t_init(&encap_info);
   7312             encap_info.encap_service = BCM_SWITCH_ENCAP_SERVICE_CUSTOM_HEADER;
   7313             encap_info.value32 = GH2_VXLAN_RIOT_CH_HEADER_MASK;
   7314             BCM_IF_ERROR_RETURN(
   7315                 bcm_esw_switch_encap_create(unit, &encap_info, &encap_id));
   7316 
   7317             vxlan_info->riot_custom_header_index0_ref_count++;
   7318         } else if (encap_info.value32 == GH2_VXLAN_RIOT_CH_HEADER_MASK) {
   7319             vxlan_info->riot_custom_header_index0_ref_count++;
   7320         }
   7321     }
   7322 
   7323     /*
   7324      * For all VXLAN RIOT flow support (loopback, access or network ports),
   7325      * we must use vxlan_port->match_port for Custom Header related
   7326      * configurations
   7327      */
   7328     BCM_IF_ERROR_RETURN(
   7329         _bcm_esw_gport_resolve(unit, vxlan_port->match_port, &mod_out,
   7330                                &port_out, &trunk_id, &gport_id));
   7331 
   7332     sal_memset(local_port_out, 0, sizeof(local_port_out));
   7333     if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) {
   7334         /* Trunk port */
   7335         BCM_IF_ERROR_RETURN(
   7336             _bcm_esw_trunk_local_members_get(unit, trunk_id,
   7337                                              SOC_MAX_NUM_PORTS,
   7338                                              local_port_out,
   7339                                              &local_member_count));
   7340 
   7341         if ((vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_NONE) ||
   7342             (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_VN_ID)) {
   7343             vxlan_info->match_key[vp].trunk_id = trunk_id;
   7344             vxlan_info->match_key[vp].modid = -1;
   7345         }
   7346     } else {
   7347         /* Local port */
   7348         local_port_out[0] = port_out;
   7349         local_member_count++;
   7350 
   7351         if ((vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_NONE) ||
   7352             (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_VN_ID)) {
   7353             vxlan_info->match_key[vp].port = port_out;
   7354             vxlan_info->match_key[vp].modid = mod_out;
   7355             vxlan_info->match_key[vp].trunk_id = -1;
   7356         }
   7357     }
   7358 
   7359     /* Get current MY_MODID */
   7360     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &lmodid));
   7361 
   7362     vp_info = &(vxlan_info->vxlan_vp_info[vp]);
   7363     for (port_idx = 0; port_idx < local_member_count; port_idx++) {
   7364         if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) {
   7365             /*
   7366              * For Loopback Ports:
   7367              * - Enable Custom Header match/encap on loopbcak port
   7368              */
   7369 
   7370             /* Enable the capability of Custom Header match detection */
   7371             bcm_switch_match_control_info_t_init(&match_control_info);
   7372             match_control_info.port_enable = TRUE;
   7373             BCM_IF_ERROR_RETURN(
   7374                 bcm_esw_switch_match_control_set(
   7375                     unit, bcmSwitchMatchServiceCustomHeader,
   7376                     bcmSwitchMatchControlPortEnable,
   7377                     local_port_out[port_idx], &match_control_info));
   7378 
   7379             /* Enable the capability of Custom Header encapsulation */
   7380             BCM_IF_ERROR_RETURN(
   7381                 bcm_esw_port_control_set(
   7382                     unit, local_port_out[port_idx],
   7383                     bcmPortControlCustomHeaderEncapEnable, TRUE));
   7384         } else {
   7385             /*
   7386              * For Access or Network Ports:
   7387              * - Prepare Custom Header encap, match and policy entries:
   7388              *   Encap - 1 entry per access/network port
   7389              *   Match and Policy - 2 entries for each table
   7390              */
   7391 
   7392             /* Encap: Create one Custom Header encap */
   7393             bcm_switch_encap_info_t_init(&encap_info);
   7394             encap_info.encap_service = BCM_SWITCH_ENCAP_SERVICE_CUSTOM_HEADER;
   7395             encap_info.value32 =
   7396                 GH2_VXLAN_RIOT_CH_ENCAP_VALUE(0, lmodid,
   7397                                               local_port_out[port_idx]);
   7398             rv = bcm_esw_switch_encap_create(unit, &encap_info, &encap_id);
   7399             if (BCM_SUCCESS(rv) || rv == BCM_E_EXISTS) {
   7400                 if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) ==
   7401                     _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER) {
   7402                     BCM_IF_ERROR_RETURN(
   7403                         _bcm_hr3_switch_encap_id2idx(unit, encap_id, 1,
   7404                                                      index_array));
   7405                 } else {
   7406                     return BCM_E_INTERNAL;
   7407                 }
   7408 
   7409                 if (rv == BCM_E_EXISTS) {
   7410                     /* Increase ref_cnt */
   7411                     _bcm_common_profile_mem_ref_cnt_update
   7412                         (unit, EGR_HEADER_ENCAP_DATAm, index_array[0], 1);
   7413                 }
   7414             } else {
   7415                 return rv;
   7416             }
   7417 
   7418             /* Encap: Program EGR_GPP_ATTRIBUTES table with created encap_id */
   7419             /*
   7420              * Assign Custom Header index using the EGR_GPP_ATTRIBUTES:
   7421              * - egr_gpp_index = EGR_GPP_ATTRIBUTES_MODBASE[my_modid].BASE +
   7422              *                   source tgid or egress port
   7423              * - EGR_GPP_ATTRIBUTES[egr_gpp_index].CUSTOM_HEADER_INDEXf =
   7424              *   index_array[0] (Custom Header index)
   7425              */
   7426             BCM_IF_ERROR_RETURN(
   7427                 _bcm_esw_src_mod_port_table_index_get(unit, lmodid,
   7428                                                       local_port_out[port_idx],
   7429                                                       &egr_gpp_index));
   7430             BCM_IF_ERROR_RETURN(
   7431                 READ_EGR_GPP_ATTRIBUTESm(unit, MEM_BLOCK_ANY,
   7432                                          egr_gpp_index, &egr_gpp_entry));
   7433             soc_mem_field32_set(unit, EGR_GPP_ATTRIBUTESm, &egr_gpp_entry,
   7434                                 CUSTOM_HEADER_INDEXf, (uint32)index_array[0]);
   7435             BCM_IF_ERROR_RETURN(
   7436                 WRITE_EGR_GPP_ATTRIBUTESm(unit, MEM_BLOCK_ALL,
   7437                                           egr_gpp_index, &egr_gpp_entry));
   7438 
   7439             vp_info->ch_encap_id = encap_id;
   7440 
   7441 
   7442             /* QoS mapping: get current DSCP map mode on this port */
   7443             BCM_IF_ERROR_RETURN(
   7444                 bcm_esw_port_dscp_map_mode_get(unit,
   7445                                                local_port_out[port_idx],
   7446                                                &mode));
   7447             if (mode == BCM_PORT_DSCP_MAP_NONE) {
   7448                 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set
   7449                     (unit, local_port_out[port_idx], _BCM_CPU_TABS_NONE,
   7450                      USE_CUSTOM_HEADER_FOR_PRIf,
   7451                      GH2_VXLAN_RIOT_CH_COS_REMAP_INT_PRI_MAP));
   7452 
   7453                 BCM_IF_ERROR_RETURN(
   7454                     _bcm_esw_port_tab_get(unit, local_port_out[port_idx],
   7455                                           TRUST_DOT1P_PTRf, &qos_map_ptr));
   7456             } else {
   7457                 /* trust incoming IPv4/IPv6 DSCP */
   7458                 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set
   7459                     (unit, local_port_out[port_idx], _BCM_CPU_TABS_NONE,
   7460                      USE_CUSTOM_HEADER_FOR_PRIf,
   7461                      GH2_VXLAN_RIOT_CH_COS_REMAP_DSCP_QOS_MAP));
   7462 
   7463                 qos_map_ptr = local_port_out[port_idx];
   7464             }
   7465 
   7466             /* Match and Policy: Setup two Custom Header match and policy */
   7467             for (i = 0; i < 2; i++) {
   7468                 is_ipmc = i; /* i = 0: non-IPMC, i = 1: IPMC */
   7469 
   7470                 /* Setup Custom Header match */
   7471                 match_id_ptr = (is_ipmc) ? &match_id_ipmc : &match_id_non_ipmc;
   7472 
   7473                 bcm_switch_match_config_info_t_init(&match_info);
   7474                 match_info.value32 =
   7475                     GH2_VXLAN_RIOT_CH_ENCAP_VALUE((is_ipmc) ? 1 : 0, lmodid,
   7476                                                   local_port_out[port_idx]);
   7477                 rv = bcm_esw_switch_match_config_add
   7478                          (unit, bcmSwitchMatchServiceCustomHeader,
   7479                           &match_info, match_id_ptr);
   7480                 if (BCM_SUCCESS(rv) || rv == BCM_E_EXISTS) {
   7481                     BCM_IF_ERROR_RETURN(
   7482                         bcmi_switch_match_hw_id_get(
   7483                             unit, *match_id_ptr, &match_service,
   7484                             &match_id_hw));
   7485                     if (match_service != bcmSwitchMatchServiceCustomHeader) {
   7486                         return BCM_E_INTERNAL;
   7487                     }
   7488 
   7489                     if (rv == BCM_E_EXISTS) {
   7490                         /* Increase ref_cnt */
   7491                         _bcm_common_profile_mem_ref_cnt_update
   7492                             (unit, CUSTOM_HEADER_MATCHm, (int)match_id_hw, 1);
   7493                     }
   7494                 } else {
   7495                     return rv;
   7496                 }
   7497 
   7498                 /* Setup Custom Header policy table */
   7499                 sal_memset(&policy_entry, 0, sizeof(policy_entry));
   7500 
   7501                 SOC_IF_ERROR_RETURN(
   7502                     soc_mem_read(unit, CUSTOM_HEADER_POLICY_TABLEm,
   7503                                  MEM_BLOCK_ANY, match_id_hw, &policy_entry));
   7504 
   7505                 soc_mem_field32_set(unit, CUSTOM_HEADER_POLICY_TABLEm,
   7506                                     &policy_entry, VALIDf, 1);
   7507                 soc_mem_field32_set(unit, CUSTOM_HEADER_POLICY_TABLEm,
   7508                                     &policy_entry, REPLACE_SGPPf, 1);
   7509                 soc_mem_field32_set(unit, CUSTOM_HEADER_POLICY_TABLEm,
   7510                                     &policy_entry, VFI_INVALIDf,
   7511                                     (is_ipmc) ? 1 : 0);
   7512 
   7513                 /* Setup Custom Header QoS mapping */
   7514                 soc_mem_field32_set(unit, CUSTOM_HEADER_POLICY_TABLEm,
   7515                                     &policy_entry, QOS_MAPPING_PTRf,
   7516                                     qos_map_ptr);
   7517 
   7518                 SOC_IF_ERROR_RETURN(
   7519                     soc_mem_write(unit, CUSTOM_HEADER_POLICY_TABLEm,
   7520                                   MEM_BLOCK_ALL, match_id_hw, &policy_entry));
   7521             }
   7522 
   7523             vp_info->ch_match_id_ipmc = match_id_ipmc;
   7524             vp_info->ch_match_id_non_ipmc = match_id_non_ipmc;
   7525         }
   7526 
   7527     }
   7528 
   7529     return BCM_E_NONE;
   7530 }
   7531 
   7532 /*
   7533  * Function:
   7534  *    bcmi_gh2_vxlan_riot_custom_header_delete
   7535  * Purpose:
   7536  *    Delete Custom Header entry for 2-Pass VXLAN RIOT support.
   7537  * Parameters:
   7538  *    unit       - (IN) Device Number
   7539  *    vxlan_port - (IN) vxlan_port information
   7540  *    vp         - (IN) Source Virtual Port
   7541  * Returns:
   7542  *    BCM_X_XXX
   7543  */
   7544 STATIC int
   7545 bcmi_gh2_vxlan_riot_custom_header_delete(
   7546     int unit,
   7547     bcm_vxlan_port_t *vxlan_port,
   7548     int vp)
   7549 {
   7550     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   7551     gh2_vxlan_vp_info_t *vp_info;
   7552     _bcm_port_info_t *port_info;
   7553     bcm_switch_match_control_info_t match_control_info;
   7554     bcm_switch_encap_info_t encap_info;
   7555     int index_array[2];
   7556     bcm_if_t encap_id;
   7557     bcm_module_t mod_out = -1;
   7558     bcm_port_t port_out = -1;
   7559     bcm_trunk_t trunk_id = -1;
   7560     int gport_id = -1;
   7561     int local_port_out[SOC_MAX_NUM_PORTS];
   7562     int local_member_count = 0;
   7563     int port_idx = 0;
   7564     int i;
   7565     int is_ipmc;
   7566     int match_id_ptr;
   7567     bcm_switch_match_service_t match_service;
   7568     uint32 match_id_hw;
   7569     custom_header_policy_table_entry_t policy_entry;
   7570     bcm_module_t lmodid;
   7571     int egr_gpp_index = 0;
   7572     egr_gpp_attributes_entry_t egr_gpp_entry;
   7573     int ref_count = 0;
   7574 
   7575     /* Input parameter check */
   7576     if (NULL == vxlan_port) {
   7577         return BCM_E_PARAM;
   7578     }
   7579 
   7580     /* Get VXLAN bookkeeping info instance */
   7581     BCM_IF_ERROR_RETURN(
   7582         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   7583 
   7584     /*
   7585      * Delete dummy Custom Header encap entry with index = 0 :
   7586      * - the Custom Header index could not be 0 when using
   7587      *   the EGR_GPP_ATTRIBUTES
   7588      */
   7589     if (!(vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK)) {
   7590         index_array[0] = 0; /* hw index = 0 */
   7591         BCM_IF_ERROR_RETURN(
   7592             _bcm_hr3_switch_encap_idx2id(unit,
   7593                                          _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER,
   7594                                          1, index_array, &encap_id));
   7595 
   7596         bcm_switch_encap_info_t_init(&encap_info);
   7597         BCM_IF_ERROR_RETURN(
   7598             bcm_esw_switch_encap_get(unit, encap_id, &encap_info));
   7599 
   7600         if (encap_info.value32 == GH2_VXLAN_RIOT_CH_HEADER_MASK) {
   7601             if (vxlan_info->riot_custom_header_index0_ref_count >= 1) {
   7602                 vxlan_info->riot_custom_header_index0_ref_count--;
   7603             }
   7604 
   7605             if (vxlan_info->riot_custom_header_index0_ref_count == 0) {
   7606                 BCM_IF_ERROR_RETURN(
   7607                     bcm_esw_switch_encap_destroy(unit, encap_id));
   7608             }
   7609         }
   7610     }
   7611 
   7612     BCM_IF_ERROR_RETURN(
   7613         _bcm_esw_gport_resolve(unit, vxlan_port->match_port, &mod_out,
   7614                                &port_out, &trunk_id, &gport_id));
   7615 
   7616     sal_memset(local_port_out, 0, sizeof(local_port_out));
   7617     if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) {
   7618         /* Trunk port */
   7619         BCM_IF_ERROR_RETURN(
   7620             _bcm_esw_trunk_local_members_get(unit, trunk_id,
   7621                                              SOC_MAX_NUM_PORTS,
   7622                                              local_port_out,
   7623                                              &local_member_count));
   7624     } else {
   7625         /* Local port */
   7626         local_port_out[0] = port_out;
   7627         local_member_count++;
   7628     }
   7629 
   7630     vp_info = &(vxlan_info->vxlan_vp_info[vp]);
   7631     for (port_idx = 0; port_idx < local_member_count; port_idx++) {
   7632         /* Get current VP count on this local port */
   7633         _bcm_port_info_access(unit, local_port_out[port_idx], &port_info);
   7634 
   7635         if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) {
   7636                 /*
   7637                  * For Loopback Ports:
   7638                  * - Disable Custom Header match/encap when (vp_count == 1)
   7639                  *   on loopbcak port
   7640                  */
   7641             if (port_info->vp_count == 1) {
   7642                 /* Disable the capability of Custom Header match detection */
   7643                 bcm_switch_match_control_info_t_init(&match_control_info);
   7644                 match_control_info.port_enable = FALSE;
   7645                 BCM_IF_ERROR_RETURN(
   7646                     bcm_esw_switch_match_control_set(
   7647                         unit, bcmSwitchMatchServiceCustomHeader,
   7648                         bcmSwitchMatchControlPortEnable,
   7649                         local_port_out[port_idx], &match_control_info));
   7650 
   7651                 /* Disable the capability of Custom Header encapsulation */
   7652                 BCM_IF_ERROR_RETURN(
   7653                     bcm_esw_port_control_set(
   7654                         unit, local_port_out[port_idx],
   7655                         bcmPortControlCustomHeaderEncapEnable, FALSE));
   7656             }
   7657         } else {
   7658             /*
   7659              * For Access or Network Ports:
   7660              * - Destroy Custom Header encap, match and policy entries:
   7661              *   Encap - 1 entry per access/network port
   7662              *   Match and Policy - 2 entries for each table
   7663              */
   7664 
   7665             /* Encap: Delete Custom Header encap */
   7666             encap_id = vp_info->ch_encap_id;
   7667             if ((encap_id >> _BCM_SWITCH_ENCAP_SHIFT) ==
   7668                 _BCM_SWITCH_ENCAP_TYPE_CUSTOM_HEADER) {
   7669                 BCM_IF_ERROR_RETURN(
   7670                     _bcm_hr3_switch_encap_id2idx(unit, encap_id, 1,
   7671                                                  index_array));
   7672             } else {
   7673                 return BCM_E_INTERNAL;
   7674             }
   7675 
   7676             BCM_IF_ERROR_RETURN(
   7677                 _bcm_egr_header_encap_data_entry_ref_count_get
   7678                     (unit, (uint32)index_array[0], &ref_count));
   7679             if (ref_count >= 2) {
   7680                 /* Decrease ref_cnt */
   7681                 _bcm_common_profile_mem_ref_cnt_update
   7682                     (unit, EGR_HEADER_ENCAP_DATAm, index_array[0], -1);
   7683             } else {
   7684                 BCM_IF_ERROR_RETURN(
   7685                     bcm_esw_switch_encap_destroy(unit, encap_id));
   7686             }
   7687 
   7688             /* Match and Policy: Delete two Custom Header match and policy */
   7689             for (i = 0; i < 2; i++) {
   7690                 is_ipmc = i; /* i = 0: non-IPMC, i = 1: IPMC */
   7691 
   7692                 /* Setup Custom Header match */
   7693                 match_id_ptr = (is_ipmc) ? vp_info->ch_match_id_ipmc :
   7694                                            vp_info->ch_match_id_non_ipmc;
   7695 
   7696                 BCM_IF_ERROR_RETURN(
   7697                     bcmi_switch_match_hw_id_get(
   7698                         unit, match_id_ptr, &match_service, &match_id_hw));
   7699                 if (match_service != bcmSwitchMatchServiceCustomHeader) {
   7700                     return BCM_E_INTERNAL;
   7701                 }
   7702 
   7703                 BCM_IF_ERROR_RETURN(
   7704                     _bcm_custom_header_match_entry_ref_count_get
   7705                         (unit, match_id_hw, &ref_count));
   7706                 if (ref_count >= 2) {
   7707                     /* Decrease ref_cnt */
   7708                     _bcm_common_profile_mem_ref_cnt_update
   7709                         (unit, CUSTOM_HEADER_MATCHm, (int)match_id_hw, -1);
   7710                 } else {
   7711                     BCM_IF_ERROR_RETURN(
   7712                         bcm_esw_switch_match_config_delete(
   7713                             unit, bcmSwitchMatchServiceCustomHeader,
   7714                             match_id_ptr));
   7715                 }
   7716 
   7717                 /* Clear Custom Header policy table when (vp_count == 1) */
   7718                 if (port_info->vp_count == 1) {
   7719                     sal_memset(&policy_entry, 0, sizeof(policy_entry));
   7720                     SOC_IF_ERROR_RETURN(
   7721                         soc_mem_write(unit, CUSTOM_HEADER_POLICY_TABLEm,
   7722                                       MEM_BLOCK_ALL, match_id_hw,
   7723                                       &policy_entry));
   7724                 }
   7725             }
   7726 
   7727             if (port_info->vp_count == 1) {
   7728                 /* Encap: Reset related EGR_GPP_ATTRIBUTES table */
   7729                 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &lmodid));
   7730                 BCM_IF_ERROR_RETURN(
   7731                     _bcm_esw_src_mod_port_table_index_get
   7732                         (unit, lmodid, local_port_out[port_idx],
   7733                          &egr_gpp_index));
   7734                 BCM_IF_ERROR_RETURN(
   7735                     READ_EGR_GPP_ATTRIBUTESm(unit, MEM_BLOCK_ANY,
   7736                                              egr_gpp_index, &egr_gpp_entry));
   7737                 soc_mem_field32_set(unit, EGR_GPP_ATTRIBUTESm, &egr_gpp_entry,
   7738                                     CUSTOM_HEADER_INDEXf, 0x0);
   7739                 BCM_IF_ERROR_RETURN(
   7740                     WRITE_EGR_GPP_ATTRIBUTESm(unit, MEM_BLOCK_ALL,
   7741                                               egr_gpp_index, &egr_gpp_entry));
   7742 
   7743                 /* Reset Custom Header QoS mapping on this port */
   7744                 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set
   7745                     (unit, local_port_out[port_idx], _BCM_CPU_TABS_NONE,
   7746                      USE_CUSTOM_HEADER_FOR_PRIf,
   7747                      GH2_VXLAN_RIOT_CH_COS_REMAP_NONE));
   7748             }
   7749         }
   7750     }
   7751     vp_info->ch_encap_id = 0;
   7752     vp_info->ch_match_id_ipmc = 0;
   7753     vp_info->ch_match_id_non_ipmc = 0;
   7754 
   7755     return BCM_E_NONE;
   7756 }
   7757 
   7758 /*
   7759  * Function:
   7760  *    bcmi_gh2_vxlan_match_trunk_cleanup
   7761  * Purpose:
   7762  *    Helper function to clearnup VXLAN match trunk
   7763  * Parameters:
   7764  *    unit - (IN) Device Number
   7765  *    tgid - (IN) Trunk group Id
   7766  *    vpn  - (IN) VPN instance ID
   7767  *    port_out   - (IN) member ports array in trunk
   7768  *    port_count - (IN) trunk member port count
   7769  *    port_op    - (IN) Port operation for Normal/VFI
   7770  * Returns:
   7771  *    BCM_E_XXX
   7772  */
   7773 STATIC int
   7774  bcmi_gh2_vxlan_match_trunk_cleanup(
   7775     int unit,
   7776     bcm_trunk_t tgid,
   7777     bcm_vpn_t vpn,
   7778     int *port_out,
   7779     int port_count,
   7780     uint32 port_op)
   7781 {
   7782     int rv = BCM_E_NONE;
   7783     int port_idx = 0;
   7784     int *local_port_out = NULL;
   7785 
   7786     /* Input parameter check */
   7787     if (NULL == port_out) {
   7788         return BCM_E_PARAM;
   7789     }
   7790 
   7791     local_port_out = port_out;
   7792     port_idx = port_count;
   7793     if (port_op == GH2_VXLAN_PORT_OPERATION_NORMAL) {
   7794         for (; port_idx >= 0; port_idx--) {
   7795             (void)_bcm_esw_port_tab_set(unit, local_port_out[port_idx],
   7796                                         _BCM_CPU_TABS_NONE, PORT_OPERATIONf,
   7797                                         port_op);
   7798 
   7799             (void)bcmi_gh2_vxlan_trunk_table_reset(unit, local_port_out[port_idx]);
   7800         }
   7801     } else if (port_op == GH2_VXLAN_PORT_OPERATION_VFI) {
   7802         for (; port_idx >= 0; port_idx--) {
   7803             (void)_bcm_esw_port_tab_set(unit, local_port_out[port_idx],
   7804                                         _BCM_CPU_TABS_NONE, PORT_OPERATIONf,
   7805                                         port_op);
   7806 
   7807             (void)bcmi_gh2_vxlan_trunk_table_set(unit, local_port_out[port_idx],
   7808                                                  tgid, vpn);
   7809         }
   7810     } else {
   7811         return BCM_E_PARAM;
   7812     }
   7813 
   7814     return rv;
   7815 }
   7816 
   7817 /*
   7818  * Function:
   7819  *    bcmi_gh2_vxlan_match_trunk_add
   7820  * Purpose:
   7821  *    Assign SVP of VXLAN Trunk port
   7822  * Parameters:
   7823  *    unit - (IN) Device Number
   7824  *    tgid - (IN) Trunk group Id
   7825  *    vpn  - (IN) VPN instance ID
   7826  * Returns:
   7827  *    BCM_E_XXX
   7828  */
   7829 STATIC int
   7830  bcmi_gh2_vxlan_match_trunk_add(int unit, bcm_trunk_t tgid, bcm_vpn_t vpn)
   7831 {
   7832     int rv = BCM_E_NONE, rv2 = BCM_E_NONE;
   7833     int port_idx = 0;
   7834     int local_port_out[SOC_MAX_NUM_PORTS];
   7835     int local_member_count = 0;
   7836 
   7837     BCM_IF_ERROR_RETURN(
   7838         _bcm_esw_trunk_local_members_get(unit, tgid, SOC_MAX_NUM_PORTS,
   7839                                          local_port_out, &local_member_count));
   7840     for (port_idx = 0; port_idx < local_member_count; port_idx++) {
   7841         rv = bcmi_gh2_vxlan_trunk_table_set(unit, local_port_out[port_idx],
   7842                                             tgid, vpn);
   7843         if (BCM_FAILURE(rv)) {
   7844             rv2 = bcmi_gh2_vxlan_match_trunk_cleanup
   7845                       (unit, tgid, vpn, local_port_out, port_idx,
   7846                        GH2_VXLAN_PORT_OPERATION_NORMAL);
   7847             if (BCM_FAILURE(rv2)) {
   7848                 return rv2;
   7849             }
   7850 
   7851             return rv;
   7852         }
   7853         rv = _bcm_esw_port_tab_set(unit, local_port_out[port_idx],
   7854                                    _BCM_CPU_TABS_NONE,
   7855                                    PORT_OPERATIONf,
   7856                                    GH2_VXLAN_PORT_OPERATION_VFI);
   7857         if (BCM_FAILURE(rv)) {
   7858             rv2 = bcmi_gh2_vxlan_match_trunk_cleanup
   7859                       (unit, tgid, vpn, local_port_out, port_idx,
   7860                        GH2_VXLAN_PORT_OPERATION_NORMAL);
   7861             if (BCM_FAILURE(rv2)) {
   7862                 return rv2;
   7863             }
   7864 
   7865             return rv;
   7866         }
   7867 
   7868         rv = bcmi_gh2_vxlan_port_untagged_profile_set(
   7869             unit, local_port_out[port_idx]);
   7870         if (BCM_FAILURE(rv)) {
   7871             rv2 = bcmi_gh2_vxlan_match_trunk_cleanup
   7872                       (unit, tgid, vpn, local_port_out, port_idx,
   7873                        GH2_VXLAN_PORT_OPERATION_NORMAL);
   7874             if (BCM_FAILURE(rv2)) {
   7875                 return rv2;
   7876             }
   7877 
   7878             rv2 = bcmi_gh2_vxlan_port_untagged_profile_reset
   7879                       (unit, local_port_out[port_idx]);
   7880             if (BCM_FAILURE(rv2)) {
   7881                 return rv2;
   7882             }
   7883 
   7884             return rv;
   7885         }
   7886     }
   7887 
   7888     return rv;
   7889 }
   7890 
   7891 /*
   7892  * Function:
   7893  *    bcmi_gh2_vxlan_match_trunk_delete
   7894  * Purpose:
   7895  *    Remove SVP of VXLAN Trunk port
   7896  * Parameters:
   7897  *    unit - (IN) Device Number
   7898  *    tgid - (IN) Trunk group Id
   7899  *    vpn  - (IN) VPN instance ID
   7900  * Returns:
   7901  *    BCM_E_XXX
   7902  */
   7903 STATIC int
   7904 bcmi_gh2_vxlan_match_trunk_delete(int unit, bcm_trunk_t tgid, bcm_vpn_t vpn)
   7905 {
   7906     int rv = BCM_E_NONE, rv2 = BCM_E_NONE;
   7907     int port_idx = 0;
   7908     int local_port_out[SOC_MAX_NUM_PORTS];
   7909     int local_member_count = 0;
   7910 
   7911     BCM_IF_ERROR_RETURN(
   7912         _bcm_esw_trunk_local_members_get(unit, tgid, SOC_MAX_NUM_PORTS,
   7913                                          local_port_out, &local_member_count));
   7914 
   7915     for (port_idx = 0; port_idx < local_member_count; port_idx++) {
   7916         rv = bcmi_gh2_vxlan_trunk_table_reset(unit, local_port_out[port_idx]);
   7917         if (BCM_FAILURE(rv)) {
   7918             rv2 = bcmi_gh2_vxlan_match_trunk_cleanup
   7919                       (unit, tgid, vpn, local_port_out, port_idx,
   7920                        GH2_VXLAN_PORT_OPERATION_VFI);
   7921             if (BCM_FAILURE(rv2)) {
   7922                 return rv2;
   7923             }
   7924 
   7925             return rv;
   7926         }
   7927         rv = _bcm_esw_port_tab_set(unit, local_port_out[port_idx],
   7928                                    _BCM_CPU_TABS_NONE,
   7929                                    PORT_OPERATIONf,
   7930                                    GH2_VXLAN_PORT_OPERATION_NORMAL);
   7931         if (BCM_FAILURE(rv)) {
   7932             rv2 = bcmi_gh2_vxlan_match_trunk_cleanup
   7933                       (unit, tgid, vpn, local_port_out, port_idx,
   7934                        GH2_VXLAN_PORT_OPERATION_VFI);
   7935             if (BCM_FAILURE(rv2)) {
   7936                 return rv2;
   7937             }
   7938 
   7939             return rv;
   7940         }
   7941 
   7942         rv = bcmi_gh2_vxlan_port_untagged_profile_reset
   7943                   (unit, local_port_out[port_idx]);
   7944         if (BCM_FAILURE(rv)) {
   7945             rv2 = bcmi_gh2_vxlan_match_trunk_cleanup
   7946                       (unit, tgid, vpn, local_port_out, port_idx,
   7947                        GH2_VXLAN_PORT_OPERATION_VFI);
   7948             if (BCM_FAILURE(rv2)) {
   7949                 return rv2;
   7950             }
   7951 
   7952             return rv;
   7953         }
   7954     }
   7955 
   7956     return rv;
   7957 }
   7958 
   7959 /*
   7960  * Function:
   7961  *    bcmi_gh2_vxlan_match_clear
   7962  * Purpose:
   7963  *    Clear VXLAN Match Software State
   7964  * Parameters:
   7965  *    unit - (IN) Device Number
   7966  *    vp  - (IN) Source Virtual Port
   7967  * Returns:
   7968  *    void
   7969  */
   7970 STATIC void
   7971 bcmi_gh2_vxlan_match_clear(int unit, int vp)
   7972 {
   7973     int num_vp;
   7974     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info = GH2_VXLAN_INFO(unit);
   7975 
   7976     if (NULL == vxlan_info) {
   7977         return;
   7978     }
   7979 
   7980     num_vp = vxlan_info->num_vxlan_vp;
   7981     if ((vp < 0) || (vp >= num_vp)) {
   7982         return;
   7983     }
   7984 
   7985     vxlan_info->match_key[vp].flags = 0;
   7986     vxlan_info->match_key[vp].match_vlan = 0;
   7987     vxlan_info->match_key[vp].match_inner_vlan = 0;
   7988     vxlan_info->match_key[vp].trunk_id = -1;
   7989     vxlan_info->match_key[vp].port = 0;
   7990     vxlan_info->match_key[vp].modid = -1;
   7991     vxlan_info->match_key[vp].match_tunnel_index = 0;
   7992 
   7993     return;
   7994 }
   7995 
   7996 /*
   7997  * Function:
   7998  *    bcmi_gh2_vxlan_match_add
   7999  * Purpose:
   8000  *    Assign match criteria of an VXLAN port
   8001  * Parameters:
   8002  *    unit - (IN) Device Number
   8003  *    vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id)
   8004  *    vp   - (IN) Source Virtual Port
   8005  *    vpn  - (IN) VPN instance ID
   8006  * Returns:
   8007  *    BCM_E_XXX
   8008  */
   8009 int
   8010 bcmi_gh2_vxlan_match_add(
   8011     int unit,
   8012     bcm_vxlan_port_t *vxlan_port,
   8013     int vp,
   8014     bcm_vpn_t vpn)
   8015 {
   8016     int rv = BCM_E_NONE;
   8017     bcm_module_t mod_out = -1;
   8018     bcm_port_t port_out = -1;
   8019     bcm_trunk_t trunk_id = -1;
   8020     soc_mem_t mem;
   8021     uint32 vent[SOC_MAX_MEM_WORDS];
   8022     int src_trk_idx = 0; /* Source Trunk table index.*/
   8023     int gport_id = -1;
   8024     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   8025     int tunnel_idx = -1;
   8026     int vfi_index = -1;
   8027     gh2_vxlan_vpn_info_t *vfi_info;
   8028 
   8029     /* Input parameter check */
   8030     if (NULL == vxlan_port) {
   8031         return BCM_E_PARAM;
   8032     }
   8033 
   8034     /* Get VXLAN bookkeeping info instance */
   8035     BCM_IF_ERROR_RETURN(
   8036         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   8037 
   8038     if (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_NONE) {
   8039         vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_NONE;
   8040         return BCM_E_NONE;
   8041     }
   8042 
   8043     if (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_SHARE) {
   8044         /* there is no criteria to be configured for shared vp,
   8045            only updating software state to indicate this is a shared vp */
   8046         /* GH2 doesn't support SHARE criteria and flags */
   8047         return BCM_E_UNAVAIL;
   8048     }
   8049 
   8050     sal_memset(vent, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS));
   8051 
   8052     mem = VLAN_XLATEm;
   8053     /* To create additional IVXLT for Loopback VP (GH2-B0 only) */
   8054     if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) {
   8055         /* Loopback VP is only support when VXLAN RIOT is enabled */
   8056         if (!BCM_VLAN_VALID(vxlan_port->match_vlan)) {
   8057             return BCM_E_PARAM;
   8058         }
   8059 
   8060         soc_mem_field32_set(unit, mem, vent,
   8061                             KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_OVID);
   8062         soc_mem_field32_set(unit, mem, vent,
   8063                             XLATE__OVIDf, vxlan_port->match_vlan);
   8064         /* incoming port not used in lookup key, set field to all 1's */
   8065         soc_mem_field32_set(unit, mem, vent, XLATE__GLPf,
   8066                             SOC_VLAN_XLATE_GLP_WILDCARD(unit));
   8067 
   8068         rv = bcmi_gh2_vxlan_match_vxlate_entry_set(unit, vpn,
   8069                                                    vxlan_port, vent);
   8070         BCM_IF_ERROR_RETURN(rv);
   8071     }
   8072 
   8073     sal_memset(vent, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS));
   8074     if (vxlan_port->criteria != BCM_VXLAN_PORT_MATCH_VN_ID) {
   8075         rv = _bcm_esw_gport_resolve(unit, vxlan_port->match_port, &mod_out,
   8076                                     &port_out, &trunk_id, &gport_id);
   8077         BCM_IF_ERROR_RETURN(rv);
   8078 
   8079         if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) {
   8080             soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 0x1);
   8081             soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf, trunk_id);
   8082         } else {
   8083             soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf, mod_out);
   8084             soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf, port_out);
   8085         }
   8086     }
   8087 
   8088     if (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_PORT_VLAN) {
   8089         if (!BCM_VLAN_VALID(vxlan_port->match_vlan)) {
   8090             return BCM_E_PARAM;
   8091         }
   8092 
   8093         soc_mem_field32_set(unit, mem, vent,
   8094                             KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_OVID);
   8095         soc_mem_field32_set(unit, mem, vent,
   8096                             XLATE__OVIDf, vxlan_port->match_vlan);
   8097 
   8098         rv = bcmi_gh2_vxlan_match_vxlate_entry_set(unit, vpn,
   8099                                                    vxlan_port, vent);
   8100         BCM_IF_ERROR_RETURN(rv);
   8101 
   8102         if (vxlan_info->match_key[vp].flags !=
   8103             _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
   8104             vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_VLAN;
   8105             vxlan_info->match_key[vp].match_vlan = vxlan_port->match_vlan;
   8106             if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) {
   8107                 vxlan_info->match_key[vp].trunk_id = trunk_id;
   8108                 vxlan_info->match_key[vp].modid = -1;
   8109             } else {
   8110                 vxlan_info->match_key[vp].port = port_out;
   8111                 vxlan_info->match_key[vp].modid = mod_out;
   8112                 vxlan_info->match_key[vp].trunk_id = -1;
   8113             }
   8114         }
   8115 
   8116         if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
   8117             bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, 1);
   8118         }
   8119     } else if (vxlan_port->criteria ==
   8120         BCM_VXLAN_PORT_MATCH_PORT_INNER_VLAN) {
   8121         if (!BCM_VLAN_VALID(vxlan_port->match_inner_vlan)) {
   8122             return BCM_E_PARAM;
   8123         }
   8124 
   8125         soc_mem_field32_set(unit, mem, vent,
   8126                             KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_IVID);
   8127         soc_mem_field32_set(unit, mem, vent,
   8128                             XLATE__IVIDf, vxlan_port->match_inner_vlan);
   8129 
   8130         rv = bcmi_gh2_vxlan_match_vxlate_entry_set(unit, vpn,
   8131                                                    vxlan_port, vent);
   8132         BCM_IF_ERROR_RETURN(rv);
   8133 
   8134         if (vxlan_info->match_key[vp].flags !=
   8135             _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
   8136             vxlan_info->match_key[vp].flags =
   8137                 _BCM_VXLAN_PORT_MATCH_TYPE_INNER_VLAN;
   8138             vxlan_info->match_key[vp].match_inner_vlan =
   8139                 vxlan_port->match_inner_vlan;
   8140             if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) {
   8141                 vxlan_info->match_key[vp].trunk_id = trunk_id;
   8142                 vxlan_info->match_key[vp].modid = -1;
   8143             } else {
   8144                 vxlan_info->match_key[vp].port = port_out;
   8145                 vxlan_info->match_key[vp].modid = mod_out;
   8146                 vxlan_info->match_key[vp].trunk_id = -1;
   8147             }
   8148         }
   8149 
   8150         if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
   8151             bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, 1);
   8152         }
   8153     } else if (vxlan_port->criteria ==
   8154         BCM_VXLAN_PORT_MATCH_PORT_VLAN_STACKED) {
   8155         if (!BCM_VLAN_VALID(vxlan_port->match_vlan) ||
   8156             !BCM_VLAN_VALID(vxlan_port->match_inner_vlan)) {
   8157             return BCM_E_PARAM;
   8158         }
   8159 
   8160         soc_mem_field32_set(unit, mem, vent,
   8161                             KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_IVID_OVID);
   8162         soc_mem_field32_set(unit, mem, vent,
   8163                             XLATE__OVIDf, vxlan_port->match_vlan);
   8164         soc_mem_field32_set(unit, mem, vent,
   8165                             XLATE__IVIDf, vxlan_port->match_inner_vlan);
   8166 
   8167         rv = bcmi_gh2_vxlan_match_vxlate_entry_set(unit, vpn,
   8168                                                    vxlan_port, vent);
   8169         BCM_IF_ERROR_RETURN(rv);
   8170 
   8171         if (vxlan_info->match_key[vp].flags !=
   8172             _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
   8173             vxlan_info->match_key[vp].flags =
   8174                 _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_STACKED;
   8175             vxlan_info->match_key[vp].match_vlan =
   8176                 vxlan_port->match_vlan;
   8177             vxlan_info->match_key[vp].match_inner_vlan =
   8178                 vxlan_port->match_inner_vlan;
   8179             if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) {
   8180                 vxlan_info->match_key[vp].trunk_id = trunk_id;
   8181                 vxlan_info->match_key[vp].modid = -1;
   8182             } else {
   8183                 vxlan_info->match_key[vp].port = port_out;
   8184                 vxlan_info->match_key[vp].modid = mod_out;
   8185                 vxlan_info->match_key[vp].trunk_id = -1;
   8186             }
   8187         }
   8188 
   8189         if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
   8190             bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, 1);
   8191         }
   8192     } else if (vxlan_port->criteria ==
   8193         BCM_VXLAN_PORT_MATCH_VLAN_PRI) {
   8194 
   8195         soc_mem_field32_set(unit, mem, vent,
   8196                             KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_PRI_CFI);
   8197         /* match_vlan: Bits 12-15 contains VLAN_PRI + CFI, vlan = BCM_E_NONE */
   8198         soc_mem_field32_set(unit, mem, vent,
   8199                             XLATE__OTAGf, vxlan_port->match_vlan);
   8200 
   8201         rv = bcmi_gh2_vxlan_match_vxlate_entry_set(unit, vpn,
   8202                                                    vxlan_port, vent);
   8203         BCM_IF_ERROR_RETURN(rv);
   8204 
   8205         if (vxlan_info->match_key[vp].flags !=
   8206             _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
   8207             vxlan_info->match_key[vp].flags =
   8208                 _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_PRI;
   8209             vxlan_info->match_key[vp].match_vlan =
   8210                 vxlan_port->match_vlan;
   8211             if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) {
   8212                 vxlan_info->match_key[vp].trunk_id = trunk_id;
   8213                 vxlan_info->match_key[vp].modid = -1;
   8214             } else {
   8215                 vxlan_info->match_key[vp].port = port_out;
   8216                 vxlan_info->match_key[vp].modid = mod_out;
   8217                 vxlan_info->match_key[vp].trunk_id = -1;
   8218             }
   8219         }
   8220 
   8221         if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
   8222             bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, 1);
   8223         }
   8224     } else if (vxlan_port->criteria ==
   8225         BCM_VXLAN_PORT_MATCH_PORT) {
   8226         int is_local = 0, vfi = 0;
   8227 
   8228         if (vxlan_info->match_key[vp].flags ==
   8229             _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
   8230             return BCM_E_PARAM;
   8231         }
   8232 
   8233         if (BCM_GPORT_IS_TRUNK(vxlan_port->match_port)) {
   8234             BCM_IF_ERROR_RETURN(
   8235                 bcmi_gh2_vxlan_match_trunk_add(unit, trunk_id, vpn));
   8236             vxlan_info->match_key[vp].flags =
   8237                 _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK;
   8238             vxlan_info->match_key[vp].trunk_id = trunk_id;
   8239         } else {
   8240             BCM_IF_ERROR_RETURN(
   8241                 _bcm_esw_modid_is_local(unit, mod_out, &is_local));
   8242 
   8243             /* Get index to source trunk map table */
   8244             BCM_IF_ERROR_RETURN(
   8245                 _bcm_esw_src_mod_port_table_index_get(unit, mod_out,
   8246                                                       port_out, &src_trk_idx));
   8247 
   8248             /* Set vfi to provide default VFI (for untag & ptag packets) */
   8249             if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, VFIf)) {
   8250                 if (vpn != BCM_VXLAN_VPN_INVALID) {
   8251                     _BCM_VXLAN_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
   8252                     if (!bcmi_gh2_vxlan_vfi_used_get(unit, vfi)) {
   8253                         return BCM_E_NOT_FOUND;
   8254                     }
   8255                 } else {
   8256                     return BCM_E_PARAM;
   8257                 }
   8258                 /* Set vfi to provide default VFI (for untag & ptag packets) */
   8259                 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
   8260                                             src_trk_idx, VFIf, vfi);
   8261                 BCM_IF_ERROR_RETURN(rv);
   8262             }
   8263 
   8264             /* Disable VLAN check for SOURCE_TRUNK_MAP_TABLEm */
   8265             if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm,
   8266                                     DISABLE_VLAN_CHECKSf)) {
   8267                 rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
   8268                                             src_trk_idx, DISABLE_VLAN_CHECKSf,
   8269                                             1);
   8270                 BCM_IF_ERROR_RETURN(rv);
   8271             }
   8272 
   8273             if (is_local) {
   8274                 rv = _bcm_esw_port_tab_set(unit, vxlan_port->match_port,
   8275                                            _BCM_CPU_TABS_NONE,
   8276                                            PORT_OPERATIONf,
   8277                                            GH2_VXLAN_PORT_OPERATION_VFI);
   8278                 BCM_IF_ERROR_RETURN(rv);
   8279 
   8280                 /* Set TAG_ACTION_PROFILE_PTR */
   8281                 rv = bcmi_gh2_vxlan_port_untagged_profile_set(
   8282                     unit, vxlan_port->match_port);
   8283                 BCM_IF_ERROR_RETURN(rv);
   8284             }
   8285             /*
   8286              * The vp has been created based on trunk.
   8287              * When a new port is added into the trunk, a match will be
   8288              * added for the vp through bcm_port_match_add.
   8289              */
   8290             if ((vxlan_info->match_key[vp].flags !=
   8291                 _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK) &&
   8292                 (vxlan_info->match_key[vp].flags !=
   8293                 _BCM_VXLAN_PORT_MATCH_TYPE_SHARED)) {
   8294                 vxlan_info->match_key[vp].flags =
   8295                     _BCM_VXLAN_PORT_MATCH_TYPE_PORT;
   8296                 vxlan_info->match_key[vp].index = src_trk_idx;
   8297                 vxlan_info->match_key[vp].port = port_out;
   8298                 vxlan_info->match_key[vp].modid = mod_out;
   8299                 vxlan_info->match_key[vp].trunk_id = -1;
   8300             }
   8301         }
   8302     } else if (vxlan_port->criteria ==
   8303         BCM_VXLAN_PORT_MATCH_VN_ID) {
   8304 
   8305         if (!BCM_GPORT_IS_TUNNEL(vxlan_port->match_tunnel_id)) {
   8306             return BCM_E_BADID;
   8307         }
   8308 
   8309         tunnel_idx = BCM_GPORT_TUNNEL_ID_GET(vxlan_port->match_tunnel_id);
   8310         GH2_VXLAN_TUNNEL_ID_IF_INVALID_RETURN(unit, tunnel_idx);
   8311 
   8312         /* Configure Ingress VNID (use VLAN_XLATE) */
   8313         _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
   8314         /* Get VFI info for VN_ID */
   8315         vfi_info = &(vxlan_info->vxlan_vpn_info[vfi_index]);
   8316 
   8317         soc_mem_field32_set(unit, mem, vent,
   8318                             KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_VNID);
   8319         soc_mem_field32_set(unit, mem, vent,
   8320                             XLATE__VNIDf, vfi_info->vnid);
   8321         /* incoming port not used in lookup key, set field to all 1's */
   8322         soc_mem_field32_set(unit, mem, vent, XLATE__GLPf,
   8323                             SOC_VLAN_XLATE_GLP_WILDCARD(unit));
   8324 
   8325         rv = bcmi_gh2_vxlan_match_vxlate_entry_set(unit, vpn,
   8326                                                    vxlan_port, vent);
   8327         BCM_IF_ERROR_RETURN(rv);
   8328 
   8329         if (vxlan_info->match_key[vp].flags !=
   8330             _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
   8331             vxlan_info->match_key[vp].flags = _BCM_VXLAN_PORT_MATCH_TYPE_VNID;
   8332             vxlan_info->match_key[vp].match_tunnel_index = tunnel_idx;
   8333         }
   8334     }
   8335 
   8336     return rv;
   8337 }
   8338 
   8339 /*
   8340  * Function:
   8341  *    bcmi_gh2_vxlan_match_delete
   8342  * Purpose:
   8343  *    Delete match criteria of an VXLAN port
   8344  * Parameters:
   8345  *    unit - (IN) Device Number
   8346  *    vp   - (IN) Source Virtual Port
   8347  *    vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id)
   8348  *    vpn  - (IN) VPN instance ID
   8349  * Returns:
   8350  *    BCM_E_XXX
   8351  */
   8352 int
   8353 bcmi_gh2_vxlan_match_delete(
   8354     int unit,
   8355     int vp,
   8356     bcm_vxlan_port_t vxlan_port,
   8357     bcm_vpn_t vpn)
   8358 {
   8359     int rv = BCM_E_NONE;
   8360     soc_mem_t mem;
   8361     uint32 vent[SOC_MAX_MEM_WORDS];
   8362     bcm_trunk_t trunk_id;
   8363     int src_trk_idx = 0;   /* Source Trunk table index */
   8364     int mod_id_idx = 0;   /* Module_Id */
   8365     int port = 0;
   8366     bcm_module_t mod_out = -1;
   8367     bcm_port_t port_out = -1;
   8368     int gport_id = -1;
   8369     int vfi_index = -1;
   8370     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   8371     gh2_vxlan_vpn_info_t *vfi_info;
   8372 
   8373     /* Get VXLAN bookkeeping info instance */
   8374     BCM_IF_ERROR_RETURN(
   8375         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   8376 
   8377     sal_memset(vent, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS));
   8378 
   8379     mem = VLAN_XLATEm;
   8380     /* To delete additional IVXLT for Loopback VP (GH2-B0 only) */
   8381     if (vxlan_port.flags & BCM_VXLAN_PORT_LOOPBACK) {
   8382         /* Loopback VP is only support when VXLAN RIOT is enabled */
   8383         soc_mem_field32_set(unit, mem, vent,
   8384                             KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_OVID);
   8385         soc_mem_field32_set(unit, mem, vent,
   8386                             XLATE__OVIDf,
   8387                             vxlan_info->match_key[vp].match_vlan);
   8388         /* incoming port not used in lookup key, set field to all 1's */
   8389         soc_mem_field32_set(unit, mem, vent, XLATE__GLPf,
   8390                             SOC_VLAN_XLATE_GLP_WILDCARD(unit));
   8391 
   8392         rv = bcmi_gh2_vxlan_match_vxlate_entry_reset(unit, vent);
   8393         BCM_IF_ERROR_RETURN(rv);
   8394     }
   8395 
   8396     sal_memset(vent, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS));
   8397     if (vxlan_info->match_key[vp].flags == _BCM_VXLAN_PORT_MATCH_TYPE_VLAN) {
   8398         soc_mem_field32_set(unit, mem, vent,
   8399                             KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_OVID);
   8400         soc_mem_field32_set(unit, mem, vent,
   8401                             XLATE__OVIDf,
   8402                             vxlan_info->match_key[vp].match_vlan);
   8403         if (vxlan_info->match_key[vp].modid != -1) {
   8404             soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf,
   8405                                 vxlan_info->match_key[vp].modid);
   8406             soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf,
   8407                                 vxlan_info->match_key[vp].port);
   8408         } else {
   8409             soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 0x1);
   8410             soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf,
   8411                                 vxlan_info->match_key[vp].trunk_id);
   8412         }
   8413         rv = bcmi_gh2_vxlan_match_vxlate_entry_reset(unit, vent);
   8414         BCM_IF_ERROR_RETURN(rv);
   8415 
   8416         bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, -1);
   8417     } else if (vxlan_info->match_key[vp].flags ==
   8418         _BCM_VXLAN_PORT_MATCH_TYPE_INNER_VLAN) {
   8419         soc_mem_field32_set(unit, mem, vent,
   8420                             KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_IVID);
   8421         soc_mem_field32_set(unit, mem, vent,
   8422                             XLATE__IVIDf,
   8423                             vxlan_info->match_key[vp].match_inner_vlan);
   8424         if (vxlan_info->match_key[vp].modid != -1) {
   8425             soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf,
   8426                                 vxlan_info->match_key[vp].modid);
   8427             soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf,
   8428                                 vxlan_info->match_key[vp].port);
   8429         } else {
   8430             soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 0x1);
   8431             soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf,
   8432                                 vxlan_info->match_key[vp].trunk_id);
   8433         }
   8434         rv = bcmi_gh2_vxlan_match_vxlate_entry_reset(unit, vent);
   8435         BCM_IF_ERROR_RETURN(rv);
   8436 
   8437         bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, -1);
   8438     } else if (vxlan_info->match_key[vp].flags ==
   8439         _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_STACKED) {
   8440         soc_mem_field32_set(unit, mem, vent,
   8441                             KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_IVID_OVID);
   8442         soc_mem_field32_set(unit, mem, vent,
   8443                             XLATE__OVIDf,
   8444                             vxlan_info->match_key[vp].match_vlan);
   8445         soc_mem_field32_set(unit, mem, vent,
   8446                             XLATE__IVIDf,
   8447                             vxlan_info->match_key[vp].match_inner_vlan);
   8448         if (vxlan_info->match_key[vp].modid != -1) {
   8449             soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf,
   8450                                 vxlan_info->match_key[vp].modid);
   8451             soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf,
   8452                                 vxlan_info->match_key[vp].port);
   8453         } else {
   8454             soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 0x1);
   8455             soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf,
   8456                                 vxlan_info->match_key[vp].trunk_id);
   8457         }
   8458         rv = bcmi_gh2_vxlan_match_vxlate_entry_reset(unit, vent);
   8459         BCM_IF_ERROR_RETURN(rv);
   8460 
   8461         bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, -1);
   8462     } else if (vxlan_info->match_key[vp].flags ==
   8463         _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_PRI) {
   8464         soc_mem_field32_set(unit, mem, vent,
   8465                             KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_PRI_CFI);
   8466         soc_mem_field32_set(unit, mem, vent,
   8467                             XLATE__OTAGf,
   8468                             vxlan_info->match_key[vp].match_vlan);
   8469         if (vxlan_info->match_key[vp].modid != -1) {
   8470             soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf,
   8471                                 vxlan_info->match_key[vp].modid);
   8472             soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf,
   8473                                 vxlan_info->match_key[vp].port);
   8474         } else {
   8475             soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 0x1);
   8476             soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf,
   8477                                 vxlan_info->match_key[vp].trunk_id);
   8478         }
   8479         rv = bcmi_gh2_vxlan_match_vxlate_entry_reset(unit, vent);
   8480         BCM_IF_ERROR_RETURN(rv);
   8481 
   8482         bcmi_gh2_vxlan_port_match_count_adjust(unit, vp, -1);
   8483     } else if ((vxlan_info->match_key[vp].flags ==
   8484         _BCM_VXLAN_PORT_MATCH_TYPE_PORT) ||
   8485         ((vxlan_info->match_key[vp].flags ==
   8486         _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK) &&
   8487         (!BCM_GPORT_IS_TRUNK(vxlan_port.match_port)))) {
   8488 
   8489         if (vxlan_info->match_key[vp].flags ==
   8490             _BCM_VXLAN_PORT_MATCH_TYPE_PORT) {
   8491             src_trk_idx = vxlan_info->match_key[vp].index;
   8492         } else {
   8493             /*
   8494              * The vp has been created based on trunk.
   8495              * When a new port is deleted from the trunk, a match
   8496              * will be deleted for the vp through bcm_port_match_delete.
   8497              */
   8498             BCM_IF_ERROR_RETURN(
   8499                 _bcm_esw_gport_resolve(unit, vxlan_port.match_port, &mod_out,
   8500                                        &port_out, &trunk_id, &gport_id));
   8501             /* Get index to source trunk map table */
   8502             BCM_IF_ERROR_RETURN(
   8503                 _bcm_esw_src_mod_port_table_index_get(unit, mod_out,
   8504                                                       port_out, &src_trk_idx));
   8505         }
   8506 
   8507         /* Disable VFI */
   8508         if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, VFIf)) {
   8509             rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
   8510                                         src_trk_idx, VFIf, 0x0);
   8511             BCM_IF_ERROR_RETURN(rv);
   8512         }
   8513 
   8514         if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm,
   8515                                 DISABLE_VLAN_CHECKSf)) {
   8516             rv = soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_TABLEm,
   8517                                         src_trk_idx, DISABLE_VLAN_CHECKSf, 0x0);
   8518             BCM_IF_ERROR_RETURN(rv);
   8519         }
   8520 
   8521         mod_id_idx = vxlan_info->match_key[vp].modid;
   8522         port = vxlan_info->match_key[vp].port;
   8523         rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   8524                                      mod_id_idx, port, &mod_out, &port_out);
   8525         BCM_IF_ERROR_RETURN(rv);
   8526 
   8527         rv = _bcm_esw_port_tab_set(unit, port_out,
   8528                                    _BCM_CPU_TABS_NONE,
   8529                                    PORT_OPERATIONf,
   8530                                    GH2_VXLAN_PORT_OPERATION_NORMAL);
   8531         BCM_IF_ERROR_RETURN(rv);
   8532 
   8533         /* Reset TAG_ACTION_PROFILE_PTR */
   8534         rv = bcmi_gh2_vxlan_port_untagged_profile_reset(unit, port_out);
   8535         BCM_IF_ERROR_RETURN(rv);
   8536     } else if (vxlan_info->match_key[vp].flags ==
   8537         _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK) {
   8538         trunk_id = vxlan_info->match_key[vp].trunk_id;
   8539 
   8540         rv = bcmi_gh2_vxlan_match_trunk_delete(unit, trunk_id, vpn);
   8541         BCM_IF_ERROR_RETURN(rv);
   8542     } else if (vxlan_info->match_key[vp].flags ==
   8543         _BCM_VXLAN_PORT_MATCH_TYPE_VNID) {
   8544 
   8545         _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
   8546         /* Get VFI info for VN_ID */
   8547         vfi_info = &(vxlan_info->vxlan_vpn_info[vfi_index]);
   8548 
   8549         soc_mem_field32_set(unit, mem, vent,
   8550                             KEY_TYPEf, GH2_VLXLT_HASH_KEY_TYPE_VNID);
   8551         soc_mem_field32_set(unit, mem, vent,
   8552                             XLATE__VNIDf, vfi_info->vnid);
   8553         /* incoming port not used in lookup key, set field to all 1's */
   8554         soc_mem_field32_set(unit, mem, vent, XLATE__GLPf,
   8555                             SOC_VLAN_XLATE_GLP_WILDCARD(unit));
   8556 
   8557         rv = bcmi_gh2_vxlan_match_vxlate_entry_reset(unit, vent);
   8558         BCM_IF_ERROR_RETURN(rv);
   8559     }
   8560 
   8561     return rv;
   8562 }
   8563 
   8564 /*
   8565  * Function:
   8566  *    bcmi_gh2_vxlan_match_get
   8567  * Purpose:
   8568  *    Obtain match information of an VXLAN port
   8569  * Parameters:
   8570  *    unit - (IN) Device Number
   8571  *    vxlan_port - (IN/OUT) vxlan_port information
   8572  *    vp   - (IN) Source Virtual Port
   8573  *    vpn  - (IN) VPN instance ID (unused for GH2)
   8574  * Returns:
   8575  *    BCM_E_XXX
   8576  */
   8577 int
   8578 bcmi_gh2_vxlan_match_get(
   8579     int unit,
   8580     bcm_vxlan_port_t *vxlan_port,
   8581     int vp,
   8582     bcm_vpn_t vpn)
   8583 {
   8584     int rv = BCM_E_NONE;
   8585     bcm_module_t mod_in = 0, mod_out = 0;
   8586     bcm_port_t port_in = 0, port_out = 0;
   8587     bcm_trunk_t trunk_id = 0;
   8588     int tunnel_idx = -1;
   8589     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   8590 
   8591     /* Input parameter check */
   8592     if (NULL == vxlan_port) {
   8593         return BCM_E_PARAM;
   8594     }
   8595 
   8596     /* Get VXLAN bookkeeping info instance */
   8597     BCM_IF_ERROR_RETURN(
   8598         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   8599 
   8600     if (vxlan_info->match_key[vp].flags & _BCM_VXLAN_PORT_MATCH_TYPE_VLAN) {
   8601         vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_PORT_VLAN;
   8602         vxlan_port->match_vlan = vxlan_info->match_key[vp].match_vlan;
   8603 
   8604         if (vxlan_info->match_key[vp].trunk_id != -1) {
   8605             trunk_id = vxlan_info->match_key[vp].trunk_id;
   8606             BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id);
   8607         } else {
   8608             port_in = vxlan_info->match_key[vp].port;
   8609             mod_in = vxlan_info->match_key[vp].modid;
   8610             rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   8611                                          mod_in, port_in, &mod_out, &port_out);
   8612             vxlan_port->match_port =
   8613                 _bcm_esw_port_gport_get_from_modport(unit, mod_out, port_out);
   8614         }
   8615     } else if (vxlan_info->match_key[vp].flags &
   8616         _BCM_VXLAN_PORT_MATCH_TYPE_INNER_VLAN) {
   8617         vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_PORT_INNER_VLAN;
   8618         vxlan_port->match_inner_vlan =
   8619             vxlan_info->match_key[vp].match_inner_vlan;
   8620 
   8621         if (vxlan_info->match_key[vp].trunk_id != -1) {
   8622             trunk_id = vxlan_info->match_key[vp].trunk_id;
   8623             BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id);
   8624         } else {
   8625             port_in = vxlan_info->match_key[vp].port;
   8626             mod_in = vxlan_info->match_key[vp].modid;
   8627             rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   8628                                          mod_in, port_in, &mod_out, &port_out);
   8629             vxlan_port->match_port =
   8630                 _bcm_esw_port_gport_get_from_modport(unit, mod_out, port_out);
   8631         }
   8632     } else if (vxlan_info->match_key[vp].flags &
   8633         _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_STACKED) {
   8634         vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_PORT_VLAN_STACKED;
   8635         vxlan_port->match_vlan = vxlan_info->match_key[vp].match_vlan;
   8636         vxlan_port->match_inner_vlan =
   8637             vxlan_info->match_key[vp].match_inner_vlan;
   8638 
   8639         if (vxlan_info->match_key[vp].trunk_id != -1) {
   8640             trunk_id = vxlan_info->match_key[vp].trunk_id;
   8641             BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id);
   8642         } else {
   8643             port_in = vxlan_info->match_key[vp].port;
   8644             mod_in = vxlan_info->match_key[vp].modid;
   8645             rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   8646                                          mod_in, port_in, &mod_out, &port_out);
   8647             vxlan_port->match_port =
   8648                 _bcm_esw_port_gport_get_from_modport(unit, mod_out, port_out);
   8649         }
   8650     } else if (vxlan_info->match_key[vp].flags &
   8651         _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_PRI) {
   8652         vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_VLAN_PRI;
   8653         vxlan_port->match_vlan = vxlan_info->match_key[vp].match_vlan;
   8654 
   8655         if (vxlan_info->match_key[vp].trunk_id != -1) {
   8656             trunk_id = vxlan_info->match_key[vp].trunk_id;
   8657             BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id);
   8658         } else {
   8659             port_in = vxlan_info->match_key[vp].port;
   8660             mod_in = vxlan_info->match_key[vp].modid;
   8661             rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   8662                                          mod_in, port_in, &mod_out, &port_out);
   8663             vxlan_port->match_port =
   8664                 _bcm_esw_port_gport_get_from_modport(unit, mod_out, port_out);
   8665         }
   8666     } else if (vxlan_info->match_key[vp].flags &
   8667         _BCM_VXLAN_PORT_MATCH_TYPE_PORT) {
   8668         port_in = vxlan_info->match_key[vp].port;
   8669         mod_in = vxlan_info->match_key[vp].modid;
   8670 
   8671         vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_PORT;
   8672         rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   8673                                      mod_in, port_in, &mod_out, &port_out);
   8674         vxlan_port->match_port =
   8675             _bcm_esw_port_gport_get_from_modport(unit, mod_out, port_out);
   8676     } else if (vxlan_info->match_key[vp].flags &
   8677         _BCM_VXLAN_PORT_MATCH_TYPE_TRUNK) {
   8678         trunk_id = vxlan_info->match_key[vp].trunk_id;
   8679 
   8680         vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_PORT;
   8681         BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id);
   8682     } else if ((vxlan_info->match_key[vp].flags &
   8683         _BCM_VXLAN_PORT_MATCH_TYPE_VNID)) {
   8684         vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_VN_ID;
   8685 
   8686         tunnel_idx = vxlan_info->match_key[vp].match_tunnel_index;
   8687         BCM_GPORT_TUNNEL_ID_SET(vxlan_port->match_tunnel_id, tunnel_idx);
   8688         vxlan_port->match_vlan = vxlan_info->match_key[vp].match_vlan;
   8689     } else if (vxlan_info->match_key[vp].flags &
   8690         _BCM_VXLAN_PORT_MATCH_TYPE_SHARED) {
   8691         rv = BCM_E_INTERNAL;
   8692     } else {
   8693         vxlan_port->criteria = BCM_VXLAN_PORT_MATCH_NONE;
   8694     }
   8695 
   8696     /*
   8697      * For all VXLAN RIOT flow support (loopback, access or network ports),
   8698      * we must use vxlan_port->match_port for Custom Header
   8699      * related configurations
   8700      */
   8701     if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   8702         if ((vxlan_info->match_key[vp].flags &
   8703             _BCM_VXLAN_PORT_MATCH_TYPE_VNID) ||
   8704             (vxlan_info->match_key[vp].flags &
   8705             _BCM_VXLAN_PORT_MATCH_TYPE_NONE)) {
   8706             if (vxlan_info->match_key[vp].trunk_id != -1) {
   8707                 trunk_id = vxlan_info->match_key[vp].trunk_id;
   8708                 BCM_GPORT_TRUNK_SET(vxlan_port->match_port, trunk_id);
   8709             } else {
   8710                 port_in = vxlan_info->match_key[vp].port;
   8711                 mod_in = vxlan_info->match_key[vp].modid;
   8712                 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   8713                                              mod_in, port_in,
   8714                                              &mod_out, &port_out);
   8715                 vxlan_port->match_port =
   8716                     _bcm_esw_port_gport_get_from_modport(unit, mod_out,
   8717                                                          port_out);
   8718             }
   8719         }
   8720     }
   8721 
   8722     return rv;
   8723 }
   8724 
   8725 /*
   8726  * Function:
   8727  *    bcmi_gh2_vxlan_elan_port_add
   8728  * Purpose:
   8729  *    Add VXLAN ELAN port to a VPN
   8730  * Parameters:
   8731  *    unit - (IN) Device Number
   8732  *    vpn  - (IN) VPN instance ID
   8733  *    vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id)
   8734  * Returns:
   8735  *    BCM_E_XXX
   8736  */
   8737 STATIC int
   8738 bcmi_gh2_vxlan_elan_port_add(
   8739     int unit,
   8740     bcm_vpn_t vpn,
   8741     bcm_vxlan_port_t *vxlan_port)
   8742 {
   8743     int rv = BCM_E_PARAM, rv_error = BCM_E_NONE;
   8744     int vp, num_vp, vfi = 0;
   8745     bcmi_vxlan_vp_info_t vxlan_vp_info;
   8746     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   8747     gh2_vxlan_vp_info_t *vp_info =NULL;
   8748     int old_tpid_valid = 0;
   8749     uint16 old_tpid = 0, new_tpid = 0;
   8750     bcm_switch_tpid_info_t tpid_info;
   8751     int tpid_enable = 0;
   8752     bcm_vxlan_port_t old_vxlan_port;
   8753 
   8754     /* Get VXLAN bookkeeping info instance */
   8755     BCM_IF_ERROR_RETURN(
   8756         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   8757 
   8758     /* Input parameter check */
   8759     if (vpn != BCM_VXLAN_VPN_INVALID) {
   8760         _BCM_VXLAN_VPN_GET(vfi, _BCM_VXLAN_VPN_TYPE_ELAN, vpn);
   8761         if (!bcmi_gh2_vxlan_vfi_used_get(unit, vfi)) {
   8762             return BCM_E_NOT_FOUND;
   8763         }
   8764     } else {
   8765         vfi = _BCM_VXLAN_VFI_INVALID;
   8766     }
   8767 
   8768     if (NULL == vxlan_port) {
   8769         return BCM_E_PARAM;
   8770     }
   8771 
   8772     if (vxlan_port->flags & BCM_VXLAN_PORT_DROP) {
   8773         return BCM_E_PARAM;
   8774     }
   8775 
   8776     num_vp = vxlan_info->num_vxlan_vp;
   8777 
   8778     bcmi_gh2_vxlan_vp_info_init(&vxlan_vp_info);
   8779     if (vxlan_port->flags & BCM_VXLAN_PORT_NETWORK) {
   8780         vxlan_vp_info.flags |= GH2_VXLAN_VP_INFO_NETWORK_PORT;
   8781     } else if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) {
   8782         /* Only support for GH2-B0 when VXLAN RIOT is enabled */
   8783         vxlan_vp_info.flags |= GH2_VXLAN_VP_INFO_LOOPBACK_PORT;
   8784     }
   8785     if ((vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_SHARE) ||
   8786         (vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) {
   8787         /* GH2 doesn't support SHARE criteria and flags */
   8788         return BCM_E_UNAVAIL;
   8789     }
   8790 
   8791     /* =============== Allocate/Get Virtual Port =============== */
   8792     if (vxlan_port->flags & BCM_VXLAN_PORT_REPLACE) {
   8793         vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
   8794 
   8795         if (vp == -1) {
   8796             return BCM_E_PARAM;
   8797         }
   8798         if (!bcmi_gh2_vxlan_vp_used_get(unit, vp)) {
   8799             return BCM_E_NOT_FOUND;
   8800         }
   8801 
   8802         /* Decrease old-port's nexthop count */
   8803         BCM_IF_ERROR_RETURN(
   8804             bcmi_gh2_vxlan_port_nh_delete(unit, vpn, vp));
   8805         /* Decrease old-port's VP count */
   8806         BCM_IF_ERROR_RETURN(
   8807             bcmi_gh2_vxlan_port_cnt_update(unit, vxlan_port->vxlan_port_id,
   8808                                            vp, FALSE));
   8809 
   8810         /* Get old-port's vxlan_port information when VXLAN RIOT is enabled */
   8811         if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   8812             bcm_vxlan_port_t_init(&old_vxlan_port);
   8813             old_vxlan_port.vxlan_port_id = vxlan_port->vxlan_port_id;
   8814 
   8815             BCM_IF_ERROR_RETURN(
   8816                 bcmi_gh2_vxlan_port_get(unit, vpn, &old_vxlan_port));
   8817         }
   8818     } else if (vxlan_port->flags & BCM_VXLAN_PORT_WITH_ID) {
   8819         if (!BCM_GPORT_IS_VXLAN_PORT(vxlan_port->vxlan_port_id)) {
   8820              return BCM_E_BADID;
   8821         }
   8822 
   8823         vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
   8824         if (vp == -1) {
   8825             return BCM_E_PARAM;
   8826         }
   8827         /*
   8828          * In TD2, Vp index zero is reserved in function _bcm_virtual_init
   8829          * because of HW restriction. No such restriction on GH2.
   8830          */
   8831         if ((vp < 0) || (vp >= num_vp)) {
   8832             return BCM_E_BADID;
   8833         }
   8834         if (bcmi_gh2_vxlan_vp_used_get(unit, vp)) {
   8835             return BCM_E_EXISTS;
   8836         }
   8837 
   8838         BCM_IF_ERROR_RETURN(
   8839             bcmi_gh2_vxlan_vp_used_set(unit, vp, vxlan_vp_info));
   8840     } else {
   8841         /* Allocate a new VP index */
   8842         BCM_IF_ERROR_RETURN(
   8843             bcmi_gh2_vxlan_vp_alloc(unit, 0, (num_vp - 1), 1,
   8844                                     vxlan_vp_info, &vp));
   8845         BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port->vxlan_port_id, vp);
   8846     }
   8847 
   8848     /* =============== Configure Next-Hop Properties =============== */
   8849     rv = bcmi_gh2_vxlan_port_nh_add(unit, vxlan_port, vp, vpn);
   8850     if (BCM_FAILURE(rv)) {
   8851         if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
   8852             (void)bcmi_gh2_vxlan_vp_free(unit, 1, vp);
   8853         }
   8854         return rv;
   8855     }
   8856 
   8857     /* Need to parse Service-Tag Properties */
   8858     if (vxlan_port->flags & BCM_VXLAN_PORT_SERVICE_TAGGED) {
   8859         sal_memset(&tpid_info, 0, sizeof(tpid_info));
   8860         tpid_info.tpid_type = bcmTpidTypeVxlanPayloadOuter;
   8861         tpid_info.tpid_value = vxlan_port->egress_service_tpid;
   8862 
   8863         rv = bcm_esw_switch_tpid_add(unit, 0, &tpid_info);
   8864         if (BCM_FAILURE(rv) && rv != BCM_E_EXISTS) {
   8865             if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
   8866                 rv_error = bcmi_gh2_vxlan_port_nh_delete(unit, vpn, vp);
   8867                 if (BCM_FAILURE(rv_error) && rv_error != BCM_E_NOT_FOUND) {
   8868                     return rv_error;
   8869                 }
   8870                 (void)bcmi_gh2_vxlan_vp_free(unit, 1, vp);
   8871             }
   8872             return rv;
   8873         }
   8874 
   8875         tpid_enable = 1;
   8876 
   8877         /* Get current VXLAN Outer TPID info with specified VP */
   8878         vp_info = &(vxlan_info->vxlan_vp_info[vp]);
   8879         old_tpid_valid = vp_info->tpid_valid;
   8880         old_tpid = vp_info->tpid_value; /* old TPID value */
   8881         new_tpid = tpid_info.tpid_value; /* new TPID value */
   8882         if (old_tpid_valid) {
   8883             if (new_tpid != old_tpid) {
   8884                 /* Decrease ref_count for old VXLAN Outer TPID */
   8885                 (void)bcmi_gh2_vxlan_outer_tpid_ref_dec(unit, old_tpid);
   8886 
   8887                 /* Increase ref_count for new VXLAN Outer TPID */
   8888                 (void)bcmi_gh2_vxlan_outer_tpid_ref_inc(unit, new_tpid);
   8889 
   8890                 /* Update latest VXLAN Outer TPID info with specified VP */
   8891                 vp_info->tpid_value = new_tpid;
   8892             }
   8893         } else {
   8894             /* Increase ref_count for new VXLAN Outer TPID */
   8895             (void)bcmi_gh2_vxlan_outer_tpid_ref_inc(unit, new_tpid);
   8896 
   8897             /* Update latest VXLAN Outer TPID info with specified VP */
   8898             vp_info->tpid_valid = 1;
   8899             vp_info->tpid_value = new_tpid;
   8900         }
   8901     }
   8902 
   8903     /* Configure VP match criteria */
   8904     rv = bcmi_gh2_vxlan_match_add(unit, vxlan_port, vp, vpn);
   8905     if (BCM_FAILURE(rv)) {
   8906         if (tpid_enable) {
   8907             if (old_tpid_valid) {
   8908                 if (new_tpid != old_tpid) {
   8909                     /* Decrease ref_count for new VXLAN Outer TPID */
   8910                     (void)bcmi_gh2_vxlan_outer_tpid_ref_dec(unit, new_tpid);
   8911 
   8912                     /* Restore ref_count for old VXLAN Outer TPID */
   8913                     sal_memset(&tpid_info, 0, sizeof(tpid_info));
   8914                     tpid_info.tpid_type = bcmTpidTypeVxlanPayloadOuter;
   8915                     tpid_info.tpid_value = old_tpid;
   8916                     rv_error = bcm_esw_switch_tpid_add(unit, 0, &tpid_info);
   8917                     if (BCM_FAILURE(rv_error) && rv_error != BCM_E_EXISTS) {
   8918                         return rv_error;
   8919                     }
   8920                     (void)bcmi_gh2_vxlan_outer_tpid_ref_inc(unit, old_tpid);
   8921                     vp_info->tpid_value = old_tpid;
   8922                 }
   8923             } else {
   8924                 /* Decrease ref_count for new VXLAN Outer TPID */
   8925                 (void)bcmi_gh2_vxlan_outer_tpid_ref_dec(unit, new_tpid);
   8926                 vp_info->tpid_valid = 0;
   8927                 vp_info->tpid_value = 0x0;
   8928             }
   8929         }
   8930 
   8931         if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
   8932             rv_error = bcmi_gh2_vxlan_port_nh_delete(unit, vpn, vp);
   8933             if (BCM_FAILURE(rv_error) && rv_error != BCM_E_NOT_FOUND) {
   8934                 return rv_error;
   8935             }
   8936             (void)bcmi_gh2_vxlan_vp_free(unit, 1, vp);
   8937         }
   8938         return rv;
   8939     }
   8940 
   8941     /* Increment new-port's VP count */
   8942     rv = bcmi_gh2_vxlan_port_cnt_update(unit, vxlan_port->vxlan_port_id,
   8943                                         vp, TRUE);
   8944     if (BCM_FAILURE(rv)) {
   8945         if (tpid_enable) {
   8946             if (old_tpid_valid) {
   8947                 if (new_tpid != old_tpid) {
   8948                     /* Decrease ref_count for new VXLAN Outer TPID */
   8949                     (void)bcmi_gh2_vxlan_outer_tpid_ref_dec(unit, new_tpid);
   8950 
   8951                     /* Restore ref_count for old VXLAN Outer TPID */
   8952                     sal_memset(&tpid_info, 0, sizeof(tpid_info));
   8953                     tpid_info.tpid_type = bcmTpidTypeVxlanPayloadOuter;
   8954                     tpid_info.tpid_value = old_tpid;
   8955                     rv_error = bcm_esw_switch_tpid_add(unit, 0, &tpid_info);
   8956                     if (BCM_FAILURE(rv_error) && rv_error != BCM_E_EXISTS) {
   8957                         return rv_error;
   8958                     }
   8959                     (void)bcmi_gh2_vxlan_outer_tpid_ref_inc(unit, old_tpid);
   8960                     vp_info->tpid_value = old_tpid;
   8961                 }
   8962             } else {
   8963                 /* Decrease ref_count for new VXLAN Outer TPID */
   8964                 (void)bcmi_gh2_vxlan_outer_tpid_ref_dec(unit, new_tpid);
   8965                 vp_info->tpid_valid = 0;
   8966                 vp_info->tpid_value = 0x0;
   8967             }
   8968         }
   8969 
   8970         if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
   8971             rv_error = bcmi_gh2_vxlan_match_delete(unit, vp, *vxlan_port, vpn);
   8972             if (BCM_FAILURE(rv_error) && rv_error != BCM_E_NOT_FOUND) {
   8973                 return rv_error;
   8974             }
   8975 
   8976             rv_error = bcmi_gh2_vxlan_port_nh_delete(unit, vpn, vp);
   8977             if (BCM_FAILURE(rv_error) && rv_error != BCM_E_NOT_FOUND) {
   8978                 return rv_error;
   8979             }
   8980             (void)bcmi_gh2_vxlan_vp_free(unit, 1, vp);
   8981         }
   8982         return rv;
   8983     }
   8984 
   8985     /* Configure VP related Custom Header when VXLAN RIOT is enabled */
   8986     if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   8987         rv = bcmi_gh2_vxlan_riot_custom_header_add(unit, vxlan_port,
   8988                                                    &old_vxlan_port, vp);
   8989         if (BCM_FAILURE(rv)) {
   8990             if (tpid_enable) {
   8991                 if (old_tpid_valid) {
   8992                     if (new_tpid != old_tpid) {
   8993                         /* Decrease ref_count for new VXLAN Outer TPID */
   8994                         (void)bcmi_gh2_vxlan_outer_tpid_ref_dec(unit,
   8995                                                                 new_tpid);
   8996 
   8997                         /* Restore ref_count for old VXLAN Outer TPID */
   8998                         sal_memset(&tpid_info, 0, sizeof(tpid_info));
   8999                         tpid_info.tpid_type = bcmTpidTypeVxlanPayloadOuter;
   9000                         tpid_info.tpid_value = old_tpid;
   9001                         rv_error =
   9002                             bcm_esw_switch_tpid_add(unit, 0, &tpid_info);
   9003                         if (BCM_FAILURE(rv_error) &&
   9004                             rv_error != BCM_E_EXISTS) {
   9005                             return rv_error;
   9006                         }
   9007                         (void)bcmi_gh2_vxlan_outer_tpid_ref_inc(unit,
   9008                                                                 old_tpid);
   9009                         vp_info->tpid_value = old_tpid;
   9010                     }
   9011                 } else {
   9012                     /* Decrease ref_count for new VXLAN Outer TPID */
   9013                     (void)bcmi_gh2_vxlan_outer_tpid_ref_dec(unit, new_tpid);
   9014                     vp_info->tpid_valid = 0;
   9015                     vp_info->tpid_value = 0x0;
   9016                 }
   9017             }
   9018 
   9019             if (!(vxlan_port->flags & BCM_VXLAN_PORT_REPLACE)) {
   9020                 /* Decrement port's VP count */
   9021                 BCM_IF_ERROR_RETURN(
   9022                     bcmi_gh2_vxlan_port_cnt_update(unit,
   9023                                                    vxlan_port->vxlan_port_id,
   9024                                                    vp, FALSE));
   9025 
   9026                 rv_error =
   9027                     bcmi_gh2_vxlan_match_delete(unit, vp, *vxlan_port, vpn);
   9028                 if (BCM_FAILURE(rv_error) && rv_error != BCM_E_NOT_FOUND) {
   9029                     return rv_error;
   9030                 }
   9031 
   9032                 rv_error = bcmi_gh2_vxlan_port_nh_delete(unit, vpn, vp);
   9033                 if (BCM_FAILURE(rv_error) && rv_error != BCM_E_NOT_FOUND) {
   9034                     return rv_error;
   9035                 }
   9036                 (void)bcmi_gh2_vxlan_vp_free(unit, 1, vp);
   9037             }
   9038             return rv;
   9039         }
   9040     }
   9041 
   9042     return BCM_E_NONE;
   9043 }
   9044 
   9045 /*
   9046  * Function:
   9047  *    bcmi_gh2_vxlan_elan_port_delete
   9048  * Purpose:
   9049  *    Delete VXLAN ELAN port from a VPN
   9050  * Parameters:
   9051  *    unit - (IN) Device Number
   9052  *    vpn  - (IN) VPN instance ID
   9053  *    vp   - (IN) VP
   9054  * Returns:
   9055  *    BCM_E_XXX
   9056  */
   9057 int
   9058 bcmi_gh2_vxlan_elan_port_delete(int unit, bcm_vpn_t vpn, int vp)
   9059 {
   9060     int rv = BCM_E_NONE;
   9061     bcm_gport_t vxlan_port_id;
   9062     bcm_vxlan_port_t vxlan_port;
   9063     bcmi_vxlan_vp_info_t vxlan_vp_info;
   9064 
   9065     if (!bcmi_gh2_vxlan_vp_used_get(unit, vp)) {
   9066         return BCM_E_NOT_FOUND;
   9067     }
   9068 
   9069     /* Check for Network-Port */
   9070     BCM_IF_ERROR_RETURN(
   9071         bcmi_gh2_vxlan_vp_info_get(unit, vp, &vxlan_vp_info));
   9072 
   9073     /* Set VXLAN port ID */
   9074     BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port_id, vp);
   9075     bcm_vxlan_port_t_init(&vxlan_port);
   9076     vxlan_port.vxlan_port_id = vxlan_port_id;
   9077     BCM_IF_ERROR_RETURN(
   9078         bcmi_gh2_vxlan_port_get(unit, vpn, &vxlan_port));
   9079 
   9080     rv = bcmi_gh2_vxlan_match_delete(unit, vp, vxlan_port, vpn);
   9081     if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) {
   9082         return rv;
   9083     }
   9084 
   9085     /* Delete VP related Custom Header setting when VXLAN RIOT is enabled */
   9086     if (GH2_VXLAN_RIOT_ENABLE(unit)) {
   9087         BCM_IF_ERROR_RETURN(
   9088             bcmi_gh2_vxlan_riot_custom_header_delete(unit, &vxlan_port, vp));
   9089     }
   9090 
   9091     /* Decrement port's VP count */
   9092     BCM_IF_ERROR_RETURN(
   9093         bcmi_gh2_vxlan_port_cnt_update(unit, vxlan_port_id, vp, FALSE));
   9094 
   9095     /* Delete the next-hop info */
   9096     rv = bcmi_gh2_vxlan_port_nh_delete(unit, vpn, vp);
   9097     if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) {
   9098         return rv;
   9099     }
   9100 
   9101     (void)bcmi_gh2_vxlan_match_clear(unit, vp);
   9102 
   9103     /* Free the VP */
   9104     BCM_IF_ERROR_RETURN(bcmi_gh2_vxlan_vp_free(unit, 1, vp));
   9105 
   9106     return BCM_E_NONE;
   9107 }
   9108 
   9109 /*
   9110  * Function:
   9111  *    bcmi_gh2_vxlan_egress_get
   9112  * Purpose:
   9113  *    Get VXLAN Egress NextHop
   9114  * Parameters:
   9115  *    unit - (IN) Device Number
   9116  *    egr  - (OUT) L3 Egress object info
   9117  *    nh_index - (IN) nh_index
   9118  * Returns:
   9119  *    BCM_E_XXX
   9120  */
   9121 int
   9122 bcmi_gh2_vxlan_egress_get(int unit, bcm_l3_egress_t *egr, int nh_index)
   9123 {
   9124     int int_l3_flag;
   9125     int_l3_flag = BCM_XGS3_L3_ENT_FLAG(BCM_XGS3_L3_TBL_PTR(unit, next_hop),
   9126                                        nh_index);
   9127 
   9128     /* Input parameter check */
   9129     if (NULL == egr) {
   9130         return BCM_E_PARAM;
   9131     }
   9132 
   9133     if (int_l3_flag == _BCM_L3_VXLAN_ONLY) {
   9134          egr->flags |= BCM_L3_VXLAN_ONLY;
   9135     }
   9136 
   9137     return BCM_E_NONE;
   9138 }
   9139 
   9140 /*
   9141  * Function:
   9142  *    bcmi_gh2_vxlan_port_vlan_get
   9143  * Purpose:
   9144  *    Obtain vlan information
   9145  * Parameters:
   9146  *    unit - (IN) Device Number
   9147  *    vp  - (IN) Virtual Port
   9148  *    vxlan_port - (OUT) VXLAN port information
   9149  * Returns:
   9150  *    BCM_E_XXX
   9151  */
   9152 STATIC int
   9153 bcmi_gh2_vxlan_port_vlan_get(int unit, int vp, bcm_vxlan_port_t *vxlan_port)
   9154 {
   9155     int rv = BCM_E_NONE, index = 0;
   9156     soc_mem_t mem;
   9157     uint32 vent[SOC_MAX_MEM_WORDS], ret_vent[SOC_MAX_MEM_WORDS];
   9158     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   9159 
   9160     /* Input parameter check */
   9161     if (NULL == vxlan_port) {
   9162         return BCM_E_PARAM;
   9163     }
   9164 
   9165     /* Get VXLAN bookkeeping info instance */
   9166     BCM_IF_ERROR_RETURN(
   9167         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   9168 
   9169     sal_memset(vent, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS));
   9170     sal_memset(ret_vent, 0, (sizeof(uint32) * SOC_MAX_MEM_WORDS));
   9171 
   9172     mem = VLAN_XLATEm;
   9173     if (vxlan_info->match_key[vp].flags == _BCM_VXLAN_PORT_MATCH_TYPE_VLAN) {
   9174         soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1);
   9175         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
   9176                             GH2_VLXLT_HASH_KEY_TYPE_OVID);
   9177         soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf,
   9178                             vxlan_info->match_key[vp].match_vlan);
   9179     } else if (vxlan_info->match_key[vp].flags ==
   9180         _BCM_VXLAN_PORT_MATCH_TYPE_INNER_VLAN) {
   9181         soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1);
   9182         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
   9183                             GH2_VLXLT_HASH_KEY_TYPE_IVID);
   9184         soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf,
   9185                             vxlan_info->match_key[vp].match_inner_vlan);
   9186     } else if (vxlan_info->match_key[vp].flags ==
   9187         _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_STACKED) {
   9188         soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1);
   9189         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
   9190                             GH2_VLXLT_HASH_KEY_TYPE_IVID_OVID);
   9191         soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf,
   9192                             vxlan_info->match_key[vp].match_vlan);
   9193         soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf,
   9194                             vxlan_info->match_key[vp].match_inner_vlan);
   9195     } else if (vxlan_info->match_key[vp].flags ==
   9196         _BCM_VXLAN_PORT_MATCH_TYPE_VLAN_PRI) {
   9197         soc_mem_field32_set(unit, mem, vent, VALIDf, 0x1);
   9198         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf,
   9199                             GH2_VLXLT_HASH_KEY_TYPE_PRI_CFI);
   9200         soc_mem_field32_set(unit, mem, vent, XLATE__OTAGf,
   9201                             vxlan_info->match_key[vp].match_vlan);
   9202     }
   9203 
   9204     if (soc_mem_field32_get(unit, mem, vent, VALIDf)) {
   9205         if (vxlan_info->match_key[vp].modid != -1) {
   9206             soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf,
   9207                                 vxlan_info->match_key[vp].modid);
   9208             soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf,
   9209                                 vxlan_info->match_key[vp].port);
   9210         } else {
   9211             soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 0x1);
   9212             soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf,
   9213                                 vxlan_info->match_key[vp].trunk_id);
   9214         }
   9215 
   9216         rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY,
   9217                             &index, vent, ret_vent, 0);
   9218         BCM_IF_ERROR_RETURN(rv);
   9219         if (!soc_mem_field32_get(unit, mem, ret_vent,
   9220                                  XLATE__DISABLE_VLAN_CHECKSf)) {
   9221             vxlan_port->flags |= BCM_VXLAN_PORT_ENABLE_VLAN_CHECKS;
   9222         }
   9223     }
   9224 
   9225     return rv;
   9226 }
   9227 
   9228 /*
   9229  * Function:
   9230  *    bcmi_gh2_vxlan_port_vp_get
   9231  * Purpose:
   9232  *    Get VXLAN port information from a VPN and VP
   9233  * Parameters:
   9234  *    unit - (IN) Device Number
   9235  *    vpn  - (IN) VPN instance ID
   9236  *    vp   - (IN) VPN instance ID
   9237  *    vxlan_port - (IN/OUT) VXLAN port information
   9238  * Returns:
   9239  *    BCM_E_XXX
   9240  */
   9241 STATIC int
   9242 bcmi_gh2_vxlan_port_vp_get(
   9243     int unit,
   9244     bcm_vpn_t vpn,
   9245     int vp,
   9246     bcm_vxlan_port_t *vxlan_port)
   9247 {
   9248     int network_port_flag = 0, loopback_port_flag = 0;
   9249     bcmi_vxlan_vp_info_t vxlan_vp_info;
   9250     int tpid_enable, tpid_index;
   9251     uint16 tpid = 0;
   9252     uint64 reg_val64;
   9253 
   9254     /* Input parameter check */
   9255     if (NULL == vxlan_port) {
   9256         return BCM_E_PARAM;
   9257     }
   9258 
   9259     /* Check for Network-Port */
   9260     BCM_IF_ERROR_RETURN(
   9261         bcmi_gh2_vxlan_vp_info_get(unit, vp, &vxlan_vp_info));
   9262     if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_NETWORK_PORT) {
   9263         network_port_flag = TRUE;
   9264     } else if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_LOOPBACK_PORT) {
   9265         loopback_port_flag = TRUE;
   9266     }
   9267 
   9268     if (network_port_flag) {
   9269         vxlan_port->flags |= BCM_VXLAN_PORT_NETWORK;
   9270         vxlan_port->flags |= BCM_VXLAN_PORT_EGRESS_TUNNEL;
   9271         vxlan_port->flags |= BCM_VXLAN_PORT_VPN_BASED;
   9272         if (vxlan_vp_info.flags & GH2_VXLAN_VP_INFO_SHARED_PORT) {
   9273             /* Note: no such case in GH2 */
   9274             vxlan_port->flags |= BCM_VXLAN_PORT_SHARE;
   9275             /* Shared VXLAN port is used only for multicast now */
   9276             vxlan_port->flags |= BCM_VXLAN_PORT_MULTICAST;
   9277         }
   9278     } else if (loopback_port_flag) {
   9279         vxlan_port->flags |= BCM_VXLAN_PORT_LOOPBACK;
   9280     }
   9281 
   9282     /* Get the match parameters */
   9283     BCM_IF_ERROR_RETURN(
   9284         bcmi_gh2_vxlan_match_get(unit, vxlan_port, vp, vpn));
   9285 
   9286     /* Get the BCM_VXLAN_PORT_ENABLE_VLAN_CHECKS flag */
   9287     BCM_IF_ERROR_RETURN(
   9288         bcmi_gh2_vxlan_port_vlan_get(unit, vp, vxlan_port));
   9289 
   9290     /*
   9291      * Get the next-hop parameters,
   9292      * - for shared VXLAN port, don't get next hop here
   9293      */
   9294     if (!(vxlan_port->flags & BCM_VXLAN_PORT_SHARE)) {
   9295         BCM_IF_ERROR_RETURN(
   9296             bcmi_gh2_vxlan_port_nh_get(unit, vpn, vp, vxlan_port));
   9297     }
   9298 
   9299     COMPILER_64_ZERO(reg_val64);
   9300 
   9301     /* VXLAN payload outer TPIDs */
   9302     BCM_IF_ERROR_RETURN(
   9303         READ_ING_VXLAN_CONTROLr(unit, &reg_val64));
   9304     tpid_enable = soc_reg64_field32_get(unit, ING_VXLAN_CONTROLr,
   9305                                         reg_val64, PAYLOAD_OUTER_TPID_ENABLEf);
   9306     if (tpid_enable) {
   9307         vxlan_port->flags |= BCM_VXLAN_PORT_SERVICE_TAGGED;
   9308 
   9309         tpid_index = 0;
   9310         while (tpid_enable) {
   9311             /* Get the first found TPID since it is per chip not per VP */
   9312             if (tpid_enable & 0x1) {
   9313                 BCM_IF_ERROR_RETURN(
   9314                     _bcm_fb2_outer_tpid_entry_get(unit, &tpid,
   9315                                                   tpid_index));
   9316                 break;
   9317             }
   9318             tpid_enable >>= 1;
   9319             tpid_index++;
   9320         }
   9321 
   9322         vxlan_port->egress_service_tpid = tpid;
   9323     }
   9324 
   9325     /* Set VXLAN port ID */
   9326     BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port->vxlan_port_id, vp);
   9327 
   9328     return BCM_E_NONE;
   9329 }
   9330 
   9331 /*
   9332  * Function:
   9333  *    bcmi_gh2_vxlan_port_to_nh_ecmp_index
   9334  * Purpose:
   9335  *    Translate VXLAN port (vp) to Next Hot or ECMP index
   9336  * Parameters:
   9337  *    unit - (IN) Device Number
   9338  *    vp   - (IN) Virtual port number
   9339  *    ecmp - (OUT) ECMP type
   9340  *    nh_ecmp_index - (OUT) Next Hot or ECMP index
   9341  * Returns:
   9342  *    BCM_E_XXX.
   9343  */
   9344 int
   9345 bcmi_gh2_vxlan_port_to_nh_ecmp_index(
   9346     int unit,
   9347     int vp,
   9348     int *ecmp,
   9349     int *nh_ecmp_index)
   9350 {
   9351     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   9352     gh2_vxlan_vp_info_t *vp_info;
   9353 
   9354     if ((NULL == ecmp) || (NULL == nh_ecmp_index)) {
   9355         return BCM_E_PARAM;
   9356     }
   9357 
   9358     /* Get VXLAN bookkeeping info instance */
   9359     BCM_IF_ERROR_RETURN(
   9360         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   9361 
   9362     if (!bcmi_gh2_vxlan_vp_used_get(unit, vp)) {
   9363         return BCM_E_PARAM;
   9364     }
   9365 
   9366     vp_info = &(vxlan_info->vxlan_vp_info[vp]);
   9367     *ecmp = vp_info->ecmp;
   9368     *nh_ecmp_index = vp_info->nh_ecmp_index;
   9369 
   9370     return BCM_E_NONE;
   9371 }
   9372 
   9373 /*
   9374  * Function:
   9375  *    bcmi_gh2_vxlan_port_from_nh_ecmp_index
   9376  * Purpose:
   9377  *    Translate Next Hot or ECMP index to VXLAN port (vp)
   9378  * Parameters:
   9379  *    unit - (IN) Device Number
   9380  *    ecmp - (IN) ECMP type
   9381  *    nh_ecmp_index - (IN) Next Hot or ECMP index
   9382  *    vp   - (OUT) Virtual port number
   9383  * Returns:
   9384  *    BCM_E_XXX.
   9385  */
   9386 int
   9387 bcmi_gh2_vxlan_port_from_nh_ecmp_index(
   9388     int unit,
   9389     int ecmp,
   9390     int nh_ecmp_index,
   9391     int *vp)
   9392 {
   9393     int num_vp, idx;
   9394     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   9395     gh2_vxlan_vp_info_t *vp_info;
   9396 
   9397     if (NULL == vp) {
   9398         return BCM_E_PARAM;
   9399     }
   9400 
   9401     /* Get VXLAN bookkeeping info instance */
   9402     BCM_IF_ERROR_RETURN(
   9403         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   9404 
   9405     num_vp = vxlan_info->num_vxlan_vp;
   9406     for (idx = 0; idx < num_vp; idx++) {
   9407         if (bcmi_gh2_vxlan_vp_used_get(unit, idx)) {
   9408             vp_info = &(vxlan_info->vxlan_vp_info[idx]);
   9409             if ((vp_info->ecmp == ecmp) &&
   9410                 (vp_info->nh_ecmp_index == nh_ecmp_index)) {
   9411                 break;
   9412             }
   9413         }
   9414     }
   9415 
   9416     if (idx == num_vp) {
   9417         return BCM_E_NOT_FOUND;
   9418     }
   9419 
   9420     *vp = idx;
   9421 
   9422     return BCM_E_NONE;
   9423 }
   9424 
   9425 /*
   9426  * Function:
   9427  *    bcmi_gh2_vxlan_port_add
   9428  * Purpose:
   9429  *    Add VXLAN port to a VPN
   9430  * Parameters:
   9431  *    unit - (IN) Device Number
   9432  *    vpn  - (IN) VPN instance ID
   9433  *    vxlan_port - (IN/OUT) vxlan_port information (OUT : vxlan_port_id)
   9434  * Returns:
   9435  *    BCM_E_XXX
   9436  */
   9437 int
   9438 bcmi_gh2_vxlan_port_add(
   9439     int unit,
   9440     bcm_vpn_t vpn,
   9441     bcm_vxlan_port_t *vxlan_port)
   9442 {
   9443     int rv = BCM_E_PARAM;
   9444     int mode = 0;
   9445     uint8 is_eline = 0;
   9446 
   9447     /* L3 egress mode check */
   9448     BCM_IF_ERROR_RETURN(
   9449         bcm_xgs3_l3_egress_mode_get(unit, &mode));
   9450     if (!mode) {
   9451         LOG_INFO(BSL_LS_BCM_VXLAN,
   9452                  (BSL_META_U(unit,
   9453                              "L3 egress mode must be set first\n")));
   9454         return BCM_E_DISABLED;
   9455     }
   9456 
   9457     /* Input parameter check */
   9458     if (NULL == vxlan_port) {
   9459         return BCM_E_PARAM;
   9460     }
   9461 
   9462     if ((vxlan_port->if_class != 0) || (vxlan_port->mtu != 0)) {
   9463         return BCM_E_PARAM;
   9464     }
   9465 
   9466     if (vxlan_port->criteria == BCM_VXLAN_PORT_MATCH_SHARE) {
   9467         if (soc_feature(unit, soc_feature_vp_sharing)) {
   9468             if (vpn != BCM_VXLAN_VPN_INVALID) {
   9469                 return BCM_E_PARAM;
   9470             }
   9471         } else {
   9472             return BCM_E_UNAVAIL;
   9473         }
   9474     }
   9475 
   9476     /*
   9477      * To indicate a network VP is non-sharing for VXLAN-LITE on GH2.
   9478      * - the sharing network VP is not supported on GH2 currently
   9479      */
   9480     if (vxlan_port->flags & BCM_VXLAN_PORT_VPN_BASED) {
   9481         if (!(vxlan_port->flags & BCM_VXLAN_PORT_EGRESS_TUNNEL)) {
   9482             return BCM_E_PARAM;
   9483         }
   9484     }
   9485     if (vxlan_port->flags & BCM_VXLAN_PORT_SHARE) {
   9486         return BCM_E_UNAVAIL;
   9487     }
   9488 
   9489     /* GH2 doesn't have default virtual port support */
   9490     if (vxlan_port->flags & BCM_VXLAN_PORT_DEFAULT) {
   9491         return BCM_E_UNAVAIL;
   9492     }
   9493 
   9494     /* To indicate a Loopback VP for VXLAN-LITE RIOT support (GH2-B0 only) */
   9495     if (vxlan_port->flags & BCM_VXLAN_PORT_LOOPBACK) {
   9496         if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   9497             /* Loopback VP is only support when VXLAN RIOT is enabled */
   9498             if (!GH2_VXLAN_RIOT_ENABLE(unit)) {
   9499                 return BCM_E_PARAM;
   9500             }
   9501 
   9502             /* Can't set VP as Loopback and Network simultaneously */
   9503             if (vxlan_port->flags & BCM_VXLAN_PORT_NETWORK) {
   9504                 return BCM_E_PARAM;
   9505             }
   9506         } else {
   9507             return BCM_E_UNAVAIL;
   9508         }
   9509     }
   9510 
   9511     if (vpn != BCM_VXLAN_VPN_INVALID) {
   9512         BCM_IF_ERROR_RETURN(
   9513             bcmi_gh2_vxlan_vpn_is_eline(unit, vpn, &is_eline));
   9514     }
   9515 
   9516     /* Currently, VXLAN-LITE only support ELAN */
   9517     if (is_eline == 0) {
   9518         rv = bcmi_gh2_vxlan_elan_port_add(unit, vpn, vxlan_port);
   9519     } else {
   9520         rv = BCM_E_UNAVAIL;
   9521     }
   9522 
   9523     return rv;
   9524 }
   9525 
   9526 /*
   9527  * Function:
   9528  *    bcmi_gh2_vxlan_port_delete
   9529  * Purpose:
   9530  *    Delete VXLAN port from a VPN
   9531  * Parameters:
   9532  *    unit - (IN) Device Number
   9533  *    vpn  - (IN) VPN instance ID
   9534  *    vxlan_port_id - (IN) vxlan port information
   9535  * Returns:
   9536  *    BCM_E_XXX
   9537  */
   9538 int
   9539 bcmi_gh2_vxlan_port_delete(
   9540     int unit,
   9541     bcm_vpn_t vpn,
   9542     bcm_gport_t vxlan_port_id)
   9543 {
   9544     int rv = BCM_E_UNAVAIL;
   9545     int vp = 0;
   9546     uint8 is_eline = 0;
   9547 
   9548     /* Check for valid VPN */
   9549     if (vpn != BCM_VXLAN_VPN_INVALID) {
   9550         BCM_IF_ERROR_RETURN(
   9551             bcmi_gh2_vxlan_vpn_is_valid(unit, vpn));
   9552     }
   9553 
   9554     vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port_id);
   9555     if (vp == -1) {
   9556         return BCM_E_PARAM;
   9557     }
   9558 
   9559     if (!bcmi_gh2_vxlan_vp_used_get(unit, vp)) {
   9560         return BCM_E_NOT_FOUND;
   9561     }
   9562 
   9563     BCM_IF_ERROR_RETURN(
   9564         bcmi_gh2_vxlan_vp_is_eline(unit, vp, &is_eline));
   9565 
   9566     /* Currently, VXLAN-LITE only support ELAN */
   9567     if (is_eline == 0) {
   9568         rv = bcmi_gh2_vxlan_elan_port_delete(unit, vpn, vp);
   9569     } else {
   9570         rv = BCM_E_UNAVAIL;
   9571     }
   9572 
   9573     return rv;
   9574 }
   9575 
   9576 /*
   9577  * Function:
   9578  *    bcmi_gh2_vxlan_port_delete_all
   9579  * Purpose:
   9580  *    Delete all VXLAN ports from a VPN
   9581  * Parameters:
   9582  *    unit - (IN) Device Number
   9583  *    vpn  - (IN) VPN instance ID
   9584  * Returns:
   9585  *    BCM_E_XXX
   9586  */
   9587 int
   9588 bcmi_gh2_vxlan_port_delete_all(int unit, bcm_vpn_t vpn)
   9589 {
   9590     int rv = BCM_E_NONE;
   9591     int vfi_index = 0;
   9592     uint8 is_eline = 0;
   9593     bcm_gport_t vxlan_port_id;
   9594     uint32 vp = 0, num_vp;
   9595     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   9596     gh2_vxlan_vp_info_t *vp_info;
   9597 
   9598     /* Get VXLAN bookkeeping info instance */
   9599     BCM_IF_ERROR_RETURN(
   9600         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   9601 
   9602     if (vpn != BCM_VXLAN_VPN_INVALID) {
   9603         _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
   9604         BCM_IF_ERROR_RETURN(
   9605             bcmi_gh2_vxlan_vpn_is_eline(unit, vpn, &is_eline));
   9606     } else {
   9607         vfi_index = _BCM_VXLAN_VFI_INVALID;
   9608     }
   9609 
   9610     if (is_eline == 0x1) {
   9611         /* VXLAN-LITE doesn't have ELINE support */
   9612         return BCM_E_UNAVAIL;
   9613     }
   9614 
   9615     /* Currently, VXLAN-LITE only support ELAN (is_eline = 0x0) */
   9616     num_vp = vxlan_info->num_vxlan_vp;
   9617 
   9618     SHR_BIT_ITER(vxlan_info->vxlan_vp_bitmap, num_vp, vp) {
   9619         vp_info = &(vxlan_info->vxlan_vp_info[vp]);
   9620         if (vp_info->vfi == vfi_index) {
   9621             /* Set VXLAN port ID */
   9622             BCM_GPORT_VXLAN_PORT_ID_SET(vxlan_port_id, vp);
   9623             rv = bcmi_gh2_vxlan_port_delete(unit, vpn, vxlan_port_id);
   9624             if (BCM_FAILURE(rv)) {
   9625                 /*
   9626                  * Need to take care rv == BCM_E_DISABLED case
   9627                  * since L3 Egress Mode could be disabled after L3 initialized
   9628                  */
   9629                 if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_DISABLED)) {
   9630                     return rv;
   9631                 }
   9632             }
   9633         }
   9634     }
   9635 
   9636     return BCM_E_NONE;
   9637 }
   9638 
   9639 /*
   9640  * Function:
   9641  *    bcmi_gh2_vxlan_port_get
   9642  * Purpose:
   9643  *    Get an VXLAN port from a VPN
   9644  * Parameters:
   9645  *    unit - (IN) Device Number
   9646  *    vpn  - (IN) VPN instance ID
   9647  *    vxlan_port - (IN/OUT) VXLAN port information
   9648  */
   9649 int
   9650 bcmi_gh2_vxlan_port_get(
   9651     int unit,
   9652     bcm_vpn_t vpn,
   9653     bcm_vxlan_port_t *vxlan_port)
   9654 {
   9655     int vp = 0;
   9656 
   9657     /* Input parameter check */
   9658     if (NULL == vxlan_port) {
   9659         return BCM_E_PARAM;
   9660     }
   9661 
   9662     vp = BCM_GPORT_VXLAN_PORT_ID_GET(vxlan_port->vxlan_port_id);
   9663     if (vp == -1) {
   9664         return BCM_E_PARAM;
   9665     }
   9666 
   9667     if (!bcmi_gh2_vxlan_vp_used_get(unit, vp)) {
   9668         return BCM_E_NOT_FOUND;
   9669     }
   9670 
   9671     if (vpn != BCM_VXLAN_VPN_INVALID) {
   9672         BCM_IF_ERROR_RETURN(
   9673             bcmi_gh2_vxlan_vpn_is_valid(unit, vpn));
   9674     }
   9675 
   9676     BCM_IF_ERROR_RETURN(
   9677         bcmi_gh2_vxlan_port_vp_get(unit, vpn, vp, vxlan_port));
   9678 
   9679     return BCM_E_NONE;
   9680 }
   9681 
   9682 /*
   9683  * Function:
   9684  *    bcmi_gh2_vxlan_port_get_all
   9685  * Purpose:
   9686  *    Get all VXLAN ports from a VPN
   9687  * Parameters:
   9688  *    unit - (IN) Device Number
   9689  *    vpn  - (IN) VPN instance ID
   9690  *    port_max   - (IN) Maximum number of interfaces in array
   9691  *    port_array - (OUT) Array of VXLAN ports
   9692  *    port_count - (OUT) Number of interfaces in array
   9693  */
   9694 int
   9695 bcmi_gh2_vxlan_port_get_all(
   9696     int unit,
   9697     bcm_vpn_t vpn,
   9698     int port_max,
   9699     bcm_vxlan_port_t *port_array,
   9700     int *port_count)
   9701 {
   9702     int vp;
   9703     int vfi_index = -1;
   9704     uint8 is_eline = 0;
   9705     int num_vp;
   9706     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   9707     gh2_vxlan_vp_info_t *vp_info;
   9708 
   9709     /* Input parameter check */
   9710     if ((NULL == port_array) || (NULL == port_count)) {
   9711         return BCM_E_PARAM;
   9712     }
   9713 
   9714     /* Get VXLAN bookkeeping info instance */
   9715     BCM_IF_ERROR_RETURN(
   9716         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   9717 
   9718     if (vpn != BCM_VXLAN_VPN_INVALID) {
   9719         _BCM_VXLAN_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
   9720         BCM_IF_ERROR_RETURN(
   9721             bcmi_gh2_vxlan_vpn_is_eline(unit, vpn, &is_eline));
   9722     } else {
   9723         vfi_index = _BCM_VXLAN_VFI_INVALID;
   9724     }
   9725 
   9726     if (is_eline == 0x1) {
   9727         /* VXLAN-LITE doesn't have ELINE support */
   9728         return BCM_E_UNAVAIL;
   9729     } else {
   9730         /* Currently, VXLAN-LITE only support ELAN (is_eline = 0x0) */
   9731         *port_count = 0;
   9732         num_vp = vxlan_info->num_vxlan_vp;
   9733 
   9734         SHR_BIT_ITER(vxlan_info->vxlan_vp_bitmap, num_vp, vp) {
   9735             vp_info = &(vxlan_info->vxlan_vp_info[vp]);
   9736             if ((vp_info->vp_type) && (vp_info->vfi == vfi_index)) {
   9737                 /* Check if number of ports is requested */
   9738                 if (port_max == 0) {
   9739                     (*port_count)++;
   9740                     continue;
   9741                 } else if (*port_count == port_max) {
   9742                     break;
   9743                 }
   9744 
   9745                BCM_IF_ERROR_RETURN(
   9746                    bcmi_gh2_vxlan_port_vp_get(unit, vpn,
   9747                                               vp, &port_array[*port_count]));
   9748                (*port_count)++;
   9749             }
   9750         }
   9751 
   9752         if (*port_count == 0) {
   9753             return BCM_E_NOT_FOUND;
   9754         }
   9755     }
   9756 
   9757     return BCM_E_NONE;
   9758 }
   9759 
   9760 /*
   9761  * Function:
   9762  *    bcmi_gh2_vxlan_port_traverse
   9763  * Purpose:
   9764  *    Get information about a port instance
   9765  * Parameters:
   9766  *    unit - (IN) Device Number
   9767  *    cb   - (IN) User-provided callback
   9768  *    user_data  - (IN/OUT) callback user data
   9769  * Returns:
   9770  *    BCM_E_XXX
   9771  */
   9772 int
   9773 bcmi_gh2_vxlan_port_traverse(
   9774     int unit,
   9775     bcm_vxlan_port_traverse_cb cb,
   9776     void *user_data)
   9777 {
   9778     int rv = BCM_E_NONE;
   9779     int idx = 0, num_vp = 0;
   9780     bcm_vxlan_port_t info;
   9781     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   9782 
   9783     if (NULL == cb) {
   9784         return BCM_E_PARAM;
   9785     }
   9786 
   9787     /* Get VXLAN bookkeeping info instance */
   9788     BCM_IF_ERROR_RETURN(
   9789         gh2_vxlan_bk_info_instance_get(unit, &vxlan_info));
   9790 
   9791     num_vp = vxlan_info->num_vxlan_vp;
   9792     for (idx = 0; idx < num_vp; idx++) {
   9793         if (bcmi_gh2_vxlan_vp_used_get(unit, idx)) {
   9794             bcm_vxlan_port_t_init(&info);
   9795 
   9796             rv = bcmi_gh2_vxlan_port_vp_get(unit, BCM_VXLAN_VPN_INVALID,
   9797                                             idx, &info);
   9798             if (BCM_SUCCESS(rv)) {
   9799                 BCM_IF_ERROR_RETURN(
   9800                     cb(unit, &info, user_data));
   9801             }
   9802         }
   9803     }
   9804 
   9805     return rv;
   9806 }
   9807 
   9808 /*
   9809  * Function:
   9810  *    bcmi_gh2_vxlan_egress_entry_mac_replace
   9811  * Purpose:
   9812  *    Replace VXLAN egress MAC entry
   9813  * Parameters:
   9814  *    unit - (IN) Device Number
   9815  *    nh_index  - (IN) Egress L3 NH idx
   9816  *    egr - (IN) Egress forwarding destination
   9817  */
   9818 int
   9819 bcmi_gh2_vxlan_egress_entry_mac_replace(
   9820     int unit,
   9821     int nh_index,
   9822     bcm_l3_egress_t *egr)
   9823 {
   9824     egr_l3_next_hop_entry_t egr_nh;
   9825     uint32 new_macda_index = -1, old_macda_index = -1;
   9826     void *entries[1];
   9827     int rv = BCM_E_NONE;
   9828     int entry_type;
   9829     egr_mac_da_profile_entry_t old_macda_entry, new_macda_entry;
   9830 
   9831     /* Parameter Check */
   9832     if (egr == NULL) {
   9833         return BCM_E_PARAM;
   9834     }
   9835     if (nh_index < soc_mem_index_min(unit, EGR_L3_NEXT_HOPm) ||
   9836         nh_index > soc_mem_index_max(unit, EGR_L3_NEXT_HOPm)) {
   9837         return BCM_E_PARAM;
   9838     }
   9839 
   9840     BCM_IF_ERROR_RETURN(
   9841         soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   9842                      nh_index, &egr_nh));
   9843     entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9844                                      ENTRY_TYPEf);
   9845     /* Replace vxlan egress mac da */
   9846     if (entry_type == 0xa) {
   9847         /* Get old mac_da_profile info */
   9848         old_macda_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9849                                               VXLAN__MAC_DA_PROFILE_INDEXf);
   9850         sal_memset(&old_macda_entry, 0, sizeof(old_macda_entry));
   9851         BCM_IF_ERROR_RETURN(
   9852             soc_mem_read(unit, EGR_MAC_DA_PROFILEm, MEM_BLOCK_ANY,
   9853                          old_macda_index, &old_macda_entry));
   9854         /* Delete old mac_da_profile index */
   9855         BCM_IF_ERROR_RETURN(
   9856             _bcm_mac_da_profile_entry_delete(unit, old_macda_index));
   9857 
   9858         /* Add new mac_da_profile index */
   9859         sal_memset(&new_macda_entry, 0, sizeof(new_macda_entry));
   9860         soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, &new_macda_entry,
   9861                              MAC_ADDRESSf, egr->mac_addr);
   9862         entries[0] = &new_macda_entry;
   9863         rv = _bcm_mac_da_profile_entry_add(unit, entries,
   9864                                            1, &new_macda_index);
   9865         if (BCM_FAILURE(rv)) {
   9866             /* Restore previous old mac_da_profile info */
   9867             entries[0] = &old_macda_entry;
   9868             BCM_IF_ERROR_RETURN(
   9869                 _bcm_mac_da_profile_entry_add(unit, entries,
   9870                                               1, &new_macda_index));
   9871         }
   9872 
   9873         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   9874                             VXLAN__MAC_DA_PROFILE_INDEXf, new_macda_index);
   9875         BCM_IF_ERROR_RETURN(
   9876             soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL,
   9877                           nh_index, &egr_nh));
   9878     }
   9879 
   9880     return rv;
   9881 }
   9882 
   9883 #ifndef BCM_SW_STATE_DUMP_DISABLE
   9884 /*
   9885  * Function:
   9886  *    bcmi_gh2_vxlan_sw_dump
   9887  * Purpose:
   9888  *    Displays VXLAN information maintained by software.
   9889  * Parameters:
   9890  *    unit - (IN) Device Number
   9891  * Returns:
   9892  *    None
   9893  */
   9894 void
   9895 bcmi_gh2_vxlan_sw_dump(int unit)
   9896 {
   9897     int i, num_tnl, num_vp, num_vfi;
   9898     bcm_ip6_t dip6, sip6;
   9899     bcmi_gh2_vxlan_bookkeeping_t *vxlan_info;
   9900 
   9901     /* Get VXLAN bookkeeping info instance */
   9902     (void)gh2_vxlan_bk_info_instance_get(unit, &vxlan_info);
   9903 
   9904     num_tnl = vxlan_info->num_vxlan_tnl;
   9905     LOG_CLI((BSL_META_U(unit,
   9906                         "Tunnel Initiator Endpoints:\n")));
   9907     for (i = 0; i < num_tnl; i++) {
   9908         if (vxlan_info->vxlan_tunnel_init[i].dip != 0 &&
   9909             vxlan_info->vxlan_tunnel_init[i].sip != 0) {
   9910             /* Tunnel for IPv4 */
   9911             LOG_CLI((BSL_META_U(unit,
   9912                                 "Tunnel idx:%d, sip:%x, dip:%x, vlan:%x\n"), i,
   9913                     vxlan_info->vxlan_tunnel_init[i].sip,
   9914                     vxlan_info->vxlan_tunnel_init[i].dip,
   9915                     vxlan_info->vxlan_tunnel_init[i].vlan));
   9916         } else if (!bcmi_gh2_vxlan_tunnel_ip6_is_zero
   9917                        (vxlan_info->vxlan_tunnel_init[i].dip6) &&
   9918                    !bcmi_gh2_vxlan_tunnel_ip6_is_zero
   9919                        (vxlan_info->vxlan_tunnel_init[i].sip6)) {
   9920             /* Tunnel for IPv6 */
   9921             sal_memcpy(sip6,
   9922                        vxlan_info->vxlan_tunnel_init[i].sip6,
   9923                        BCM_IP6_ADDRLEN);
   9924             sal_memcpy(dip6,
   9925                        vxlan_info->vxlan_tunnel_init[i].dip6,
   9926                        BCM_IP6_ADDRLEN);
   9927             LOG_CLI((BSL_META_U
   9928                         (unit, "Tunnel idx:%d, "
   9929                          "sip6:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x, "
   9930                          "dip6:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x, "
   9931                          "vlan:%x\n"), i,
   9932                     sip6[0], sip6[1], sip6[2], sip6[3], sip6[4], sip6[5],
   9933                     sip6[6], sip6[7], sip6[8], sip6[9], sip6[10], sip6[11],
   9934                     sip6[12], sip6[13], sip6[14], sip6[15],
   9935                     dip6[0], dip6[1], dip6[2], dip6[3], dip6[4], dip6[5],
   9936                     dip6[6], dip6[7], dip6[8], dip6[9], dip6[10], dip6[11],
   9937                     dip6[12], dip6[13], dip6[14], dip6[15],
   9938                     vxlan_info->vxlan_tunnel_init[i].vlan));
   9939         }
   9940     }
   9941 
   9942     LOG_CLI((BSL_META_U(unit,
   9943                         "\nTunnel Terminator Endpoints:\n")));
   9944     for (i = 0; i < num_tnl; i++) {
   9945         if (vxlan_info->vxlan_tunnel_term[i].dip != 0 &&
   9946             vxlan_info->vxlan_tunnel_term[i].sip != 0) {
   9947             /* Tunnel for IPv4 */
   9948             LOG_CLI((BSL_META_U(unit,
   9949                                 "Tunnel idx:%d, sip:%x, dip:%x, vlan:%x\n"), i,
   9950                     vxlan_info->vxlan_tunnel_term[i].sip,
   9951                     vxlan_info->vxlan_tunnel_term[i].dip,
   9952                     vxlan_info->vxlan_tunnel_term[i].vlan));
   9953         } else if (!bcmi_gh2_vxlan_tunnel_ip6_is_zero
   9954                        (vxlan_info->vxlan_tunnel_term[i].dip6) &&
   9955                    !bcmi_gh2_vxlan_tunnel_ip6_is_zero
   9956                        (vxlan_info->vxlan_tunnel_term[i].sip6)) {
   9957             /* Tunnel for IPv6 */
   9958             sal_memcpy(sip6,
   9959                        vxlan_info->vxlan_tunnel_term[i].sip6,
   9960                        BCM_IP6_ADDRLEN);
   9961             sal_memcpy(dip6,
   9962                        vxlan_info->vxlan_tunnel_term[i].dip6,
   9963                        BCM_IP6_ADDRLEN);
   9964             LOG_CLI((BSL_META_U
   9965                         (unit, "Tunnel idx:%d, "
   9966                          "sip6:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x, "
   9967                          "dip6:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x, "
   9968                          "vlan:%x\n"), i,
   9969                     sip6[0], sip6[1], sip6[2], sip6[3], sip6[4], sip6[5],
   9970                     sip6[6], sip6[7], sip6[8], sip6[9], sip6[10], sip6[11],
   9971                     sip6[12], sip6[13], sip6[14], sip6[15],
   9972                     dip6[0], dip6[1], dip6[2], dip6[3], dip6[4], dip6[5],
   9973                     dip6[6], dip6[7], dip6[8], dip6[9], dip6[10], dip6[11],
   9974                     dip6[12], dip6[13], dip6[14], dip6[15],
   9975                     vxlan_info->vxlan_tunnel_term[i].vlan));
   9976         }
   9977     }
   9978 
   9979     num_vp = vxlan_info->num_vxlan_vp;
   9980     LOG_CLI((BSL_META_U(unit,
   9981                         "\n  Match Info    : \n")));
   9982     for (i = 0; i < num_vp; i++) {
   9983         if ((vxlan_info->match_key[i].trunk_id == 0 ||
   9984             vxlan_info->match_key[i].trunk_id == -1) &&
   9985             (vxlan_info->match_key[i].modid == 0 ||
   9986             vxlan_info->match_key[i].modid == -1) &&
   9987             (vxlan_info->match_key[i].port == 0) &&
   9988             (vxlan_info->match_key[i].flags == 0)) {
   9989             continue;
   9990         }
   9991         LOG_CLI((BSL_META_U(unit,
   9992                             "\n  VXLAN port vp = %d\n"), i));
   9993         LOG_CLI((BSL_META_U(unit,
   9994                             "Flags = %x\n"), vxlan_info->match_key[i].flags));
   9995         LOG_CLI((BSL_META_U(unit,
   9996                             "Index = %x\n"), vxlan_info->match_key[i].index));
   9997         LOG_CLI((BSL_META_U(unit,
   9998                             "TGID = %d\n"), vxlan_info->match_key[i].trunk_id));
   9999         LOG_CLI((BSL_META_U(unit,
  10000                             "Modid = %d\n"), vxlan_info->match_key[i].modid));
  10001         LOG_CLI((BSL_META_U(unit,
  10002                             "Port = %d\n"), vxlan_info->match_key[i].port));
  10003         LOG_CLI((BSL_META_U(unit,
  10004                             "Match VLAN = %d\n"),
  10005                 vxlan_info->match_key[i].match_vlan));
  10006         LOG_CLI((BSL_META_U(unit,
  10007                             "Match Inner VLAN = %d\n"),
  10008                 vxlan_info->match_key[i].match_inner_vlan));
  10009         LOG_CLI((BSL_META_U(unit,
  10010                             "Match tunnel Index = %x\n"),
  10011                 vxlan_info->match_key[i].match_tunnel_index));
  10012         LOG_CLI((BSL_META_U(unit,
  10013                             "Match count = %x\n"),
  10014                 vxlan_info->match_key[i].match_count));
  10015         LOG_CLI((BSL_META_U(unit,
  10016                             "Related VFI = %d\n"),
  10017                 vxlan_info->match_key[i].vfi));
  10018     }
  10019 
  10020     num_vfi = vxlan_info->num_vxlan_vfi;
  10021     LOG_CLI((BSL_META_U(unit,
  10022                         "\nVxlan VPN INFO:\n")));
  10023     for (i = 0; i < num_vfi; i++) {
  10024         if (vxlan_info->vxlan_vpn_info[i].valid != 0 ||
  10025             vxlan_info->vxlan_vpn_info[i].vnid != 0) {
  10026             LOG_CLI((BSL_META_U(unit,
  10027                                 "\nVxlan VPN VFI %d:\n"), i));
  10028             LOG_CLI((BSL_META_U(unit,
  10029                                 "VXLAN VPN VFI VALID = %x \n"),
  10030                     vxlan_info->vxlan_vpn_info[i].valid));
  10031             LOG_CLI((BSL_META_U(unit,
  10032                                 "VXLAN VPN VNID = %d \n"),
  10033                     vxlan_info->vxlan_vpn_info[i].vnid));
  10034         }
  10035     }
  10036 
  10037     LOG_CLI((BSL_META_U(unit,
  10038                         "\nVxlan Outer TPID INFO:\n")));
  10039     for (i = 0; i < vxlan_info->num_vxlan_outer_tpid; i++) {
  10040         LOG_CLI((BSL_META_U(unit,
  10041                             "Index %d: "), i));
  10042         LOG_CLI((BSL_META_U(unit,
  10043                             "TPID value = %x, "),
  10044                 vxlan_info->vxlan_outer_tpid[i].tpid_value));
  10045         LOG_CLI((BSL_META_U(unit,
  10046                             "Ref count = %d \n"),
  10047                 vxlan_info->vxlan_outer_tpid[i].ref_count));
  10048     }
  10049 
  10050     LOG_CLI((BSL_META_U(unit,
  10051                         "\nVxlan VLAN translation INFO:\n")));
  10052     for (i = 0; i < vxlan_info->num_vxlan_vfi; i++) {
  10053         if (vxlan_info->vxlan_vlan_xlate[i].ref_count != 0) {
  10054             LOG_CLI((BSL_META_U(unit,
  10055                                 "Index %d: "), i));
  10056             LOG_CLI((BSL_META_U(unit,
  10057                                 "Ref count = %d \n"),
  10058                     vxlan_info->vxlan_vlan_xlate[i].ref_count));
  10059         }
  10060     }
  10061 
  10062     return;
  10063 }
  10064 #endif /* BCM_SW_STATE_DUMP_DISABLE */
  10065 
  10066 #endif /* BCM_GREYHOUND2_SUPPORT && INCLUDE_L3 */
  10067